name: 分类建模 description: 使用逻辑回归、决策树和集成方法构建二元和多类分类模型,用于分类预测和分类
分类建模
概览
分类建模预测分类目标值,根据输入特征将观察结果分配到离散类别或类别中。
使用场景
- 预测二元结果,如客户流失、贷款违约或电子邮件垃圾邮件
- 将项目分类到多个类别,如产品类型或情感
- 构建信用评分模型或风险评估系统
- 从患者数据中识别疾病诊断或医疗条件
- 预测客户购买可能性或对营销的响应
- 在生产系统中检测欺诈、异常或质量缺陷
分类类型
- 二元分类: 两个类别(是/否,成功/失败)
- 多类: 超过两个类别
- 多标签: 每个观察结果有多个类别
常用算法
- 逻辑回归: 线性分类
- 决策树: 基于规则的非线性
- 随机森林: 决策树集成
- 梯度提升: 顺序树构建
- SVM: 支持向量机
- 朴素贝叶斯: 概率分类器
关键指标
- 准确率: 正确的总体预测
- 精确度: 真正例 / (真正例 + 假正例)
- 召回率: 真正例 / (真正例 + 假负例)
- F1-Score: 精确度/召回率的调和平均数
- AUC-ROC: 接收者操作特征曲线下的面积
Python实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.metrics import (
confusion_matrix, classification_report, roc_auc_score, roc_curve,
precision_recall_curve, f1_score, accuracy_score
)
import seaborn as sns
# 生成样本二元分类数据
np.random.seed(42)
from sklearn.datasets import make_classification
X, y = make_classification(
n_samples=1000, n_features=20, n_informative=10,
n_redundant=5, random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
# 标准化特征
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 逻辑回归
lr_model = LogisticRegression(max_iter=1000)
lr_model.fit(X_train_scaled, y_train)
y_pred_lr = lr_model.predict(X_test_scaled)
y_proba_lr = lr_model.predict_proba(X_test_scaled)[:, 1]
print("逻辑回归:")
print(classification_report(y_test, y_pred_lr))
print(f"AUC-ROC: {roc_auc_score(y_test, y_proba_lr):.4f}
")
# 决策树
dt_model = DecisionTreeClassifier(max_depth=10, random_state=42)
dt_model.fit(X_train, y_train)
y_pred_dt = dt_model.predict(X_test)
y_proba_dt = dt_model.predict_proba(X_test)[:, 1]
print("决策树:")
print(classification_report(y_test, y_pred_dt))
print(f"AUC-ROC: {roc_auc_score(y_test, y_proba_dt):.4f}
")
# 随机森林
rf_model = RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42)
rf_model.fit(X_train, y_train)
y_pred_rf = rf_model.predict(X_test)
y_proba_rf = rf_model.predict_proba(X_test)[:, 1]
print("随机森林:")
print(classification_report(y_test, y_pred_rf))
print(f"AUC-ROC: {roc_auc_score(y_test, y_proba_rf):.4f}
")
# 梯度提升
gb_model = GradientBoostingClassifier(n_estimators=100, max_depth=5, random_state=42)
gb_model.fit(X_train, y_train)
y_pred_gb = gb_model.predict(X_test)
y_proba_gb = gb_model.predict_proba(X_test)[:, 1]
print("梯度提升:")
print(classification_report(y_test, y_pred_gb))
print(f"AUC-ROC: {roc_auc_score(y_test, y_proba_gb):.4f}
")
# 混淆矩阵
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
models = [
(y_pred_lr, '逻辑回归'),
(y_pred_dt, '决策树'),
(y_pred_rf, '随机森林'),
(y_pred_gb, '梯度提升'),
]
for idx, (y_pred, title) in enumerate(models):
cm = confusion_matrix(y_test, y_pred)
ax = axes[idx // 2, idx % 2]
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=ax)
ax.set_title(title)
ax.set_ylabel('真实标签')
ax.set_xlabel('预测标签')
plt.tight_layout()
plt.show()
# ROC曲线
plt.figure(figsize=(10, 8))
probas = [
(y_proba_lr, '逻辑回归'),
(y_proba_dt, '决策树'),
(y_proba_rf, '随机森林'),
(y_proba_gb, '梯度提升'),
]
for y_proba, label in probas:
fpr, tpr, _ = roc_curve(y_test, y_proba)
auc = roc_auc_score(y_test, y_proba)
plt.plot(fpr, tpr, label=f'{label} (AUC={auc:.4f})')
plt.plot([0, 1], [0, 1], 'k--', label='随机分类器')
plt.xlabel('假正例率')
plt.ylabel('真正例率')
plt.title('ROC曲线比较')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 精确度-召回率曲线
plt.figure(figsize=(10, 8))
for y_proba, label in probas:
precision, recall, _ = precision_recall_curve(y_test, y_proba)
f1 = f1_score(y_test, (y_proba > 0.5).astype(int))
plt.plot(recall, precision, label=f'{label} (F1={f1:.4f})')
plt.xlabel('召回率')
plt.ylabel('精确度')
plt.title('精确度-召回率曲线')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 特征重要性
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 基于树的特征重要性
feature_importance_rf = pd.Series(
rf_model.feature_importances_, index=range(X.shape[1])
).sort_values(ascending=False)
axes[0].barh(range(10), feature_importance_rf.values[:10])
axes[0].set_yticks(range(10))
axes[0].set_yticklabels([f'特征 {i}' for i in feature_importance_rf.index[:10]])
axes[0].set_title('随机森林 - 前10个特征')
axes[0].set_xlabel('重要性')
# 逻辑回归系数
lr_coef = pd.Series(lr_model.coef_[0], index=range(X.shape[1])).abs().sort_values(ascending=False)
axes[1].barh(range(10), lr_coef.values[:10])
axes[1].set_yticks(range(10))
axes[1].set_yticklabels([f'特征 {i}' for i in lr_coef.index[:10]])
axes[1].set_title('逻辑回归 - 前10个特征(绝对系数值)')
axes[1].set_xlabel('绝对系数')
plt.tight_layout()
plt.show()
# 模型比较
results = pd.DataFrame({
'模型': ['逻辑回归', '决策树', '随机森林', '梯度提升'],
'准确率': [
accuracy_score(y_test, y_pred_lr),
accuracy_score(y_test, y_pred_dt),
accuracy_score(y_test, y_pred_rf),
accuracy_score(y_test, y_pred_gb),
],
'AUC-ROC': [
roc_auc_score(y_test, y_proba_lr),
roc_auc_score(y_test, y_proba_dt),
roc_auc_score(y_test, y_proba_rf),
roc_auc_score(y_test, y_proba_gb),
],
'F1-Score': [
f1_score(y_test, y_pred_lr),
f1_score(y_test, y_pred_dt),
f1_score(y_test, y_pred_rf),
f1_score(y_test, y_pred_gb),
]
})
print("模型比较:")
print(results)
# 交叉验证
cv_scores = cross_val_score(
RandomForestClassifier(n_estimators=100, random_state=42),
X_train, y_train, cv=5, scoring='roc_auc'
)
print(f"
交叉验证AUC分数: {cv_scores}")
print(f"平均CV AUC: {cv_scores.mean():.4f} (+/- {cv_scores.std():.4f})")
# 概率校准
from sklearn.calibration import calibration_curve
prob_true, prob_pred = calibration_curve(y_test, y_proba_rf, n_bins=10)
plt.figure(figsize=(8, 6))
plt.plot(prob_pred, prob_true, 'o-', label='随机森林')
plt.plot([0, 1], [0, 1], 'k--', label='完美校准')
plt.xlabel('平均预测概率')
plt.ylabel('正例比例')
plt.title('校准曲线')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
类不平衡处理
- 过采样: 增加少数类样本
- 欠采样: 减少多数类样本
- SMOTE: 合成少数过采样
- 类别权重: 对错误分类少数类进行惩罚
阈值选择
- 默认 (0.5): 等同误分类成本
- 自定义阈值: 基于业务需求
- 最优: 最大化F1分数或AUC
交付物
- 分类指标(准确率、精确度、召回率、F1)
- 所有模型的混淆矩阵
- ROC和精确度-召回率曲线
- 特征重要性分析
- 模型比较表
- 最佳模型推荐
- 概率校准图