文章目錄
- 一、 數據集劃分:訓練集與評估集
- 二、 K 折交叉驗證:提升評估可靠性
- 1. 基本原理
- 1.1. K折交叉驗證基本原理
- 1.2. 邏輯回歸算法與L2
- 2. 基于K折交叉驗證L2算法
- 三、棄一交叉驗證(Leave-One-Out)
- 1、基本原理
- 2、代碼實現
- 四、ShuffleSplit交叉驗證
- 1、基本原理
- 2、為什么能降低方差
- 3、代碼測試
- 五、 選擇建議
在機器學習中,評估算法的核心目標是衡量模型在“未知數據”上的表現,而不是僅僅追求訓練集上的高分。只有通過科學的評估方法,我們才能判斷模型是否具備良好的泛化能力,避免“過擬合”陷阱。
因此,合理劃分數據集并選擇合適的評估策略,是每一個機器學習項目的基礎環節。
一、 數據集劃分:訓練集與評估集
常見做法是將原始數據集分為訓練集和評估集(也稱測試集),常用比例為67%訓練,33%評估。這種劃分方式簡單高效,適合數據量較大的場景。
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 導入數據
filename = 'pima_data.csv'
names = ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
data = read_csv(filename, names=names)
# 將數據分為輸入數據和輸出結果
array = data.values
X = array[:, 0:8]
Y = array[:, 8]
test_size = 0.33
seed = 4 # 將數據隨機分離
X_train, X_test, Y_traing, Y_test =
train_test_split(X, Y, test_size=test_size, random_state=seed)model = LogisticRegression() # 初始化邏輯回歸模型。
model.fit(X_train, Y_traing) # 模型進行訓練
result = model.score(X_test, Y_test)
print("算法評估結果:%.3f%%" % (result * 100))算法評估結果:80.709%
test_size=0.33
:指定33%數據作為評估集。random_state=42
:設置隨機種子,保證每次劃分結果一致,便于復現實驗。
注意:評估結果(如準確率)只能代表模型在未見過數據上的表現,不能用訓練集直接評估,否則會高估模型能力。
?
二、 K 折交叉驗證:提升評估可靠性
1. 基本原理
1.1. K折交叉驗證基本原理
當數據量有限時,單次劃分可能導致評估結果不穩定。K 折交叉驗證(K-Fold Cross Validation)通過多次劃分和訓練,有效提升評估的穩健性。
原理簡述:
- 將數據分為 K 份,每次用 K-1 份訓練,剩下1份評估。
- 重復 K 次,每份都做一次評估,最后取平均分。
?
1.2. 邏輯回歸算法與L2
邏輯回歸是一種用于二分類問題的機器學習算法。它通過一個特殊的函數(sigmoid函數)將線性組合轉換為0到1之間的概率值。
P(y=1)=1/(1+e(?z))P(y=1) = 1 / (1 + e^{(-z)}) P(y=1)=1/(1+e(?z))
其中 z = w?x? + w?x? + … + w?x? + b,這里的權重 w?, w?, ..., w?
決定了每個特征的重要性。當某個特征的權重很大時,這個特征對預測結果的影響就很大。
而L2正則化是防止它過擬合的關鍵技術。
當特征很多或數據量較小時,邏輯回歸容易過擬合。模型可能學習到一些噪聲模式,導致在訓練集上表現很好,但在新數據上表現很差。這是因為模型"記住"了訓練數據中的隨機波動,而不是學習到真正的規律。
L2正則化通過懲罰大的權重值來防止過擬合。
總損失=交叉熵損失+λ×Σ(權重2)總損失 = 交叉熵損失 + λ × Σ(權重2)總損失=交叉熵損失+λ×Σ(權重2)
λ × Σ(權重2):衡量所有權重的平方和。
交叉熵損失=?Σ[y×log(p)+(1?y)×log(1?p)]交叉熵損失 = -Σ[y × log(p) + (1-y) × log(1-p)] 交叉熵損失=?Σ[y×log(p)+(1?y)×log(1?p)]
- y 是真實標簽(0或1)
- p 是模型預測的概率
現在舉例說明L2原理,假設模型有如下4個權重,現在對不同模型引入懲罰系數,
# 模型A:權重較大
權重_A = [5.0, -4.0, 6.0, -5.0]
預測準確率 = 95%
交叉熵損失 = 0.1
L2懲罰項 = 0.1 × (25+16+36+25) = 0.1 × 102 = 10.2
總損失 = 0.1 + 10.2 = 10.3# 模型B:權重較小
權重_B = [2.0, -1.5, 2.5, -2.0]
預測準確率 = 94%
交叉熵損失 = 0.15
L2懲罰項 = 0.1 × (4+2.25+6.25+4) = 0.1 × 16.5 = 1.65
總損失 = 0.15 + 1.65 = 1.8
結果分析
L2正則化的目標是最小化總損失,而不是最大化預測準確率。雖然模型A的預測準確率更高(95% vs 94%),但它的總損失更大(10.3 vs 1.8)。那為什么總損失更重要?
- 過擬合風險:模型A的權重很大,說明它可能"記住"了訓練數據中的噪聲,而不是學習到真正的規律。雖然現在預測準確,但在新數據上可能表現很差。
- 泛化能力:模型B的權重較小,說明它更"保守",不會過分依賴某些特征。雖然準確率稍低,但更穩定,在新數據上表現更好。
所以,L2正則化選擇總損失更小的模型,即使它的預測準確率稍低。這是因為較小的權重意味著模型更穩定,泛化能力更強,不容易過擬合。這就是為什么模型B雖然準確率94%,但總損失1.8,比模型A的10.3更優。
?
2. 基于K折交叉驗證L2算法
from pandas import read_csv
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression。。。數據集劃分見上
# 創建K折交叉驗證對象
# n_splits=num_folds: 將數據集分成num_folds份,進行num_folds次訓練和驗證
# random_state=seed: 設置隨機種子,確保每次運行結果一致
# shuffle=True: 在分割前先打亂數據,避免數據順序對結果的影響
kfold = KFold(n_splits=num_folds, random_state=seed, shuffle=True)# 創建邏輯回歸模型
# LogisticRegression(): 默認使用L2正則化,適用于二分類問題
# 可以通過參數調整正則化強度、求解器等
model = LogisticRegression()# 使用交叉驗證評估模型性能
# cross_val_score(): 自動進行K折交叉驗證,返回每折的得分
# model: 要評估的模型
# X: 特征矩陣
# Y: 目標變量
# cv=kfold: 使用上面定義的K折交叉驗證策略
result = cross_val_score(model, X, Y, cv=kfold)# 輸出評估結果
print("算法評估結果:%.3f%% (%.3f%%)" % (result.mean() * 100, result.std() * 100))算法評估結果:77.864% (4.735%)
優缺點:
- 優點:充分利用數據,評估更穩健。
- 缺點:計算量較大,尤其是K值較高時。
?
三、棄一交叉驗證(Leave-One-Out)
1、基本原理
棄一交叉驗證(LOOCV)是一種特殊的交叉驗證方法,專門用于極小數據集。它的核心思想很簡單:每次只留一個樣本做測試,其余全部用于訓練,這樣循環N次(N為樣本總數)。
當數據集很小時,傳統的K折交叉驗證可能不夠可靠。比如只有10個樣本,分成5折意味著每折只有2個樣本,這樣的評估結果波動很大,不夠穩定。LOOCV通過最大化訓練數據來解決這個問題。
每次訓練時,模型都能使用N-1個樣本,這在小數據集上是非常寶貴的。同時,每個樣本都會被用作測試集一次,確保了評估的全面性。
?
2、代碼實現
from sklearn.model_selection import LeaveOneOut# 創建棄一交叉驗證對象
# loocv:自動實現每次留一個樣本的驗證策略
# 如果數據集有N個樣本,會進行N次訓練和測試
loocv = LeaveOneOut()# 使用棄一交叉驗證評估模型性能
# cross_val_score:自動進行N次訓練和測試,返回每次的得分
# model:要評估的模型(如邏輯回歸、隨機森林等)
# X:特征矩陣
# Y:目標變量
# cv=loocv:使用棄一交叉驗證策略
result = cross_val_score(model, X, Y, cv=loocv)# 輸出評估結果
# result.mean():計算所有N次評估的平均得分
# result.std():計算所有N次評估的標準差,衡量模型穩定性
print("算法評估結果:%.3f%% (%.3f%%)" % (result.mean() * 100, result.std() * 100))
棄一交叉驗證是極小數據集上最可靠的評估方法。它通過最大化訓練數據利用,為每個樣本提供最全面的評估,從而獲得最穩定的性能指標。雖然計算成本高,但在數據稀缺的情況下,這種"奢侈"是值得的。
?
四、ShuffleSplit交叉驗證
1、基本原理
傳統的K折交叉驗證雖然有效,但在某些情況下可能不夠靈活。比如當數據分布不均勻(某折訓練集某些特征數據很少),或者我們希望獲得更穩健的評估結果時,需要一種更靈活的驗證方法。
ShuffleSplit通過隨機劃分數據來解決這個問題。每次隨機選擇一部分數據作為測試集,其余作為訓練集,然后重復這個過程多次。這樣既保證了評估的隨機性,又通過多次重復降低了結果的方差。
假設設置10次劃分,測試集比例為33%:
- 第1次:隨機選擇33%數據做測試,67%做訓練
- 第2次:重新隨機選擇33%數據做測試,67%做訓練
- 第3次:再次重新隨機選擇…
- …重復10次
?
2、為什么能降低方差
1. 減少偶然性
傳統K折使用固定劃分,如果某折恰好包含異常數據,整個評估結果就會受影響。而ShuffleSplit通過多次隨機劃分,將異常數據的影響分散到不同次評估中,從而降低了單次異常對整體結果的影響。
2. 更全面的評估
傳統K折中每個樣本只在固定的某折中測試一次,而ShuffleSplit中每個樣本可能在不同次評估中被測試,獲得更全面的性能評估。這種隨機性確保了評估結果更加客觀和全面。
3. 統計穩定性
傳統K折通常只進行5次評估,結果可能波動很大。而ShuffleSplit可以進行10次或更多次評估,通過增加評估次數來提高統計穩定性,使結果更加可靠。
 
