2. 代碼實現

2.1 數據讀取

import pandas as pd
df = pd.read_excel('Auto MPG.xlsx')
df.head()

數據涉及城市循環燃油消耗,以每加侖英里數 (miles per gallon, mpg) 為單位,根據 3 個多值離散屬性和 5 個連續屬性來預測mpg。

2.2 缺失值處理

df.isnull().sum()

horsepower列存在6條缺失值,采用基于K最近鄰的缺失值填充算法,假設相似的樣本在特征空間中具有相似的特征值,從而使得填充后的數據盡可能保持原有的分布特性。

# 采用KNN算法填補缺失值
from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=3)
imputed = imputer.fit_transform(df)
data = pd.DataFrame(imputed, columns=df.columns, index = df.index)
data.isnull().sum()

2.3 數據集劃分

from sklearn.model_selection import train_test_split

# 首先將數據集劃分為訓練集和測試集
X_temp, X_test, y_temp, y_test = train_test_split(df.iloc[:,0:7], df['mpg'], test_size=0.2, random_state=42)

# 然后將訓練集進一步劃分為訓練集和驗證集
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.125, random_state=42) # 0.125 x 0.8 = 0.1

# 輸出數據集的大小
print(f"訓練集維度: {X_train.shape}")
print(f"驗證集維度: {X_val.shape}")
print(f"測試集維度: {X_test.shape}")

函數train_test_split函數是可以直接進行數據集的訓練集和測試集分割的,然而,它不能直接將數據分為訓練集、驗證集和測試集三部分,于是利用函數對數據集進行兩次分割,首先將數據劃分為訓練集和測試集,然后將訓練集進一步分割為訓練集和驗證集,并保證訓練集、驗證集、測試集的比例約為7:1:2。

2.4 歸一化目標變量

from sklearn.preprocessing import MinMaxScaler

def normalize_dataframe(y_train, y_val, y_test):
scaler = MinMaxScaler()
scaler.fit(np.array(y_train).reshape(-1, 1)) # 在訓練集上擬合歸一化模型 MinMaxScaler輸入數據形狀為二維數組

train = pd.DataFrame(scaler.transform(np.array(y_train).reshape(-1, 1)), index=y_train.index)
val = pd.DataFrame(scaler.transform(np.array(y_val).reshape(-1, 1)), index=y_val.index)
test = pd.DataFrame(scaler.transform(np.array(y_test).reshape(-1, 1)), index=y_test.index)

return train, val, test, scaler

train_y, val_y, test_y, scaler_y = normalize_dataframe(y_train, y_val, y_test)

2.5 定義和訓練模型

import lightgbm as lgb
import xgboost as xgb

# LightGBM模型參數
params_lgb = {
'learning_rate': 0.02, # 學習率,控制每一步的步長,用于防止過擬合。典型值范圍:0.01 - 0.1
'boosting_type': 'gbdt', # 提升方法,這里使用梯度提升樹(Gradient Boosting Decision Tree,簡稱GBDT)
'objective': 'mse', # 損失函數
'metric': 'rmse', # 評估指標
'num_leaves': 127, # 每棵樹的葉子節點數量,控制模型復雜度。較大值可以提高模型復雜度但可能導致過擬合
'verbose': -1, # 控制 LightGBM 輸出信息的詳細程度,-1表示無輸出,0表示最少輸出,正數表示輸出更多信息
'seed': 42, # 隨機種子,用于重現模型的結果
'n_jobs': -1, # 并行運算的線程數量,-1表示使用所有可用的CPU核心
'feature_fraction': 0.8, # 每棵樹隨機選擇的特征比例,用于增加模型的泛化能力
'bagging_fraction': 0.9, # 每次迭代時隨機選擇的樣本比例,用于增加模型的泛化能力
'bagging_freq': 4 # 每隔多少次迭代進行一次bagging操作,用于增加模型的泛化能力
}
model_lgb = lgb.LGBMRegressor(**params_lgb)

# XGBoost模型參數
params_xgb = {
'learning_rate': 0.02, # 學習率,控制每一步的步長,用于防止過擬合。典型值范圍:0.01 - 0.1
'booster': 'gbtree', # 提升方法,這里使用梯度提升樹(Gradient Boosting Tree)
'objective': 'reg:squarederror',# 損失函數
'max_leaves': 127, # 每棵樹的葉子節點數量,控制模型復雜度。較大值可以提高模型復雜度但可能導致過擬合
'verbosity': 1, # 控制 XGBoost 輸出信息的詳細程度,0表示無輸出,1表示輸出進度信息
'seed': 42, # 隨機種子,用于重現模型的結果
'nthread': -1, # 并行運算的線程數量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵樹隨機選擇的特征比例,用于增加模型的泛化能力
'subsample': 0.7, # 每次迭代時隨機選擇的樣本比例,用于增加模型的泛化能力
'early_stopping_rounds': None # 早停參數在fit時單獨設置
}
model_xgb = xgb.XGBRegressor(**params_xgb)

