# 应对机器学习中类不平衡的10种技巧

### 总览

• 熟悉类失衡

• 了解处理不平衡类的各种技术，例如-

• 随机欠采样
• 随机过采样
• NearMiss
• 你可以检查代码的执行在我的GitHub库在这里

• 欺诈识别
• 垃圾邮件过滤
• 疾病筛查
• SaaS订阅流失
• 广告点击

### 信用卡欺诈检测示例

def transaction(transaction_data):
return 'No fradulent transaction'

• 所有这些非欺诈性的交易，你都将拥有100％的准确性。

• 那些欺诈性的交易，你的准确性为0％。

• 仅仅因为大多数交易不是欺诈性的（不是因为你的模型很好），你的总体准确性就很高。

### 数据

# check the target variable that is fraudulet and not fradulent transactiondata['Class'].value_counts()# 0 -> non fraudulent
# 1 -> fraudulent

# visualize the target variable
g = sns.countplot(data['Class'])
g.set_xticklabels(['Not Fraud','Fraud'])
plt.show()  

### 指标陷阱

# import linrary
from xgboost import XGBClassifier

xgb_model = XGBClassifier().fit(x_train, y_train)

# predict
xgb_y_predict = xgb_model.predict(x_test)

# accuracy score
xgb_score = accuracy_score(xgb_y_predict, y_test)

print('Accuracy score is:', xbg_score)OUTPUT
Accuracy score is: 0.992

### 重采样技术

# class count
class_count_0, class_count_1 = data['Class'].value_counts()

# Separate class
class_0 = data[data['Class'] == 0]
class_1 = data[data['Class'] == 1]# print the shape of the class
print('class 0:', class_0.shape)
print('class 1:', class_1.shape

#### 1.随机欠采样

class_0_under = class_0.sample(class_count_1)

test_under = pd.concat([class_0_under, class_1], axis=0)

print("total class of 1 and0:",test_under['Class'].value_counts())# plot the count after under-sampeling
test_under['Class'].value_counts().plot(kind='bar', title='count (target)')

#### 2.随机过采样

class_1_over = class_1.sample(class_count_0, replace=True)

test_over = pd.concat([class_1_over, class_0], axis=0)

print("total class of 1 and 0:",test_under['Class'].value_counts())# plot the count after under-sampeling
test_over['Class'].value_counts().plot(kind='bar', title='count (target)')

#### 使用不平衡学习python模块平衡数据

import imblearn

#### 3.使用imblearn进行随机欠采样

RandomUnderSampler通过为目标类别随机选择数据子集来平衡数据的快速简便方法。通过随机选择有或没有替代品的样本对多数类别进行欠采样。

# import library
from imblearn.under_sampling import RandomUnderSampler

rus = RandomUnderSampler(random_state=42, replacement=True)# fit predictor and target variable
x_rus, y_rus = rus.fit_resample(x, y)

print('original dataset shape:', Counter(y))
print('Resample dataset shape', Counter(y_rus))

#### 4.使用imblearn进行随机过采样

# import library
from imblearn.over_sampling import RandomOverSampler

ros = RandomOverSampler(random_state=42)

# fit predictor and target variablex_ros, y_ros = ros.fit_resample(x, y)

print('Original dataset shape', Counter(y))
print('Resample dataset shape', Counter(y_ros))

#### 5.欠采样：Tomek链接

Tomek链接是一对非常接近的实例，但类别相反。删除每对多数类的实例会增加两个类之间的空间，从而有助于分类过程。

# import library

tl = RandomOverSampler(sampling_strategy='majority')

# fit predictor and target variable
x_tl, y_tl = ros.fit_resample(x, y)

print('Original dataset shape', Counter(y))
print('Resample dataset shape', Counter(y_ros))

#### 6. Synthetic Minority Oversampling Technique (SMOTE)

SMOTE（合成少数过采样技术）的工作原理是从少数类中随机选取一个点并计算该点的k近邻。合成点被添加到所选的点和它的相邻点之间。

SMOTE算法通过以下四个简单步骤工作：

1. 选择少数类作为输入向量

2. 查找其k个最近邻（在SMOTE()函数中将k_neighbors指定为参数）

3. 选择这些邻居中的一个，并将合成点放置在连接考虑中的点及其所选邻居的线上的任何位置

4. 重复这些步骤，直到数据平衡

# import library
from imblearn.over_sampling import SMOTE

smote = SMOTE()

# fit predictor and target variable
x_smote, y_smote = smote.fit_resample(x, y)

print('Original dataset shape', Counter(y))
print('Resample dataset shape', Counter(y_ros))

#### 7. NearMiss

NearMiss是欠采样技术。与其使用距离重新采样少数类，不如将多数类等同于少数类。

from imblearn.under_sampling import NearMiss

nm = NearMiss()

x_nm, y_nm = nm.fit_resample(x, y)

print('Original dataset shape:', Counter(y))
print('Resample dataset shape:', Counter(y_nm))

#### 8.更改性能指标

• 混淆矩阵：显示正确预测和错误预测类型的表。

• 精度：真实阳性的数目除以所有阳性预测。精度也称为正预测值。它是分类器准确性的度量。低精度表示大量误报。

• 召回率：真实阳性的数量除以测试数据中的阳性值的数量。召回也称为敏感度或真实阳性率。它是分类器完整性的度量。较低的召回率表示大量假阴性。

• F1：得分：准确性和召回率的加权平均值。

• ROC曲线下面积(AUROC)：AUROC表示模型将观测值与两个类区分开来的可能性。

#### 9.惩罚算法（成本敏感训练）

# load library
from sklearn.svm import SVC

svc_model = SVC(class_weight='balanced', probability=True)

svc_model.fit(x_train, y_train)

svc_predict = svc_model.predict(x_test)# check performance
print('ROCAUC score:',roc_auc_score(y_test, svc_predict))
print('Accuracy score:',accuracy_score(y_test, svc_predict))
print('F1 score:',f1_score(y_test, svc_predict))

#### 10.更改算法

# load library
from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier()

# fit the predictor and target
rfc.fit(x_train, y_train)

# predict
rfc_predict = rfc.predict(x_test)# check performance
print('ROCAUC score:',roc_auc_score(y_test, rfc_predict))
print('Accuracy score:',accuracy_score(y_test, rfc_predict))
print('F1 score:',f1_score(y_test, rfc_predict))

#### 欠采样的优点和缺点

• 当训练数据集很大时，它可以通过减少训练数据样本的数量来帮助改善运行时间和存储问题。

• 它可以丢弃可能有用的信息，这对于构建规则分类器可能很重要。

• 通过随机欠采样选择的样本可能是有偏差的样本。可能导致实际测试数据集的结果不准确。

#### 过采样的优缺点

• 与欠采样不同，此方法不会导致信息丢失。
• 在抽样条件下表现更佳

• 由于它复制了少数群体事件，因此增加了过度拟合的可能性。

### 结论

http://panchuang.net/

sklearn机器学习中文官方文档：
http://sklearn123.com/

http://docs.panchuang.net/