第100+8步 ChatGPT文献复现:ARIMA-NARNN预测出血热

基于WIN10的64位系统演示

一、写在前面

这一次,我们来继续解读ARIMA组合模型文章,也是老文章了:

《PLoS One》杂志的2015年一篇题目为《Comparison of Two Hybrid Models for Forecasting the Incidence of Hemorrhagic Fever with Renal Syndrome in Jiangsu Province, China》文章的公开数据做案例。

这文章做的是用:使用两种ARIMA组合模型预测江苏省出血热发病率。

文章是用单纯的ARIMA模型作为对照,对比了两种组合模型:ARIMA-GRNN模型和ARIMA-NARNN模型。上一期,我们来重现了ARIMA-GRNN模型。本期,我们来尝试ARIMA-NARNN模型。

二、闲聊和复现:

1单纯ARIMA模型构建

同上期

(2)ARIMA-NARNN组合模型

①首先,使用GPT-4弄清楚文章使用的策略是啥:

不知道大家看懂了没,我又用一个具体例子再次验证:

比如说2001年到2010年的数据构建ARIMA模型,预测2011年的数据。得到2001年到2010年的残差序列,然后使用残差序列构建NARNN模型,预测出2011年的残差,在与ARIMA模型预测的2011年的数据做矫正,得到组合模型的结果?

GPT-4的回答:

简单来说就是,首先使用2004-01到2011-12的数据构建并找出最优模型ARIMA (0,1,1)×(0,1,1)12,并使用模型进行拟合(2004-01至2011-12)和预测(2012-01至2012-12)。然后,根据真实值计算得到2004-01到2011-12的拟合残差序列,以及2012-01至2012-12的预测残差序列。之后,用2004-01到2011-12的拟合残差序列再进行一次时间序列建模,模型用的是NARNN,得到拟合(2004-01至2011-12)和预测(2012-01至2012-12)的残差结果,再用来与ARIMA模型的拟合与预测结果进行校正,输出的就是ARIMA-NARNN组合模型的结果。

很绕是不是?其实就是在把残差序列用另一个模型再预测一次。把NARNN模型换成其他模型,可能就是ARIMA-其他模型的组合模型了。

②那就让GPT-4帮生成代码吧:

倒是生成了代码,不过有瑕疵,经过我多次微调,如下:

import torch
import torch.nn as nn
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
import numpy as np
from sklearn.metrics import mean_squared_error, mean_absolute_error

# 计算MAPE
def mean_absolute_percentage_error(y_true, y_pred):
    y_true, y_pred = np.array(y_true), np.array(y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100

# 数据加载
data = pd.read_csv('data1.csv')
residuals = data['incidence'].values.astype(float)

# 数据归一化
scaler = MinMaxScaler(feature_range=(-1, 1))
residuals_normalized = scaler.fit_transform(residuals.reshape(-1, 1)).flatten()

# 使用前83个数据进行建模
train_data = residuals_normalized[:83]

# 准备时间序列数据
def create_sequences(data, seq_length):
    xs, ys = [], []
    for i in range(len(data)-seq_length):
        x = data[i:(i+seq_length)]
        y = data[i+seq_length]
        xs.append(x)
        ys.append(y)
    return np.array(xs), np.array(ys)

seq_length = 6  # 使用6个时间点预测下一个时间点
X, y = create_sequences(train_data, seq_length)
X_tensor = torch.FloatTensor(X).view(-1, seq_length, 1)
y_tensor = torch.FloatTensor(y).view(-1, 1)

# 定义模型
class NARNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, num_layers=1):
        super(NARNN, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(x.device)
        out, _ = self.rnn(x, h0)
        out = self.fc(out[:, -1, :])
        return out

# 设置超参数
input_size = 1
output_size = 1
hidden_size = 50
num_layers = 1
learning_rate = 0.001
num_epochs = 100

model = NARNN(input_size, hidden_size, output_size, num_layers)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)

# 训练模型
for epoch in range(num_epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(X_tensor)
    loss = criterion(outputs, y_tensor)
    loss.backward()
    optimizer.step()

    if epoch == num_epochs - 1:  # 最后一个epoch计算训练集的MSE, MAE, MAPE
        y_pred_train = outputs.detach().numpy()
        y_true_train = y_tensor.numpy()
        mse_train = mean_squared_error(y_true_train, y_pred_train)
        mae_train = mean_absolute_error(y_true_train, y_pred_train)
        mape_train = mean_absolute_percentage_error(y_true_train, y_pred_train)
        print(f'Train MSE: {mse_train:.4f}, Train MAE: {mae_train:.4f}, Train MAPE: {mape_train:.4f}%')

# 使用最后的模型进行预测最后12个数据
model.eval()
test_data = residuals_normalized[83-seq_length:83]  # 使用从71到82的数据开始预测
predictions = []
for _ in range(12):
    with torch.no_grad():
        x_test_tensor = torch.FloatTensor(test_data).view(1, seq_length, 1)
        pred = model(x_test_tensor)
        predictions.append(pred.numpy().flatten()[0])
        test_data = np.append(test_data[1:], pred.numpy().flatten()[0])  # 更新输入数组

# 反归一化预测结果
predictions = scaler.inverse_transform(np.array(predictions).reshape(-1, 1)).flatten()
original_values = scaler.inverse_transform(residuals_normalized[83:].reshape(-1, 1)).flatten()

# 计算验证集的MSE, MAE, MAPE
mse_val = mean_squared_error(original_values, predictions)
mae_val = mean_absolute_error(original_values, predictions)
mape_val = mean_absolute_percentage_error(original_values, predictions)

print(f'Validation MSE: {mse_val:.4f}, Validation MAE: {mae_val:.4f}, Validation MAPE: {mape_val:.4f}%')

③很好奇NARNN模型的参数是什么:

看来,文章其实也没说清楚:

④NARNN模型的参数我就简单设置了:使用6个数据预测下一个,其他默认参数了。最终的结果及其不理想,哈哈哈,大家自行调整了,毕竟参数那么多。不过,感觉吧,就是个玄学。

预测的MAPE为61.9%,比ARIMA模型的还大。拟合的更加惨,甚至大于100%。

三、个人感悟

可以看到,ARIMA-NARNN组合模型的构建策略,也可以延伸出ARIMA-LSTM、ARIMA-CNN、ARIMA-Xgboost等一堆组合模型。至于有没有效果,那就看具体数据和大家的调参能力了。

还是那句话:其实有些数据吧,用组合模型,性能反而变差了,它并不是万能的。

四、数据

链接:https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0135492

有童鞋问咋下载数据:

  • 8
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jet4505

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值