import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel('california.xlsx')

from sklearn.model_selection import train_test_split

X = df.drop(['price'],axis=1)
y = df['price']

X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 然后將訓(xùn)練集進(jìn)一步劃分為訓(xùn)練集和驗(yàn)證集
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

# 數(shù)據(jù)集標(biāo)準(zhǔn)化
x_mean = X_train.mean()
x_std = X_train.std()
y_mean = y.mean()
y_std = y.std()
X_train = (X_train - x_mean)/x_std
y_train = (y_train-y_mean)/y_std
X_val = (X_val - x_mean)/x_std
y_val = (y_val - y_mean)/y_std
X_test = (X_test - x_mean)/x_std
y_test = (y_test - y_mean)/y_std

對(duì)加利福尼亞房?jī)r(jià)數(shù)據(jù)集進(jìn)行處理,首先將數(shù)據(jù)集分割為訓(xùn)練集、驗(yàn)證集和測(cè)試集,然后對(duì)特征和目標(biāo)變量進(jìn)行標(biāo)準(zhǔn)化,以確保不同特征在同一尺度上進(jìn)行模型訓(xùn)練和評(píng)估

模型參數(shù)定義

LightGBM模型參數(shù)

from ngboost import NGBRegressor
from catboost import CatBoostRegressor
import lightgbm as lgb
import xgboost as xgb

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

XGBoost模型參數(shù)

# XGBoost模型參數(shù)
params_xgb = {
'learning_rate': 0.02, # 學(xué)習(xí)率,控制每一步的步長(zhǎng),用于防止過(guò)擬合。典型值范圍:0.01 - 0.1
'booster': 'gbtree', # 提升方法,這里使用梯度提升樹(shù)(Gradient Boosting Tree)
'objective': 'reg:squarederror', # 損失函數(shù),這里使用平方誤差
'max_leaves': 127, # 每棵樹(shù)的葉子節(jié)點(diǎn)數(shù)量,控制模型復(fù)雜度。較大值可以提高模型復(fù)雜度但可能導(dǎo)致過(guò)擬合
'verbosity': 1, # 控制 XGBoost 輸出信息的詳細(xì)程度,0表示無(wú)輸出,1表示輸出進(jìn)度信息
'seed': 42, # 隨機(jī)種子,用于重現(xiàn)模型的結(jié)果
'nthread': -1, # 并行運(yùn)算的線程數(shù)量,-1表示使用所有可用的CPU核心
'colsample_bytree': 0.6, # 每棵樹(shù)隨機(jī)選擇的特征比例,用于增加模型的泛化能力
'subsample': 0.7, # 每次迭代時(shí)隨機(jī)選擇的樣本比例,用于增加模型的泛化能力
'early_stopping_rounds': 100, # 早停輪數(shù),在驗(yàn)證集上性能不提升時(shí)提前停止訓(xùn)練
'eval_metric': 'rmse' # 評(píng)估指標(biāo),這里使用均方根誤差(Root Mean Squared Error,簡(jiǎn)稱(chēng)RMSE)
}
model_xgb = xgb.XGBRegressor(**params_xgb)

CatBoost模型參數(shù)

# CatBoost模型參數(shù)
params_cat = {
'learning_rate': 0.02, # 學(xué)習(xí)率,控制每一步的步長(zhǎng),用于防止過(guò)擬合。典型值范圍:0.01 - 0.1
'iterations': 1000, # 弱學(xué)習(xí)器(決策樹(shù))的數(shù)量
'depth': 6, # 決策樹(shù)的深度,控制模型復(fù)雜度
'eval_metric': 'RMSE', # 評(píng)估指標(biāo),這里使用均方根誤差(Root Mean Squared Error,簡(jiǎn)稱(chēng)RMSE)
'random_seed': 42, # 隨機(jī)種子,用于重現(xiàn)模型的結(jié)果
'verbose': 100 # 控制CatBoost輸出信息的詳細(xì)程度,每100次迭代輸出一次
}
model_cat = CatBoostRegressor(**params_cat)

NGBoost模型參數(shù)

