##耶拿天气预测,根据输入几天的数据点预测24小时之后的气温###########
##
import os
data_dir = './data/jena_climate_2009_2016.csv'
fname = os.path.join(data_dir,'jena_climate_2009_2016.csv')
f = open(fname)
data = f.read()
f.close()
lines = data.split('\n')#得到第一行
header = lines[0].split(',')#得到第一行的列头
lines = lines[1:]#第一行以后是数据列
print(header)
print(len(lines))#420551行数据42万
##############将行数据转为numpy数组#####################
import numpy as np
float_data = np.zeros((len(lines),len(header) - 1))
for i,line in enumerate(lines):
values = [float(x) for x in line.split(',')[1:]]#取出第二列到最后,然后转为float
float_data[i,:] = values
#绘制出温度图
#from matplotlib import pyplot as plt
#temp=float_data[:,1]#可以用emeditor查看对照,取出所有第二列数据
#plt.plot(range(len(temp)),temp)
#前10天的温度时间序列
#plt.plot(range(1440),temp[:1440])#没10分钟采集一次,每天有144个数据
#数据预处理。减去平均值,除以标准差。使用前200000个时间步
#作为训练数据,所有只处理这些数据
mean = float_data[:200000].mean(axis=0)#得到平均值
float_data-=mean#减去平均值
std = float_data[:200000].std(axis=0)#得到标准差
float_data/=std#除以标准差
print(data.shape[-1])
###定义数据生成器,生成(samples,targets)的张量#####################
def generator(data,lookback,delay,min_index,max_index,
shffle=False,batch_size=128,step=6):
#"""data原始数据组 lockback回顾,输入数据应该包括过去多少个时间步假设是100
#delay目标在未来多少个时间步之后
#min_index,max_index是data数组中的索引,用于界定需要抽取的时间步的范围
#shuffle打乱样本 batch_size每个批量的样本数
#step数据采样的周期.6就是没小时抽取一个数据点."""
if max_index is None:
max_index = len(data) - delay - 1#如果没指定就自动计算
i = min_index + lookback
while 1:
if shuffle:#如果打乱
rows = np.random.randint(min_index + lookback,max_index,batch_size)
#randint随机生成指定范围内的整数
else:
if i + batch_size >= max_index:
i = min_index + lookback
rows = np.arange(i,min(i + batch_size,max_index))
#根据前两个参数指定的范围生成序列,第三个是步长
i+=len(rows)
samples = np.zeros((len(rows),
lookback // step,#取整除
data.shape[-1]))
print('Sample Shape:',samples.shape)
targets = np.zeros((len(rows),))
print('Targets Shape:',targets.shape)
for j,row in enumerate(rows):
indices = range(rows[j] - lookback,rows[j],step)
samples[j] = data[indices]
targets[j] = data[rows[j] + delay][1]
yield sameples,targets
#使用generator实例化3个生成器:训练、验证、测试##############################
#训练器读20000个;验证器读后100000个;测试的读剩下的
lookback = 1440#10天的步数
step = 6#跳6步一次采样,就是1小时一次
delay = 144#144步目标是未来24小时之后的数据
batch_size = 128
train_gen = generator(float_data,lookback=lookback,delay=delay,min_index=0,
max_index=200000,shuffle=True,step=step,
batch_size=batch_size)
val_gen = generator(float_data,lookback=lookback,delay=delay,min_index=200001,
max_index=300000,step=step,batch_size=batch_size)
test_gen = generator(float_data,lookback=lookback,delay=delay,min_index=300001,
max_index=None,step=step,batch_size=batch_size)
val_steps = (300000 - 200001 - lookback) // batch_size#为了查看整个验证集,要从val_gen中抽取多少次
test_steps = (len(float_data) - 300001 - lookback) // batch_size#查看测试集,要从test_gen中抽取多少次
##使用代码建立常识方法(非深度学习)来根据百分比(总是猜测百分比高的哪个值)来预测温度###
##深度学习必须战胜这种简单统计逻辑才能说明她又价值##########################
#书上是伪代码,结果是和温度误差的绝对值是2.57摄氏度。见Page178
###############################################################################
###建立第一种深度学习模型:密集连接模型。#####################################
#然后逐渐增加模型复杂度,以确定模型的复杂度的增加是合理的######################
#先用整个密集模型来和常识方法的2.57摄氏度比较
#from keras import models,layers,optimizers
#model = models.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=optimizers.RMSprop(),loss='mae')
#history=model.fit_generator(ttrain_gen,steps_per_epoch=500,
# epochs=20,
# validation_data=val_gen,
# validation_steps=val_steps
# )
#效果不好。
##建立第二种深度学习模型使用GRU(gated recurrent unit门控循环单元)层,比LSTM层##
##的计算代价低,相应的表示力也低点儿###########
#from keras import models,layers,optimizers
#model=models.Sequential()
#model.add(layers.GRU(32,input_shape=(None,float_data.shape[-1])))
#model.add(layers.Dense(1))
#model.compile(optimizer=optimizers.RMSprop(),loss='mae')
#history=model.fit_generator(train_gen,steps_per_epoch=500,
# epochs=20,
# validation_data=val_gen,
# val_steps=val_steps)
#效果好多了!远优于基于常识的基准方法。这证明了机器学习的
#价值,也证明了循环网络与序列展平的密集网络相比在这种任务上的优势。
#和温度误差的绝对值是2.35摄氏度。比常识方法的2.57摄氏度好很多。
#建立第三种模型:使用内置于GRD层的dropout解决过拟合,因为dropout正则化的网络总
#是需要更长的时间才能完全收敛,所以网络训练轮次增加为原来的2倍。
#from keras import models,layers,optimizers
#model = models.Sequential()
#model.add(layers.GRU(32,dropout=0.2,recurrent_dropout=0.2,
# input_shape=(None, float_data.shape[-1])))
#model.add(layers.Dense(1))
#model.compile(optimizer=optimizers.RMSprop(), loss='mae')
#history = model.fit_generator(train_gen,
# steps_per_epoch=500,
# epochs=40,
# validation_data=val_gen,
# validation_steps=val_steps)
#这样使得训练的loss值更加稳定平滑可控。但是不再过拟合,说明网络的容量
#不足了。使用循环层堆叠增加融了。使用堆叠层要返回完整序列因为GRU层
#是一种RNN层,默认不返回完整训练序列。
#建立第四个模型:使用堆叠GRU层的模型。
from keras import models,layers,optimizers
model = models.Sequential()
model.add(layers.GRU(32,dropout=0.1,recurrent_dropout=0.5,
return_sequence=True,
input_shape=(None, float_data.shape[-1])))
model.add(layers.GRU(64,activation='relu',dropout=0.1,
recurrent_dropout=0.5))
model.add(layers.Dense(1))
model.compile(optimizer=optimizers.RMSprop(), loss='mae')
history = model.fit_generator(train_gen,
steps_per_epoch=500,
epochs=40,
validation_data=val_gen,
validation_steps=val_steps)
#增加了网络层,有所改善但是不明显。但是计算成本会提高。
#尝试建立第五种模型:使用双向RNN.
#就是使用GRU、LSTM分别从正序和倒序进行学习。
#使用2个分枝训练合并。见"_6_3_8_2....py"和“_6_3_3...py“
#Keras内置了Bidirectional双向层。
##绘图
import matplotlib.pyplot as plt
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()