其中:

2. 輸入門(Input Gate)

決定當(dāng)前輸入信息是否寫入記憶單元中,用于更新記憶內(nèi)容。輸入門同樣通過sigmoid函數(shù)生成一個0到1的值,表示當(dāng)前輸入數(shù)據(jù)的重要性。

數(shù)學(xué)公式為:

同時,我們會計算一個候選記憶狀態(tài)(Candidate Memory Cell),用于提取輸入信息的主要特征,并將其加入到記憶單元中:

3. 輸出門(Output Gate)

決定當(dāng)前記憶單元中的信息輸出到隱藏狀態(tài)的程度,用于產(chǎn)生當(dāng)前時刻的隱藏狀態(tài)h2?,并將其傳遞給下一個時間步和最終輸出層。

數(shù)學(xué)公式:

然后,將更新后的記憶單元狀態(tài)與輸出門的控制相結(jié)合,得到新的隱藏狀態(tài):

記憶單元更新

LSTM 整體流程

通過上述過程,LSTM在每個時間步的操作可以概括為以下步驟:

通過這種記憶單元狀態(tài)的更新與控制機(jī)制,LSTM能夠有效地在較長的序列中保持記憶,從而適用于時間序列預(yù)測等長時序依賴的任務(wù)。

2. 數(shù)據(jù)預(yù)處理與虛擬數(shù)據(jù)集生成

為了更好的理解算法本身,實際數(shù)據(jù)非常大,不利于我們學(xué)習(xí),我們構(gòu)建一個虛擬天氣數(shù)據(jù)集,包括溫度、濕度、風(fēng)速等變量。假設(shè)我們有一年的歷史數(shù)據(jù),每日更新。我們將模擬這些數(shù)據(jù)并將其用于訓(xùn)練和測試。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 生成虛擬天氣數(shù)據(jù)集
np.random.seed(42)
days = 365 # 一年數(shù)據(jù)
temperature = 30 + 5 * np.sin(np.linspace(0, 2 * np.pi, days)) + np.random.normal(0, 1, days)
humidity = 50 + 10 * np.sin(np.linspace(0, 2 * np.pi, days)) + np.random.normal(0, 2, days)
wind_speed = 10 + 3 * np.sin(np.linspace(0, 2 * np.pi, days)) + np.random.normal(0, 1, days)

data = pd.DataFrame({
'temperature': temperature,
'humidity': humidity,
'wind_speed': wind_speed
})

data.head()

數(shù)據(jù)標(biāo)準(zhǔn)化

在訓(xùn)練模型之前,需要將數(shù)據(jù)標(biāo)準(zhǔn)化,以便LSTM能夠更有效地學(xué)習(xí)數(shù)據(jù)特征。

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler(feature_range=(0, 1))
data_scaled = scaler.fit_transform(data)

3. LSTM模型構(gòu)建與訓(xùn)練

數(shù)據(jù)切分

將數(shù)據(jù)分為訓(xùn)練集和測試集(80%訓(xùn)練,20%測試)。

train_size = int(len(data_scaled) * 0.8)
train_data = data_scaled[:train_size]
test_data = data_scaled[train_size:]

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 = 7 # 用前7天的數(shù)據(jù)預(yù)測第8天
X_train, y_train = create_sequences(train_data, seq_length)
X_test, y_test = create_sequences(test_data, seq_length)

模型定義

我們使用PyTorch構(gòu)建LSTM模型。

import torch
import torch.nn as nn

class WeatherLSTM(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers=1):
super(WeatherLSTM, self).__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)

def forward(self, x):
out, _ = self.lstm(x)
out = self.fc(out[:, -1, :])
return out

# 定義超參數(shù)
input_size = 3 # 特征數(shù):溫度、濕度、風(fēng)速
hidden_size = 64
output_size = 3
num_layers = 1

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

模型訓(xùn)練

import torch.optim as optim

num_epochs = 100
for epoch in range(num_epochs):
model.train()
optimizer.zero_grad()
outputs = model(torch.Tensor(X_train))
loss = criterion(outputs, torch.Tensor(y_train))
loss.backward()
optimizer.step()

if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

4. 預(yù)測與可視化分析

模型訓(xùn)練完成后,我們對測試集進(jìn)行預(yù)測,用圖形展示給大家~

預(yù)測結(jié)果

