总第97篇

这一篇主要说一下机器学习中非平衡数据的处理方式以及用python如何实现.

在前面的一篇推文中我们提到过,非平衡数据会影响最后的评判效果,严重的会带来过拟合的效果,即模型总是把样本划分到样本量较多的那一种。为了让模型的评判更准确,我们需要对非平衡数据进行一定的处理,主要有以下几种方式:

  • 欠采样

  • 过采样

  • 人工合成

  • 调权重

在开始介绍不同的处理方式之前,我们先引入一组非平衡数据。

#导入一些相关库
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report
from sklearn.metrics import roc_curve, auc
from sklearn.preprocessing import scale
#导入数据
df=pd.read_excel(r"C:\Users\zhangjunhong\Desktop\Unbanlanced-data.xlsx").fillna(0)

看一下正负样本的具体数据量情况。

x=df.iloc[:,1:-1]
y=df["label"]
print(y.value_counts())
print("-------------------------")
print(y.value_counts(normalize=True))

该数据量的正负样本比例接近7:3,我们看一下不做任何处理的情况下,模型的预测效果如何。

#将模型进行封装,方便调用
def get_result_data(x,y):x_=scale(x,with_mean=True,with_std=True)x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.4,random_state=0)model=LogisticRegression()clf=model.fit(x_train,y_train)print("LR模型测试成绩:{:.2f}".format(clf.score(x_test,y_test)))y_pred=clf.predict(x_test)target_names = ['class 0', 'class 1']print(classification_report(y_test, y_pred, target_names=target_names))y_pred1=clf.decision_function(x_test)fpr,tpr,threshold=roc_curve(y_test,y_pred1)rocauc=auc(fpr,tpr)#计算AUCprint("ROC分数:{:.2f}".format(rocauc))if __name__=="__main__":get_result_data(x,y)

模型的准确率是0.75,ROC分数也就是AUC值为0.76,看着还不错,但是class1的召回率要明显高于class0的召回率,这是因为原样本量中,class1的量要明显高于class0的原因。

欠采样

下采样(under-sampling),是对非平衡数据中样本数较多的那一类进行采样,采样使其约等于样本量较少那一类的样本量。

df1=df[df["label"]==1]#正样本部分
df0=df[df["label"]==0]#负样本部分#对正样本按0.5的比例进行下采样
df2=df1.sample(frac=0.5)#将下采样后的正样本与负样本进行组合
df_new=pd.concat([df0,df2])x=df_new.iloc[:,1:-1]
y=df_new["label"]#下采样以后正负样本量情况
print(y.value_counts())
print("-------------------------")
print(y.value_counts(normalize=True))

对模型进行下采样以后,正负样本的样本量基本接近1:1,符合我们目的,接下来看看下采样后的模型表现。

if __name__=="__main__":get_result_data(x,y)

模型的准确率略有下降,但是ROC分数没发生什么变化,class0和class1的召回率也接近相等。

过采样

过采样(over-sampling),是对非平衡数据中样本数较少的那一类进行采样,常规的做法就是将其复制几遍来达到正负样本平衡,因为是同样的数据复制多份,很容易发生过拟合,一般比较少用。具体的实现方式就比较简单啦,这里不罗列。

人工合成

人工合成就是人为地去合成一些样本量较少的数据,来达到正负样本平衡,人工合成数据能够很好地避免过采样带来的模型过拟合。比较常用的方法就是SMOTE。

SMOTE的算法原理如下:

  1. 根据正负样本比例,确认采样的比例,即要合成样本的数量(k值)

  2. 对于少数样本中的每个x,利用KNN算法,选取k个待采样的值x_n

  3. 然后对x_n进行如下运算得到对应的x_new:x_new=x+rand(1)*|x-x_n|

(rand(1)表示生成0-1之间的一个随机数)

关于SMOTE算法的实现也由现成的库,我们直接pip安装就可以使用。

from collections import Counter
from imblearn.over_sampling import SMOTE
print('Original dataset shape {}'.format(Counter(y)))
sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_sample(x, y)
print('Resampled dataset shape {}'.format(Counter(y_res)))

原本正负样本绝对量分别为12193:5617,人工合成部分样本量以后,正负样本的绝对量变为了12193:12193,完全平衡。

人工合成以后模型预测效果

if __name__=="__main__":get_result_data(X_res, y_res)

模型的准确率和ROC分数较欠采样都有略微的上涨,其中class0的召回上涨,class1略降。

调权重

调权重就是调整模型中正负样本的在模型表现中的表决权重,以此来平衡样本绝对量的不平衡。比如正负样本绝对量的比值为1:10,为了抵消这种量级上的不平衡,我们在模型中可以给与模型正负样本10:1的表决权重,也就是10个正样本的表决相当于1个负样本的表决。

这个过程我们也可以直接设置模型参数class_weight="balanced"进行实现。

x_=scale(x,with_mean=True,with_std=True)
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.4,random_state=0)model=LogisticRegression(class_weight="balanced")
clf=model.fit(x_train,y_train)
print("LR模型测试成绩:{:.2f}".format(clf.score(x_test,y_test)))
y_pred=clf.predict(x_test)target_names = ['class 0', 'class 1']
print(classification_report(y_test, y_pred, target_names=target_names))y_pred1=clf.decision_function(x_test)
fpr,tpr,threshold=roc_curve(y_test,y_pred1)
rocauc=auc(fpr,tpr)#计算AUC
print("ROC分数:{:.2f}".format(rocauc))

