RNN时间序列预测空气质量

关于RNN可以参考这篇文章博文地址

背景

时间序列是一个比较场景的问题,

获取数据

从UIC下载学习库下载地址下载其中的csv文件

图片.png

其各个数据特征如下
图片.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
图片.png

查看数据情况可以用data.head在jupyter会显示前5行

data.head()
图片.png

pm2.5就是我们需要的label通过下面操作查看是否有空的数据

data['pm2.5'].isna().sum()

可以看到有2067行数据包含空的pm2.5

图片.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) 

查看下数据的情况


图片.png

设置成按照时间索引

#设置成按时间索引
data=data.set_index('time')

从数据中可以看到cbwd不是一些数值标量,这需要对它进行转换,先查看cbwd有哪些内容

#找到cbwd有哪些内容
data.cbwd.unique()
图片.png

将这几个标识编码

#把风向编码化
data=data.join(pd.get_dummies(data.cbwd))

编码化完成后删除cbwd列

del data['cbwd']

查看下表格,可以看到4个标识已经编码化了

data.tail()
图片.png

可以下面代码查看最后1000次pm2.5变化情况

data['pm2.5'][-1000:].plot()
图片.png

最后1000次温度变化情况

data['TEMP'][-1000:].plot()
图片.png

可以通过查看列数查看特征数量

#特征数量
len(data.columns)
图片.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个特征


图片.png

将采样的数据转换成np的array

data_ = np.array([df.values for df in data_])
data_.shape
图片.png

洗牌数据

np.random.shuffle(data_)

特征切片

#特征切片
x = data_[:, :5*24, :]
# label
y = data_[:,-1, 0]

查看下x,y的数据形状

x.shape
y.shape
图片.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)
                   )
图片.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') #测试数据
图片.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'] #平均绝对误差
)
图片.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()

可以很明显的看到效果的提升


图片.png

图片.png
  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值