Python数据分析案例36——基于神经网络的AQI多步预测(空气质量预测)

案例背景

不知道大家发现了没,现在的神经网络做时间序列的预测都是单步预测,即(需要使用X的t-n期到X的t-1期的数据去预测X的t期的数据),这种预测只能预测一个点,我需要预测X的t+1期的数据就没办法了,有的同学说可以把预测的结果X的t+1拿进来作为新的x去预测。。。我只能说这种情况是有误差的,而且误差会累加,这样效果很差。(看很多ARIMA的预测效果一条直线就知道了)

很多时候需要进行多步预测,即(需要使用X的t-n期到X的t-1期的数据去预测X的t期到t+n期的数据,预测出来的就不止一个点。这种方法,ARIMA这种传统统计学的方法是做不到的了,神经网络可以做到,因为神经网络可以接受一条序列作为y,这样去训练就可以得到多步预测模型了。

本次案例使用某城市的AQI数据,去预测未来一年365天的数据。来看看我怎么完成的。


数据介绍

没啥好介绍的,一般下载城市的数据都是这样的,我们只需要AQI这一列就行。

任务介绍:基于空气质量检测数据,采用人工神经网络对AQI进行回归预测。

  • (1)利用Python实现回归预测并得出2024年的预测结果。
  • (2)展示随迭代次数增加,不同激活函数下的损失函数的变化情况。

当然,需要本次演示案例的数据和所有代码文件的同学可以参考: AQI预测


代码实现

导入包

python 复制代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']  #解决中文显示乱码问题
plt.rcParams['axes.unicode_minus']=False

from keras.models import Sequential
from keras.layers import LSTM, Dense,Flatten
from keras.callbacks import EarlyStopping
from sklearn.preprocessing import MinMaxScaler

读取数据,设置日期索引:

python 复制代码
data=pd.read_excel('AQI数据.xlsx')#.set_index('日期')
data['日期']=pd.to_datetime(data['日期'])
data=data.set_index('日期')
data

数据跨度从2019-2023年,日度数据。

简单画个图看看

python 复制代码
data.aqi.plot(figsize=(10,3))

很符合AQI的摸样,波动很大,参差不齐,还有一定的周期性。


数据准备

时间序列做神经网络预测,一般都需要进行三维化,即把数据变为(n,t,p)的形状,n是样本量,t是时间步长,p是特征数量。一般 的表格数据都是(n,p)的结构,时间序列要多一个时间t的维度。

数据构建X和y之前要归一化,神经网络很需要,不然模型会不收敛。

python 复制代码
# 数据预处理
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_aqi = scaler.fit_transform(data['aqi'].values.reshape(-1, 1))

# 创建LSTM需要的序列数据
def create_dataset(dataset, start_index, end_index, history_size, target_size):
    data = [] ; labels = []

    start_index = start_index + history_size
    if end_index is None:
        end_index = len(dataset) - target_size

    for i in range(start_index, end_index):
        indices = range(i-history_size, i)
        data.append(np.reshape(dataset[indices], (history_size, 1)))
        labels.append(dataset[i:i+target_size])
    return np.array(data), np.array(labels)

# 用过去的700天数据来预测接下来的365天
past_history = 700
future_target = 365

X_train, y_train = create_dataset(scaled_aqi, 0, None, past_history, future_target)
y_train=y_train.reshape(y_train.shape[0],y_train.shape[1])
X_train.shape, y_train.shape

我定义了一个转化时间序列构建X和y的函数,然后采用时间窗口为700,也就是t=700的时间步长,然后去预测未来365天的数据,也就是一年。

为什么是700,,,没有为什么,因为要预测365个点,我需要时间步长大一点,那就大概2倍的数据吧,我就选择了凑个整数700,当然699,701,710,720,730,都是可以的,可以去试试。

是不是时间步长越长越好?不一定,首先看你样本量,我数据只有1500多个点,我选择了700时间步长,其实就损失了700个样本了,可以看到我样本量只有486个,有点少。其次,时间步长过长会造成运行时间过长,你也不想体验等一次运行结果要等上一天的感觉吧。。。

当然大家可以更具自己的需要预测的时间长度,还有样本量来调整自己的时间步长t。


预测2024年数据(默认tanh激活函数)

这里构建的是最简单的神经网络MLP模型,一个小案例,就没使用LSTM,GRU,transform这种序列模型了。大家感兴趣可以自己改一下试试。

python 复制代码
# 创建MLP模型
model = Sequential()
model.add(Flatten())
model.add(Dense(512))
model.add(Dense(128))
model.add(Dense(future_target))
model.compile(optimizer='adam', loss='mse')

# 训练模型
early_stop = EarlyStopping(monitor='loss', patience=10)
history=model.fit(X_train, y_train, epochs=50, batch_size=32, callbacks=[early_stop], verbose=1)

训练了50轮,loss没怎么变了。

画图看看:

python 复制代码
plt.figure(figsize=(7,3))
plt.plot(history.history['loss'], label=f'loss')
plt.legend()
plt.show()

基本收敛了,然后我们预测,预测的数据要逆归一化回来,然后加上预测的日期的索引。

python 复制代码
# 进行预测
prediction = model.predict(X_train[-1].reshape(1, past_history, 1))
# 逆缩放预测结果
predicted_aqi = scaler.inverse_transform(prediction).flatten()
predicted_aqi.shape

# 创建预测日期的范围
last_date = data.index[-1]
predicted_dates = pd.date_range(start=last_date, periods=future_target+1, closed='right')

# 创建包含预测结果的DataFrame
predicted_df = pd.DataFrame({
    '日期': predicted_dates,
    '预测aqi': predicted_aqi})

画个图看看:

python 复制代码
# 绘制预测和实际的AQI值
plt.figure(figsize=(12, 3),dpi=128)
plt.plot(data.index, data['aqi'], label='Actual AQI')
plt.plot(predicted_dates, predicted_aqi, label='Predicted AQI', linestyle='dashed')
plt.title('AQI Prediction')
plt.xlabel('Date')
plt.ylabel('AQI')
plt.legend()
plt.show()

后面橙色的虚线就是我预测的数据了。看这效果还不错的样子,波动性学到了,季节性也学到了。

由于目前还没有真实的2024年的AQI数据,也不知道效果好不好。。。也不知道别的LSTM之类的模型效果好不好。。所以没法计算误差去评价。


储存预测结果

python 复制代码
## 储存
predicted_df.to_excel('AQI预测结果.xlsx')

保存了,可以本地excel查看了。


不同损失函数

下面是一个其他任务的彩蛋吧,看看不同的激活函数对模型的训练过程是否有影响。

有兴趣的同学可以看看。

展示随迭代次数增加,不同激活函数下的损失函数的变化情况。

  • (用了五种激活函数)['relu', 'tanh', 'sigmoid','elu','softplus']

定义和训练:

python 复制代码
# Function to create and train LSTM model with different activation functions
def train_lstm_model(X_train, y_train, activation='relu', epochs=100, batch_size=32):
    model = Sequential()
    model.add(Flatten())
    model.add(Dense(512))
    model.add(Dense(128))
    model.add(Dense(future_target))
    model.compile(optimizer='adam', loss='mse')
    # Early stopping to prevent overfitting
    early_stop = EarlyStopping(monitor='loss', patience=10, verbose=1)

    # Train the model
    history = model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, verbose=0, callbacks=[early_stop])

    return model, history

