欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Imbalanced Classes(处理不平衡特征)

程序员文章站 2022-06-12 16:57:32
...

Disease Screening Example

url:https://elitedatascience.com/imbalanced-classes
url:阿里云译文

First, please note that we’re not going to split out a separate test set, tune hyperparameters, or implement cross-validation. In other words, we’re not going to follow best practices (which are covered in our Data Science Primer).

Instead, this tutorial is focused purely on addressing imbalanced classes.

如何处理数据集中类别的不平衡,例如,类别A在数据集中有500个而B只有10个。

平衡方式:
1.上采样少数类别:上采样是从少数类别中随机复制观测样本以增强其信号的过程。
2.下采样多数类别:下采样包括从多数类别中随机地移除观测样本,以防止它的信息主导学习算法。
3. 改变你的性能指标:考虑使用其他性能指标来评估模型。对于分类的通用指标,我们推荐使用 ROC 曲线下面积 (AUROC)。AUROC 表示从中类别中区别观测样本的可能性。
换句话说,如果你从每个类别中随机选择一个观察样本,它将被正确的“分类”的概率是多大?
4.惩罚算法 (代价敏感学习):接下来的策略是使用惩罚学习算法来增加对少数类别分类错误的代价。对于这种技术,一个流行的算法是惩罚性-SVM:支持向量机
5. 使用基于树的算法:最后一个策略我们将考虑使用基于树的算法。决策树通常在不平衡数据集上表现良好,因为它们的层级结构允许它们从两个类别去学习。

在现代应用机器学习中,树集合(随机森林、梯度提升树等) 几乎总是优于单一决策树,所以我们将跳过单一决策树直接使用树集合模型:随机森林

import pandas as pd
import numpy as np 

# 读数据
data_url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/balance-scale/balance-scale.data'
df = pd.read_csv(data_url, names=['balance', 'var1', 'var2', 'var3', 'var4'])
df['balance'] = [1 if b == 'B' else 0 for b in df.balance]
# df['balance'].value_counts()

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 分离特征和目标数据
y = df.balance
X = df.drop('balance', axis=1)

# 训练逻辑蒂斯回归模型
clf_0 = LogisticRegression().fit(X, y)

# 预测
pred_y_0 = clf_0.predict(X)

# 打印预测的准确率
print(accuracy_score(y, pred_y_0))

# 准确率这么高是因为塔只预测了一个类
print(np.unique(pred_y_0))


0.9216
[0]
# 处理不平衡类的第一个方法:上采样少数类别
from sklearn.utils import resample

# 分离多数类别数据和少数类别数据
df_majority = df[df.balance==0]
df_minority = df[df.balance==1]

# 进行上采样少数类别方法
df_minority_upsampled = resample(df_minority,
                                replace=True, 
                                n_samples=567, # 这是设置重复到多少数量,多数类也有567个样本
                                random_state=123) # 随机种子

# 组合多数类和上采样后的少数类
df_upsampled = pd.concat([df_majority, df_minority_upsampled])

# 组合成的类别的数量
# 1    576
# 0    576
# Name: balance, dtype: int64

# 在处理后的数据集上进行训练
y = df_upsampled.balance
X = df_upsampled.drop('balance', axis=1)

# 训练模型
clf_1 = LogisticRegression().fit(X, y)

# 预测
pred_y_1 = clf_1.predict(X)

# 现在预测的类别有几类
print(np.unique(pred_y_1))
# [0 1]

# 现在的精准度
print(accuracy_score(y, pred_y_1))
# [0 1]
# 0.5091863517060368
[0 1]
0.5091863517060368
# 处理不平衡类的第二个方法:下采样少数类别

# 分离多数类别数据和少数类别数据
df_majority = df[df.balance==0]
df_minority = df[df.balance==1]

# 进行下采样少数类别方法
df_majority_downsampled = resample(df_majority,
                                replace=False,  # 不使用替代采样
                                n_samples=49, # 这是设置匹配到多少数量,少数类有49个样本
                                random_state=123) # 随机种子

# 组合多数类和下采样后的多数类
df_downsampled = pd.concat([df_majority_downsampled, df_minority])

# 组合成的类别的数量
# 1    49
# 0    49
# Name: balance, dtype: int64

# 在处理后的数据集上进行训练
y = df_downsampled.balance
X = df_downsampled.drop('balance', axis=1)

# 训练模型
clf_2 = LogisticRegression().fit(X, y)

# 预测
pred_y_2 = clf_2.predict(X)

# 现在预测的类别有几类
print(np.unique(pred_y_2))
# [0 1]

# 现在的精准度
print(accuracy_score(y, pred_y_2))
# [0 1]
# 0.5816326530612245
[0 1]
0.5816326530612245
# 处理不平衡类的第三个方法:更改绩效指标(使用ROC曲线下面积)

from sklearn.metrics import roc_auc_score
# 预测类的概率
prob_y_2 = clf_2.predict_proba(X)

# 取正类的概率
prob_y_2 = [p[1] for p in prob_y_2]

# 展示正类的概率
prob_y_2[:5]

# [0.45419197226479624,
#  0.4820596221328387,
#  0.46862327066392456,
#  0.4786837883268912,
#  0.5814385682015967]


# 好的......这与在不平衡数据集上训练的原始模型相比如何?
prob_y_0 = clf_0.predict_proba(X)
prob_y_0 = [p[1] for p in prob_y_0]

print(roc_auc_score(y, prob_y_0))
# 0.47480216576426487


# 注意: 如果 AUROC 的值为 0.47,这仅仅意味着你需要翻转预测,因为 Scikit-Learn 误解释了正向类别。 AUROC 应该 >= 0.5。
0.47480216576426487
# 处理不平衡类的第四个方法:惩罚算法 (代价敏感学习)(支持向量机)

from sklearn.svm import SVC
# 数据分离
y = df.balance
X = df.drop('balance', axis=1)

# 训练模型
# 在训练期间,我们可以使用参数 class_weight = 'balanced'   来惩罚少数群体类的错误,其数量与其代表性不足的数量成正比。
clf_3 = SVC(kernel='linear',
           class_weight='balanced',
           probability=True)

clf_3.fit(X, y)

# 预测
pred_y_3 = clf_3.predict(X)

# 查看预测的类
print(np.unique(pred_y_3))

# 预测的准确性
print(accuracy_score(y, pred_y_3))


# 预测的AUROC值
prob_y_3 = clf_3.predict_proba(X)
prob_y_3 = [p[1] for p in prob_y_3]
print(roc_auc_score(y, prob_y_3))

# [0 1]
# 0.688
# 0.46947633219954643
[0 1]
0.688
0.46947633219954643
# 处理不平衡类的第五个方法:使用基于树的算法

from sklearn.ensemble import RandomForestClassifier

# 数据分割
y = df.balance
X = df.drop('balance', axis=1)

# 训练模型,随机森林
clf_4 = RandomForestClassifier().fit(X, y)

# 预测
pred_y_4 = clf_4.predict(X)

# 预测的类别有
print(np.unique(pred_y_4))

# 准确度
print(accuracy_score(y, pred_y_4))

# 计算预测1的AUROC值
prob_y_4 = clf_4.predict_proba(X)
prob_y_4 = [p[1] for p in prob_y_4]

print(roc_auc_score(y, prob_y_4))

# [0 1]
# 0.976
# 0.9975375566893423
[0 1]
0.976
0.9975375566893423
相关标签: 学习记录