網站首頁 編程語言 正文
前言
關鍵步驟主要分為數據準備和模型構建兩大部分,其中,
數據準備主要工作:
- 1、訓練集和測試集的劃分
- 2、訓練數據的歸一化
- 3、規范輸入數據的格式
模型構建部分主要工作
1、構建網絡層、前向傳播forward()
class LSTM(nn.Module):#注意Module首字母需要大寫
def __init__(self, input_size=1, hidden_layer_size=100, output_size=1):
super().__init__()
self.hidden_layer_size = hidden_layer_size
# 創建LSTM層和linear層,LSTM層提取特征,linear層用作最后的預測
# LSTM算法接受三個輸入:先前的隱藏狀態,先前的單元狀態和當前輸入。
self.lstm = nn.LSTM(input_size, hidden_layer_size)
self.linear = nn.Linear(hidden_layer_size, output_size)
#初始化隱含狀態及細胞狀態C,hidden_cell變量包含先前的隱藏狀態和單元狀態
self.hidden_cell = (torch.zeros(1, 1, self.hidden_layer_size),
torch.zeros(1, 1, self.hidden_layer_size))
# 為什么的第二個參數也是1
# 第二個參數代表的應該是batch_size吧
# 是因為之前對數據已經進行過切分了嗎?????
def forward(self, input_seq):
#lstm的輸出是當前時間步的隱藏狀態ht和單元狀態ct以及輸出lstm_out
lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq), 1, -1), self.hidden_cell)
#按照lstm的格式修改input_seq的形狀,作為linear層的輸入
predictions = self.linear(lstm_out.view(len(input_seq), -1))
#返回predictions的最后一個元素
return predictions[-1]
定義好每層之后,最后還需要通過前向傳播的方式把這些串起來,這就涉及如何定義forward函數。
forward函數的任務需要把輸入層、網絡層、輸出層鏈接起來,實現信息的前向傳導。
forward該函數的參數一般為輸入數據,返回值是輸出數據。
2、實例化網絡,定義損失函數和優化器
#創建LSTM()類的對象,定義損失函數和優化器
model = LSTM()
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)#建立優化器實例
print(model)
3、訓練模型、反向傳播backward()
epochs = 150
for i in range(epochs):
for seq, labels in train_inout_seq:
#清除網絡先前的梯度值
optimizer.zero_grad()
#初始化隱藏層數據
model.hidden_cell = (torch.zeros(1, 1, model.hidden_layer_size),
torch.zeros(1, 1, model.hidden_layer_size))
#實例化模型
y_pred = model(seq)
#計算損失,反向傳播梯度以及更新模型參數
#訓練過程中,正向傳播生成網絡的輸出,計算輸出和實際值之間的損失值
single_loss = loss_function(y_pred, labels)
single_loss.backward()#調用backward()自動生成梯度
optimizer.step()#使用optimizer.step()執行優化器,把梯度傳播回每個網絡
# 查看模型訓練的結果
if i%25 == 1:
print(f'epoch:{i:3} loss:{single_loss.item():10.8f}')
print(f'epoch:{i:3} loss:{single_loss.item():10.10f}')
訓練模型時需要使模型處于訓練模式,即調用model.train()。
缺省情況下梯度是累加的,需要手工把梯度初始化或者清零,調用optimizer.zero_grad()。
在訓練過程中正向傳播生成網絡的輸出,計算輸出與實際值之間的損失值。調用loss.backward()自動生成反向傳播梯度,然后使用optimizer.step()執行優化器,把梯度傳播回每個網絡。
實現梯度反向傳播的方法主要是復合函數的鏈式法則。Pytorch提供了自動反向傳播的功能,使用nn工具箱,無需自己編寫反向傳播,直接讓損失函數調用backward()即可。
反向傳播中,優化器十分重要,這類優化算法通過使用參數的梯度值更新參數。
4、測試模型
fut_pred = 12
test_inputs = train_data_normalized[-train_window:].tolist()#首先打印出數據列表的最后12個值
print(test_inputs)
#更改模型為測試或者驗證模式
model.eval()#把training屬性設置為false,使模型處于測試或驗證狀態
for i in range(fut_pred):
seq = torch.FloatTensor(test_inputs[-train_window:])
with torch.no_grad():
model.hidden = (torch.zeros(1, 1, model.hidden_layer_size),
torch.zeros(1, 1, model.hidden_layer_size))
test_inputs.append(model(seq).item())
#打印最后的12個預測值
print(test_inputs[fut_pred:])
#由于對訓練集數據進行了標準化,因此預測數據也是標準化了的
#需要將歸一化的預測值轉換為實際的預測值。通過inverse_transform實現
actual_predictions = scaler.inverse_transform(np.array(test_inputs[train_window:]).reshape(-1, 1))
print(actual_predictions)
全部代碼如下:
import torch
import torch.nn as nn
import torch.nn.functional
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
"""
導入數據
"""
flight_data = sns.load_dataset("flights")
print(flight_data.head())
print(flight_data.shape)
#繪制每月乘客的出行頻率
fig_size = plt.rcParams['figure.figsize']
fig_size[0] = 15
fig_size[1] = 5
plt.rcParams['figure.figsize'] = fig_size
plt.title('Month vs Passenger')
plt.ylabel('Total Passengers')
plt.xlabel('Months')
plt.grid(True)
plt.autoscale(axis='x',tight=True)
plt.plot(flight_data['passengers'])
plt.show()
"""
數據預處理
"""
flight_data.columns#顯示數據集中 列的數據類型
all_data = flight_data['passengers'].values.astype(float)#將passengers列的數據類型改為float
#劃分測試集和訓練集
test_data_size = 12
train_data = all_data[:-test_data_size]#除了最后12個數據,其他全取
test_data = all_data[-test_data_size:]#取最后12個數據
print(len(train_data))
print(len(test_data))
#最大最小縮放器進行歸一化,減小誤差,注意,數據標準化只應用于訓練數據而不應用于測試數據
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler(feature_range=(-1, 1))
train_data_normalized = scaler.fit_transform(train_data.reshape(-1, 1))
#查看歸一化之后的前5條數據和后5條數據
print(train_data_normalized[:5])
print(train_data_normalized[-5:])
#將數據集轉換為tensor,因為PyTorch模型是使用tensor進行訓練的,并將訓練數據轉換為輸入序列和相應的標簽
train_data_normalized = torch.FloatTensor(train_data_normalized).view(-1)
#view相當于numpy中的resize,參數代表數組不同維的維度;
#參數為-1表示,這個維的維度由機器自行推斷,如果沒有-1,那么view中的所有參數就要和tensor中的元素總個數一致
#定義create_inout_sequences函數,接收原始輸入數據,并返回一個元組列表。
def create_inout_sequences(input_data, tw):
inout_seq = []
L = len(input_data)
for i in range(L-tw):
train_seq = input_data[i:i+tw]
train_label = input_data[i+tw:i+tw+1]#預測time_step之后的第一個數值
inout_seq.append((train_seq, train_label))#inout_seq內的數據不斷更新,但是總量只有tw+1個
return inout_seq
train_window = 12#設置訓練輸入的序列長度為12,類似于time_step = 12
train_inout_seq = create_inout_sequences(train_data_normalized, train_window)
print(train_inout_seq[:5])#產看數據集改造結果
"""
注意:
create_inout_sequences返回的元組列表由一個個序列組成,
每一個序列有13個數據,分別是設置的12個數據(train_window)+ 第13個數據(label)
第一個序列由前12個數據組成,第13個數據是第一個序列的標簽。
同樣,第二個序列從第二個數據開始,到第13個數據結束,而第14個數據是第二個序列的標簽,依此類推。
"""
"""
創建LSTM模型
參數說明:
1、input_size:對應的及特征數量,此案例中為1,即passengers
2、output_size:預測變量的個數,及數據標簽的個數
2、hidden_layer_size:隱藏層的特征數,也就是隱藏層的神經元個數
"""
class LSTM(nn.Module):#注意Module首字母需要大寫
def __init__(self, input_size=1, hidden_layer_size=100, output_size=1):
super().__init__()
self.hidden_layer_size = hidden_layer_size
# 創建LSTM層和linear層,LSTM層提取特征,linear層用作最后的預測
##LSTM算法接受三個輸入:先前的隱藏狀態,先前的單元狀態和當前輸入。
self.lstm = nn.LSTM(input_size, hidden_layer_size)
self.linear = nn.Linear(hidden_layer_size, output_size)
#初始化隱含狀態及細胞狀態C,hidden_cell變量包含先前的隱藏狀態和單元狀態
self.hidden_cell = (torch.zeros(1, 1, self.hidden_layer_size),
torch.zeros(1, 1, self.hidden_layer_size))
# 為什么的第二個參數也是1
# 第二個參數代表的應該是batch_size吧
# 是因為之前對數據已經進行過切分了嗎?????
def forward(self, input_seq):
lstm_out, self.hidden_cell = self.lstm(input_seq.view(len(input_seq), 1, -1), self.hidden_cell)
#lstm的輸出是當前時間步的隱藏狀態ht和單元狀態ct以及輸出lstm_out
#按照lstm的格式修改input_seq的形狀,作為linear層的輸入
predictions = self.linear(lstm_out.view(len(input_seq), -1))
return predictions[-1]#返回predictions的最后一個元素
"""
forward方法:LSTM層的輸入與輸出:out, (ht,Ct)=lstm(input,(h0,C0)),其中
一、輸入格式:lstm(input,(h0, C0))
1、input為(seq_len,batch,input_size)格式的tensor,seq_len即為time_step
2、h0為(num_layers * num_directions, batch, hidden_size)格式的tensor,隱藏狀態的初始狀態
3、C0為(seq_len, batch, input_size)格式的tensor,細胞初始狀態
二、輸出格式:output,(ht,Ct)
1、output為(seq_len, batch, num_directions*hidden_size)格式的tensor,包含輸出特征h_t(源于LSTM每個t的最后一層)
2、ht為(num_layers * num_directions, batch, hidden_size)格式的tensor,
3、Ct為(num_layers * num_directions, batch, hidden_size)格式的tensor,
"""
#創建LSTM()類的對象,定義損失函數和優化器
model = LSTM()
loss_function = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)#建立優化器實例
print(model)
"""
模型訓練
batch-size是指1次迭代所使用的樣本量;
epoch是指把所有訓練數據完整的過一遍;
由于默認情況下權重是在PyTorch神經網絡中隨機初始化的,因此可能會獲得不同的值。
"""
epochs = 150
for i in range(epochs):
for seq, labels in train_inout_seq:
#清除網絡先前的梯度值
optimizer.zero_grad()#訓練模型時需要使模型處于訓練模式,即調用model.train()。缺省情況下梯度是累加的,需要手工把梯度初始化或者清零,調用optimizer.zero_grad()
#初始化隱藏層數據
model.hidden_cell = (torch.zeros(1, 1, model.hidden_layer_size),
torch.zeros(1, 1, model.hidden_layer_size))
#實例化模型
y_pred = model(seq)
#計算損失,反向傳播梯度以及更新模型參數
single_loss = loss_function(y_pred, labels)#訓練過程中,正向傳播生成網絡的輸出,計算輸出和實際值之間的損失值
single_loss.backward()#調用loss.backward()自動生成梯度,
optimizer.step()#使用optimizer.step()執行優化器,把梯度傳播回每個網絡
# 查看模型訓練的結果
if i%25 == 1:
print(f'epoch:{i:3} loss:{single_loss.item():10.8f}')
print(f'epoch:{i:3} loss:{single_loss.item():10.10f}')
"""
預測
注意,test_input中包含12個數據,
在for循環中,12個數據將用于對測試集的第一個數據進行預測,然后將預測值附加到test_inputs列表中。
在第二次迭代中,最后12個數據將再次用作輸入,并進行新的預測,然后 將第二次預測的新值再次添加到列表中。
由于測試集中有12個元素,因此該循環將執行12次。
循環結束后,test_inputs列表將包含24個數據,其中,最后12個數據將是測試集的預測值。
"""
fut_pred = 12
test_inputs = train_data_normalized[-train_window:].tolist()#首先打印出數據列表的最后12個值
print(test_inputs)
#更改模型為測試或者驗證模式
model.eval()#把training屬性設置為false,使模型處于測試或驗證狀態
for i in range(fut_pred):
seq = torch.FloatTensor(test_inputs[-train_window:])
with torch.no_grad():
model.hidden = (torch.zeros(1, 1, model.hidden_layer_size),
torch.zeros(1, 1, model.hidden_layer_size))
test_inputs.append(model(seq).item())
#打印最后的12個預測值
print(test_inputs[fut_pred:])
#由于對訓練集數據進行了標準化,因此預測數據也是標準化了的
#需要將歸一化的預測值轉換為實際的預測值。通過inverse_transform實現
actual_predictions = scaler.inverse_transform(np.array(test_inputs[train_window:]).reshape(-1, 1))
print(actual_predictions)
"""
根據實際值,繪制預測值
"""
x = np.arange(132, 132+fut_pred, 1)
plt.title('Month vs Passenger')
plt.ylabel('Total Passengers')
plt.xlabel('Months')
plt.grid(True)
plt.autoscale(axis='x', tight=True)
plt.plot(flight_data['passengers'])
plt.plot(x, actual_predictions)
plt.show()
#繪制最近12個月的實際和預測乘客數量,以更大的尺度觀測數據
plt.title('Month vs Passenger')
plt.ylabel('Total Passengers')
plt.xlabel('Months')
plt.grid(True)
plt.autoscale(axis='x', tight=True)
plt.plot(flight_data['passengers'][-train_window:])
plt.plot(x, actual_predictions)
plt.show()
原文鏈接:https://blog.csdn.net/ch206265/article/details/106962354
相關推薦
- 2023-03-17 redis中hash數據結構及說明_Redis
- 2022-04-06 C++的友元和內部類你了解嗎_C 語言
- 2022-08-14 Python全局變量關鍵字global的簡單使用_python
- 2022-02-17 Error: Network Error
- 2022-05-13 當你敲完Hello World后的第一步——C語言
- 2022-10-06 python中關于對super()函數疑問解惑_python
- 2022-03-23 C++通過文件指針獲取文件大小的方法實現_C 語言
- 2022-04-12 【debug】illegal hardware instruction
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支