model.eval()
with torch.no_grad():
predicted = model(torch.Tensor(X_test)).detach().numpy()
predicted = scaler.inverse_transform(predicted)
actual = scaler.inverse_transform(y_test)

# 轉(zhuǎn)為DataFrame便于可視化
predicted_df = pd.DataFrame(predicted, columns=['temperature', 'humidity', 'wind_speed'])
actual_df = pd.DataFrame(actual, columns=['temperature', 'humidity', 'wind_speed'])

可視化分析

1. 溫度預(yù)測結(jié)果:展示LSTM對溫度的預(yù)測與實際值的比較。

2. 濕度預(yù)測結(jié)果:展示LSTM對濕度的預(yù)測與實際值的差距。

3. 風(fēng)速預(yù)測結(jié)果:分析風(fēng)速的預(yù)測效果。

4. 多特征趨勢對比:對比所有特征在不同時間段的預(yù)測效果。

colors = ['#1f77b4', '#ff7f0e']  # 藍(lán)色:實際值,橙色:預(yù)測值
fig, axes = plt.subplots(3, 1, figsize=(12, 10))

# 標(biāo)題和字體設(shè)置
fig.suptitle('Weather Prediction Using LSTM', fontsize=16, weight='bold')

# 溫度預(yù)測圖
axes[0].plot(actual_df['temperature'], color=colors[0], label='Actual Temperature', linewidth=1.5)
axes[0].plot(predicted_df['temperature'], color=colors[1], linestyle='--', label='Predicted Temperature', linewidth=1.5)
axes[0].set_title('Temperature Prediction', fontsize=14, weight='bold')
axes[0].set_ylabel('Temperature (°C)', fontsize=12)
axes[0].legend(fontsize=10, loc='upper right')
axes[0].grid(alpha=0.3)

# 濕度預(yù)測圖
axes[1].plot(actual_df['humidity'], color=colors[0], label='Actual Humidity', linewidth=1.5)
axes[1].plot(predicted_df['humidity'], color=colors[1], linestyle='--', label='Predicted Humidity', linewidth=1.5)
axes[1].set_title('Humidity Prediction', fontsize=14, weight='bold')
axes[1].set_ylabel('Humidity (%)', fontsize=12)
axes[1].legend(fontsize=10, loc='upper right')
axes[1].grid(alpha=0.3)

# 風(fēng)速預(yù)測圖
axes[2].plot(actual_df['wind_speed'], color=colors[0], label='Actual Wind Speed', linewidth=1.5)
axes[2].plot(predicted_df['wind_speed'], color=colors[1], linestyle='--', label='Predicted Wind Speed', linewidth=1.5)
axes[2].set_title('Wind Speed Prediction', fontsize=14, weight='bold')
axes[2].set_ylabel('Wind Speed (km/h)', fontsize=12)
axes[2].set_xlabel('Days', fontsize=12)
axes[2].legend(fontsize=10, loc='upper right')
axes[2].grid(alpha=0.3)

# 調(diào)整布局并顯示
plt.tight_layout(rect=[0, 0, 1, 0.96])
plt.show()

我們使用了三個基本的折線圖來對比LSTM模型在溫度、濕度和風(fēng)速預(yù)測方面的實際值和預(yù)測值。

溫度預(yù)測的圖形展示了LSTM模型對溫度時間序列的捕捉能力。如果預(yù)測線能夠緊密跟隨實際溫度曲線,說明模型能較好地捕捉溫度的變化趨勢。如果偏差較大,則需要調(diào)整模型復(fù)雜度或序列長度。

濕度預(yù)測的圖形反映了LSTM對濕度時序變化的擬合效果。通常濕度變化較溫度更不規(guī)則,因此濕度預(yù)測的誤差可能更大,這提示我們可以考慮將濕度數(shù)據(jù)的平滑度處理,減少噪聲。

風(fēng)速圖形反映了模型在風(fēng)速數(shù)據(jù)上的預(yù)測效果。如果預(yù)測值偏差較大,可能說明風(fēng)速的時序特征在當(dāng)前的LSTM結(jié)構(gòu)下未能得到充分捕捉,這時可以嘗試增加風(fēng)速數(shù)據(jù)的周期性特征,或調(diào)整輸入序列長度。

5. 模型優(yōu)化與調(diào)參建議

LSTM模型的性能在很大程度上依賴于參數(shù)設(shè)置和數(shù)據(jù)處理。下面論述一些比較重要的方面~

