其中:

每一輪訓練,XGBoost都會構建一棵新的樹來修正上一棵樹的殘差,最終模型是所有樹預測結果的加權和。

XGBoost 結合時間序列模型

在時間序列問題中,傳統的模型(如ARIMA)假設數據是平穩的,并基于過去的時序模式進行預測。而在XGBoost中,我們通過生成滯后特征將時間序列問題轉化為一個標準的回歸問題。

假設我們要預測第?t天的銷售量yt?,我們可以用前幾天的銷售量以及其他因素(如天氣、促銷、節假日)作為特征:

其中:

通過這種方式,我們將時間序列問題轉化為一個回歸問題,并利用XGBoost的強大性能來進行預測。

時間序列中的窗口特征

在處理時間序列問題時,常用的特征生成方式包括滯后特征(Lag Features)?和?滾動窗口特征(Rolling Window Features)

3. 模型原理

為了進一步細化,假設我們定義的時間序列回歸模型的目標是根據前??p天的銷售數據以及其他特征預測第?t天的銷售量:

其中:

XGBoost中,模型通過不斷迭代構建弱學習器(決策樹)來擬合銷售數據和其他特征的關系,預測值是所有樹預測結果的加權和:

其中:

4. 銷售數據集

這里,我們生成一個虛擬的銷售數據集來模擬真實的銷售情況。

該數據集將包含以下特征:

我們假設天氣、節假日和促銷都會影響每天的銷售量,并且銷售量具有一定的周期性(如每月的波動)。

生成虛擬數據集:

import pandas as pd
import numpy as np
import random

# 生成日期范圍
dates = pd.date_range(start='2022-01-01', periods=1000, freq='D')

# 模擬銷售量數據,假設其具有周期性和隨機波動
np.random.seed(42)
sales = 200 + 10 * np.sin(np.arange(len(dates)) / 30) + np.random.normal(0, 20, len(dates))

# 隨機生成天氣、節假日和促銷數據
weather = np.random.choice(['Sunny', 'Rainy', 'Cloudy'], size=len(dates))
holiday = np.random.choice([0, 1], size=len(dates), p=[0.9, 0.1]) # 10% 是節假日
promotion = np.random.choice([0, 1], size=len(dates), p=[0.8, 0.2]) # 20% 有促銷活動

# 創建DataFrame
df = pd.DataFrame({
'Date': dates,
'Sales': sales,
'Weather': weather,
'Holiday': holiday,
'Promotion': promotion
})

# 顯示前幾行數據
df.head()

在這個數據集中:

通過上述步驟,我們生成了一個完整的虛擬銷售數據集,包含365天的銷售記錄。

5. 數據預處理與特征工程

在數據預處理階段,我們需要對數據進行多項處理,包括:

  1. 日期特征處理:將日期信息拆解為年、月、日和星期幾等特征。
  2. 類別特征編碼:將天氣、節假日、促銷等類別特征轉換為模型可以接受的數值格式。
  3. 時間序列滯后特征:生成銷售量的滯后特征,以捕捉歷史數據對當前銷售的影響。

日期特征處理

將日期信息轉換為年、月、日、星期幾等特征,以便模型能夠捕捉到時間的季節性規律。

# 日期特征處理
df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Day'] = df['Date'].dt.day
df['DayOfWeek'] = df['Date'].dt.dayofweek

類別特征編碼

將類別變量轉換為數值特征,通常使用獨熱編碼(One-Hot Encoding)

# 使用獨熱編碼將天氣特征轉換為數值特征
df = pd.get_dummies(df, columns=['Weather'], drop_first=True)

滯后特征生成

為了捕捉歷史數據對未來銷售量的影響,我們需要生成滯后特征。假設我們使用過去7天的銷售量作為滯后特征。

# 生成滯后特征
for lag in range(1, 8):
df[f'Sales_lag_{lag}'] = df['Sales'].shift(lag)

