模型训练数据不平衡怎么办? 使用 imbalanced-learn库 !!专治各种不平衡

1. Python imbalanced-learn库是什么?

imbalanced-learn(imblearn)是一个专门处理不平衡数据集的Python库。它是scikit-learn的扩展库,提供了多种重采样技术来处理分类问题中的类别不平衡问题。该库提供了以下主要功能:

  • 过采样技术:如SMOTE(合成少数类过采样技术)、ADASYN(自适应合成采样)等
  • 欠采样技术:如随机欠采样、Tomek Links、NearMiss等
  • 结合过采样和欠采样的混合技术
  • 集成学习方法:将重采样技术与分类器结合

imbalanced-learn遵循scikit-learn的API设计,使其能够轻松集成到机器学习工作流程中,包括在Pipeline中使用。

2. AI领域,imbalanced-learn作用?

在AI和机器学习领域,imbalanced-learn解决了一个关键问题:不平衡数据集处理。这一功能十分重要,原因如下:

  1. 提高少数类预测性能:在许多实际应用中(如欺诈检测、医疗诊断、异常检测),关注的目标类通常是数据集中的少数类。标准机器学习算法在不平衡数据上往往偏向多数类,导致对少数类的预测性能差。

  2. 适应不同领域需求

    • 医疗AI:疾病诊断数据通常高度不平衡
    • 金融科技:欺诈交易在所有交易中占比很小
    • 网络安全:恶意行为检测中正常行为占大多数
    • 故障预测:设备故障事件通常很少见
    • 自然语言处理:特定类别的文本可能非常罕见
  3. 定制评估指标:该库支持特定于不平衡学习的评估指标,如精确率-召回率曲线、ROC曲线等

  4. 与深度学习集成:可以在深度学习预处理阶段用于平衡训练数据

  5. 优化决策阈值:提供了工具来调整分类决策阈值,这对不平衡数据的性能评估至关重要

imbalanced-learn使AI系统能够更公平、更准确地处理现实世界中固有的不平衡数据分布,从而改善对少数类别样本的识别能力,这在许多关键应用中尤为重要。

3. 欠采样处理在客户流失预测中的应用

需求分析

背景

某电信公司面临客户流失问题。公司拥有大量客户数据,包括服务使用情况、账单信息和客户服务互动等。公司希望建立一个预测模型来识别可能流失的客户,从而采取针对性措施挽留这些客户。

挑战

数据集中流失客户(正类)只占总体的15%,而非流失客户(负类)占85%。这种不平衡会导致标准机器学习模型倾向于预测大多数类,忽视少数类,而公司更关心的恰恰是少数类(即可能流失的客户)。

目标

  1. 建立能准确识别潜在流失客户的分类模型
  2. 解决数据不平衡问题,特别是通过欠采样技术
  3. 评估不同欠采样方法的效果
  4. 为业务部门提供可解释的模型和建议

代码构建思路

  1. 数据探索与预处理
    • 加载数据并理解特征
    • 处理缺失值和异常值
    • 特征工程和编码
  2. 处理数据不平衡
    • 使用imbalanced-learn库实现多种欠采样技术
    • 比较随机欠采样、Tomek Links、NearMiss等方法
  3. 模型构建与评估
    • 训练多个分类模型(如随机森林、XGBoost)
    • 使用适合不平衡数据的评估指标(如AUC、F1分数、召回率)
    • 实现交叉验证确保模型稳定性
  4. 结果比较与解释
    • 比较不同欠采样技术的效果
    • 提取特征重要性进行业务解释
    • 模型部署建议

完整实现

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 机器学习库
from sklearn.model_selection import train_test_split, cross_val_score, StratifiedKFold
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix, roc_curve, auc, precision_recall_curve
from sklearn.feature_selection import SelectFromModel
from xgboost import XGBClassifier

# 导入不平衡学习库
from imblearn.under_sampling import RandomUnderSampler, TomekLinks, NearMiss
from imblearn.pipeline import Pipeline as ImbPipeline

# 结果可视化
import matplotlib.pyplot as plt
import seaborn as sns

# 设置随机种子以确保结果可复现
np.random.seed(42)

# 1. 数据加载与探索
print("1. 数据加载与初步探索")
# 加载电信客户流失数据集
# 此数据集包含电信公司的客户信息及其是否已流失的标记
df = pd.read_csv('https://raw.githubusercontent.com/IBM/telco-customer-churn-on-icp4d/master/data/Telco-Customer-Churn.csv')

# 显示数据集基本信息
print(f"数据集形状: {
     
      
      df.shape}")
print("\n数据集前5行:")
print(df.head())

# 检查数据类型和缺失值
print("\n数据类型和缺失值统计:")
print(df.info())
print("\n缺失值统计:")
print(df.isnull().sum())

# 目标变量分布 - 检查流失率
print("\n客户流失情况统计:")
print(df['Churn'].value_counts())
print(df['Churn'].value_counts(normalize=True) * 100)

# 2. 数据预处理
print("\n2. 数据预处理")

# 将目标变量转换为二进制值
df['Churn'] = df['Churn'].map({
   
    
    'Yes': 1, 'No': 0})

# 删除不相关的列
df = df.drop(['customerID'], axis=1)

# 处理TotalCharges列(可能包含空格字符)
df['TotalCharges'] = pd.to_numeric(df['TotalCharges'], errors='coerce')
df['TotalCharges'].fillna(df['MonthlyCharges'] * df[