提升演算法的核心概念是結合多個弱學習器以構建強學習器,但容易過擬合。透過正則化技術,例如 L1 和 L2 正則化,可以有效控制模型複雜度,避免過擬合。交叉驗證是評估模型泛化能力的重要手段,透過將資料集分割成訓練集和驗證集,可以更準確地評估模型的效能。XGBoost 作為一種高效的提升演算法實作,提供了豐富的超引數,可以根據實際問題進行調整。理解這些超引數的意義和作用,並結合交叉驗證進行調優,是構建高效能 XGBoost 模型的關鍵。此外,無監督學習方法,如 PCA,可以有效降低資料維度,提取關鍵特徵,並應用於預測模型中,提升模型的效率和可解釋性。
提升演算法的正則化與交叉驗證
在機器學習中,提升演算法(Boosting)是一種透過組合多個弱學習器來建立強學習器的技術。XGBoost是一種流行的提升演算法實作,它提供了多種正則化技術來防止過擬合。
使用ntreelimit引數評估模型
在R語言中,predict方法提供了一個便利的引數ntreelimit,強制只使用前i棵樹進行預測。這使得我們可以直接比較樣本內和樣本外的錯誤率隨著模型數量的增加而變化的情況。
error_default <- rep(0, 250)
error_penalty <- rep(0, 250)
for(i in 1:250){
pred_def <- predict(xgb_default, predictors[test_idx,], ntreelimit=i)
error_default[i] <- mean(abs(label[test_idx] - pred_def) >= 0.5)
pred_pen <- predict(xgb_penalty, predictors[test_idx,], ntreelimit=i)
error_penalty[i] <- mean(abs(label[test_idx] - pred_pen) >= 0.5)
}
內容解密:
- 使用
predict方法並設定ntreelimit=i來限制使用的樹數量。 - 計算預測值與真實值之間的絕對誤差,並評估錯誤率。
- 分別對預設模型和正則化模型進行評估。
在Python中,我們可以使用predict_proba方法並傳入ntree_limit引數來實作類別似的功能。
results = []
for i in range(1, 250):
train_default = xgb_default.predict_proba(train_X, ntree_limit=i)[:, 1]
train_penalty = xgb_penalty.predict_proba(train_X, ntree_limit=i)[:, 1]
pred_default = xgb_default.predict_proba(valid_X, ntree_limit=i)[:, 1]
pred_penalty = xgb_penalty.predict_proba(valid_X, ntree_limit=i)[:, 1]
results.append({
'iterations': i,
'default train': np.mean(abs(train_y - train_default) > 0.5),
'penalty train': np.mean(abs(train_y - train_penalty) > 0.5),
'default test': np.mean(abs(valid_y - pred_default) > 0.5),
'penalty test': np.mean(abs(valid_y - pred_penalty) > 0.5),
})
results = pd.DataFrame(results)
內容解密:
- 使用
predict_proba方法並設定ntree_limit=i來限制使用的樹數量。 - 計算訓練集和驗證集上的錯誤率。
- 將結果儲存在DataFrame中以便後續分析。
繪製錯誤率曲線
透過結合樣本內和樣本外的錯誤率,我們可以繪製錯誤率隨迭代次數變化的曲線。
errors <- rbind(xgb_default$evaluation_log,
xgb_penalty$evaluation_log,
data.frame(iter=1:250, train_error=error_default),
data.frame(iter=1:250, train_error=error_penalty))
errors$type <- rep(c('default train', 'penalty train',
'default test', 'penalty test'), rep(250, 4))
ggplot(errors, aes(x=iter, y=train_error, group=type)) +
geom_line(aes(linetype=type, color=type))
內容解密:
- 合併不同模型的錯誤率資料。
- 使用ggplot2繪製錯誤率曲線。
- 不同模型和資料集的錯誤率曲線使用不同的線型和顏色。
在Python中,我們可以使用pandas的plot方法來建立類別似的曲線圖。
ax = results.plot(x='iterations', y='default test')
results.plot(x='iterations', y='penalty test', ax=ax)
results.plot(x='iterations', y='default train', ax=ax)
results.plot(x='iterations', y='penalty train', ax=ax)
內容解密:
- 使用pandas的
plot方法繪製錯誤率曲線。 - 將不同模型的錯誤率曲線繪製在同一張圖上。
Ridge迴歸和Lasso迴歸
Ridge迴歸和Lasso迴歸是兩種常見的正則化技術,用於防止過擬合。Ridge迴歸使用L2正則化,而Lasso迴歸使用L1正則化。
Ridge迴歸
Ridge迴歸透過在損失函式中新增係數的平方和來正則化模型。
Lasso迴歸
Lasso迴歸透過在損失函式中新增係數的絕對值和來正則化模型。
XGBoost中的lambda和alpha引數分別對應於L2和L1正則化。
超引數調優和交叉驗證
XGBoost有多個超引數需要調優。交叉驗證是一種常用的調優方法,透過將資料分成多個折疊(fold),在每個折疊上訓練和評估模型,以評估模型的效能。
N <- nrow(loan_data)
fold_number <- sample(1:5, N, replace=TRUE)
params <- data.frame(eta = rep(c(.1, .5, .9), 3),
max_depth = rep(c(3, 6, 12), rep(3,3)))
error <- matrix(0, nrow=9, ncol=5)
for(i in 1:nrow(params)){
for(k in 1:5){
fold_idx <- (1:N)[fold_number == k]
xgb <- xgboost(data=predictors[-fold_idx,], label=label[-fold_idx],
params=list(eta=params[i, 'eta'],
max_depth=params[i, 'max_depth']),
objective='binary:logistic', nrounds=100, verbose=0)
pred <- predict(xgb, predictors[fold_idx,])
error[i, k] <- mean(abs(label[fold_idx] - pred) >= 0.5)
內容解密:
- 將資料分成5個折疊。
- 定義超引數網格。
- 在每個折疊上訓練XGBoost模型並評估其效能。
- 將評估結果儲存在矩陣中。
使用Python進行超引數調優的XGBoost分類別器
在以下Python程式碼中,我們建立了超引數的所有可能組合,並對每個組合進行模型擬合和評估:
import numpy as np
import pandas as pd
from itertools import product
from xgboost import XGBClassifier
# 假設X和y是我們的特徵和目標變數
idx = np.random.choice(range(5), size=len(X), replace=True)
error = []
for eta, max_depth in product([0.1, 0.5, 0.9], [3, 6, 9]):
xgb = XGBClassifier(objective='binary:logistic', n_estimators=250,
max_depth=max_depth, learning_rate=eta)
cv_error = []
for k in range(5):
fold_idx = idx == k
train_X = X.loc[~fold_idx]; train_y = y[~fold_idx]
valid_X = X.loc[fold_idx]; valid_y = y[fold_idx]
xgb.fit(train_X, train_y)
pred = xgb.predict_proba(valid_X)[:, 1]
cv_error.append(np.mean(abs(valid_y - pred) > 0.5))
error.append({
'eta': eta,
'max_depth': max_depth,
'avg_error': np.mean(cv_error)
})
print(error[-1])
errors = pd.DataFrame(error)
內容解密:
- 超引陣列合生成:使用
itertools.product生成eta和max_depth的所有可能組合,分別為[0.1, 0.5, 0.9]和[3, 6, 9]。 - XGBoost模型初始化:根據每個超引陣列合初始化
XGBClassifier,目標函式設為二元邏輯迴歸,樹的數量設為250。 - 交叉驗證:進行5折交叉驗證,計算每個模型的平均錯誤率。
- 錯誤率計算:對於每個模型,計算預測值與真實值之間的絕對誤差,並將平均錯誤率儲存在
error列表中。 - 結果儲存與輸出:將每個模型的超引數和平均錯誤率儲存在字典中,並列印預出來,最終將結果轉換為Pandas DataFrame。
XGBoost超引數解析
XGBoost的超引數主要用於平衡過擬合、準確性和計算複雜度。
eta/learning_rate:在提升演算法中應用的收縮因子,預設值為0.3,但對於噪聲資料,建議使用較小的值(如0.1)。在Python中,預設值為0.1。nrounds/n_estimators:提升輪數。如果eta設為較小的值,則需要增加輪數,因為演算法學習速度較慢。只要有一些引數可以防止過擬合,增加輪數不會造成傷害。max_depth:樹的最大深度,預設值為6。與隨機森林不同,提升通常擬合較淺的樹,以避免由於噪聲資料引起的複雜互動作用。在Python中,預設值為3。subsample和colsample_bytree:無放回抽樣的記錄比例和用於擬合樹的預測變數比例。這些引數與隨機森林中的類別似,有助於避免過擬合。預設值為1.0。lambda/reg_lambda和alpha/reg_alpha:正則化引數,有助於控制過擬合。在Python中,預設值分別為reg_lambda=1和reg_alpha=0。
關鍵概念
- 提升是一種根據擬合一系列模型的整合模型,在連續的輪次中,對誤差較大的記錄賦予更大的權重。
- 隨機梯度提升是最一般的提升型別,並提供最佳效能。最常見的隨機梯度提升形式使用樹模型。
- XGBoost是一種流行的、計算高效的隨機梯度提升軟體包,可在資料科學中使用的所有常見語言中使用。
- 提升容易過擬合資料,需要調整超引數以避免過擬合。
- 正則化是一種透過在模型中包含對引數數量(如樹大小)的懲罰項來避免過擬合的方法。
- 由於需要設定的大量超引數,交叉驗證對於提升尤為重要。
無監督學習簡介
無監督學習是指從資料中提取意義的統計方法,而不需要在標記資料上訓練模型。在第4章到第6章中,目標是建立一個模型(規則集)來從預測變數預測回應變數。這是有監督學習。相比之下,無監督學習也構建了資料的模型,但它不區分回應變數和預測變數。
無監督學習可以用於實作不同的目標。在某些情況下,它可以用於在沒有標記回應的情況下建立預測規則。聚類別方法可用於識別有意義的資料組。例如,使用網站上使用者的網頁點選和人口統計資料,我們可能能夠將不同型別的使用者分組。然後可以根據這些不同型別對網站進行個人化設定。
在其他情況下,目標可能是將資料的維度減少到更易於管理的變數集。然後,可以將這個縮減的集合用作預測模型(如迴歸或分類別)的輸入。例如,我們可能有成千上萬的感測器來監控工業過程。透過將資料減少到較小的特徵集,我們可能能夠構建一個更強大、更可解釋的模型來預測過程故障,而不是包含來自成千上萬個感測器的資料流。
最後,無監督學習可以被視為將探索性資料分析(見第1章)擴充套件到面對大量變數和記錄的情況。目標是深入瞭解一組資料以及不同變數之間的關係。無監督技術允許您篩選和分析這些變數,並發現關係。
無監督學習在預測中的重要性
無監督學習在迴歸和分類別問題的預測中扮演著重要角色。在某些情況下,我們需要在沒有標籤資料的情況下進行類別預測。例如,我們可能希望根據一系列衛星感測器資料預測某個地區的植被型別。由於我們沒有可用的回應變數來訓練模型,聚類別分析提供了一種方法來識別共同模式並對區域進行分類別。
聚類別分析的應用
聚類別分析是一種特別重要的工具,用於解決「冷啟動問題」。在這種問題中,例如發起新的行銷活動或識別潛在的新型詐騙或垃圾郵件,我們最初可能沒有任何可用於訓練模型的回應資料。隨著資料的收集,我們可以瞭解更多關於系統的資訊並建立傳統的預測模型。然而,聚類別分析幫助我們更快地啟動學習過程,透過識別人口細分。
無監督學習的重要性
無監督學習對於迴歸和分類別技術來說也是非常重要的基本組成部分。在大資料的情況下,如果某些小群體在整體人口中沒有得到很好的代表,訓練出的模型可能對這些小群體表現不佳。透過聚類別分析,可以識別和標記這些小群體。然後,可以為不同的小群體擬合不同的模型。或者,可以用自己的特徵來表示小群體,強制整體模型明確考慮小群體身份作為預測因子。
主成分分析(PCA)
通常,變數之間會共同變化(共變),其中一些變數的變化實際上是被其他變數的變化所重複的。主成分分析(PCA)是一種技術,用於發現數值變數之間的共變方式。
主成分分析的關鍵術語
- 主成分:預測變數的線性組合。
- 載荷:將預測變數轉換為主成分的權重。
- 碎石圖:主成分的方差圖,顯示了主成分的相對重要性,無論是作為解釋方差還是解釋方差的比例。
PCA 的思想是將多個數值預測變陣列合成一個較小的變數集合,這些變數是原始集合的加權線性組合。較小的變數集合,即主成分,「解釋」了大部分原始集合的可變性,從而降低了資料的維度。形成主成分所使用的權重揭示了原始變數對新主成分的相對貢獻。
簡單示例
對於兩個變數 $X_1$ 和 $X_2$,有兩個主成分 $Z_i$($i = 1$ 或 $2$): [ Z_i = w_{i,1}X_1 + w_{i,2}X_2 ] 權重 $w_{i,1}$、$w_{i,2}$ 被稱為成分載荷。這些載荷將原始變數轉換為主成分。第一個主成分 $Z_1$ 是最能解釋總變異的線性組合。第二個主成分 $Z_2$ 與第一個正交,並盡可能多地解釋剩餘的變異。
oil_px <- sp500_px[, c('CVX', 'XOM')]
pca <- princomp(oil_px)
pca$loadings
內容解密:
- 使用
princomp函式對 Chevron(CVX)和 ExxonMobil(XOM)的股票價格回報進行主成分分析。 pca$loadings輸出主成分的載荷,第一主成分基本上是 CVX 和 XOM 的平均值,反映了兩家能源公司之間的相關性。- 第二主成分衡量 CVX 和 XOM 股票價格之間的差異。
pcs = PCA(n_components=2)
pcs.fit(oil_px)
loadings = pd.DataFrame(pcs.components_, columns=oil_px.columns)
loadings
內容解密:
- 使用 scikit-learn 的
PCA對 CVX 和 XOM 的股票價格回報進行主成分分析。 loadingsDataFrame 顯示了主成分的載荷,第一主成分是 CVX 和 XOM 的平均值,第二主成分衡量兩者之間的差異。
視覺化主成分
透過將主成分與資料一起繪製,可以更好地理解其意義。以下是在 R 和 Python 中建立視覺化的程式碼:
loadings <- pca$loadings
ggplot(data=oil_px, aes(x=CVX, y=XOM)) +
geom_point(alpha=.3) +
stat_ellipse(type='norm', level=.99) +
geom_abline(intercept = 0, slope = loadings[2,1]/loadings[1,1]) +
geom_abline(intercept = 0, slope = loadings[2,2]/loadings[1,2])
def abline(slope, intercept, ax):
"""Calculate coordinates of a line based on slope and intercept"""
x_vals = np.array(ax.get_xlim())
return (x_vals, intercept + slope * x_vals)
ax = oil_px.plot.scatter(x='XOM', y='CVX', alpha=0.3, figsize=(4, 4))
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
ax.plot(*abline(loadings.loc[0, 'CVX'] / loadings.loc[0, 'XOM'], 0, ax),
'--', color='C1')
ax.plot(*abline(loadings.loc[1, 'CVX'] / loadings.loc[1, 'XOM'], 0, ax),
'--', color='C1')
內容解密:
- 圖中虛線表示兩個主成分的方向,第一個主成分沿著橢圓的長軸,第二個主成分沿著短軸。
- 大部分變異由第一個主成分解釋,這反映了能源股票價格傾向於一起變動的事實。