3、代碼測試
from sklearn.model_selection import ShuffleSplit# 創建ShuffleSplit對象
# n_splits=10:重復10次劃分,獲得10個評估結果
# test_size=0.33:每次33%數據做測試,67%數據做訓練
# random_state=7:設置隨機種子,確保結果可重現
kfold = ShuffleSplit(n_splits=10, test_size=0.33, random_state=7)# 使用ShuffleSplit評估模型性能
# cross_val_score:自動進行10次訓練和測試,返回每次的得分
# model:要評估的模型(如邏輯回歸、隨機森林等)
# X:特征矩陣
# Y:目標變量
# cv=kfold:使用ShuffleSplit驗證策略
result = cross_val_score(model, X, Y, cv=kfold)# 輸出評估結果
# result.mean():計算10次評估的平均得分
# result.std():計算10次評估的標準差,衡量模型穩定性
# *100:將小數轉換為百分比顯示
# %.3f:保留3位小數
print("算法評估結果:%.3f%% (%.3f%%)" % (result.mean() * 100, result.std() * 100))
優缺點分析
優點:通過多次隨機劃分降低方差,提高評估結果的穩定性;同時具有很高的靈活性,可以自由設置劃分次數和測試集比例,適應各種數據分布情況。
缺點:需要多次訓練模型,計算成本較高;不同次劃分的測試集可能有重疊,影響評估的獨立性。
ShuffleSplit通過隨機重復劃分的方式,在保持計算效率的同時,顯著降低了評估結果的方差。它特別適合需要穩健評估結果的場景,是傳統交叉驗證方法的有益補充。
?
五、 選擇建議
數據規模 | 推薦方法 | 說明 |
---|---|---|
數據量大 | 67%/33%分割或K折 | K=3、5、10均可 |
數據量小 | 棄一交叉或ShuffleSplit | 最大化數據利用,降低方差 |
需最終評估 | K折(K=10) | 行業“黃金準則” |
最佳實踐:
- 每次劃分都要設置
random_state
,保證實驗可復現。 - 評估指標要與業務目標一致(如類別不平衡時優先關注AUC等)。
- 不要用訓練集直接評估模型。
?