调权重的结果和人工合成数据的结果接近一致。

最后

通过上面几种方法的模型结果可以看出:

  • 用任意一种方式处理或者不处理,ROC基本是一致的,这也验证了我们在前面的推文中说到的,ROC是和样本是否平衡没关系的。

  • 如果不做任何处理,模型的准确率会高,但是会发生严重的过拟合。

  • 在做处理的这几种方式中,欠采样的效果要差于其他三种。

  • 综合来看,直接在模型参数中调权重是效果最好,也是最快捷的一种方式,不用事先去做什么处理。

本文最后的结论是针对本次数据得出的结论,不代表在任何数据上效果都是如此,可能会限于数据本身的原因,结果会有所不同,本文重点讲述非平衡数据不同的处理方式以及实现方式

如果对本文的一些指标不是很清楚,你可以看:机器学习模型效果评估

机器学习中非平衡数据处理相关推荐

  1. 机器学习︱非平衡数据处理方式与评估

    解决这一问题的基本思路是让正负样本在训练过程中拥有相同的话语权,比如利用采样与加权等方法.为了方便起见,我们把数据集中样本较多的那一类称为"大众类",样本较少的那一类称为" ...

  2. DataScience:深入探讨与分析机器学习中的数据处理之非线性变换—log对数变换、sigmoid/softmax变换

    DataScience:深入探讨与分析机器学习中的数据处理之非线性变换-log对数变换.sigmoid/softmax变换 目录 深入探讨与分析机器学习中的数据处理之非线性变换 log对数变换 sig ...

  3. DataScience:深入探讨与分析机器学习中的数据处理之线性变换—标准化standardization、归一化Normalization/比例化Scaling的区别与联系

    DataScience:深入探讨与分析机器学习中的数据处理之线性变换-标准化standardization.归一化Normalization/比例化Scaling的区别与联系 目录 深入探讨与分析机器 ...

  4. 如何使用机器学习自动修复bug: 数据处理和模型搭建

    如何使用机器学习自动修复bug: 数据处理和模型搭建 上一篇<如何使用机器学习自动修复bug: 上手指南>我们介绍了使用CodeBERT自动修复bug的操作方法. 估计对于很多想了解原理的 ...

  5. 非平衡数据处理方式与评估

    解决这一问题的基本思路是让正负样本在训练过程中拥有相同的话语权,比如利用采样与加权等方法.为了方便起见,我们把数据集中样本较多的那一类称为"大众类",样本较少的那一类称为" ...

  6. 机器学习中原始数据处理的常用数据变换方法整理汇总

    在机器学习进行数据处理前,首先要保证所有数据是无量纲的,并且数据是可以比较的,需要采用标准化方法来消除不同数据之间存在的差异.将原始数据进行处理,变为无量纲可比较的过程实际可以看做是归一化的过程. 目 ...

  7. 【机器学习】平衡你的数据集的几项技巧

    作者 | Praveen Thenraj 编译 | VK 来源 | Towards Data Science "如果你被问题的规模所压倒,把它分解成更小的部分--" 机器学习中的类 ...

  8. Python数据分析与机器学习实战(8)数据处理与转换

    数据处理与转换 编译环境:anaconda Jupyter Notebook import pandas as pd import numpy as np df = pd.read_excel('da ...

  9. 【阿里天池算法学习赛】测测你的一见钟情指数/机器学习/深度学习/数据处理/Python基础

    [阿里天池算法学习赛]测测你的一见钟情指数 地址:https://tianchi.aliyun.com/competition/entrance/531825/introduction?spm=517 ...

最新文章

  1. iMeta | 第1卷第1期在线正式发布(2022/3/28)
  2. 现学现卖微信小程序开发(二)
  3. codevs 4560 NOIP2015 D2T2 子串
  4. 【unity】与Android Activity交互并调用JAVA代码传递参数
  5. log4j.properties log4j.xml 路径问题
  6. 立志10天学会C++基础应用—day01
  7. 微软Kubernetes服务AKS开发正式版空间服务
  8. Tips--tensorboard在win系统中jupyter notebook上打开方式
  9. PAT乙级 1027 打印沙漏
  10. 新版Ubuntu安装日文输入法
  11. day17 appium环境搭建
  12. 九、全面提高人民生话水平
  13. webpack入门1
  14. python report_python之Reportlab模块
  15. JAVA课程设计坦克大战源码
  16. 从URDF到KDL(C++Python)
  17. 1217609-84-1,Biotin-PEG4-alcohol,Biotin-PEG4-OH含有可衍生的伯羟基
  18. 关于人工智能写作的发展以及看法
  19. 韩松手机摄影笔记第三课--经营画面的原则
  20. Android实现ListView下拉刷新思路以及流程

热门文章

  1. winowsformshost 的构造函数执行符合指定的绑定约束的_C# 应该允许为 struct 定义无参构造函数...
  2. eclipse环境lsp4e --- org.eclipse.lsp4e
  3. ptaa乘以b_《C语言程序设计》实验作业--PTA顺序结构练习
  4. tar time stamp in the future问题
  5. 正则表达式实现手机号中间4位数隐藏或者只显示末尾四位数
  6. 理解React-组件生命周期
  7. Nagios(页面)报错: Return code of 13 is out of bounds
  8. 反写规则-销售订单关闭后不允许出库 (销售订单-销售出库单)
  9. 数据类型字符串得索引及切片
  10. shell的变量以及常见符号