終于把機器學習中的交叉驗證搞懂了??!
今天給大家分享機器學習中的一個關鍵概念,交叉驗證。
交叉驗證(Cross-Validation)是機器學習中一種廣泛使用的模型評估方法,用于評估預測模型在未見數據上的表現。
它通過將數據集劃分為多個子集,重復訓練和驗證模型,以減少評估結果的方差并提供更穩定、可靠的性能估計。交叉驗證能夠更可靠地估計模型的泛化能力,減少由于數據分割方式不同帶來的評估偏差。
基本原理
1.數據劃分
將原始數據集劃分為多個部分,通常稱為“折”(folds)。
2.循環驗證
每次迭代中,將一個折作為驗證集(測試集),其余折作為訓練集。模型在訓練集上訓練后,在驗證集上評估性能。
3.綜合結果
對所有迭代的評估結果(例如準確率、精度、召回率等)取平均值,作為模型的整體性能。
通過這種方式,可以減少因單一訓練/測試分割可能帶來的隨機性和偏差,提供對模型性能更穩健的估計。
交叉驗證的應用
模型選擇
通過交叉驗證評估不同模型的性能,從而選擇最優的模型。
例如,在分類問題中,可以通過K折交叉驗證比較邏輯回歸、支持向量機和隨機森林等模型的準確率,選擇表現最佳的模型。
超參數調優
許多機器學習模型具有超參數,需要通過調優來優化模型性能。
交叉驗證可以用于評估不同超參數組合下的模型表現,從而選擇最佳的超參數。
例如,支持向量機中的核函數參數和正則化參數,可以通過交叉驗證找到最佳組合。
特征選擇
在高維數據中,選擇相關特征對于提高模型性能至關重要。
交叉驗證可以用于評估不同特征子集下的模型表現,幫助選擇最具預測能力的特征組合。
常見的交叉驗證技術
1.k 折交叉驗證
k 折交叉驗證是最常用的交叉驗證方法之一,通過將數據集分成 k 個相等或近似相等的子集(folds,折),并進行 k 次訓練和驗證,以評估模型的性能。
步驟:
- 將數據隨機劃分為 K 個非重疊子集。
- 在第 i 次迭代中
- 使用第 i 個子集作為驗證集。
- 使用其他 K-1 個子集作為訓練集。
- 計算每次迭代的性能指標。
- 取所有迭代的性能指標的平均值作為最終評估結果。
適用場景
適用于大多數機器學習任務,尤其是數據量中等且對計算效率要求不苛刻的場景。
優缺點:
優點
- 實現簡單,廣泛支持于各類機器學習框架。
- 每個樣本都被用作訓練集和驗證集,充分利用了數據。
缺點
- 計算成本較高,尤其當 K 較大時。
from sklearn.model_selection import KFold
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import numpy as np
# 創建示例數據
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
# 初始化模型
model = RandomForestClassifier()
# K-Fold Cross Validation
kf = KFold(n_splits=5)
accuracies = []
for train_index, test_index in kf.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracies.append(accuracy_score(y_test, y_pred))
print("K-Fold Accuracies:", accuracies)
print("Mean Accuracy:", np.mean(accuracies))
2.留一法交叉驗證
留一法交叉驗證是 k 折交叉驗證的極端情況,其中 k 等于樣本數量。
每次迭代中,選擇一個樣本作為驗證集,其余所有樣本作為訓練集。
步驟:
- 數據集中有 N 個樣本。
- 每次迭代中:
- 使用 N-1 個樣本作為訓練集。
- 剩余 1 個樣本作為驗證集。
- 計算 N 次迭代的性能指標,并取平均值作為最終評估結果。
適用場景
適用于數據量較小的場景,尤其是在希望最大限度利用訓練數據時。
優缺點
優點
- 理論上提供模型的無偏估計。
- 最大限度地利用了訓練數據,每次訓練使用 n-1 個樣本,特別適用于小數據集。
缺點
- 計算成本非常高(N 次模型訓練)。
- 對異常值非常敏感,可能導致性能波動。
from sklearn.model_selection import LeaveOneOut
# Leave-One-Out Cross Validation
loo = LeaveOneOut()
accuracies = []
for train_index, test_index in loo.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracies.append(accuracy_score(y_test, y_pred))
print("LOOCV Mean Accuracy:", np.mean(accuracies))
3.分層 K 折交叉驗證
分層 k 折交叉驗證是 k 折交叉驗證的一個變種,特別適用于分類任務,
通過保持每個折中各類別的比例與整個數據集一致,確保模型在訓練和驗證過程中能夠見到各類別的代表性樣本。
步驟
- 根據數據的類別分布,將數據分為 K 個子集,保證每個子集的類別分布與原始數據集一致。
- 像普通 K折交叉驗證一樣進行模型訓練和驗證。
適用場景
適用于分類任務,尤其是當目標變量類別分布不平衡時。
優缺點
優點:
- 提供更公正的性能估計。
- 避免因類別不平衡而導致性能評估偏差。
缺點:
- 需要額外的分層處理,復雜性稍高。
from sklearn.model_selection import StratifiedKFold
# Stratified K-Fold
skf = StratifiedKFold(n_splits=5)
accuracies = []
for train_index, test_index in skf.split(X, y):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracies.append(accuracy_score(y_test, y_pred))
print("Stratified K-Fold Accuracies:", accuracies)
print("Mean Accuracy:", np.mean(accuracies))
4.重復k折交叉驗證
重復 k 折交叉驗證通過多次隨機劃分k折交叉驗證,提高評估結果的穩定性和可靠性。每次重復都會隨機打亂數據集并重新劃分 k 折。
步驟
1.設定重復次數
選擇重復的次數(如重復10次)。
2.多次k折劃分
對于每次重復,隨機打亂數據集并進行 k 折交叉驗證。
3.匯總結果
收集所有重復的 k 次評估結果,計算總體的平均性能和方差。
適用場景
當需要更精確和穩健的模型評估,且計算資源允許時。
優缺點
優點
- 通過多次不同的劃分,減少單次 k 折交叉驗證可能引入的偏差和方差。
- 多次重復提供了更穩健的性能估計。
缺點
- 相對于單次 k 折交叉驗證,重復 k 折需要更多的計算資源和時間。
from sklearn.model_selection import RepeatedKFold
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import numpy as np
# 創建示例數據
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
# 初始化模型
model = RandomForestClassifier()
# Repeated K-Fold Cross Validation
rkf = RepeatedKFold(n_splits=5, n_repeats=3, random_state=42) # 5 折,重復 3 次
accuracies = []
for train_index, test_index in rkf.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracies.append(accuracy_score(y_test, y_pred))
print("Repeated K-Fold Accuracies:", accuracies)
print("Mean Accuracy:", np.mean(accuracies))
5.時間序列交叉驗證
時間序列交叉驗證專門用于時間序列數據,保持時間順序,避免未來信息泄露到訓練集中。
常見的方法包括滾動窗口(Rolling Window)和擴展窗口(Expanding Window)。
滾動窗口交叉驗證
滾動窗口法通過固定大小的訓練集窗口,隨著時間的推進,窗口向前滑動,包含最新的數據,同時排除最早的數據。
1.初始劃分
選擇一個固定長度的訓練集(例如前 60 個月的數據)和一個固定長度的驗證集(例如接下來的1個月)。
2.訓練與驗證
- 使用初始訓練集訓練模型。
- 在驗證集上評估模型性能。
- 滾動窗口:將訓練集窗口向前滑動一個時間步長(例如一個月),包含最新的數據,排除最早的數據。
- 重復訓練與驗證過程,直到覆蓋整個數據集。
3.結果匯總
計算所有驗證階段的性能指標的平均值,作為模型的最終評估結果。
擴展窗口交叉驗證
擴展窗口法從固定的初始訓練集開始,隨著時間的推進,訓練集不斷擴大,包含所有之前的歷史數據。
- 初始劃分
選擇一個初始長度的訓練集(例如前60個月的數據)和一個固定長度的驗證集(例如接下來的1個月)。 - 訓練與驗證
- 使用初始訓練集訓練模型。
- 在驗證集上評估模型性能。
- 擴展訓練集:將驗證集的數據加入訓練集。
- 選擇下一個時間步長作為新的驗證集。
- 重復訓練與驗證過程,直到覆蓋整個數據集。
- 結果匯總
計算所有驗證階段的性能指標的平均值,作為模型的最終評估結果。
適用場景
時間序列預測、金融數據分析、任何需要考慮時間依賴性的任務。
優缺點
優點
- 保持時間順序:防止未來數據泄露,提高評估的真實性。
缺點
- 實現復雜:需要根據具體的時間序列特性設計窗口策略。
- 參數選擇敏感:窗口大小和步長等參數選擇對結果影響較大。
from sklearn.model_selection import TimeSeriesSplit
import numpy as np
# 創建示例數據
X = np.arange(1000).reshape(-1, 1) # 示例特征數據
y = np.arange(1000) # 示例目標值
# 初始化模型
model = RandomForestClassifier()
# Time Series Split
tscv = TimeSeriesSplit(n_splits=5) # 5 個時間序列劃分
accuracies = []
for train_index, test_index in tscv.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracies.append(accuracy_score(y_test, y_pred))
print("Time Series Split Accuracies:", accuracies)
print("Mean Accuracy:", np.mean(accuracies))
6.嵌套交叉驗證
嵌套交叉驗證用于同時進行模型評估和超參數調優,避免在調參過程中引入評估偏差。
其結構包含內層交叉驗證用于超參數選擇,外層交叉驗證用于模型性能評估。
嵌套交叉驗證的工作流程
- 外層交叉驗證
- 用途:用于評估模型的泛化能力。
- 過程:將數據劃分為 K 個折,依次將每個折作為驗證集,其余折作為訓練集。
- 結果:每個折計算一個性能指標(如準確率、均方誤差等),最終對 K 個性能指標求平均值,作為模型的總體性能。
- 內層交叉驗證
- 用途:用于超參數調優。
- 過程:在外層訓練集的基礎上再次劃分為 M 個折,依次將每個折作為驗證集,其余折作為訓練集。
- 結果:對所有超參數組合進行測試,選擇在內層驗證集上性能最優的超參數。
步驟
假設使用 K 折外層交叉驗證和 M 折內層交叉驗證。
1.將數據劃分為 K 個外層折。
2.在第 i 個外層折中
- 將外層訓練集劃分為 M 個內層折。
- 在每個內層折上,調整模型超參數,選擇最佳參數組合。
- 將第 i 折作為驗證集,其他 K-1 折作為外層訓練集。
- 對外層訓練集進行內層交叉驗證
- 用內層交叉驗證得到的最佳參數,在外層訓練集上訓練模型。
- 在外層驗證集上評估模型性能。
3.重復 K 次外層交叉驗證。
4.對 K 次外層驗證集的性能結果求平均,得到模型的最終評估指標。
適用場景
需要同時進行模型選擇、超參數調優和性能評估的復雜任務。
from sklearn.model_selection import KFold, GridSearchCV, cross_val_score
from sklearn.datasets import make_classification
from sklearn.svm import SVC
# 創建示例數據
X, y = make_classification(n_samples=500, n_features=20, random_state=42)
# 定義超參數搜索范圍
param_grid = {
'C': [0.1, 1, 10],
'kernel': ['linear', 'rbf']
}
# 外層交叉驗證 (用于評估模型性能)
outer_cv = KFold(n_splits=5, shuffle=True, random_state=42)
# 初始化模型和內層 Grid Search
model = SVC()
inner_cv = KFold(n_splits=3, shuffle=True, random_state=42)
grid_search = GridSearchCV(estimator=model, param_grid=param_grid, cv=inner_cv)
# 嵌套交叉驗證
nested_scores = cross_val_score(grid_search, X, y, cv=outer_cv)
print("Nested Cross-Validation Scores:", nested_scores)
print("Mean Nested CV Accuracy:", nested_scores.mean())
交叉驗證的優缺點
優點
- 提供更穩定和可靠的性能評估,減少因數據劃分帶來的偏差。
- 有效利用有限的數據,特別適用于小數據集。
- 可以用于模型選擇、超參數調優和特征選擇,提升模型性能。
缺點
- 計算成本較高,尤其是數據量大或 K 值較大時。
- 可能對模型的訓練時間要求較高,不適用于實時或大規模數據場景。
- 不同的交叉驗證方法適用的場景不同,選擇不當可能影響評估結果的有效性。