# 一种基于常识的、非机器学习的基准方法-->始终预测24小时后的温度等于现在的温度 def evaluate_naive_method(): batch_maes = [] for step in range (val_steps): samples, targets = next (val_gen) preds = samples[:, -1, 1] mae = np.mean (np.abs (preds - targets)) batch_maes.append (mae)evaluate_naive_method ()# 将MAE转换成摄氏温度误差 std = float_data[:200000].std (axis=0) celsius_mae = 0.29 * std[1] # celsius_mae
|
|
from keras.models import Sequential from keras import layers#对比1.全连接网络 model = Sequential() model.add(layers.Flatten(input_shape=(lookback//step,float_data.shape[-1]))) model.add(layers.Dense(32,activation='relu')) model.add(layers.Dense(1))model.compile(optimizer='RMSprop',loss='mae')history = model.fit_generator( train_gen, steps_per_epoch=50, epochs=10, validation_data=val_gen, validation_steps=val_steps )
|
|
总结
第一个全连接方法的效果并不好,但这并不意味机器学习不适用于这个问题,该方法首先将时间序列展平,
这从输入数据中删除了时间的概念。 数据本身是个序列,其中因果关系和顺序都很重要。
|
#对比2.循环网络GRU #训练并评估一个基于GRU的模型 from keras.models import Sequential from keras.layers import Dense,GRUmodel = Sequential() model.add(GRU(32,input_shape=(None,float_data.shape[-1]))) model.add(Dense(1))model.compile(optimizer='rmsprop',loss='mae') history = model.fit_generator(train_gen, steps_per_epoch=50, epochs=5, validation_data = val_gen, validation_steps = val_steps)# loss: 0.3403 - val_loss: 0.3160
|
|
#使用dropout来降低过拟合 from keras.models import Sequential from keras.layers import Dense,GRUmodel = Sequential() model.add(GRU(32,dropout=0.2,recurrent_dropout=0.2,input_shape=(None,float_data.shape[-1]))) model.add(Dense(1))model.compile(optimizer='RMSprop',loss='mae') history = model.fit_generator(train_gen, steps_per_epoch=50, epochs=5, validation_data = val_gen, validation_steps = val_steps)
|
|
模型不再过拟合,但似乎遇到了性能瓶颈,所以我们应该考虑增加网络容量。
增加网络容量直到过拟合变成主要的障碍。
只要过拟合不是太严重,那么很可能是容量不足的问题
|
#对比3.循环层堆叠 #训练并评估一个使用dropout正则化的堆叠GRU模型 #数据集:温度 from keras.models import Sequential from keras.layers import Dense,GRUmodel = Sequential() model.add(GRU(32,dropout=0.1,recurrent_dropout=0.5,input_shape=(None,float_data.shape[-1]),return_sequences=True)) # return_sequences=True,在keras中逐个堆叠循环层,所有中间层都应该返回完整的输出序列, # 而不是只返回最后一个时间步的输出 model.add(GRU(64,activation='relu',dropout=0.1,recurrent_dropout=0.5)) # 但是最后一个LSTM层return_sequences通常为false model.add(Dense(1))model.summary() model.compile(optimizer='rmsprop',loss='mae') history = model.fit_generator(train_gen, steps_per_epoch=50, epochs=5, validation_data = val_gen, validation_steps = val_steps)
|
|
|
结果如上图所示,可以看出,添加一层的确对结果有所改进,但并不显著,
我们可以得到两个结论:
1.因为过拟合仍然不是很严重,所以可以放心的增大每层的大小,
以进一步改进验证损失,但这么做的计算成本很高
2.添加一层厚模型并没有显著改进,所以你可能发现,提高网络能力
的回报在逐渐减小
|
#对比4:逆序序列评估LSTM #数据集 imdb from keras.datasets import imdb from keras.preprocessing import sequence from keras import layers from keras.models import Sequentialmax_features = 10000 max_len = 500(x_train,y_train),(x_test,y_test) = imdb.load_data(num_words = max_features) x_train = [x[::-1] for x in x_train] x_test = [x[::-1] for x in x_test]x_train = sequence.pad_sequences(x_train,maxlen = max_len) x_test = sequence.pad_sequences(x_test,maxlen = max_len)model = Sequential() model.add(layers.Embedding(max_features,128)) model.add(layers.LSTM(32)) #return_sequences=True model.add(Dense(1,activation='sigmoid')) model.summary()model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics = ['acc']) history = model.fit(x_train,y_train, epochs=2, batch_size=128, validation_split=0.2) #没有分val出来,直接写0.2就表示从train数据集中分0.2出来当做验证集
|
|
总结:模型性能与正序LSTM几乎相同,这证实了一个假设,虽然单词顺序对理解语言很重要,但使用哪种顺序不重要。
双向RNN正是利用这个想法来提高正序RNN的性能,他从两个方向查看数据,从而得到更加丰富的表示,并捕捉到仅使用正序RNN时可能忽略的一些模式
|
(3)Bidirectional RNN
#训练并评估一个双向LSTM #数据集imdb model = Sequential() model.add(layers.Embedding(max_features,32)) model.add(layers.Bidirectional(layers.LSTM(32))) model.add(layers.Dense(1,activation='sigmoid'))model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['acc']) history = model.fit(x_train,y_train, epochs = 5, batch_size = 128, validation_split = 0.2)
|
|
#训练一个双向GRU #数据集 温度 model = Sequential() model.add(layers.Bidirectional(layers.GRU(32),input_shape=(None,float_data.shape[-1]))) model.add(layers.Dense(1))model.compile(optimizer='rmsprop',loss='mae') history = model.fit_generator(train_gen, epochs = 5, steps_per_epoch = 50, validation_data = val_gen, validation_steps = val_steps)
|
|
更多尝试
- 在堆叠循环层中调节每层的单元个数,当前取值在很大程度上是任意选择的,因此可能不是最优的。
- 调节rmsprop优化器的学习率
- 尝试使用LSTM层代替GRU
- 在循环层上面尝试使用更大的密集连接回归器,即更大的Dense层或Dense层的堆叠
- 在测试集上运行性能最佳的模型,否则,开发的网络架构将会对验证集过拟合
|