# Activations to try
activations = ['relu', 'tanh', 'sigmoid','elu','softplus']
# Dictionary to store models and histories
models = {}
histories = {}

# Training models with different activation functions
for activation in activations:
    model, history = train_lstm_model(X_train, y_train, activation=activation)
    models[activation] = model
    histories[activation] = history.history['loss']

画图查看:

python 复制代码
## 五种激活函数
plt.figure(figsize=(9, 3),dpi=128)
for activation in activations:
    plt.plot(histories[activation], label=f'Activation = {activation}')
plt.title('Training Loss with Different Activation Functions')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend()
plt.show()

五种激活函数差不多,区别不大。


创作不易,看官觉得写得还不错的话点个关注和赞吧,本人会持续更新python数据分析领域的代码文章~

相关推荐
白拾3 分钟前
使用Conda管理python环境的指南
开发语言·python·conda
是刃小木啦~23 分钟前
三维模型点云化工具V1.0使用介绍:将三维模型进行点云化生成
python·软件工程·pyqt·工业软件
总裁余(余登武)29 分钟前
算法竞赛(Python)-万变中的不变“随机算法”
开发语言·python·算法
一个闪现必杀技36 分钟前
Python练习2
开发语言·python
Eric.Lee202141 分钟前
音频文件重采样 - python 实现
人工智能·python·深度学习·算法·audio·音频重采样
大神薯条老师42 分钟前
Python从入门到高手5.1节-Python简单数据类型
爬虫·python·深度学习·机器学习·数据分析
Mr.D学长1 小时前
毕业设计 深度学习社交距离检测系统(源码+论文)
python·毕业设计·毕设
wdxylb1 小时前
解决Python使用Selenium 时遇到网页 <body> 划不动的问题
python
代码骑士1 小时前
【一起学NLP】Chapter3-使用神经网络解决问题
python·神经网络·自然语言处理
wxin_VXbishe2 小时前
springboot合肥师范学院实习实训管理系统-计算机毕业设计源码31290
java·spring boot·python·spring·servlet·django·php