鍵.png)
如何高效爬取全球新聞網(wǎng)站 – 整合Scrapy、Selenium與Mediastack API實現(xiàn)自動化新聞采集
其中:
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在每個時間步的操作可以概括為以下步驟:
通過這種記憶單元狀態(tài)的更新與控制機(jī)制,LSTM能夠有效地在較長的序列中保持記憶,從而適用于時間序列預(yù)測等長時序依賴的任務(wù)。
為了更好的理解算法本身,實際數(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()
在訓(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)
將數(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)
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}')
模型訓(xùn)練完成后,我們對測試集進(jìn)行預(yù)測,用圖形展示給大家~
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)整輸入序列長度。
LSTM模型的性能在很大程度上依賴于參數(shù)設(shè)置和數(shù)據(jù)處理。下面論述一些比較重要的方面~
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ù),一般來說,較小的批量可以幫助捕捉更多的特征信息。
在優(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