关于RNN可以参考这篇文章博文地址
背景
时间序列是一个比较场景的问题,
获取数据
从UIC下载学习库下载地址下载其中的csv文件
![](https://img.haomeiwen.com/i5782625/16b4fa1ee4b69490.png)
其各个数据特征如下
![](https://img.haomeiwen.com/i5782625/fbdb9381bbf616f7.png)
处理数据
先导入需要用到的模块
这里用到了keras的API关于keras的使用可以看官方教程点击前往
from tensorflow import keras
from tensorflow.keras import layers
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
导入数据
data = pd.read_csv('D:\machine\project/testbeijinpm2.5/PRSA_data_2010.1.1-2014.12.31.csv')
查看下列信息看是否导入成功
data.columns
![](https://img.haomeiwen.com/i5782625/a3c2db9c5de3aa65.png)
查看数据情况可以用data.head在jupyter会显示前5行
data.head()
![](https://img.haomeiwen.com/i5782625/88f887dd2f16150f.png)
pm2.5就是我们需要的label通过下面操作查看是否有空的数据
data['pm2.5'].isna().sum()
可以看到有2067行数据包含空的pm2.5
![](https://img.haomeiwen.com/i5782625/eb60c7674cdeb84c.png)
对于这些空的数据,如果采取删除的动作,那样会导致数据不连续,可能对于训练的结果产生影响,这里采用的处理方式是讲空值处理成它最近的点的值,这样可以保证数据的连续性和前后关联性,有不至于有太大误差
运行如下操作处理
data=data.iloc[24:].fillna(method='ffill')
可以观察到时间的年月日小时分布在不同列
它们应该分布在同一列属于同一个特征
这里导入python的时间模块进行处理
import datetime
将数据 中的year,month,day,hour整合成一条数据赋值给data['time']
#时间组合
data['time']=data.apply(lambda x: datetime.datetime(year=x['year'],
month=x['month'],
day=x['day'],
hour=x['hour']),
axis=1
)
删除原本的year,month,day,no列
data.drop(columns=['year','month','day','hour','No'],inplace=True)
查看下数据的情况
![](https://img.haomeiwen.com/i5782625/a0e220d22ef12976.png)
设置成按照时间索引
#设置成按时间索引
data=data.set_index('time')
从数据中可以看到cbwd不是一些数值标量,这需要对它进行转换,先查看cbwd有哪些内容
#找到cbwd有哪些内容
data.cbwd.unique()
![](https://img.haomeiwen.com/i5782625/1f67ef97e8d021a0.png)
将这几个标识编码
#把风向编码化
data=data.join(pd.get_dummies(data.cbwd))
编码化完成后删除cbwd列
del data['cbwd']
查看下表格,可以看到4个标识已经编码化了
data.tail()
![](https://img.haomeiwen.com/i5782625/d6ca75b826e6d1b3.png)
可以下面代码查看最后1000次pm2.5变化情况
data['pm2.5'][-1000:].plot()
![](https://img.haomeiwen.com/i5782625/d44ebfe5150df3e0.png)
最后1000次温度变化情况
data['TEMP'][-1000:].plot()
![](https://img.haomeiwen.com/i5782625/cbe74eb64cec2e57.png)
可以通过查看列数查看特征数量
#特征数量
len(data.columns)
![](https://img.haomeiwen.com/i5782625/9dae22163b0366b7.png)
时间序列预测是观测过去多久的值,来预测未来多久的值,因此这里定义两个变量seq_length代表过去5×24小时的数据,来预测未来24小时的数据。
seq_length = 5*24
delay = 24
然后我们就可以采用数据,以seq_length和delay来采样
#采样的数据
data_ = []
for t in range(len(data) - seq_length - delay):
data_.append(data.iloc[t:t + seq_length + delay ])
查看下采样后的数据形状
data_[0].shape
可以看到144个样例,11个特征
![](https://img.haomeiwen.com/i5782625/7f7cd1c3b0080dd0.png)
将采样的数据转换成np的array
data_ = np.array([df.values for df in data_])
data_.shape
![](https://img.haomeiwen.com/i5782625/7217f412b54add1e.png)
洗牌数据
np.random.shuffle(data_)
特征切片
#特征切片
x = data_[:, :5*24, :]
# label
y = data_[:,-1, 0]
查看下x,y的数据形状
x.shape
y.shape
![](https://img.haomeiwen.com/i5782625/13cc51a28c023342.png)
划分80%数据用于训练集 20%用于测试集合
split_b = data_.shape[0]*0.8
split_b = int(split_b)
train_x = x[ :split_b]
train_y = y[ :split_b]
test_x = x[split_b: ]
test_y = y[split_b: ]
数据归一化,让不同特征规范统一范围,有效利用神经网络的训练避免引起误差。
#计算均值
#数据归一化,
mean = test_x.mean(axis = 0)
std = train_x.std(axis = 0)
train_x = (train_x - mean)/std
test_x = (test_x - mean) / std
搭建神经网络
全链接神经网络方式
batch_size = 128 #每次训练128个数据
model = keras.Sequential()
model.add(layers.Flatten(input_shape=(train_x.shape[1:])))
model.add(layers.Dense(32,activation='relu'))
model.add(layers.Dense(1))
model.compile(
optimizer='adam', #优化算法
loss = 'mse', #均方差
metrics= ['mae'] #平均绝对误差
)
history = model.fit(train_x, train_y,
batch_size =batch_size,
epochs = 50,
validation_data=(test_x,test_y)
)
![](https://img.haomeiwen.com/i5782625/edf2e3fd8b80f86e.png)
#画图看情况
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(history.epoch,history.history['mean_absolute_error'],c='r') #训练数据
plt.plot(history.epoch,history.history['val_mean_absolute_error'],c='g') #测试数据
![](https://img.haomeiwen.com/i5782625/63401bef2fd29915.png)
LSTM方式
在训练过程中可以看到速度明显要比全连接的方式要好慢上许多,而训练的效果也比全链接网络的要要很多。
train_x.shape #第一维度大小,第二维度观测次数,第三维度每次观测的特征
这只有一层的LSTM
model = keras.Sequential()
model.add(layers.LSTM(32,input_shape=(120,11)))
model.add(layers.Dense(1))
编译选择模型的优化方式
model.compile(
optimizer='adam', #优化算法
loss = 'mse', #均方差
metrics= ['mae'] #平均绝对误差
)
![](https://img.haomeiwen.com/i5782625/2f789dda5d6d0dea.png)
history = model.fit(train_x, train_y,
batch_size =batch_size,
epochs = 200,
validation_data=(test_x,test_y)
)
plt.plot(history.epoch,history.history.get('mean_absolute_error'),'y',label='Training loss')
plt.plot(history.epoch,history.history.get('val_mean_absolute_error'),'b',label= 'Test loss')
plt.legend()
LSTM层优化
添加多层优化拟合能力,需要添加
return_sequences,最后一层不需要
可以观察到训练速度更加缓慢,但训练效果却是跨越式的进展。
model = keras.Sequential()
model.add(layers.LSTM(32,input_shape=(120,11),return_sequences=True))
model.add(layers.LSTM(32,return_sequences=True))
model.add(layers.LSTM(32,return_sequences=True))
model.add(layers.LSTM(32))
model.add(layers.Dense(1))
#在训练过程中降低学习速率,加快训练速度同时增加训练的效果
#连续的3个val_LOSS没有降低则降低学习速率0.3,最小的学习速率为0.000001
lr_reduce = keras.callbacks.ReduceLROnPlateau('val_loss',patience=3,factor=0.3,min_lr=0.00001)
model.compile(
optimizer='adam', #优化算法
loss = 'mse', #均方差
metrics= ['mae'] #平均绝对误差
)
history = model.fit(train_x, train_y,
batch_size =batch_size,
epochs = 200,
callbacks = [lr_reduce],
validation_data=(test_x,test_y)
)
plt.plot(history.epoch,history.history.get('mean_absolute_error'),'y',label='Training loss')
plt.plot(history.epoch,history.history.get('val_mean_absolute_error'),'b',label= 'Test loss')
plt.legend()
可以很明显的看到效果的提升
![](https://img.haomeiwen.com/i5782625/49d4a78d900acd54.png)
![](https://img.haomeiwen.com/i5782625/a1701246d3d95f54.png)
网友评论