# 刪除缺失值(由于滯后特征的產生,前幾行會產生缺失值)
df = df.dropna()

滯后特征生成后,我們的數據集將包含過去7天的銷售量特征,這對于捕捉時間序列中的依賴關系非常重要。

滾動窗口特征生成

除了滯后特征,滾動窗口特征也是常用的手段之一。我們可以計算過去幾天的銷售量的均值、方差等統計量,以更好地捕捉銷售趨勢。

# 生成滾動窗口的均值和標準差特征
df['Rolling_mean_7'] = df['Sales'].rolling(window=7).mean().shift(1)
df['Rolling_std_7'] = df['Sales'].rolling(window=7).std().shift(1)

# 同樣需要刪除因滾動窗口導致的缺失值
df = df.dropna()

通過生成上述特征,我們完成了特征工程,數據集現在不僅包含原始的銷售數據和外部特征,還增加了大量的時序特征。

6. 基于XGBoost的時間序列銷售預測模型的構建

在數據預處理完成之后,我們可以開始構建基于XGBoost時間序列預測模型。這里我們將使用PyTorch來實現一個簡單的神經網絡,并XGBoost的行為。

數據準備

首先,我們將數據劃分為訓練集和測試集,并轉換為PyTorch的張量格式。

from sklearn.model_selection import train_test_split
import torch

# 準備訓練和測試集
X = df.drop(columns=['Date', 'Sales']).values
y = df['Sales'].values

# 確保沒有 NaN
X = np.nan_to_num(X) # 將 NaN 轉換為 0 或其他默認數值
y = np.nan_to_num(y)

# 確保數據類型都是數值型
X = X.astype(np.float32)
y = y.astype(np.float32)

# 數據集劃分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

# 轉換為PyTorch張量
X_train = torch.tensor(X_train, dtype=torch.float32)
X_test = torch.tensor(X_test, dtype=torch.float32)
y_train = torch.tensor(y_train, dtype=torch.float32).view(-1, 1)
y_test = torch.tensor(y_test, dtype=torch.float32).view(-1, 1)

模型結構定義

在這里,我們定義一個簡單的XGBoost的回歸模型結構。雖然XGBoost本質上是樹模型,但我們來體現其非線性擬合能力。

import torch.nn as nn

# 定義神經網絡模型
class XGBoostTimeSeriesModel(nn.Module):
def __init__(self, input_dim):
super(XGBoostTimeSeriesModel, self).__init__()
self.fc1 = nn.Linear(input_dim, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 1)

def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x

# 初始化模型
input_dim = X_train.shape[1]
model = XGBoostTimeSeriesModel(input_dim)

損失函數與優化器

我們使用均方誤差(MSE)作為損失函數,并使用Adam優化器進行模型優化。

import torch.optim as optim

# 定義損失函數和優化器
criterion = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

模型訓練

通過梯度下降法訓練模型,進行500次迭代訓練。

# 模型訓練
epochs = 500
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()

if epoch % 50 == 0:
print(f'Epoch {epoch}/{epochs}, Loss: {loss.item()}')

模型測試

訓練完成后,我們可以在測試集上進行預測,并計算模型的性能。

from sklearn.metrics import mean_squared_error

# 模型預測
model.eval()
predictions = model(X_test).detach().numpy()

# 計算均方誤差
mse = mean_squared_error(y_test, predictions)
print(f'Test MSE: {mse}')

7. 結果可視化

為了更直觀地展示模型的表現,我們將預測值與真實值進行對比繪圖,并繪制其他有助于分析模型性能的圖形。

預測值與真實值對比圖

展示模型在測試集上的預測效果,通過對比可以看到模型是否準確地捕捉到銷售趨勢。

import matplotlib.pyplot as plt

