【机器学习基础】如何在Python中处理不平衡数据
特征锦囊:如何在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 Counter
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score
import pandas as pd
import numpy as np
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)from sklearn.svm import SVC
from sklearn.metrics import classification_report, roc_auc_score
from 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/1
df['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))# 调用支持向量机算法 SVC
model=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))# 调用支持向量机算法 SVC
model=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 SMOTE
from imblearn.under_sampling import RandomUnderSampler
from 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 SMOTE
from imblearn.under_sampling import RandomUnderSampler
from imblearn.pipeline import Pipeline# 划分因变量和自变量
X = df.iloc[:,:-1]
y = df.iloc[:,-1]# values to evaluate
over_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 pipelinemodel = SVC()over = SMOTE(sampling_strategy=o)under = RandomUnderSampler(sampling_strategy=u)steps = [('over', over), ('under', under), ('model', model)]pipeline = Pipeline(steps=steps)# evaluate pipelinescores = 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
往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载机器学习的数学基础专辑
获取本站知识星球优惠券,复制链接直接打开:
https://t.zsxq.com/y7uvZF6
本站qq群704220115。加入微信群请扫码:
【机器学习基础】如何在Python中处理不平衡数据相关推荐
- linux中python如何调用matlab的数据_特征锦囊:如何在Python中处理不平衡数据
今日锦囊 特征锦囊:如何在Python中处理不平衡数据 ? Index 1.到底什么是不平衡数据 2.处理不平衡数据的理论方法 3.Python里有什么包可以处理不平衡样本 4.Python中具体如何 ...
- python构造icmp数据包_如何在python中构造ICMP数据包
为了学习,我目前正在尝试创建一个简单的python porgram来向某个设备发送ICMP ping数据包.为了开始,我查看了python模块Pyping:https://github.com/Akh ...
- pythonstdin_如何在Python中执行将数据写入stdin的进程?
我的 Python脚本中有一个标志,指定我是否设置和使用外部进程.此过程是一个名为my_command的命令,它从标准输入中获取数据.如果我在命令行上运行它,它将是这样的: $my_command & ...
- python解析http数据包_如何在python中嗅探HTTP数据包?
I want to sniff all the HTTP packets in my computer via python(version2.6.. is this possible? can I ...
- python中如何画logistic_如何在 Python 中建立和训练线性和 logistic 回归 ML 模型?
原标题:如何在 Python 中建立和训练线性和 logistic 回归 ML 模型? 英语原文: 翻译:(Key.君思) 线性回归与logistic回归,是. 在我的里,你们已经学习了线性回归机器学 ...
- 如何在Python中建立回归模型
数据科学 (DATA SCIENCE) If you are an aspiring data scientist or a veteran data scientist, this article ...
- python set 排序_python set 排序_如何在Python中使用sorted()和sort()
点击"蓝字"关注我们 ?"Python基础知识" 大卫·丰达科夫斯基 著 18财税3班 李潇潇 译 日期:2019年5月6日 一. 使用sorted() ...
- 什么是python中子类父类_零基础入门:python中子类继承父类的__init__方法实例
前言: 今天为大家带来的内容是零基础入门:python中子类继承父类的__init__方法实例!具有不错的参考意义,希望在此能够帮助到各位!(喜欢的话记得点赞转发关注不迷路哦) 使用Python写过面 ...
- python中knn_如何在python中从头开始构建knn
python中knn k最近邻居 (k-Nearest Neighbors) k-Nearest Neighbors (KNN) is a supervised machine learning al ...
最新文章
- 【JavaScript总结】JavaScript语法基础:数据类型
- cpu安装_CPU是AMD的,老台式电脑可以加装固态硬盘安装Win10系统吗?
- linux 内核钩子 khook 项目介绍
- 美媒看衰马斯克超级高铁:纽约到华盛顿挖隧道要挖100年
- 【linux】截断日志文件
- figma下载_在Figma中进行原型制作的技巧和窍门
- vit-pytorch
- Struts12---文件的下载
- But don‘t be fooled, this phone does not
- android——根据MVC框架设计的结构
- sip协议的功能及其应用
- 电钢琴插件:Applied Acoustics Systems Lounge Lizard EP-4 for Mac
- python支持强大的科学计算功能_Python可以做什么——Python语言的一个简要导引
- python地震数据处理_Python爬虫之实时地震数据
- 使用CrossApp实现版本更新管理(iOS端给AppStore链接,android端下载apk并替换)
- rose怎么画业务流程图_子流程图怎么画(流程图中的子流程)
- eclipse Helio项目简介
- mysql交并补_集合交并补运算顺序是什么?
- 蓝桥杯单片机备战(四)共阳数码管的静态显示
- 什么是UserAgent
热门文章
- .net中的socket异步通信实现--客户端代码
- The Design and Implementation of Open vSwitch
- 抽取随即人员——SqlServer_Proc_Random
- php+nginx上传文件配置
- MySQL创建用户与授权方法
- JS常用的设计模式(7)—— 外观模式
- 图解面向对象中的聚合与耦合概念
- win2003+sql2005配置
- [转]JS中判断鼠标按键判断
- Python DataFrame数据清洗后行索引不连续——reset_index