模型優(yōu)化方向

1. 隱藏層數(shù)量和單元數(shù)優(yōu)化

在 LSTM 中,隱藏層數(shù)量和每一層的隱藏單元數(shù)會影響模型的復(fù)雜度。通常情況下,較高的隱藏單元數(shù)和更多的LSTM層能夠捕捉更復(fù)雜的時序特征,但過多的隱藏單元數(shù)和層數(shù)可能導(dǎo)致過擬合。

因此,我們可以嘗試:

2. 學(xué)習(xí)率調(diào)整

學(xué)習(xí)率是優(yōu)化器的重要參數(shù)之一,它決定了每次參數(shù)更新的步長。在訓(xùn)練過程中,可以使用學(xué)習(xí)率衰減策略,即隨著訓(xùn)練輪次增加逐步減小學(xué)習(xí)率,幫助模型在接近最優(yōu)點時更加平穩(wěn)地收斂。常見策略:

scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
for epoch in range(num_epochs):
# 模型訓(xùn)練代碼...
optimizer.step()
scheduler.step() # 調(diào)整學(xué)習(xí)率

3. 正則化手段

LSTM 模型可能會因數(shù)據(jù)有限而出現(xiàn)過擬合問題,適當(dāng)?shù)恼齽t化手段可以提高模型的泛化能力:

self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, dropout=0.2)

4. 批量大小調(diào)整

批量大小決定了每次訓(xùn)練中使用的數(shù)據(jù)量,合適的批量大?。ㄈ?2、64、128等)在計算效率和泛化性能上會有較好的平衡。對于時間序列數(shù)據(jù),一般來說,較小的批量可以幫助捕捉更多的特征信息。

調(diào)參流程

在優(yōu)化模型時,系統(tǒng)化的調(diào)參流程能夠提高效率并找到最佳參數(shù)組合。

推薦的幾個調(diào)參方式:

1. 確定基本模型結(jié)構(gòu):先從簡單的LSTM結(jié)構(gòu)入手,比如1層LSTM,16個隱藏單元,學(xué)習(xí)率0.01。

2. 逐步增加復(fù)雜度:根據(jù)模型初始結(jié)果,逐漸增加隱藏單元數(shù)或?qū)訑?shù),并觀察訓(xùn)練集和測試集的誤差變化。

3. 優(yōu)化學(xué)習(xí)率和批量大小:通過實驗不同的學(xué)習(xí)率(0.01,0.001等)和批量大小,找到誤差最小且收斂速度較快的組合。

4. 添加正則化項:當(dāng)模型效果較好但存在過擬合時,添加正則化手段(如Dropout)并調(diào)整比例(如0.1、0.2等)。

5. 迭代實驗:通過實驗記錄并分析結(jié)果曲線,繼續(xù)微調(diào)參數(shù),直至得到滿意的結(jié)果。

最后

咱們這次實驗,通過LSTM模型來預(yù)測未來一周的天氣變化,涵蓋了數(shù)據(jù)預(yù)處理、模型構(gòu)建、訓(xùn)練、預(yù)測和結(jié)果分析等多個環(huán)節(jié)。通過優(yōu)化模型參數(shù),我們實現(xiàn)了對溫度、濕度和風(fēng)速等氣象變量的預(yù)測,在圖形中得到了直觀展示。

未來的改進(jìn)方向,大家可以考慮下面幾點:

1. 集成模型:可以嘗試使用多模型集成方法(如LSTM + GRU,LSTM + CNN)進(jìn)一步提高模型的預(yù)測性能。

2. 多特征工程:引入更多氣象數(shù)據(jù)(如氣壓、降水量等),并考慮時間因素(如季節(jié)性)來豐富輸入特征。

3. 多步預(yù)測:通過多步預(yù)測來實現(xiàn)對更長期的天氣預(yù)測。

4. 動態(tài)序列長度:針對不同氣象變量優(yōu)化序列長度,找到每個變量的最佳時間窗口。

以上內(nèi)容,希望可以幫助大家理解LSTM模型在預(yù)測問題上的有效性和可行性。

文章轉(zhuǎn)自微信公眾號@深夜努力寫Python

上一篇:

突破LightGBM!最強(qiáng)時間序列模型?。?/h5>

下一篇:

通透!十大時間序列技術(shù) !!
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費