文章目錄
- 一、前期準備工作
- 1.導入數據
- 2. 數據集可視化
- 二、構建數據集
- 1. 數據集預處理
- 2. 設置X, y
- 3. 劃分數據集
- 三、模型訓練
- 1. 構建模型
- 2. 定義訓練函數
- 3. 定義測試函數
- 4. 正式訓練模型
- 四、模型評估
- 1. Loss圖片
- 2. 調用模型進行預測
- 3. R2值評估
- 總結:
- 🍨 本文為🔗365天深度學習訓練營 中的學習記錄博客
- 🍖 原作者:K同學啊
一、前期準備工作
import torch.nn.functional as F
import numpy as np
import pandas as pd
import torch
from torch import nn
1.導入數據
data = pd.read_csv("woodpine2.csv")data
Time | Tem1 | CO 1 | Soot 1 | |
---|---|---|---|---|
0 | 0.000 | 25.0 | 0.000000 | 0.000000 |
1 | 0.228 | 25.0 | 0.000000 | 0.000000 |
2 | 0.456 | 25.0 | 0.000000 | 0.000000 |
3 | 0.685 | 25.0 | 0.000000 | 0.000000 |
4 | 0.913 | 25.0 | 0.000000 | 0.000000 |
... | ... | ... | ... | ... |
5943 | 366.000 | 295.0 | 0.000077 | 0.000496 |
5944 | 366.000 | 294.0 | 0.000077 | 0.000494 |
5945 | 367.000 | 292.0 | 0.000077 | 0.000491 |
5946 | 367.000 | 291.0 | 0.000076 | 0.000489 |
5947 | 367.000 | 290.0 | 0.000076 | 0.000487 |
5948 rows × 4 columns
2. 數據集可視化
import matplotlib.pyplot as plt
import seaborn as snsplt.rcParams['savefig.dpi'] = 500 #圖片像素
plt.rcParams['figure.dpi'] = 500 #分辨率fig, ax =plt.subplots(1,3,constrained_layout=True, figsize=(14, 3))sns.lineplot(data=data["Tem1"], ax=ax[0])
sns.lineplot(data=data["CO 1"], ax=ax[1])
sns.lineplot(data=data["Soot 1"], ax=ax[2])
plt.show()
dataFrame = data.iloc[:,1:]dataFrame
Tem1 | CO 1 | Soot 1 | |
---|---|---|---|
0 | 25.0 | 0.000000 | 0.000000 |
1 | 25.0 | 0.000000 | 0.000000 |
2 | 25.0 | 0.000000 | 0.000000 |
3 | 25.0 | 0.000000 | 0.000000 |
4 | 25.0 | 0.000000 | 0.000000 |
... | ... | ... | ... |
5943 | 295.0 | 0.000077 | 0.000496 |
5944 | 294.0 | 0.000077 | 0.000494 |
5945 | 292.0 | 0.000077 | 0.000491 |
5946 | 291.0 | 0.000076 | 0.000489 |
5947 | 290.0 | 0.000076 | 0.000487 |
5948 rows × 3 columns
二、構建數據集
1. 數據集預處理
from sklearn.preprocessing import MinMaxScalerdataFrame = data.iloc[:,1:].copy()
sc = MinMaxScaler(feature_range=(0, 1)) #將數據歸一化,范圍是0到1for i in ['CO 1', 'Soot 1', 'Tem1']:dataFrame[i] = sc.fit_transform(dataFrame[i].values.reshape(-1, 1))dataFrame.shape
(5948, 3)
2. 設置X, y
width_X = 8
width_y = 1##取前8個時間段的Tem1、CO 1、Soot 1為X,第9個時間段的Tem1為y。
X = []
y = []in_start = 0for _, _ in data.iterrows():in_end = in_start + width_Xout_end = in_end + width_yif out_end < len(dataFrame):X_ = np.array(dataFrame.iloc[in_start:in_end , ])y_ = np.array(dataFrame.iloc[in_end :out_end, 0])X.append(X_)y.append(y_)in_start += 1X = np.array(X)
y = np.array(y).reshape(-1,1,1)X.shape, y.shape
((5939, 8, 3), (5939, 1, 1))
檢查數據集中是否有空值
print(np.any(np.isnan(X)))
print(np.any(np.isnan(y)))
False
False
3. 劃分數據集
X_train = torch.tensor(np.array(X[:5000]), dtype=torch.float32)
y_train = torch.tensor(np.array(y[:5000]), dtype=torch.float32)X_test = torch.tensor(np.array(X[5000:]), dtype=torch.float32)
y_test = torch.tensor(np.array(y[5000:]), dtype=torch.float32)
X_train.shape, y_train.shape
(torch.Size([5000, 8, 3]), torch.Size([5000, 1, 1]))
from torch.utils.data import TensorDataset, DataLoadertrain_dl = DataLoader(TensorDataset(X_train, y_train),batch_size=64, shuffle=False)test_dl = DataLoader(TensorDataset(X_test, y_test),batch_size=64, shuffle=False)
三、模型訓練
1. 構建模型
class model_lstm(nn.Module):def __init__(self):super(model_lstm, self).__init__()self.lstm0 = nn.LSTM(input_size=3 ,hidden_size=320, num_layers=1, batch_first=True)self.lstm1 = nn.LSTM(input_size=320 ,hidden_size=320, num_layers=1, batch_first=True)self.fc0 = nn.Linear(320, 1)def forward(self, x):out, hidden1 = self.lstm0(x) out, _ = self.lstm1(out, hidden1) out = self.fc0(out) return out[:, -1:, :] #取1個預測值,否則經過lstm會得到8*1個預測model = model_lstm()
model
model_lstm((lstm0): LSTM(3, 320, batch_first=True)(lstm1): LSTM(320, 320, batch_first=True)(fc0): Linear(in_features=320, out_features=1, bias=True)
)
model(torch.rand(30,8,3)).shape
torch.Size([30, 1, 1])
2. 定義訓練函數
# 訓練循環
import copy
def train(train_dl, model, loss_fn, opt, lr_scheduler=None):size = len(train_dl.dataset) num_batches = len(train_dl) train_loss = 0 # 初始化訓練損失和正確率for x, y in train_dl: x, y = x.to(device), y.to(device)# 計算預測誤差pred = model(x) # 網絡輸出loss = loss_fn(pred, y) # 計算網絡輸出和真實值之間的差距# 反向傳播opt.zero_grad() # grad屬性歸零loss.backward() # 反向傳播opt.step() # 每一步自動更新# 記錄losstrain_loss += loss.item()if lr_scheduler is not None:lr_scheduler.step()print("learning rate = {:.5f}".format(opt.param_groups[0]['lr']), end=" ")train_loss /= num_batchesreturn train_loss
3. 定義測試函數
def test (dataloader, model, loss_fn):size = len(dataloader.dataset) # 測試集的大小num_batches = len(dataloader) # 批次數目test_loss = 0# 當不進行訓練時,停止梯度更新,節省計算內存消耗with torch.no_grad():for x, y in dataloader:x, y = x.to(device), y.to(device)# 計算lossy_pred = model(x)loss = loss_fn(y_pred, y)test_loss += loss.item()test_loss /= num_batchesreturn test_loss
4. 正式訓練模型
#設置GPU訓練
device=torch.device("cuda" if torch.cuda.is_available() else "cpu")
device
device(type=‘cpu’)
#訓練模型
model = model_lstm()
model = model.to(device)
loss_fn = nn.MSELoss() # 創建損失函數
learn_rate = 1e-1 # 學習率
opt = torch.optim.SGD(model.parameters(),lr=learn_rate,weight_decay=1e-4)
epochs = 50
train_loss = []
test_loss = []
lr_scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(opt,epochs, last_epoch=-1) for epoch in range(epochs):model.train()epoch_train_loss = train(train_dl, model, loss_fn, opt, lr_scheduler)model.eval()epoch_test_loss = test(test_dl, model, loss_fn)train_loss.append(epoch_train_loss)test_loss.append(epoch_test_loss)template = ('Epoch:{:2d}, Train_loss:{:.5f}, Test_loss:{:.5f}')print(template.format(epoch+1, epoch_train_loss, epoch_test_loss))print("="*20, 'Done', "="*20)
learning rate = 0.09990 Epoch: 1, Train_loss:0.00123, Test_loss:0.01228
learning rate = 0.09961 Epoch: 2, Train_loss:0.01404, Test_loss:0.01183
learning rate = 0.09911 Epoch: 3, Train_loss:0.01365, Test_loss:0.01135
learning rate = 0.09843 Epoch: 4, Train_loss:0.01321, Test_loss:0.01085
learning rate = 0.09755 Epoch: 5, Train_loss:0.01270, Test_loss:0.01029
learning rate = 0.09649 Epoch: 6, Train_loss:0.01212, Test_loss:0.00968
learning rate = 0.09524 Epoch: 7, Train_loss:0.01144, Test_loss:0.00901
learning rate = 0.09382 Epoch: 8, Train_loss:0.01065, Test_loss:0.00827
learning rate = 0.09222 Epoch: 9, Train_loss:0.00975, Test_loss:0.00748
learning rate = 0.09045 Epoch:10, Train_loss:0.00876, Test_loss:0.00665
learning rate = 0.08853 Epoch:11, Train_loss:0.00769, Test_loss:0.00580
learning rate = 0.08645 Epoch:12, Train_loss:0.00658, Test_loss:0.00497
learning rate = 0.08423 Epoch:13, Train_loss:0.00548, Test_loss:0.00418
learning rate = 0.08187 Epoch:14, Train_loss:0.00444, Test_loss:0.00346
learning rate = 0.07939 Epoch:15, Train_loss:0.00349, Test_loss:0.00283
learning rate = 0.07679 Epoch:16, Train_loss:0.00268, Test_loss:0.00230
learning rate = 0.07409 Epoch:17, Train_loss:0.00200, Test_loss:0.00188
learning rate = 0.07129 Epoch:18, Train_loss:0.00147, Test_loss:0.00154
learning rate = 0.06841 Epoch:19, Train_loss:0.00107, Test_loss:0.00129
learning rate = 0.06545 Epoch:20, Train_loss:0.00078, Test_loss:0.00110
learning rate = 0.06243 Epoch:21, Train_loss:0.00057, Test_loss:0.00096
learning rate = 0.05937 Epoch:22, Train_loss:0.00042, Test_loss:0.00085
learning rate = 0.05627 Epoch:23, Train_loss:0.00032, Test_loss:0.00078
learning rate = 0.05314 Epoch:24, Train_loss:0.00025, Test_loss:0.00072
learning rate = 0.05000 Epoch:25, Train_loss:0.00021, Test_loss:0.00068
learning rate = 0.04686 Epoch:26, Train_loss:0.00017, Test_loss:0.00065
learning rate = 0.04373 Epoch:27, Train_loss:0.00015, Test_loss:0.00062
learning rate = 0.04063 Epoch:28, Train_loss:0.00014, Test_loss:0.00060
learning rate = 0.03757 Epoch:29, Train_loss:0.00013, Test_loss:0.00059
learning rate = 0.03455 Epoch:30, Train_loss:0.00012, Test_loss:0.00058
learning rate = 0.03159 Epoch:31, Train_loss:0.00012, Test_loss:0.00057
learning rate = 0.02871 Epoch:32, Train_loss:0.00011, Test_loss:0.00056
learning rate = 0.02591 Epoch:33, Train_loss:0.00011, Test_loss:0.00055
learning rate = 0.02321 Epoch:34, Train_loss:0.00011, Test_loss:0.00055
learning rate = 0.02061 Epoch:35, Train_loss:0.00011, Test_loss:0.00055
learning rate = 0.01813 Epoch:36, Train_loss:0.00012, Test_loss:0.00055
learning rate = 0.01577 Epoch:37, Train_loss:0.00012, Test_loss:0.00055
learning rate = 0.01355 Epoch:38, Train_loss:0.00012, Test_loss:0.00056
learning rate = 0.01147 Epoch:39, Train_loss:0.00012, Test_loss:0.00056
learning rate = 0.00955 Epoch:40, Train_loss:0.00013, Test_loss:0.00057
learning rate = 0.00778 Epoch:41, Train_loss:0.00013, Test_loss:0.00058
learning rate = 0.00618 Epoch:42, Train_loss:0.00014, Test_loss:0.00058
learning rate = 0.00476 Epoch:43, Train_loss:0.00014, Test_loss:0.00059
learning rate = 0.00351 Epoch:44, Train_loss:0.00014, Test_loss:0.00059
learning rate = 0.00245 Epoch:45, Train_loss:0.00014, Test_loss:0.00059
learning rate = 0.00157 Epoch:46, Train_loss:0.00014, Test_loss:0.00060
learning rate = 0.00089 Epoch:47, Train_loss:0.00014, Test_loss:0.00060
learning rate = 0.00039 Epoch:48, Train_loss:0.00014, Test_loss:0.00060
learning rate = 0.00010 Epoch:49, Train_loss:0.00014, Test_loss:0.00060
learning rate = 0.00000 Epoch:50, Train_loss:0.00014, Test_loss:0.00060
==================== Done ====================
四、模型評估
1. Loss圖片
import matplotlib.pyplot as plt
from datetime import datetime
current_time = datetime.now() # 獲取當前時間plt.figure(figsize=(5, 3),dpi=120)plt.plot(train_loss , label='LSTM Training Loss')
plt.plot(test_loss, label='LSTM Validation Loss')plt.title('Training and Validation Loss')
plt.xlabel(current_time) # 打卡請帶上時間戳,否則代碼截圖無效
plt.legend()
plt.show()
2. 調用模型進行預測
predicted_y_lstm = sc.inverse_transform(model(X_test).detach().numpy().reshape(-1,1)) # 測試集輸入模型進行預測
y_test_1 = sc.inverse_transform(y_test.reshape(-1,1))
y_test_one = [i[0] for i in y_test_1]
predicted_y_lstm_one = [i[0] for i in predicted_y_lstm]plt.figure(figsize=(5, 3),dpi=120)
# 畫出真實數據和預測數據的對比曲線
plt.plot(y_test_one[:2000], color='red', label='real_temp')
plt.plot(predicted_y_lstm_one[:2000], color='blue', label='prediction')plt.title('Title')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()
3. R2值評估
from sklearn import metrics
"""
RMSE :均方根誤差 -----> 對均方誤差開方
R2 :決定系數,可以簡單理解為反映模型擬合優度的重要的統計量
"""
RMSE_lstm = metrics.mean_squared_error(predicted_y_lstm_one, y_test_1)**0.5
R2_lstm = metrics.r2_score(predicted_y_lstm_one, y_test_1)print('均方根誤差: %.5f' % RMSE_lstm)
print('R2: %.5f' % R2_lstm)
均方根誤差: 6.92733
R2: 0.83259
總結:
本周主要學習了LSTM模型,并且通過實踐更加深入地了解到了LSTM模型。