鍵.png)
如何高效爬取全球新聞網(wǎng)站 – 整合Scrapy、Selenium與Mediastack API實現(xiàn)自動化新聞采集
優(yōu)點:
缺點:
適用場景:適合平穩(wěn)的時間序列,如金融數(shù)據(jù)、溫度變化等。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 設(shè)置種子以確??芍貜?fù)性
np.random.seed(42)
# 模擬數(shù)據(jù) AR(2) 模型
n = 1000
y = np.zeros(n)
epsilon = np.random.normal(0, 1, n)
phi = [0.5, -0.3]
# 生成時間序列
for t in range(2, n):
y[t] = phi[0] * y[t-1] + phi[1] * y[t-2] + epsilon[t]
# 創(chuàng)建一個數(shù)據(jù)框架
df = pd.DataFrame({'Time': np.arange(n), 'Value': y})
# 繪制圖像:時間序列圖和自相關(guān)圖
fig, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=120)
# 時間序列圖
ax[0].plot(df['Time'], df['Value'], color='blue')
ax[0].set_title('AR(2) Time Series')
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Value')
# 自相關(guān)圖
pd.plotting.autocorrelation_plot(df['Value'], ax=ax[1])
ax[1].set_title('Autocorrelation of AR(2) Series')
plt.tight_layout()
plt.show()
時間序列圖:展示時間序列的變化趨勢,確認數(shù)據(jù)的平穩(wěn)性。
自相關(guān)圖 (ACF 圖):自相關(guān)圖展示了不同滯后時間下序列與其自身的相關(guān)性。我們使用自相關(guān)圖來驗證 AR 模型的合理性,若自相關(guān)性在某些滯后期顯著,則表明該模型是合理的。
移動平均模型 (MA) 假設(shè)時間序列的當(dāng)前值是過去誤差項的線性組合。與自回歸模型不同,MA 模型強調(diào)的是誤差項的影響,而非時間序列自身的歷史值。
移動平均模型的公式為:
優(yōu)點:
缺點:
適用場景:適合隨機波動較強的平穩(wěn)時間序列。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 設(shè)置種子
np.random.seed(42)
# 模擬數(shù)據(jù) MA(1) 模型
n = 100
epsilon = np.random.normal(0, 1, n)
y = np.zeros(n)
theta = 0.6
# 生成時間序列
for t in range(1, n):
y[t] = epsilon[t] + theta * epsilon[t-1]
# 創(chuàng)建數(shù)據(jù)框架
df = pd.DataFrame({'Time': np.arange(n), 'Value': y})
# 繪制圖像:時間序列圖和部分自相關(guān)圖
fig, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=120)
# 時間序列圖
ax[0].plot(df['Time'], df['Value'], color='green')
ax[0].set_title('MA(1) Time Series')
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Value')
# 部分自相關(guān)圖
from statsmodels.graphics.tsaplots import plot_pacf
plot_pacf(df['Value'], ax=ax[1], lags=20)
ax[1].set_title('Partial Autocorrelation of MA(1) Series')
plt.tight_layout()
plt.show()
時間序列圖:展示 MA(1) 模型生成的時間序列,觀察隨機波動的特征。
部分自相關(guān)圖 (PACF 圖):部分自相關(guān)圖展示了去除自回歸成分后的滯后效應(yīng)。我們使用部分自相關(guān)圖來驗證 MA 模型的合理性,滯后期為 1 的部分自相關(guān)性應(yīng)該顯著。
ARMA 模型結(jié)合了自回歸 (AR) 和移動平均 (MA) 的思想。它通過同時考慮時間序列的自身歷史值(AR部分)和過去誤差的線性組合(MA部分)來進行預(yù)測。
ARMA(p, q) 模型的公式為:
推導(dǎo):ARMA 模型是 AR 和 MA 模型的組合。AR 部分通過最小化誤差平方和 (OLS) 估計,MA 部分通過最大化誤差項的似然函數(shù) (MLE) 來估計。
優(yōu)點:
缺點:
適用場景:適用于平穩(wěn)的時間序列,如經(jīng)濟數(shù)據(jù)、氣象數(shù)據(jù)等。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# 設(shè)置種子
np.random.seed(42)
# 模擬數(shù)據(jù) ARMA(2,1) 模型
n = 100
y = np.zeros(n)
epsilon = np.random.normal(0, 1, n)
phi = [0.5, -0.4]
theta = 0.3
# 生成時間序列
for t in range(2, n):
y[t] = phi[0] * y[t-1] + phi[1] * y[t-2] + epsilon[t] + theta * epsilon[t-1]
# 創(chuàng)建數(shù)據(jù)框架
df = pd.DataFrame({'Time': np.arange(n), 'Value': y})
# 繪制圖像:時間序列圖和ACF圖
fig, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=120)
# 時間序列圖
ax[0].plot(df['Time'], df['Value'], color='purple')
ax[0].set_title('ARMA(2,1) Time Series')
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Value')
# 自相關(guān)圖
pd.plotting.autocorrelation_plot(df['Value'], ax=ax[1])
ax[1].set_title('Autocorrelation of ARMA(2,1) Series')
plt.tight_layout()
plt.show()
時間序列圖:觀察 ARMA(2, 1) 模型生成的時間序列,顯示其隨機波動和趨勢變化。
自相關(guān)圖 (ACF 圖):通過自相關(guān)圖來驗證 ARMA 模型中的滯后效應(yīng)。如果滯后期的自相關(guān)性顯著,則可以說明模型的合理性。
ARIMA 模型是 ARMA 模型的擴展,增加了一個差分項,用于處理非平穩(wěn)時間序列。差分的目的是去除時間序列中的趨勢和季節(jié)性波動,使其平穩(wěn)。
ARIMA(p, d, q) 模型的公式為:
優(yōu)點:
缺點:
適用場景:適用于非平穩(wěn)數(shù)據(jù),如股票價格、經(jīng)濟指標等。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from statsmodels.tsa.arima.model import ARIMA
# 設(shè)置種子
np.random.seed(42)
# 模擬數(shù)據(jù) ARIMA(1,1,1) 模型
n = 100
y = np.zeros(n)
epsilon = np.random.normal(0, 1, n)
phi = 0.6
theta = 0.4
# 生成時間序列 (一階差分)
for t in range(1, n):
y[t] = phi * y[t-1] + epsilon[t] + theta * epsilon[t-1]
# 創(chuàng)建數(shù)據(jù)框架
df = pd.DataFrame({'Time': np.arange(n), 'Value': y})
# 繪制圖像:原始序列與差分序列
fig, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=120)
# 原始序列
ax[0].plot(df['Time'], df['Value'], color='red')
ax[0].set_title('ARIMA(1,1,1) Time Series')
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Value')
# 一階差分
diff_y = np.diff(df['Value'], n=1)
ax[1].plot(df['Time'][:-1], diff_y, color='blue')
ax[1].set_title('First Difference of ARIMA(1,1,1) Series')
ax[1].set_xlabel('Time')
ax[1].set_ylabel('Differenced Value')
plt.tight_layout()
plt.show()
原始序列圖:展示生成的 ARIMA(1, 1, 1) 模型的時間序列,觀察其非平穩(wěn)特性。
一階差分圖:通過一階差分圖顯示經(jīng)過差分處理后的平穩(wěn)時間序列,以展示差分操作的效果。
SARIMA 模型擴展了 ARIMA 模型,增加了季節(jié)性成分,用于處理具有周期性和季節(jié)性變化的時間序列。它結(jié)合了非季節(jié)性成分和季節(jié)性成分。
推導(dǎo):非季節(jié)性成分和季節(jié)性成分分別處理,首先通過差分去除趨勢和季節(jié)性,然后應(yīng)用 ARMA 模型對剩余部分進行建模。
優(yōu)點:
缺點:
適用場景:適用于季節(jié)性數(shù)據(jù),如氣象數(shù)據(jù)、銷售數(shù)據(jù)等。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from statsmodels.tsa.statespace.sarimax import SARIMAX
# 設(shè)置種子
np.random.seed(42)
# 模擬數(shù)據(jù) SARIMA(1,1,1)(1,1,1,12) 模型
n = 120
seasonal_period = 12
y = np.zeros(n)
epsilon = np.random.normal(0, 1, n)
phi = 0.7
theta = 0.5
Phi = 0.3
Theta = 0.2
# 生成時間序列
for t in range(1, n):
if t >= seasonal_period:
y[t] = phi * y[t-1] + theta * epsilon[t-1] + Phi * y[t-seasonal_period] + Theta * epsilon[t-seasonal_period] + epsilon[t]
else:
y[t] = phi * y[t-1] + theta * epsilon[t-1] + epsilon[t]
# 創(chuàng)建數(shù)據(jù)框架
df = pd.DataFrame({'Time': np.arange(n), 'Value': y})
# 繪制圖像:原始序列與季節(jié)性分解
fig, ax = plt.subplots(1, 2, figsize=(12, 6), dpi=120)
# 原始序列
ax[0].plot(df['Time'], df['Value'], color='orange')
ax[0].set_title('SARIMA(1,1,1)(1,1,1,12) Time Series')
ax[0].set_xlabel('Time')
ax[0].set_ylabel('Value')
# 季節(jié)性分解圖
from statsmodels.tsa.seasonal import seasonal_decompose
result = seasonal_decompose(df['Value'], period=seasonal_period, model='additive')
result.seasonal.plot(ax=ax[1], color='blue')
ax[1].set_title('Seasonal Component of SARIMA Series')
ax[1].set_xlabel('Time')
plt.tight_layout()
plt.show()
原始序列圖:展示 SARIMA 模型生成的時間序列,包含季節(jié)性成分和隨機波動。
季節(jié)性分解圖:分離季節(jié)性成分,顯示時間序列中的周期性變化,幫助識別季節(jié)性波動。
指數(shù)平滑模型 (ETS, Exponential Smoothing Model)是一類用于時間序列預(yù)測的模型,其基本思想是給不同時間點的觀測值賦予不同的權(quán)重,越接近當(dāng)前時間點的數(shù)據(jù),權(quán)重越大。這種加權(quán)方式可以很好地平滑時間序列中的短期波動。ETS 模型可以處理趨勢和季節(jié)性成分。
簡單指數(shù)平滑 (Simple Exponential Smoothing)?的公式為:
推導(dǎo):ETS 模型通過平滑操作分別計算時間序列的長期趨勢、短期波動和季節(jié)性影響。通過設(shè)定不同的平滑系數(shù)來調(diào)整對各個成分的權(quán)重。
優(yōu)點:
缺點:
適用場景:適合平穩(wěn)數(shù)據(jù)以及含有周期性和趨勢成分的時間序列,如銷量預(yù)測、溫度變化等。
我們生成一個帶有季節(jié)性和趨勢的時間序列,并使用 ETS 模型進行預(yù)測。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from statsmodels.tsa.holtwinters import ExponentialSmoothing
# 設(shè)置種子
np.random.seed(42)
# 生成帶有趨勢和季節(jié)性的時間序列數(shù)據(jù)
n = 150
time = np.arange(n)
seasonal_period = 12
trend = 0.05 * time
seasonal = 10 * np.sin(2 * np.pi * time / seasonal_period)
noise = np.random.normal(0, 2, n)
y = 20 + trend + seasonal + noise
# 創(chuàng)建數(shù)據(jù)框架
df = pd.DataFrame({'Time': time, 'Value': y})
# 應(yīng)用ETS模型(加法模型)
model = ExponentialSmoothing(df['Value'], seasonal='add', trend='add', seasonal_periods=seasonal_period)
fit = model.fit()
# 預(yù)測未來的值
forecast = fit.forecast(steps=24)
# 繪制原始數(shù)據(jù)和預(yù)測數(shù)據(jù)
plt.figure(figsize=(12, 6), dpi=120)
plt.plot(df['Time'], df['Value'], label='Original Series', color='blue')
plt.plot(np.arange(n, n + len(forecast)), forecast, label='Forecast', color='orange')
plt.axvline(x=n, color='gray', linestyle='--', label='Prediction Start')
plt.title('ETS Model - Additive Trend and Seasonality')
plt.xlabel('Time')
plt.ylabel('Value')
plt.legend()
plt.show()
時間序列預(yù)測圖:展示原始時間序列以及基于 ETS 模型的預(yù)測結(jié)果,用于展示模型在處理趨勢和季節(jié)性數(shù)據(jù)時的效果。
長短期記憶網(wǎng)絡(luò) (LSTM) 是一種特殊的循環(huán)神經(jīng)網(wǎng)絡(luò) (RNN),適用于處理序列數(shù)據(jù)中的長期依賴問題。它通過引入記憶單元和門控機制,能夠選擇性地保留或遺忘先前時間點的信息,解決了傳統(tǒng) RNN 中的梯度消失問題。
LSTM 的核心組件包括遺忘門、輸入門和輸出門,分別控制如何處理記憶狀態(tài)。
1. 遺忘門:決定哪些信息需要被遺忘。
2. 輸入門:決定哪些信息需要被寫入記憶。
3. 輸出門:決定如何產(chǎn)生當(dāng)前時刻的隱狀態(tài)。
優(yōu)點:
缺點:
適用場景:適合處理復(fù)雜的時間序列數(shù)據(jù),如股票預(yù)測、語音識別、自然語言處理等。
使用 PyTorch 實現(xiàn) LSTM 進行時間序列預(yù)測的完整代碼案例。
import numpy as np
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
from sklearn.preprocessing import MinMaxScaler
from torch.autograd import Variable
# 設(shè)置隨機種子以確保可復(fù)現(xiàn)性
np.random.seed(42)
torch.manual_seed(42)
# 生成正弦波數(shù)據(jù)
def generate_sine_wave(sequence_length, num_samples):
x = np.linspace(0, 100, num_samples)
y = np.sin(x)
return y
# 參數(shù)
sequence_length = 50 # 序列長度
num_samples = 1000 # 樣本數(shù)量
# 生成數(shù)據(jù)
data = generate_sine_wave(sequence_length, num_samples)
# 可視化數(shù)據(jù)
plt.plot(data)
plt.title("Sine Wave")
plt.show()
# 數(shù)據(jù)歸一化
scaler = MinMaxScaler(feature_range=(0, 1))
data_scaled = scaler.fit_transform(data.reshape(-1, 1))
# 創(chuàng)建時間序列數(shù)據(jù)集
def create_dataset(data, sequence_length):
X, y = [], []
for i in range(len(data) - sequence_length):
X.append(data[i:i + sequence_length, 0])
y.append(data[i + sequence_length, 0])
return np.array(X), np.array(y)
# 創(chuàng)建輸入輸出數(shù)據(jù)
X, y = create_dataset(data_scaled, sequence_length)
# 轉(zhuǎn)換為 PyTorch 張量
X = torch.from_numpy(X).float().unsqueeze(-1) # shape: (samples, sequence_length, 1)
y = torch.from_numpy(y).float() # shape: (samples,)
class LSTMModel(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers=1):
super(LSTMModel, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
# 定義 LSTM 層
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):
# 初始化隱狀態(tài)和細胞狀態(tài)
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size)
c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size)
# 前向傳播 LSTM 層
out, _ = self.lstm(x, (h0, c0))
# 取最后一個時間步的輸出
out = out[:, -1, :]
# 全連接層輸出
out = self.fc(out)
return out
# 定義模型參數(shù)
input_size = 1 # 輸入特征數(shù)
hidden_size = 50 # LSTM 隱藏層單元數(shù)
output_size = 1 # 輸出特征數(shù)
num_layers = 1 # LSTM 層數(shù)
# 初始化模型
model = LSTMModel(input_size, hidden_size, output_size, num_layers)
# 打印模型結(jié)構(gòu)
print(model)
# 定義損失函數(shù)和優(yōu)化器
criterion = nn.MSELoss() # 使用均方誤差作為損失函數(shù)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
# 劃分訓(xùn)練集和測試集
train_size = int(len(X) * 0.8)
test_size = len(X) - train_size
X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]
# 訓(xùn)練模型
num_epochs = 100
for epoch in range(num_epochs):
model.train()
# 前向傳播
outputs = model(X_train)
loss = criterion(outputs, y_train)
# 反向傳播和優(yōu)化
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 打印損失
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')
# 進行預(yù)測
model.eval() # 設(shè)置為評估模式
with torch.no_grad():
predicted = model(X_test)
predicted = predicted.detach().numpy()
# 反歸一化預(yù)測值
predicted = scaler.inverse_transform(predicted)
# 反歸一化真實值
y_test = y_test.detach().numpy()
y_test = scaler.inverse_transform(y_test.reshape(-1, 1))
# 可視化結(jié)果
plt.plot(y_test, label='True Value')
plt.plot(predicted, label='Predicted Value')
plt.title('LSTM Time Series Prediction')
plt.legend()
plt.show()
使用了 PyTorch 來構(gòu)建 LSTM 模型,用于處理時間序列預(yù)測問題。
模型包含一個 LSTM 層和一個全連接層,通過 Adam 優(yōu)化器進行訓(xùn)練。
Prophet 是由 Facebook 開發(fā)的一種時間序列預(yù)測模型,基于加性模型,將趨勢、季節(jié)性和假期影響分解為不同的成分,能夠處理非線性時間序列。
ophet 的基本公式為:
使用簡單的正弦波時間序列作為數(shù)據(jù)示例,訓(xùn)練后的模型能夠預(yù)測未來的值。
Prophet 將趨勢項建模為線性或非線性,季節(jié)性使用傅里葉級數(shù)表示,假期使用顯式的日期列表。
優(yōu)點:
缺點:
適用場景:適合社交媒體分析、銷量預(yù)測、網(wǎng)站流量預(yù)測等周期性數(shù)據(jù)。
我們使用 prophet 模型對帶有周期性的虛擬數(shù)據(jù)進行預(yù)測。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from prophet import Prophet
# 生成帶有趨勢和季節(jié)性的時間序列數(shù)據(jù)
np.random.seed(42)
n = 200
time = pd.date_range(start='2022-01-01', periods=n, freq='D')
trend = np.linspace(0, 10, n)
seasonal = 5 * np.sin(2 * np.pi * np.arange(n) / 30)
noise = np.random.normal(0, 0.5, n)
y = 20 + trend + seasonal + noise
# 創(chuàng)建數(shù)據(jù)框架
df = pd.DataFrame({'ds': time, 'y': y})
# Prophet 模型
model = Prophet(yearly_seasonality=False, daily_seasonality=True)
model.fit(df)
# 預(yù)測未來30天
future = model.make_future_dataframe(periods=30)
forecast = model.predict(future)
# 繪制預(yù)測結(jié)果
model.plot(forecast)
plt.title('Prophet Time Series Prediction')
plt.show()
Prophet 預(yù)測圖:展示 Prophet 模型對時間序列數(shù)據(jù)的預(yù)測,包括趨勢和季節(jié)性成分的分解。
貝葉斯結(jié)構(gòu)時間序列模型基于貝葉斯方法,能夠結(jié)合不同的成分(趨勢、季節(jié)性等)對時間序列進行分解。它在處理非線性時間序列和捕捉不確定性方面有獨特優(yōu)勢。
TS 模型的基本公式為:
通過貝葉斯推斷,BSTS 能夠?qū)Σ煌某煞诌M行不確定性估計。
優(yōu)點:
缺點:
適用場景:適合金融市場、銷售數(shù)據(jù)、網(wǎng)絡(luò)流量等具有復(fù)雜特性的時間序列。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from bsts import BSTS
# 生成虛擬數(shù)據(jù)
np.random.seed(42)
n = 100
time = np.arange(n)
trend = 0.1 * time
noise = np.random.normal(0, 1, n)
y = trend + noise
# BSTS 模型構(gòu)建與擬合
model = BSTS()
model.fit(y)
# 預(yù)測未來值
predicted = model.predict(steps=10)
# 繪制預(yù)測結(jié)果
plt.figure(figsize=(10, 6))
plt.plot(time, y, label='Original Series')
plt.plot(np.arange(n, n+10), predicted, label='BSTS Prediction', color='orange')
plt.legend()
plt.title('BSTS Time Series Prediction')
plt.show()
時間序列預(yù)測圖:展示了 BSTS 模型對未來時間序列的預(yù)測,結(jié)合了趨勢和噪聲成分,顯示其在不確定性建模中的優(yōu)勢。
卡爾曼濾波是一種遞歸濾波算法,廣泛用于動態(tài)系統(tǒng)的狀態(tài)估計,能夠處理噪聲干擾。它通過貝葉斯推斷動態(tài)調(diào)整對當(dāng)前狀態(tài)的估計,適合平滑和預(yù)測時間序列。
曼濾波的更新公式為:
預(yù)測:
優(yōu)點:
缺點:
適用場景:適用于實時狀態(tài)估計和動態(tài)系統(tǒng)建模,如導(dǎo)航系統(tǒng)、金融市場等。
import numpy as np
import matplotlib.pyplot as plt
from pykalman import KalmanFilter
# 生成時間序列數(shù)據(jù)
n = 100
time = np.arange(n)
signal = np.sin(0.1 * time)
noise = np.random.normal(0, 0.1, n)
y = signal + noise
# 卡爾曼濾波
kf = KalmanFilter(initial_state_mean=0, n_dim_obs=1)
state_means, _ = kf.smooth(y)
# 繪制原始數(shù)據(jù)和卡爾曼濾波結(jié)果
plt.figure(figsize=(10, 6))
plt.plot(time, y, label='Noisy Signal')
plt.plot(time, state_means, label='Kalman Filtered', color='red')
plt.legend()
plt.title('Kalman Filter - Time Series Smoothing')
plt.show()
時間序列平滑圖:展示原始噪聲數(shù)據(jù)和經(jīng)過卡爾曼濾波后的平滑結(jié)果。
時間序列平滑圖:展示了卡爾曼濾波在處理帶噪聲的時間序列中的平滑效果,顯示其在動態(tài)系統(tǒng)建模中的優(yōu)越性。
文章轉(zhuǎn)自微信公眾號@深夜努力寫Python