# NGBoost模型參數(shù)
params_ngb = {
'learning_rate': 0.02, # 學(xué)習(xí)率,控制每一步的步長(zhǎng),用于防止過(guò)擬合
'n_estimators': 1000, # 弱學(xué)習(xí)器(決策樹(shù))的數(shù)量
'verbose': False, # 控制NGBoost輸出信息的詳細(xì)程度
'random_state': 42, # 隨機(jī)種子,用于重現(xiàn)模型的結(jié)果
'natural_gradient': True # 是否使用自然梯度來(lái)更新模型參數(shù)
}
model_ngb = NGBRegressor(**params_ngb)

模型訓(xùn)練

# 定義平均模型
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)], verbose=False)
elif isinstance(model, CatBoostRegressor):
model.fit(X, y, eval_set=(X_val, y_val), use_best_model=True, verbose=False)
elif isinstance(model, NGBRegressor):
model.fit(X, y, X_val=X_val, Y_val=y_val)

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

# 創(chuàng)建平均模型
average_model_four = AverageModel([model_lgb, model_xgb, model_cat, model_ngb])

# 訓(xùn)練模型
average_model_four.fit(X_train, y_train, X_val, y_val)

定義了一個(gè)名為 AverageModel 的類(lèi),用于創(chuàng)建一個(gè)平均模型,通過(guò)集成四個(gè)模型的預(yù)測(cè)結(jié)果來(lái)提升預(yù)測(cè)的穩(wěn)定性和準(zhǔn)確性,在 fit 方法中,該類(lèi)可以同時(shí)訓(xùn)練傳入的多個(gè)模型,并使用驗(yàn)證集進(jìn)行早期停止策略來(lái)防止過(guò)擬合,在 predict 方法中,該類(lèi)將多個(gè)模型的預(yù)測(cè)結(jié)果取平均作為最終的預(yù)測(cè)輸出

模型預(yù)測(cè)及評(píng)價(jià)

# 預(yù)測(cè)
y_pred_four = average_model_four.predict(X_test)

y_pred_list = y_pred_four.tolist()
mse = metrics.mean_squared_error(y_test, y_pred_list)
rmse = np.sqrt(mse)
mae = metrics.mean_absolute_error(y_test, y_pred_list)
r2 = metrics.r2_score(y_test, y_pred_list)

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

集成CatBoost與NGBoost模型

# 定義平均模型
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, NGBRegressor):
model.fit(X, y, X_val=X_val, Y_val=y_val) # NGBoost的fit方法接受驗(yàn)證集參數(shù)
elif isinstance(model, CatBoostRegressor):
model.fit(X, y, eval_set=(X_val, y_val), use_best_model=True, verbose=False)

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

# 創(chuàng)建平均模型
average_model_two = AverageModel([model_ngb, model_cat])

# 訓(xùn)練模型
average_model_two.fit(X_train, y_train, X_val, y_val)

# 預(yù)測(cè)
y_pred_two = average_model_two.predict(X_test)

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

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

由于前文梯度提升集成:LightGBM與XGBoost組合預(yù)測(cè)定義過(guò)常見(jiàn)的LightGBM與XGBoost模型,這里我們?cè)俣x并訓(xùn)練了一個(gè)只包含NGBoost和CatBoost的平均模型,通過(guò)在訓(xùn)練和驗(yàn)證數(shù)據(jù)集上分別訓(xùn)練這兩個(gè)模型,再對(duì)測(cè)試集進(jìn)行預(yù)測(cè),并計(jì)算均方誤差(MSE)、均方根誤差(RMSE)、平均絕對(duì)誤差(MAE)和擬合優(yōu)度(R-squared),以評(píng)估組合模型的預(yù)測(cè)性能

