本文目录导读:

我来详细解释如何使用Scikit-learn进行随机搜索交叉验证(RandomizedSearchCV)。
基本随机搜索配置
from sklearn.model_selection import RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
from scipy.stats import randint, uniform
import numpy as np
# 创建示例数据
X, y = make_classification(n_samples=1000, n_features=20, random_state=42)
# 定义模型
rf = RandomForestClassifier(random_state=42)
# 定义参数分布(使用概率分布)
param_dist = {
'n_estimators': randint(50, 500),
'max_depth': [None] + list(range(10, 50, 10)),
'min_samples_split': randint(2, 20),
'min_samples_leaf': randint(1, 10),
'max_features': ['sqrt', 'log2', None],
'bootstrap': [True, False]
}
# 创建随机搜索对象
random_search = RandomizedSearchCV(
rf,
param_distributions=param_dist,
n_iter=50, # 迭代次数,即尝试的参数组合数
cv=5, # 交叉验证折数
scoring='accuracy',
n_jobs=-1, # 使用所有CPU核心
random_state=42,
verbose=1
)
# 执行搜索
random_search.fit(X, y)
# 查看结果
print("最佳参数:", random_search.best_params_)
print("最佳得分:", random_search.best_score_)
不同评估指标的配置
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.metrics import make_scorer, f1_score, precision_score, recall_score
# 多指标评估
param_dist_svm = {
'svc__C': uniform(0.1, 100),
'svc__gamma': uniform(0.001, 0.1),
'svc__kernel': ['rbf', 'poly', 'sigmoid']
}
# 创建流水线
pipeline = Pipeline([
('scaler', StandardScaler()),
('svc', SVC(random_state=42))
])
# 使用多个评分指标
scoring = {
'accuracy': 'accuracy',
'f1': 'f1_macro',
'precision': 'precision_macro',
'recall': 'recall_macro'
}
random_search_multi = RandomizedSearchCV(
pipeline,
param_distributions=param_dist_svm,
n_iter=30,
cv=5,
scoring=scoring,
refit='f1', # 基于F1分数选择最佳模型
n_jobs=-1,
return_train_score=True
)
random_search_multi.fit(X, y)
# 查看不同指标的结果
print("最佳参数:", random_search_multi.best_params_)
print("最佳F1分数:", random_search_multi.best_score_)
results = random_search_multi.cv_results_
print("所有指标结果:")
for metric in ['accuracy', 'f1', 'precision', 'recall']:
key = f'mean_test_{metric}'
if key in results:
idx = random_search_multi.best_index_
print(f"{metric}: {results[key][idx]:.3f}")
高级配置和应用
from sklearn.model_selection import StratifiedKFold
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import GradientBoostingClassifier
import pandas as pd
class AdvancedRandomSearch:
"""高级随机搜索类"""
def __init__(self, estimator, param_dist, n_iter=100, cv=5, scoring='accuracy'):
self.estimator = estimator
self.param_dist = param_dist
self.n_iter = n_iter
self.cv = cv
self.scoring = scoring
self.search = None
def run_search(self, X, y, use_stratified=True):
"""执行搜索"""
# 使用分层交叉验证
if use_stratified:
cv_strategy = StratifiedKFold(n_splits=self.cv, shuffle=True, random_state=42)
else:
cv_strategy = self.cv
self.search = RandomizedSearchCV(
self.estimator,
param_distributions=self.param_dist,
n_iter=self.n_iter,
cv=cv_strategy,
scoring=self.scoring,
n_jobs=-1,
random_state=42,
verbose=1,
return_train_score=True
)
self.search.fit(X, y)
return self
def get_results_dataframe(self):
"""获取结果DataFrame"""
results = self.search.cv_results_
df = pd.DataFrame(results)
cols = ['params'] + [col for col in df.columns if 'mean_test' in col or 'std_test' in col]
return df[cols].sort_values('mean_test_score', ascending=False)
# 使用示例
gbm = GradientBoostingClassifier(random_state=42)
param_dist_gbm = {
'n_estimators': randint(50, 300),
'learning_rate': uniform(0.01, 0.3),
'subsample': uniform(0.6, 0.4),
'max_depth': randint(3, 10),
'min_samples_split': randint(2, 20),
'min_samples_leaf': randint(1, 10)
}
# 执行高级搜索
advanced_search = AdvancedRandomSearch(
gbm,
param_dist_gbm,
n_iter=100,
scoring='accuracy'
).run_search(X, y)
# 查看结果
results_df = advanced_search.get_results_dataframe()
print("前5个最佳结果:")
print(results_df.head())
print("\n最佳参数:", advanced_search.search.best_params_)
实用的随机搜索技巧
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report, confusion_matrix
import matplotlib.pyplot as plt
# 1. 提前停止搜索
def early_stopping_search(X, y, estimator, param_dist):
"""带提前停止的随机搜索"""
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)
best_score = 0
patience = 5
no_improve = 0
for i in range(100):
# 随机采样参数
params = {key: dist.rvs() if hasattr(dist, 'rvs') else np.random.choice(dist)
for key, dist in param_dist.items()}
estimator.set_params(**params)
estimator.fit(X_train, y_train)
score = estimator.score(X_val, y_val)
if score > best_score:
best_score = score
best_params = params
no_improve = 0
else:
no_improve += 1
if no_improve >= patience:
print(f"提前停止于迭代 {i+1}")
break
return best_params, best_score
# 2. 结果可视化
def plot_search_results(random_search):
"""可视化搜索过程"""
results = random_search.cv_results_
n_iter = len(results['params'])
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 绘制得分变化
axes[0, 0].plot(range(n_iter), results['mean_test_score'], 'b-', label='Test')
axes[0, 0].plot(range(n_iter), results['mean_train_score'], 'r-', label='Train')
axes[0, 0].set_xlabel('Iteration')
axes[0, 0].set_ylabel('Score')
axes[0, 0].legend()
axes[0, 0].set_title('Score vs Iteration')
# 绘制测试分数分布
axes[0, 1].hist(results['mean_test_score'], bins=20)
axes[0, 1].set_xlabel('Test Score')
axes[0, 1].set_ylabel('Frequency')
axes[0, 1].set_title('Distribution of Test Scores')
# 绘制参数与得分的关系
for i, param in enumerate(['n_estimators', 'max_depth']):
if param in results['params'][0]:
param_values = [p[param] for p in results['params']]
scores = results['mean_test_score']
axes[1, i].scatter(param_values, scores)
axes[1, i].set_xlabel(param)
axes[1, i].set_ylabel('Test Score')
axes[1, i].set_title(f'{param} vs Score')
plt.tight_layout()
plt.show()
# 3. 实际应用示例
print("开始实际应用示例...")
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 执行随机搜索
rf = RandomForestClassifier(random_state=42)
param_dist = {
'n_estimators': randint(50, 200),
'max_depth': randint(3, 20),
'min_samples_split': randint(2, 10)
}
search = RandomizedSearchCV(
rf, param_dist, n_iter=20, cv=3, scoring='accuracy',
n_jobs=-1, random_state=42
)
search.fit(X_train, y_train)
# 评估最佳模型
y_pred = search.predict(X_test)
print("\n最佳模型测试集性能:")
print(classification_report(y_test, y_pred))
# 可视化
plot_search_results(search)
# 4. 保存和加载结果
import joblib
# 保存搜索对象
joblib.dump(search, 'random_search_model.pkl')
# 加载搜索对象
# loaded_search = joblib.load('random_search_model.pkl')
# print("最佳参数:", loaded_search.best_params_)
实用注意事项
# 1. 并行处理设置
search = RandomizedSearchCV(
estimator,
param_distributions=param_dist,
n_iter=50,
cv=5,
n_jobs=-1 # 使用所有CPU核心
# n_jobs=2 # 或指定核心数
)
# 2. 随机状态设置
search = RandomizedSearchCV(
estimator,
param_distributions=param_dist,
n_iter=50,
cv=5,
random_state=42, # 确保结果可重现
n_jobs=-1
)
# 3. 结果提取
best_model = search.best_estimator_
best_params = search.best_params_
best_score = search.best_score_
all_results = search.cv_results_
# 4. 参数分布类型
from scipy.stats import randint, uniform, loguniform
# 整数参数
param_int = randint(10, 100) # 均匀整数分布
# 浮点参数
param_float = uniform(0.01, 0.5) # 均匀浮点分布
# 对数尺度参数(适用于C、gamma等)
param_log = loguniform(1e-3, 1e3) # 对数均匀分布
# 离散参数
param_list = ['a', 'b', 'c']
param_choice = param_list # 直接使用列表
这些示例涵盖了Scikit-learn中随机搜索交叉验证的主要用法,从基础配置到高级技巧,随机搜索相比网格搜索更高效,特别适合参数空间大或参数重要性不同的情况。