今日锦囊

特征锦囊:如何在Python中处理不平衡数据

? Index

1、到底什么是不平衡数据

2、处理不平衡数据的理论方法

3、Python里有什么包可以处理不平衡样本

4、Python中具体如何处理失衡样本

印象中很久之前有位朋友说要我写一篇如何处理不平衡数据的文章,整理相关的理论与实践知识(可惜本人太懒了,现在才开始写),于是乎有了今天的文章。失衡样本在我们真实世界中是十分常见的,那么我们在机器学习(ML)中使用这些失衡样本数据会出现什么问题呢?如何处理这些失衡样本呢?以下的内容希望对你有所帮助!

? 到底什么是不平衡数据

失衡数据发生在分类应用场景中,在分类问题中,类别之间的分布不均匀就是失衡的根本,假设有个二分类问题,target为y,那么y的取值范围为0和1,当其中一方(比如y=1)的占比远小于另一方(y=0)的时候,就是失衡样本了。

那么到底是需要差异多少,才算是失衡呢,根本Google Developer的说法,我们一般可以把失衡分为3个程度:

  • 轻度:20-40%
  • 中度:1-20%
  • 极度:<1%

一般来说,失衡样本在我们构建模型的时候看不出什么问题,而且往往我们还可以得到很高的accuracy,为什么呢?假设我们有一个极度失衡的样本,y=1的占比为1%,那么,我们训练的模型,会偏向于把测试集预测为0,这样子模型整体的预测准确性就会有一个很好看的数字,如果我们只是关注这个指标的话,可能就会被骗了。

? 处理不平衡数据的理论方法

在我们开始用Python处理失衡样本之前,我们先来了解一波关于处理失衡样本的一些理论知识,前辈们关于这类问题的解决方案,主要包括以下:

  • 从数据角度:通过应用一些欠采样or过采样技术来处理失衡样本。欠采样就是对多数类进行抽样,保留少数类的全量,使得两类的数量相当,过采样就是对少数类进行多次重复采样,保留多数类的全量,使得两类的数量相当。但是,这类做法也有弊端,欠采样会导致我们丢失一部分的信息,可能包含了一些重要的信息,过采样则会导致分类器容易过拟合。当然,也可以是两种技术的相互结合。
  • 从算法角度:算法角度的解决方案就是可以通过对每类的训练实例给予一定权值的调整。比如像在SVM这样子的有参分类器中,可以应用grid search(网格搜索)以及交叉验证(cross validation)来优化C以及gamma值。而对于决策树这类的非参数模型,可以通过调整树叶节点上的概率估计从而实现效果优化。

此外,也有研究员从数据以及算法的结合角度来看待这类问题,提出了两者结合体的AdaOUBoost(adaptive over-sampling and undersampling boost)算法,这个算法的新颖之处在于自适应地对少数类样本进行过采样,然后对多数类样本进行欠采样,以形成不同的分类器,并根据其准确度将这些子分类器组合在一起从而形成强大的分类器,更多的请参考:

AdaOUBoost:https://dl.acm.org/doi/10.1145/1743384.1743408

? Python里有什么包可以处理不平衡样本

这里介绍一个很不错的包,叫 imbalanced-learn,大家可以在电脑上安装一下使用。

官方文档:https://imbalanced-learn.readthedocs.io/en/stable/index.html

pip install -U imbalanced-learn

使用上面的包,我们就可以实现样本的欠采样、过采样,并且可以利用pipeline的方式来实现两者的结合,十分方便,我们下一节来简单使用一下吧!

? Python中具体如何处理失衡样本

