Scikit-learn 详解
Scikit-learn 是 Python 最流行的机器学习库,提供简单高效的工具用于数据挖掘和数据分析。
📦 核心特点
特点 | 说明 |
|---|---|
简单易用 | 统一的 API 设计,学习曲线平缓 |
功能全面 | 分类、回归、聚类、降维、模型选择等 |
高效稳定 | 基于 NumPy/SciPy,性能优秀 |
文档完善 | 官方文档详尽,示例丰富 |
生态友好 | 与 Pandas、Matplotlib、XGBoost 等无缝集成 |
🗂️ 核心模块架构
scikit-learn/
├── preprocessing # 数据预处理
├── model_selection # 模型选择与评估
├── linear_model # 线性模型
├── ensemble # 集成学习
├── tree # 决策树
├── svm # 支持向量机
├── neural_network # 神经网络
├── cluster # 聚类
├── decomposition # 降维
├── metrics # 评估指标
├── pipeline # 流水线
└── feature_selection # 特征选择
🎯 统一 API 设计
三大核心接口
# 1. 拟合模型
model.fit(X_train, y_train)
# 2. 预测
y_pred = model.predict(X_test)
# 3. 评估(部分模型支持)
score = model.score(X_test, y_test)
所有估计器(Estimator)都遵循:
from sklearn.ensemble import RandomForestClassifier
# 创建模型
model = RandomForestClassifier(n_estimators=100)
# 训练
model.fit(X_train, y_train)
# 预测
predictions = model.predict(X_test)
# 获取参数
model.get_params()
# 设置参数
model.set_params(n_estimators=200)
📊 主要功能模块详解
1️⃣ 数据预处理 (preprocessing)
from sklearn.preprocessing import StandardScaler, MinMaxScaler, OneHotEncoder
# 标准化(均值=0, 方差=1)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 归一化(缩放到 [0,1])
minmax = MinMaxScaler()
X_norm = minmax.fit_transform(X)
# 类别特征编码
encoder = OneHotEncoder()
X_encoded = encoder.fit_transform(category_features)
# 缺失值填充
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='mean') # mean/median/most_frequent
X_filled = imputer.fit_transform(X_with_missing)
2️⃣ 模型选择 (model_selection)
训练集/测试集划分
from sklearn.model_selection import train_test_split
# 基础划分
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2, # 测试集比例
random_state=42, # 随机种子
stratify=y # 分层抽样(分类问题)
)
交叉验证
from sklearn.model_selection import cross_val_score, KFold
# K 折交叉验证
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kf, scoring='accuracy')
print(f"平均准确率:{scores.mean():.3f} (+/- {scores.std():.3f})")
网格搜索(超参数调优)
from sklearn.model_selection import GridSearchCV
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [5, 10, 15, None],
'min_samples_split': [2, 5, 10]
}
grid_search = GridSearchCV(
RandomForestClassifier(),
param_grid,
cv=5,
scoring='accuracy',
n_jobs=-1 # 使用所有 CPU
)
grid_search.fit(X_train, y_train)
print(f"最佳参数:{grid_search.best_params_}")
print(f"最佳得分:{grid_search.best_score_:.3f}")
随机搜索(大数据集更快)
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint, uniform
param_dist = {
'n_estimators': randint(50, 300),
'max_depth': randint(3, 20),
'min_samples_split': randint(2, 20)
}
random_search = RandomizedSearchCV(
RandomForestClassifier(),
param_distributions=param_dist,
n_iter=50, # 尝试 50 组参数
cv=5,
n_jobs=-1
)
3️⃣ 回归模型 (linear_model & ensemble)
线性回归
from sklearn.linear_model import LinearRegression, Ridge, Lasso
# 普通线性回归
lr = LinearRegression()
lr.fit(X_train, y_train)
print(f"系数:{lr.coef_}")
print(f"截距:{lr.intercept_}")
# 岭回归(L2 正则化)
ridge = Ridge(alpha=1.0)
ridge.fit(X_train, y_train)
# Lasso 回归(L1 正则化,可做特征选择)
lasso = Lasso(alpha=0.1)
lasso.fit(X_train, y_train)
回归评估指标
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"MSE: {mse:.3f}, RMSE: {rmse:.3f}")
print(f"MAE: {mae:.3f}, R²: {r2:.3f}")
4️⃣ 分类模型
逻辑回归
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression(
C=1.0, # 正则化强度
penalty='l2', # l1/l2
solver='lbfgs', # 优化算法
max_iter=1000
)
log_reg.fit(X_train, y_train)
# 概率预测
probabilities = log_reg.predict_proba(X_test)
支持向量机 (SVM)
from sklearn.svm import SVC, SVR
# 分类
svc = SVC(
kernel='rbf', # linear/poly/rbf/sigmoid
C=1.0, # 惩罚参数
gamma='scale', # 核系数
class_weight='balanced' # 处理类别不平衡
)
svc.fit(X_train, y_train)
# 回归
svr = SVR(kernel='rbf')
svr.fit(X_train, y_train)
决策树
from sklearn.tree import DecisionTreeClassifier, export_text
dt = DecisionTreeClassifier(
max_depth=5, # 最大深度
min_samples_split=20, # 最小分裂样本数
min_samples_leaf=10, # 最小叶节点样本数
criterion='gini' # gini/entropy
)
dt.fit(X_train, y_train)
# 查看规则
print(export_text(dt, feature_names=list(X.columns)))
随机森林
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor
rf = RandomForestClassifier(
n_estimators=100, # 树的数量
max_depth=None, # 树的最大深度
min_samples_split=2,
min_samples_leaf=1,
max_features='sqrt', # 每次分裂考虑的特征数
bootstrap=True, # 是否自助采样
oob_score=True, # 袋外评分
n_jobs=-1,
random_state=42
)
rf.fit(X_train, y_train)
# 特征重要性
importances = rf.feature_importances_
梯度提升 (GBM/XGBoost/LightGBM 风格)
from sklearn.ensemble import GradientBoostingClassifier, AdaBoostClassifier
# 梯度提升
gb = GradientBoostingClassifier(
n_estimators=100,
learning_rate=0.1,
max_depth=3,
subsample=0.8, # 样本采样比例
random_state=42
)
# AdaBoost
ada = AdaBoostClassifier(
n_estimators=50,
learning_rate=1.0,
random_state=42
)
5️⃣ 聚类 (cluster)
K-Means
from sklearn.cluster import KMeans
kmeans = KMeans(
n_clusters=3, # 聚类数量
init='k-means++', # 初始化方法
n_init=10, # 运行次数
max_iter=300,
random_state=42
)
labels = kmeans.fit_predict(X)
centroids = kmeans.cluster_centers_
# 肘部法则找最佳 K
inertias = []
for k in range(1, 11):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(X)
inertias.append(kmeans.inertia_)
DBSCAN(基于密度的聚类)
from sklearn.cluster import DBSCAN
dbscan = DBSCAN(
eps=0.5, # 邻域半径
min_samples=5 # 核心点最小邻居数
)
labels = dbscan.fit_predict(X)
# -1 表示噪声点
层次聚类
from sklearn.cluster import AgglomerativeClustering
hierarchical = AgglomerativeClustering(
n_clusters=3,
linkage='ward' # ward/complete/average/single
)
labels = hierarchical.fit_predict(X)
6️⃣ 降维 (decomposition)
PCA(主成分分析)
from sklearn.decomposition import PCA
# 保留 95% 方差
pca = PCA(n_components=0.95)
X_reduced = pca.fit_transform(X)
# 指定主成分数
pca = PCA(n_components=3)
X_reduced = pca.fit_transform(X)
# 查看解释方差比
print(f"各主成分解释方差:{pca.explained_variance_ratio_}")
print(f"累计解释方差:{np.cumsum(pca.explained_variance_ratio_)}")
t-SNE(可视化高维数据)
from sklearn.manifold import TSNE
tsne = TSNE(
n_components=2, # 降维到 2D
perplexity=30, # 困惑度
learning_rate=200,
n_iter=1000
)
X_embedded = tsne.fit_transform(X)
LDA(线性判别分析)
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=2)
X_reduced = lda.fit_transform(X, y) # 需要标签
7️⃣ 评估指标 (metrics)
分类指标
from sklearn.metrics import (
accuracy_score, precision_score, recall_score,
f1_score, confusion_matrix, classification_report,
roc_auc_score, roc_curve, precision_recall_curve
)
y_pred = model.predict(X_test)
y_proba = model.predict_proba(X_test)[:, 1]
# 基础指标
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
# 混淆矩阵
cm = confusion_matrix(y_test, y_pred)
# 详细报告
report = classification_report(y_test, y_pred)
# ROC-AUC
auc = roc_auc_score(y_test, y_proba)
fpr, tpr, thresholds = roc_curve(y_test, y_proba)
回归指标
from sklearn.metrics import (
mean_squared_error, mean_absolute_error,
r2_score, explained_variance_score
)
聚类指标
from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score
silhouette = silhouette_score(X, labels)
8️⃣ 流水线 (Pipeline)
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
# 构建流水线
pipeline = Pipeline([
('scaler', StandardScaler()),
('classifier', LogisticRegression())
])
# 网格搜索(参数名 = 步骤名 + '__' + 参数名)
param_grid = {
'classifier__C': [0.1, 1, 10],
'classifier__penalty': ['l1', 'l2'],
'classifier__solver': ['liblinear', 'lbfgs']
}
grid_search = GridSearchCV(pipeline, param_grid, cv=5)
grid_search.fit(X_train, y_train)
print(f"最佳参数:{grid_search.best_params_}")
9️⃣ 特征选择 (feature_selection)
from sklearn.feature_selection import (
SelectKBest, SelectFromModel, RFE,
f_classif, mutual_info_classin
)
# 选择前 K 个特征
selector = SelectKBest(score_func=f_classif, k=10)
X_selected = selector.fit_transform(X, y)
# 基于模型的特征选择
selector = SelectFromModel(
RandomForestClassifier(n_estimators=100),
threshold='mean' # 选择重要性高于平均的特征
)
X_selected = selector.fit_transform(X, y)
# 递归特征消除
rfe = RFE(
estimator=LogisticRegression(),
n_features_to_select=10
)
X_selected = rfe.fit_transform(X, y)
🎯 完整工作流示例
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
# 1. 加载数据
df = pd.read_csv('data.csv')
X = df.drop('target', axis=1)
y = df['target']
# 2. 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# 3. 构建流水线
pipeline = Pipeline([
('scaler', StandardScaler()),
('clf', RandomForestClassifier(random_state=42))
])
# 4. 超参数调优
param_grid = {
'clf__n_estimators': [100, 200],
'clf__max_depth': [5, 10, None],
'clf__min_samples_split': [2, 5]
}
grid_search = GridSearchCV(pipeline, param_grid, cv=5, n_jobs=-1)
grid_search.fit(X_train, y_train)
# 5. 评估
best_model = grid_search.best_estimator_
y_pred = best_model.predict(X_test)
print("分类报告:")
print(classification_report(y_test, y_pred))
print("混淆矩阵:")
print(confusion_matrix(y_test, y_pred))
# 6. 交叉验证
cv_scores = cross_val_score(best_model, X, y, cv=5)
print(f"交叉验证准确率:{cv_scores.mean():.3f} (+/- {cv_scores.std():.3f})")
📚 常用超参数速查表
模型 | 关键参数 | 说明 |
|---|---|---|
RandomForest | n_estimators | 树的数量(越多越稳定) |
max_depth | 树的最大深度(控制复杂度) | |
min_samples_split | 分裂所需最小样本数 | |
max_features | 每次分裂考虑的特征数 | |
SVM | C | 惩罚参数(越大越严格) |
gamma | 核系数(越大越复杂) | |
kernel | 核函数类型 | |
LogisticRegression | C | 正则化强度(越小正则化越强) |
penalty | L1/L2正则化 | |
solver | 优化算法 | |
GradientBoosting | learning_rate | 学习率(越小越慢但可能更好) |
n_estimators | 基学习器数量 | |
subsample | 样本采样比例 |
🔧 实用技巧
1. 处理类别不平衡
# 方法 1: class_weight
model = RandomForestClassifier(class_weight='balanced')
# 方法 2: SMOTE 过采样
from imblearn.over_sampling import SMOTE
smote = SMOTE()
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
2. 保存和加载模型
import joblib
# 保存
joblib.dump(model, 'model.pkl')
# 加载
model = joblib.load('model.pkl')
3. 学习曲线(诊断过拟合/欠拟合)
from sklearn.model_selection import learning_curve
train_sizes, train_scores, test_scores = learning_curve(
model, X, y, cv=5, n_jobs=-1
)
# 绘制曲线判断模型状态
📖 学习资源
资源 | 链接 |
|---|---|
官方文档 | |
用户指南 | 非常详细,按主题组织 |
示例库 | 包含大量可运行的示例代码 |
API 参考 | 每个类/函数的完整说明 |