可以發(fā)現(xiàn)在這個(gè)數(shù)據(jù)集上,NGBoost和CatBoost的平均模型的擬合優(yōu)度(R-squared)相對(duì)于LightGBM、XGBoost、CatBoost和NGBoost的集成模型較好,可能是由于這兩個(gè)模型在這個(gè)數(shù)據(jù)集上的數(shù)據(jù)特征提取和預(yù)測(cè)方面具有更好的互補(bǔ)性和適應(yīng)性,同時(shí)避免了過(guò)多模型組合可能帶來(lái)的復(fù)雜度和過(guò)擬合問(wèn)題。當(dāng)然,讀者也可以自行選擇不同的模型進(jìn)行集成,并給不同的模型賦予不同的權(quán)重來(lái)進(jìn)一步優(yōu)化模型性能

可視化預(yù)測(cè)結(jié)果

plt.figure(figsize=(15, 5), dpi=300)
plt.subplot(1, 2, 1)
# 反標(biāo)準(zhǔn)化預(yù)測(cè)值
pred_two = y_pred_two * y_std + y_mean
y_test_rescaled = np.array(y_test * y_std + y_mean)
# 計(jì)算預(yù)測(cè)值與真實(shí)值差值的絕對(duì)值
alpha_values_two = abs(pred_two - y_test_rescaled.reshape(-1))
# 確保 alpha 值在 0 到 1 之間
alpha_values_two = np.clip(alpha_values_two, 0, 1)
plt.scatter(pred_two, y_test_rescaled, color='blue', edgecolor='k', s=50, alpha=alpha_values_two, label='預(yù)測(cè)值 vs 真實(shí)值')
plt.title('two model 預(yù)測(cè)值與真實(shí)值對(duì)比圖', fontsize=16)
plt.xlabel('預(yù)測(cè)值', fontsize=14)
plt.ylabel('真實(shí)值', fontsize=14)
max_val_two = max(max(pred_two), max(y_test_rescaled))
min_val_two = min(min(pred_two), min(y_test_rescaled))
plt.plot([min_val_two, max_val_two], [min_val_two, max_val_two], color='red', linestyle='--', linewidth=2, label='x=y')
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()

plt.subplot(1, 2, 2)
pred_four = y_pred_four * y_std + y_mean
alpha_values_four = abs(pred_four - y_test_rescaled.reshape(-1))
alpha_values_four = np.clip(alpha_values_four, 0, 1)
plt.scatter(pred_four, y_test_rescaled, color='green', edgecolor='k', s=50, alpha=alpha_values_four, label='預(yù)測(cè)值 vs 真實(shí)值')
plt.title('four model 預(yù)測(cè)值與真實(shí)值對(duì)比圖', fontsize=16)
plt.xlabel('預(yù)測(cè)值', fontsize=14)
plt.ylabel('真實(shí)值', fontsize=14)
max_val_four = max(max(pred_four), max(y_test_rescaled))
min_val_four = min(min(pred_four), min(y_test_rescaled))
plt.plot([min_val_four, max_val_four], [min_val_four, max_val_four], color='red', linestyle='--', linewidth=2, label='x=y')
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()

plt.show()

兩幅可視化分別為NGBoost和CatBoost集成模型、LightGBM、XGBoost、CatBoost和NGBoost集成模型的可視化,圖中橫軸表示模型預(yù)測(cè)的值,縱軸表示真實(shí)的標(biāo)簽值,每個(gè)點(diǎn)的透明度(alpha 值)根據(jù)預(yù)測(cè)值與真實(shí)值的差異大小動(dòng)態(tài)調(diào)整,差異越大的點(diǎn)透明度越低,紅色虛線表示理想情況下預(yù)測(cè)值等于真實(shí)值的對(duì)角線

文章轉(zhuǎn)自微信公眾號(hào)@Python機(jī)器學(xué)習(xí)AI

上一篇:

統(tǒng)計(jì)檢驗(yàn)——T檢驗(yàn)分析樣本間的顯著性差異

下一篇:

決策樹(shù)和隨機(jī)森林的決策過(guò)程路徑可視化解讀

我們有何不同?

API服務(wù)商零注冊(cè)

多API并行試用

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

查看全部API→
??

熱門(mén)場(chǎng)景實(shí)測(cè),選對(duì)API

#AI文本生成大模型API

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

25個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

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

10個(gè)渠道
一鍵對(duì)比試用API 限時(shí)免費(fèi)