Sklearn 模型选择与调优
sklearn.model_selection 模块提供交叉验证、超参数搜索、数据分割等全部模型选择工具。
✂️ 数据分割
1. train_test_split() --- 训练集/测试集分割 ⭐
python
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.3, # 测试集比例 (0.0 - 1.0)
train_size=None, # 训练集比例(与 test_size 二选一)
random_state=42, # 随机种子(复现用)
shuffle=True, # 是否先打乱
stratify=y # 分层抽样(保持类别比例)
)
重要 : 分类数据集不均衡时务必使用 stratify=y。
2. StratifiedShuffleSplit --- 分层随机分割
python
from sklearn.model_selection import StratifiedShuffleSplit
sss = StratifiedShuffleSplit(
n_splits=5,
test_size=0.2,
train_size=None,
random_state=42
)
for train_idx, test_idx in sss.split(X, y):
X_train, X_test = X[train_idx], X[test_idx]
y_train, y_test = y[train_idx], y[test_idx]
3. KFold / StratifiedKFold --- K 折交叉验证
python
from sklearn.model_selection import KFold, StratifiedKFold
# 标准 K 折
kf = KFold(
n_splits=5,
shuffle=True,
random_state=42
)
# 分层 K 折(分类推荐)⭐
skf = StratifiedKFold(
n_splits=5,
shuffle=True,
random_state=42
)
for train_idx, val_idx in skf.split(X, y):
X_train, X_val = X[train_idx], X[val_idx]
y_train, y_val = y[train_idx], y[val_idx]
4. 其他分割器
python
from sklearn.model_selection import (
ShuffleSplit, # 随机多次分割
StratifiedShuffleSplit, # 分层随机分割
RepeatedKFold, # 重复 K 折
RepeatedStratifiedKFold, # 重复分层 K 折
LeaveOneOut, # 留一法
LeavePOut, # 留 P 法
LeaveOneGroupOut, # 基于组留一法
LeavePGroupsOut, # 基于组留 P 法
GroupKFold, # 组 K 折
GroupShuffleSplit, # 组随机分割
StratifiedGroupKFold, # 分层组 K 折
TimeSeriesSplit, # 时间序列分割
PredefinedSplit, # 预定义折叠
)
# 重复分层 K 折(更稳定的评估)
from sklearn.model_selection import RepeatedStratifiedKFold
rskf = RepeatedStratifiedKFold(n_splits=5, n_repeats=3, random_state=42)
# 时间序列分割(避免未来信息泄露)
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
# 留一法(小数据集)
from sklearn.model_selection import LeaveOneOut
loo = LeaveOneOut()
🔍 交叉验证
1. cross_val_score() --- 交叉验证评分 ⭐
python
from sklearn.model_selection import cross_val_score
scores = cross_val_score(
model, X, y,
cv=5, # 折叠数或分割器实例
scoring='accuracy', # 评分指标
n_jobs=-1, # 并行核数
verbose=0,
error_score='raise' # or float('nan')
)
print(f"{scores.mean():.3f} +/- {scores.std():.3f}")
2. cross_validate() --- 多指标交叉验证
python
from sklearn.model_selection import cross_validate
results = cross_validate(
model, X, y,
cv=5,
scoring=['accuracy', 'f1_macro'], # 多个指标
return_train_score=True, # 同时返回训练集分数
return_estimator=True, # 返回每个折叠的模型
n_jobs=-1
)
print(results.keys())
# dict_keys(['fit_time', 'score_time',
# 'test_accuracy', 'test_f1_macro',
# 'train_accuracy', 'train_f1_macro',
# 'estimator'])
3. cross_val_predict() --- 交叉验证预测
python
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import confusion_matrix
y_pred_cv = cross_val_predict(
model, X, y,
cv=5,
method='predict', # 'predict', 'predict_proba', 'predict_log_proba', 'decision_function'
n_jobs=-1
)
# 基于交叉验证的混淆矩阵
cm = confusion_matrix(y, y_pred_cv)
4. learning_curve() --- 学习曲线
python
from sklearn.model_selection import learning_curve
train_sizes, train_scores, val_scores = learning_curve(
model, X, y,
cv=5,
train_sizes=np.linspace(0.1, 1.0, 10), # 训练集大小
scoring='accuracy',
n_jobs=-1,
random_state=42,
shuffle=True
)
# 计算均值和标准差
train_mean = train_scores.mean(axis=1)
train_std = train_scores.std(axis=1)
val_mean = val_scores.mean(axis=1)
val_std = val_scores.std(axis=1)
可视化:
python
import matplotlib.pyplot as plt
plt.plot(train_sizes, train_mean, 'o-', label='Training score')
plt.plot(train_sizes, val_mean, 'o-', label='Cross-validation score')
plt.fill_between(train_sizes, train_mean - train_std, train_mean + train_std, alpha=0.1)
plt.fill_between(train_sizes, val_mean - val_std, val_mean + val_std, alpha=0.1)
plt.xlabel('Training examples')
plt.ylabel('Score')
plt.legend()
plt.show()
5. validation_curve() --- 验证曲线
python
from sklearn.model_selection import validation_curve
train_scores, val_scores = validation_curve(
model, X, y,
param_name='C', # 参数名
param_range=[0.01, 0.1, 1, 10], # 参数值范围
cv=5,
scoring='accuracy',
n_jobs=-1
)
# 找到最佳参数
best_idx = val_scores.mean(axis=1).argmax()
best_param = param_range[best_idx]
6. permutation_test_score() --- 置换检验
python
from sklearn.model_selection import permutation_test_score
score, permutation_scores, pvalue = permutation_test_score(
model, X, y,
cv=5,
n_permutations=100,
n_jobs=-1,
random_state=42,
scoring='accuracy'
)
print(f"真实分数: {score:.3f}")
print(f"p-value: {pvalue:.4f}") # p < 0.05 表示显著
🎯 超参数搜索
1. GridSearchCV --- 网格搜索 ⭐
python
from sklearn.model_selection import GridSearchCV
param_grid = {
'C': [0.01, 0.1, 1, 10, 100],
'gamma': ['scale', 'auto', 0.01, 0.1, 1],
'kernel': ['rbf', 'linear', 'poly']
}
grid_search = GridSearchCV(
estimator=SVC(),
param_grid=param_grid,
scoring='accuracy',
cv=5,
n_jobs=-1,
verbose=1,
refit=True, # 用最优参数在全部训练集上重训
return_train_score=True,
error_score='raise'
)
grid_search.fit(X_train, y_train)
# 结果查看
print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳分数: {grid_search.best_score_:.3f}")
print(f"最佳模型: {grid_search.best_estimator_}")
print(f"最佳索引: {grid_search.best_index_}")
# 所有结果 DataFrame
import pandas as pd
results_df = pd.DataFrame(grid_search.cv_results_)
print(results_df[['params', 'mean_test_score', 'std_test_score', 'rank_test_score']])
2. RandomizedSearchCV --- 随机搜索 ⭐
python
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import uniform, loguniform, randint
param_distributions = {
'C': loguniform(1e-3, 1e3),
'gamma': loguniform(1e-4, 1e1),
'kernel': ['rbf', 'linear', 'poly'],
'degree': randint(2, 6)
}
random_search = RandomizedSearchCV(
estimator=SVC(),
param_distributions=param_distributions,
n_iter=100, # 采样次数
scoring='accuracy',
cv=5,
n_jobs=-1,
random_state=42,
refit=True,
verbose=1
)
random_search.fit(X_train, y_train)
3. HalvingGridSearchCV --- 减半网格搜索
自适应分配计算资源,逐步淘汰差的参数组合。
python
from sklearn.model_selection import HalvingGridSearchCV
halving_grid = HalvingGridSearchCV(
estimator=SVC(),
param_grid=param_grid,
factor=3, # 每轮保留 1/3
resource='n_samples', # 或 'n_estimators'
max_resources='auto',
min_resources='exhaust',
aggressive_elimination=False,
cv=5,
scoring='accuracy',
random_state=42
)
halving_grid.fit(X, y)
4. HalvingRandomSearchCV --- 减半随机搜索
python
from sklearn.model_selection import HalvingRandomSearchCV
halving_random = HalvingRandomSearchCV(
estimator=SVC(),
param_distributions=param_distributions,
n_candidates='exhaust',
factor=3,
resource='n_samples',
max_resources='auto',
scoring='accuracy',
cv=5,
random_state=42
)
5. ParameterGrid / ParameterSampler
手动生成参数组合。
python
from sklearn.model_selection import ParameterGrid, ParameterSampler
param_grid = {'C': [0.1, 1, 10], 'kernel': ['rbf', 'linear']}
# 遍历所有组合
for params in ParameterGrid(param_grid):
print(params)
# {'C': 0.1, 'kernel': 'rbf'}
# {'C': 0.1, 'kernel': 'linear'}
# {'C': 1, 'kernel': 'rbf'}
# ...
# 随机采样(来自分布)
param_dist = {'C': loguniform(0.01, 100), 'kernel': ['rbf', 'linear']}
for params in ParameterSampler(param_dist, n_iter=10, random_state=42):
print(params)
🔧 其他工具
check_cv() --- 验证 CV 参数
python
from sklearn.model_selection import check_cv
cv = check_cv(cv=5, y=y, classifier=True)
📝 完整调优模板
分类任务完整流程
python
from sklearn.model_selection import train_test_split, StratifiedKFold, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.svm import SVC
# 1. 分割
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 2. 管道
pipeline = Pipeline([
('scaler', StandardScaler()),
('svc', SVC())
])
# 3. 超参数网格
param_grid = {
'svc__C': [0.1, 1, 10, 100],
'svc__gamma': ['scale', 'auto', 0.01, 0.1],
'svc__kernel': ['rbf', 'linear']
}
# 4. 网格搜索
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
grid = GridSearchCV(
pipeline, param_grid, cv=cv,
scoring='accuracy', n_jobs=-1, verbose=1
)
grid.fit(X_train, y_train)
# 5. 评估
print(f"CV最佳分数: {grid.best_score_:.3f}")
print(f"测试集分数: {grid.score(X_test, y_test):.3f}")
print(f"最佳参数: {grid.best_params_}")
回归任务
python
from sklearn.model_selection import KFold, RandomizedSearchCV
from sklearn.ensemble import RandomForestRegressor
from scipy.stats import randint, uniform
param_dist = {
'n_estimators': randint(50, 500),
'max_depth': randint(3, 20),
'min_samples_split': randint(2, 20),
'min_samples_leaf': randint(1, 10),
'max_features': uniform(0.1, 0.9)
}
rf = RandomForestRegressor(random_state=42)
cv = KFold(n_splits=5, shuffle=True, random_state=42)
search = RandomizedSearchCV(
rf, param_dist, n_iter=100, cv=cv,
scoring='neg_mean_squared_error', n_jobs=-1, verbose=1
)
search.fit(X_train, y_train)
\[sklearn-总览\|← 返回总览\]