为了更好滴理解,我们引入一个数据集,来自于UCI机器学习存储库的营销活动数据集。(数据集大家可以自己去官网下载:https://archive.ics.uci.edu/ml/machine-learning-databases/00222/  下载bank-additional.zip 或者到公众号后台回复关键字“bank”来获取吧。)

我们在完成imblearn库的安装之后,就可以开始简单的操作了(其余更加复杂的操作可以直接看官方文档),以下我会从4方面来演示如何用Python处理失衡样本,分别是:

? 1、随机欠采样的实现

? 2、使用SMOTE进行过采样

? 3、欠采样和过采样的结合(使用pipeline)

? 4、如何获取最佳的采样率?

??? 那我们开始吧!
# 导入相关的库(主要就是imblearn库)from collections import Counterfrom sklearn.model_selection import train_test_splitfrom sklearn.model_selection import cross_val_scoreimport pandas as pdimport numpy as npimport warningswarnings.simplefilter(action='ignore', category=FutureWarning)

from sklearn.svm import SVCfrom sklearn.metrics import classification_report, roc_auc_scorefrom numpy import mean

# 导入数据df = pd.read_csv(r'./data/bank-additional/bank-additional-full.csv', ';') # '';'' 为分隔符df.head()

数据集是葡萄牙银行的某次营销活动的数据,其营销目标就是让客户订阅他们的产品,然后他们通过与客户的电话沟通以及其他渠道获取到的客户信息,组成了这个数据集。

关于字段释义,可以看下面的截图:

我们可以大致看看数据集是不是失衡样本:

df['y'].value_counts()/len(df)

#no     0.887346#yes    0.112654#Name: y, dtype: float64

可以看出少数类的占比为11.2%,属于中度失衡样本

# 只保留数值型变量(简单操作)df = df.loc[:,['age', 'duration', 'campaign', 'pdays',       'previous', 'emp.var.rate', 'cons.price.idx',       'cons.conf.idx', 'euribor3m', 'nr.employed','y']]# target由 yes/no 转为 0/1df['y'] = df['y'].apply(lambda x: 1 if x=='yes' else 0)df['y'].value_counts()

#0    36548#1     4640#Name: y, dtype: int64
? 1、随机欠采样的实现

欠采样在imblearn库中也是有方法可以用的,那就是 under_sampling.RandomUnderSampler,我们可以使用把方法引入,然后调用它。可见,原先0的样本有21942,欠采样之后就变成了与1一样的数量了(即2770),实现了50%/50%的类别分布。

# 1、随机欠采样的实现# 导入相关的方法from imblearn.under_sampling import RandomUnderSampler

# 划分因变量和自变量X = df.iloc[:,:-1]y = df.iloc[:,-1]

# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.40)

# 统计当前的类别占比情况print("Before undersampling: ", Counter(y_train))

# 调用方法进行欠采样undersample = RandomUnderSampler(sampling_strategy='majority')

# 获得欠采样后的样本X_train_under, y_train_under = undersample.fit_resample(X_train, y_train)

# 统计欠采样后的类别占比情况print("After undersampling: ", Counter(y_train_under))

# 调用支持向量机算法 SVCmodel=SVC()

clf = model.fit(X_train, y_train)pred = clf.predict(X_test)print("ROC AUC score for original data: ", roc_auc_score(y_test, pred))

clf_under = model.fit(X_train_under, y_train_under)pred_under = clf_under.predict(X_test)print("ROC AUC score for undersampled data: ", roc_auc_score(y_test, pred_under))

# Output:#Before undersampling:  Counter({0: 21942, 1: 2770})#After undersampling:  Counter({0: 2770, 1: 2770})#ROC AUC score for original data:  0.603521152028#ROC AUC score for undersampled data:  0.829234085179

? 2、使用SMOTE进行过采样

过采样技术中,SMOTE被认为是最为流行的数据采样算法之一,它是基于随机过采样算法的一种改良版本,由于随机过采样只是采取了简单复制样本的策略来进行样本的扩增,这样子会导致一个比较直接的问题就是过拟合。因此,SMOTE的基本思想就是对少数类样本进行分析并合成新样本添加到数据集中。

算法流程如下:

(1)对于少数类中每一个样本x,以欧氏距离为标准计算它到少数类样本集中所有样本的距离,得到其k近邻。

(2)根据样本不平衡比例设置一个采样比例以确定采样倍率N,对于每一个少数类样本x,从其k近邻中随机选择若干个样本,假设选择的近邻为xn。

(3)对于每一个随机选出的近邻xn,分别与原样本按照如下的公式构建新的样本。

# 2、使用SMOTE进行过采样# 导入相关的方法from imblearn.over_sampling import SMOTE

# 划分因变量和自变量X = df.iloc[:,:-1]y = df.iloc[:,-1]

# 划分训练集和测试集X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.40)

# 统计当前的类别占比情况print("Before oversampling: ", Counter(y_train))

# 调用方法进行过采样SMOTE = SMOTE()

# 获得过采样后的样本X_train_SMOTE, y_train_SMOTE = SMOTE.fit_resample(X_train, y_train)

# 统计过采样后的类别占比情况print("After oversampling: ",Counter(y_train_SMOTE))

# 调用支持向量机算法 SVCmodel=SVC()

clf = model.fit(X_train, y_train)pred = clf.predict(X_test)print("ROC AUC score for original data: ", roc_auc_score(y_test, pred))

clf_SMOTE= model.fit(X_train_SMOTE, y_train_SMOTE)pred_SMOTE = clf_SMOTE.predict(X_test)print("ROC AUC score for oversampling data: ", roc_auc_score(y_test, pred_SMOTE))

# Output:#Before oversampling:  Counter({0: 21980, 1: 2732})#After oversampling:  Counter({0: 21980, 1: 21980})#ROC AUC score for original data:  0.602555700614#ROC AUC score for oversampling data:  0.844305732561

? 3、欠采样和过采样的结合(使用pipeline)

那如果我们需要同时使用过采样以及欠采样,那该怎么做呢?其实很简单,就是使用 pipeline来实现。

#  3、欠采样和过采样的结合(使用pipeline)# 导入相关的方法from imblearn.over_sampling import SMOTEfrom imblearn.under_sampling import RandomUnderSamplerfrom imblearn.pipeline import Pipeline

# 划分因变量和自变量X = df.iloc[:,:-1]y = df.iloc[:,-1]

#  定义管道model = SVC()over = SMOTE(sampling_strategy=0.4)under = RandomUnderSampler(sampling_strategy=0.5)steps = [('o', over), ('u', under), ('model', model)]pipeline = Pipeline(steps=steps)

# 评估效果scores = cross_val_score(pipeline, X, y, scoring='roc_auc', cv=5, n_jobs=-1)score = mean(scores)print('ROC AUC score for the combined sampling method: %.3f' % score)

# Output:#ROC AUC score for the combined sampling method: 0.937

? 4、如何获取最佳的采样率?

在上面的栗子中,我们都是默认经过采样变成50:50,但是这样子的采样比例并非最优选择,因此我们引入一个叫 最佳采样率的概念,然后我们通过设置采样的比例,采样网格搜索的方法去找到这个最优点。

# 4、如何获取最佳的采样率?# 导入相关的方法from imblearn.over_sampling import SMOTEfrom imblearn.under_sampling import RandomUnderSamplerfrom imblearn.pipeline import Pipeline

# 划分因变量和自变量X = df.iloc[:,:-1]y = df.iloc[:,-1]

# values to evaluateover_values = [0.3,0.4,0.5]under_values = [0.7,0.6,0.5]for o in over_values:  for u in under_values:    # define pipeline    model = SVC()    over = SMOTE(sampling_strategy=o)    under = RandomUnderSampler(sampling_strategy=u)    steps = [('over', over), ('under', under), ('model', model)]    pipeline = Pipeline(steps=steps)    # evaluate pipeline    scores = cross_val_score(pipeline, X, y, scoring='roc_auc', cv=5, n_jobs=-1)    score = mean(scores)    print('SMOTE oversampling rate:%.1f, Random undersampling rate:%.1f , Mean ROC AUC: %.3f' % (o, u, score))

# Output:    #SMOTE oversampling rate:0.3, Random undersampling rate:0.7 , Mean ROC AUC: 0.938#SMOTE oversampling rate:0.3, Random undersampling rate:0.6 , Mean ROC AUC: 0.936#SMOTE oversampling rate:0.3, Random undersampling rate:0.5 , Mean ROC AUC: 0.937#SMOTE oversampling rate:0.4, Random undersampling rate:0.7 , Mean ROC AUC: 0.938#SMOTE oversampling rate:0.4, Random undersampling rate:0.6 , Mean ROC AUC: 0.937#SMOTE oversampling rate:0.4, Random undersampling rate:0.5 , Mean ROC AUC: 0.938#SMOTE oversampling rate:0.5, Random undersampling rate:0.7 , Mean ROC AUC: 0.939#SMOTE oversampling rate:0.5, Random undersampling rate:0.6 , Mean ROC AUC: 0.938#SMOTE oversampling rate:0.5, Random undersampling rate:0.5 , Mean ROC AUC: 0.938

从结果日志来看,最优的采样率就是过采样0.5,欠采样0.7。

最后,想和大家说的是没有绝对的套路,只有合适的套路,无论是欠采样还是过采样,只有合适才最重要。还有,欠采样的确会比过采样“省钱”哈(从训练时间上很直观可以感受到)。

? References

[1] SMOTE算法 https://www.jianshu.com/p/13fc0f7f5565

[2] How to deal with imbalanced data in Python

往 期 锦 囊

特征锦囊:特征无量纲化的常见操作方法

特征锦囊:怎么进行多项式or对数的数据变换?

特征锦囊:常用的统计图在Python里怎么画?

特征锦囊:怎么去除DataFrame里的缺失值?

特征锦囊:怎么把被错误填充的缺失值还原?

特征锦囊:怎么定义一个方法去填充分类变量的空值?

特征锦囊:怎么定义一个方法去填充数值变量的空值?

特征锦囊:怎么把几个图表一起在同一张图上显示?

特征锦囊:怎么把画出堆积图来看占比关系?

特征锦囊:怎么对满足某种条件的变量修改其变量值?

特征锦囊:怎么通过正则提取字符串里的指定内容?

特征锦囊:如何利用字典批量修改变量值?

特征锦囊:如何对类别变量进行独热编码?

特征锦囊:如何把“年龄”字段按照我们的阈值分段?

特征锦囊:如何使用sklearn的多项式来衍生更多的变量?

特征锦囊:如何根据变量相关性画出热力图?

特征锦囊:如何把分布修正为类正态分布?

特征锦囊:怎么找出数据集中有数据倾斜的特征?

特征锦囊:怎么尽可能地修正数据倾斜的特征?

特征锦囊:怎么简单使用PCA来划分数据且可视化呢?

特征锦囊:怎么简单使用LDA来划分数据且可视化呢?

特征锦囊:怎么来管理我们的建模项目文件?

特征锦囊:怎么批量把特征中的离群点给“安排一下”?特征锦囊:彻底了解一下WOE和IV特征锦囊:一文介绍特征工程里的卡方分箱,附代码实现

特征锦囊:今天一起搞懂机器学习里的L1与L2正则化

特征锦囊:金融风控里的WOE前的分箱一定要单调吗?

 ? GitHub传送门 

https://github.com/Pysamlam/Tips-of-Feature-engineering

原创不易,如果觉得这种学习方式有用,希望可以帮忙随手转发or点下“在看”,这是对我的极大鼓励!阿里嘎多!?

linux中python如何调用matlab的数据_特征锦囊:如何在Python中处理不平衡数据相关推荐

  1. python读取matlab数据_详解如何在python中读写和存储matlab的数据文件(*.mat)

    背景 在做deeplearning过程中,使用caffe的框架,一般使用matlab来处理图片(matlab处理图片相对简单,高效),用python来生成需要的lmdb文件以及做test产生结果.所以 ...

  2. python能调用身份证读卡器吗_华视身份证读卡机Python二次开发

    最近项目中用到华视身份证读卡机,那么本篇文章就是根据Python代码来实现对华视身份证读卡机中读卡操作. 华视身份证阅读器SDK手册 下面是官方提供的SDK使用手册,我就不描述到本篇文章中了,相信大家 ...

  3. java中没有直接调用matlab的接口函数

    java中没有直接调用matlab的接口函数,在通常的情况下我们是通过借用C++作为中间过程来实现的,使用C++主要是用c与matlab的结构实现c调用matlab的功能,将这些功能函数封装成dll文 ...

  4. 特征锦囊:怎么找出数据集中有数据倾斜的特征?

    今日锦囊 特征锦囊:怎么找出数据集中有数据倾斜的特征? 今天我们用的是一个新的数据集,也是在kaggle上的一个比赛,大家可以先去下载一下: 下载地址:https://www.kaggle.com/c ...

  5. linux中python如何调用matlab的数据_?如何在Python中加入多个数据帧?

    全文共2235字,预计学习时长7分钟 来源:Pexels 初学Python编程的人,面临的是各种未知的挑战. 下面是一个几乎让所有更有抱负的数据科学家都感到意外的场景: 你正在处理一个从多个源收集数据 ...

  6. python能调用身份证读卡器吗_用Python在Linux下调用新中新DKQ-A16D读卡器,读二代证数据...

    1.背景 最近在研究二代证读卡器,手头上的设备是新中新DKQ-A16D,在官网(https://www.onecardok.com.cn/download)逛了一圈,发现Win下的示例,浏览器插件很多 ...

  7. 如何在python中调用MATLAB代码(利用anaconda完美解决多python环境问题)

    不知道有没有小伙伴遇到和我一样的问题,需要在python代码中使用MATLAB代码运行得到的结果,但是如果直接将MATLAB改写成python,工作量又被加大 那么这时候就需要利用官方给出的方法,在p ...

  8. python读取matlab数据_两分钟搞定Python读取matlab的.mat数据

    Matlab是学术界非常受欢迎的科学计算平台,matlab提供强大的数据计算以及仿真功能.在Matlab中数据集通常保存为.mat格式.那么如果我们想要在Python中加载.mat数据应该怎么办呢?所 ...

  9. codeblocks调用matlab,matlab engine: 在Codeblocks中使用C++调用matlab | 学步园

    平台:XP,Code::Blocks 10.05(包含gcc 4.4.1),matlab 2010b 方式:C++调用matlab引擎 设置步骤: (一)系统变量:path中添加MinGW\bin; ...

最新文章

  1. 应用设计模式进行重构来消除坏味道
  2. 我用Redis实现了一个轻量级的搜索引擎!
  3. C中 #define
  4. vertx核心类之VertxImpl
  5. 题目1184:二叉树遍历
  6. Office 365 Exchange 2016 混合部署前准备
  7. oracle中序列号的使用
  8. 打造大数据和AI能力底座 联通大数据深度参与“新基建”
  9. KVO 实现两个页面之间的通信
  10. Flink Java 使用map reduce实现wordcount
  11. SQL PASS西雅图之行——会议篇
  12. 第00次博文——我对Python的期待与思考
  13. 从零开始写个编译器吧 - 程序流控制
  14. [杂谈] 2013年新目标
  15. JAVA类加载的委托模型
  16. 深度学习(十五)基于级联卷积神经网络的人脸特征点定位-CVPR 2013
  17. 用python写的,一个中英文转摩斯电码小程序
  18. u8反启用固定资产_用友怎么取消固定资产模块
  19. IPhone手机无法连接蓝牙
  20. 米塔之家.方声 | 专访元宇宙社交平台“比邻星球”联合创始人兼CEO董含灵

热门文章

  1. Lecture 3 Divide and Conquer
  2. 前嗅ForeSpider教程:创建模板
  3. 用C#写 四舍五入函数(原理版)
  4. Puppet 之 模板和模块
  5. 带彩色字体的man pages(debian centos)
  6. 【转】spin_lock、spin_lock_irq、spin_lock_irqsave区别
  7. 【swift学习笔记】三.使用xib自定义UITableViewCell
  8. poxtfix+dovecot+saslauthd+courier-authlib +mysql + extmail 完整虚拟邮箱系统部署
  9. keepalived实现高可用nginx反向代理的简单案例
  10. java判断题_【Java判断题】请大神们进来看下、这些判断题你都知道多少~