# 定義平均模型
class AverageModel:
def __init__(self, models):
self.models = models

def fit(self, X, y, X_val, y_val):
for model in self.models:
if isinstance(model, lgb.LGBMRegressor):
model.fit(X, y, eval_set=[(X_val, y_val)], eval_metric='rmse', callbacks=[lgb.early_stopping(stopping_rounds=100)])
elif isinstance(model, xgb.XGBRegressor):
model.fit(X, y, eval_set=[(X_val, y_val)], eval_metric='rmse', early_stopping_rounds=model.get_params()['early_stopping_rounds'], verbose=False)

def predict(self, X):
predictions = []
for model in self.models:
predictions.append(model.predict(X))
return sum(predictions) / len(predictions)

# 創建平均模型
average_model = AverageModel([model_lgb, model_xgb])

# 訓練模型
average_model.fit(X_train, train_y, X_val, val_y)

代碼定義了一個名為 AverageModel 的類,用于創建一個平均模型,通過集成LightGBMXGBoost模型的預測結果來提升預測的穩定性和準確性,在 fit 方法中,該類可以同時訓練傳入的多個模型,并使用驗證集進行早期停止策略來防止過擬合,在 predict 方法中,該類將多個模型的預測結果取平均作為最終的預測輸出。

這里代碼使用了一個平均模型類,將多個模型包裝起來,提供了更統一和可重用的接口,方便管理和使用多個模型,當然也可以考慮引入K折交叉驗證在每個fold內部獨立訓練和評估模型,然后手動取平均預測結果,如果希望封裝多個模型為一個整體進行訓練和預測,可以使用當前代碼的方式,如果需要更靈活的控制和理解每個模型在每個fold的表現,可以采取第二種方法進行代碼編寫。

2.6 預測測試集

y_pred = average_model.predict(X_test)
y_pred

2.7 計算評估指標

from sklearn import metrics
y_pred_list = y_pred.tolist() # 或者 y_pred_array = np.array(y_pred)
mse = metrics.mean_squared_error(test_y, y_pred_list)
rmse = np.sqrt(mse)
mae = metrics.mean_absolute_error(test_y, y_pred_list)
r2 = metrics.r2_score(test_y, y_pred_list)

print("均方誤差 (MSE):", mse)
print("均方根誤差 (RMSE):", rmse)
print("平均絕對誤差 (MAE):", mae)
print("擬合優度 (R-squared):", r2)

2.8 可視化預測結果

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 反歸一化
train_min = np.min(y_train)
train_max = np.max(y_train)
pred = y_pred * (train_max - train_min) + train_min
y_test = np.array(y_test)
plt.figure(figsize=(8, 8), dpi=300)
# 計算預測值 真實值差值的絕對值
alpha_values = abs(pred-y_test.reshape(-1)) # 值越大alpha越大
# 確保 alpha 值在 0 到 1 之間
alpha_values = np.clip(alpha_values, 0, 1)
plt.scatter(pred, y_test, color='blue', edgecolor='k', s=50, alpha=alpha_values, label='預測值 vs 真實值')
plt.title('預測值與真實值對比圖', fontsize=16)
plt.xlabel('預測值', fontsize=14)
plt.ylabel('真實值', fontsize=14)
max_val = max(max(pred), max(y_test))
min_val = min(min(pred), min(y_test))
plt.plot([min_val, max_val], [min_val, max_val], color='red', linestyle='--', linewidth=2, label='x=y')
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()
plt.show()

圖中橫軸表示模型預測的值,縱軸表示真實的標簽值,每個點的透明度(alpha 值)根據預測值與真實值的差異大小動態調整,差異越大的點透明度越低,紅色虛線表示理想情況下預測值等于真實值的對角線。

文章轉自微信公眾號@Python機器學習AI

上一篇:

SVM多分類分析:SHAP解釋各類別下各特征對模型的影響力

下一篇:

探討EMD數據泄露問題的時序預測模型:EMD-CNN-LSTM實現與分析

我們有何不同?

API服務商零注冊

多API并行試用

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

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

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

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

#AI深度推理大模型API

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

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