# 繪制預測值與真實值的對比圖
plt.figure(figsize=(12, 6))
plt.plot(df['Date'][-len(y_test):], y_test, label='True Sales', linewidth=2)
plt.plot(df['Date'][-len(y_test):], predictions, label='Predicted Sales', linestyle='--', linewidth=2)
plt.xlabel('Date')
plt.ylabel('Sales')
plt.title('Sales Prediction vs True Sales')
plt.legend()
plt.grid(True)
plt.show()

損失下降曲線

通過繪制訓練過程中的損失下降曲線,可以幫助我們判斷模型是否收斂。

# 繪制損失下降曲線
losses = []
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train)
loss = criterion(outputs, y_train)
loss.backward()
optimizer.step()

losses.append(loss.item())

plt.figure(figsize=(8, 4))
plt.plot(losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss Curve')
plt.show()

特征重要性圖

雖然XGBoost具有內建的特征重要性評估機制,但我們可以通過分析模型的權重來了解哪些特征對預測影響最大。

importances = model.fc1.weight.abs().mean(dim=0).detach().numpy()
feature_names = df.drop(columns=['Date', 'Sales']).columns
plt.figure(figsize=(10, 6))
plt.barh(feature_names, importances)
plt.xlabel('Feature Importance')
plt.title('Feature Importance in Sales Prediction')
plt.show()

8. 模型優化與調參

在實際應用中,優化模型的性能是關鍵步驟。常見的調優手段包括:

  1. 特征選擇與重要性分析:通過分析特征重要性,篩選對模型效果有貢獻的特征,并去除不重要的特征。
  2. 超參數調優:使用網格搜索或隨機搜索調優超參數,例如樹的數量、學習率、正則化參數等。
  3. 交叉驗證:使用時間序列分割的交叉驗證方法評估模型,確保模型的泛化能力。

超參數調優

XGBoost模型的關鍵超參數包括:

可以使用GridSearchCV進行網格搜索:

from sklearn.model_selection import GridSearchCV
import xgboost as xgb

# 創建XGBoost模型
xgb_model = xgb.XGBRegressor()

# 定義超參數搜索空間
param_grid = {
'learning_rate': [0.01, 0.05, 0.1],
'max_depth': [3, 5, 7],
'n_estimators': [100, 200, 300],
'reg_alpha': [0, 0.1, 0.5],
'reg_lambda': [1, 1.5, 2]
}

# 進行網格搜索
grid_search = GridSearchCV(estimator=xgb_model, param_grid=param_grid, cv=5, scoring='neg_mean_squared_error', verbose=1)
grid_search.fit(X_train, y_train)

# 輸出最佳參數
print("Best Parameters:", grid_search.best_params_)

模型驗證與早停

在訓練過程中可以引入早停機制(Early Stopping),即如果模型在驗證集上的性能在連續幾輪迭代中沒有提升,則提前終止訓練以防止過擬合。

# 使用早停機制訓練XGBoost模型
xgb_model = xgb.XGBRegressor(learning_rate=0.1, max_depth=5, n_estimators=300)
xgb_model.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=50, verbose=True)

通過這種方式,模型的訓練將更加穩健,避免因過度訓練導致的過擬合現象。

整個內容,通過結合XGBoost與時間序列模型,給大家分享了如何利用歷史銷售數據以及多維特征(如天氣、促銷、節假日等)進行銷售預測。XGBoost的強大非線性擬合能力使其在處理復雜特征和多維數據時表現優異。通過合理的特征工程、模型訓練、調參與優化,我們可以構建出一個精確且具備良好泛化能力的預測模型。

模型可繼續改進的方向:

最終,該模型可以應用于庫存管理、市場營銷以及生產計劃等多種業務場景。

文章轉自微信公眾號@深夜努力寫Python

上一篇:

突破LSTM!結合ARIMA時間序列預測 !!

下一篇:

突破LightGBM!最強時間序列模型!!
#你可能也喜歡這些API文章!

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

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

#AI深度推理大模型API

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

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