Python-sklearn-模型选择

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-总览\|← 返回总览\]

相关推荐
昭阳43 分钟前
4 个 vibe coding 项目,一个普通前端的半年
前端·人工智能·设计
LiLiYuan.1 小时前
【字符串常量池】
java·开发语言·面试
阿古大王1 小时前
Youtube视频笔记工具怎么选:NoteAi、billNotes、NoteGPT 横向对比
人工智能
Sylvia33.1 小时前
从轮询到推送:足球数据API架构演进与火星数据技术拆解
java·服务器·网络·python·websocket·架构
科技新资讯1 小时前
AIGC重构工业设计 一号设计解锁智造新势能
人工智能·重构·aigc
东方小月1 小时前
从零开发一个 Coding Agent(八):如何使用 Agent 类管理对话状态
前端·人工智能
瑞码空间1 小时前
Python爬虫进阶实战笔记
开发语言·python·计算机·python爬虫
杨超越luckly1 小时前
Agent应用指南:获取12306官网全量站点及其编码信息
python·数据挖掘·数据分析·可视化·12306
16月6日-晴1 小时前
Java面向对象进阶—static
java·开发语言
爱跳舞的烤冷面1 小时前
自学嵌入式第16天(数据结构篇--链表进阶操作)
开发语言