基于pytorch框架的气温预测项目实战
最近系统学习了pytorch相关的内容,从吴恩达老师的理论学习,到b站小土堆的pytorch实战,于是今天找了一个数据集检测一下学习成果。
数据集是从Kaggle上找的,在这里只用了训练集的部分,测试集没写,数据链接Daily Climate time series data | Kaggle
首先导入必要的库。
import matplotlib.pyplot as plt
import torch
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
from torch.utils.data import DataLoader, TensorDataset
import numpy as np
import torch.nn as nn
之后读取数据,因为是初次尝试,我只用了'mean temp'这一列的数据进行了一下测试。
Data1 = pd.read_csv("DailyDelhiClimateTrain.csv")
Data1 = Data1["meantemp"]
#绘图
plt.figure(figsize=(14, 7))
plt.plot(Data1)
plt.title("mean temp")
plt.xlabel("time")
plt.ylabel("temp (°C)")
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
得到图像,这里对于数据处理的还是比较粗糙的,后期还得学一下数据处理相关的内容。
接下来搭建CNN-LSTM神经网络。
class LSTM_CNN_Model(nn.Module):
def __init__(self):
super().__init__()
self.Conv1 = nn.Conv1d(1, 32, 3, stride=1, padding=1)
self.MaxPooling1 = nn.MaxPool1d(kernel_size=3, stride=1)
self.Relu = nn.ReLU()
self.LSTM = nn.LSTM(32, 32, 1, batch_first=True)
self.Linear = nn.Linear(32, 1)
self.dropout = nn.Dropout(0.3)
def forward(self, x):
x = x.transpose(1, 2)
x = self.Conv1(x)
x = self.Relu(x)
x = self.MaxPooling1(x)
x = self.dropout(x)
x = x.transpose(1, 2)
lstm_out, _ = self.LSTM(x)
x = lstm_out[:, -1, :]
x = self.Linear(x)
return x
这一块pytorch官网上有讲解,个人认为pytorch框架下的代码还是很好理解的。第一部分就是要写所有的方法,在这里我写了1维的卷积(时间序列数据是一维的,后期如果处理图像的话就要升高维度了,这里吴恩达老师也讲过相关的内容)、最大池化层、激活函数ReLU、LSTM层、隐藏层(作为输出层)、Dropout层(正则化,随机消除某些神经元,防止过拟合),第二部分就是要把你的这些方法进行组合起来。对于输入的数据,我需要先把它转换成CNN可以识别的格式,之后输入卷积层,经过激活函数之后再进入最大池化层,之后进入Dropout层。CNN和LSTM可以识别的数据的形式不同,于是我再进行一步转化,将它变成LSTM可以识别的形式,最后取LSTM的最后一步作为输出,经过线性层输出。
接下来就是数据处理相关的操作了
scaler = MinMaxScaler(feature_range=(0, 1))
normalised_data = scaler.fit_transform(Data1.values.reshape(-1, 1)).flatten()
def create_sequence(data, seq_length):
X_train = []
Y_train = []
for i in range(len(data) - seq_length):
X_train.append(data[i:i + seq_length])
Y_train.append(data[i + seq_length])
return np.array(X_train), np.array(Y_train)
seq_length = 20
X_train, Y_train = create_sequence(normalised_data, seq_length)
X_train = torch.from_numpy(X_train).float().unsqueeze(2)
Y_train = torch.from_numpy(Y_train).float().unsqueeze(1)
train_dataset = TensorDataset(X_train, Y_train)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=False, num_workers=0)
进行数据归一化,划分X和Y,相当于每20个数据作为一个训练样本,第21个数据作为预测值。在这里数据划分的时候我最后输出的是numpy格式,X是一个二维的,Y是一个一维的,如果要训练的话还需要变成pytorch的张量形式。深度学习一般使用的数据是浮点型,在这里也要注意转换。TensorDataset()函数相当于把X和Y进行一个捆绑,方便后期训练的时候进行对应。
接下来是模型的训练部分。由于是预测问题,我选择的损失函数就是MSE损失函数,如果要做分类的话可以选择使用交叉熵损失函数。学习率刚开始不要设置太高,设置0.001,现在也有把学习率作为超参数进行调整的做法。损失函数在实际计算过程中只需要输入两个参数,一个就是你通过训练得到的预测值,也就是outputs,另一个就是你样本中真实值Y(之前TensorDataset()函数已经处理好了)。通过正向传播来计算预测值,通过反向传播来进行梯度的更新。反向传播之前一定要先把梯度清零,避免历史的梯度影响,对loss进行反向传播,并更新模型的参数。得到损失曲线。
my_model = LSTM_CNN_Model()
loss_fn = nn.MSELoss()
learning_rate = 0.001
optimizer = torch.optim.Adam(my_model.parameters(), learning_rate)
epoch = 100
global_step = 0
loss_history = []
for i in range(epoch):
print(f"第{i}轮训练开始")
total_loss = 0
my_model.train()
for data in train_loader:
X, Y = data
outputs = my_model(X)
loss = loss_fn(outputs, Y)
total_loss += loss.item()
global_step += 1
optimizer.zero_grad()
loss.backward()
optimizer.step()
avg_loss = total_loss / len(train_loader)
loss_history.append(avg_loss)
print(f"第{i}轮的损失为{avg_loss:.6f}")
plt.figure(figsize=(14,7))
plt.plot(range(1,epoch+1),loss_history)
plt.title("Mean temp")
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()
模型在训练集上收敛还是很不错的,保存模型的权重矩阵,并用于测试集,观察测试集拟合效果,在这里不一一赘述。
更多推荐

所有评论(0)