样本类别分布不均衡方法

最近在做一个分类问题,结果样本分布不均衡,因此查阅了一些资料,大家共勉
Python库中Imblearn是专门用于处理不平衡数据
安装参考:anaconda上面安装imblearn包

引言

样本类别分布不均衡,即数据集中存在某一类样本,其数量远多于或远少于其他类样本,从而导致一些机器学习模型失效的问题。

样本类别不均衡将导致样本量少的分类所包含的特征过少,并很难从中提取规律;即使得到分类模型,也容易产生过度依赖与有限的数据样本而导致过拟合问题,当模型应用到新的数据上时,模型的准确性会很差。

解决方法

常见的解决方法有

一、 过采样(over-sampling)

对不均衡数据中样本减少的一类重复采样,通过增加分类中少数类样本的数量来实现样本均衡

1. 随机过采样

随机的复制、重复少数类样本(从少数类样本集中随机重复抽取样本(有放回)以得到更多的样本),最终使得少数类与多数类的个数相同从而得到一个新的均衡的数据集。
这种方法实现简单,但会由于数据较为单一而容易造成过拟合

from imblearn.over_sampling import RandomOverSampler

imblearn:随机过采样(过采样)

2. SMOTE

通过插值的方式加入近邻的数据点。简单来说smote算法的思想是合成新的少数类样本,合成的策略是对每个少数类样本a,从它的最近邻中随机选一个样本b,然后在a、b之间的连线上随机选一点作为新合成的少数类样本。
SMOTE实现简单,但其弊端也很明显,由于SMOTE对所有少数类样本一视同仁,并未考虑近邻样本的类别信息,往往出现样本混叠现象,导致分类效果不佳。

from collections import Counter
from sklearn.datasets import make_classification
from imblearn.over_sampling import SMOTE
X, y = make_classification(n_classes=2, class_sep=2,
                           weights=[0.1, 0.9], n_informative=2, n_redundant=0, flip_y=0,
                           n_features=2, n_clusters_per_class=1, n_samples=100,random_state=10)
print('Original dataset shape %s' % Counter(y))

sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_resample(X, y)
print('Resampled dataset shape %s' % Counter(y_res))
smote.png

我在使用SMOTE的时候出现了一个报错:

ValueError: Expected n_neighbors <= n_samples,  but n_samples = 1, n_neighbors = 6

原来是因为异常样本过少,有的只有1个,比smote算法中默认近邻个数少,需进行手动修改参数k_neighbors。

oversampler=SMOTE(ratio='auto',random_state=0,k_neighbors=2,m_neighbors=10,out_step=0.5,kind='regular',svm_estimator=None,n_jobs=1)

3. Borderline SMOTE

Borderline SMOTE是在SMOTE基础上改进的过采样算法,该算法仅使用边界上的少数类样本来合成新样本,从而改善样本的类别分布。
  Borderline SMOTE采样过程是将少数类样本分为3类,分别为Safe、Danger和Noise,具体说明如下。最后,仅对表为Danger的少数类样本过采样。
  Safe,样本周围一半以上均为少数类样本,如图中点A
  Danger:样本周围一半以上均为多数类样本,视为在边界上的样本,如图中点B
  Noise:样本周围均为多数类样本,视为噪音,如图中点C


bdsomte.png

Borderline-SMOTE又可分为Borderline-SMOTE1和Borderline-SMOTE2,Borderline-SMOTE1在对Danger点生成新样本时,在K近邻随机选择少数类样本(与SMOTE相同),Borderline-SMOTE2则是在k近邻中的任意一个样本(不关注样本类别)

from collections import Counter
from sklearn.datasets import make_classification
from imblearn.over_sampling import BorderlineSMOTE
X, y = make_classification(n_classes=2, class_sep=2,
                           weights=[0.1, 0.9], n_informative=2, n_redundant=0, flip_y=0,
                           n_features=2, n_clusters_per_class=1, n_samples=100, random_state=9)
print('Original dataset shape %s' % Counter(y))
sm = BorderlineSMOTE(random_state=42,kind="borderline-1")
X_res, y_res = sm.fit_resample(X, y)
print('Resampled dataset shape %s' % Counter(y_res))
bdsotecom.png

4. 自适应合成抽样算法 (ADASYN)

ADASYN (adaptive synthetic sampling)自适应合成抽样,与Borderline SMOTE相似,对不同的少数类样本赋予不同的权重,从而生成不同数量的样本

from collections import Counter
from sklearn.datasets import make_classification
from imblearn.over_sampling import ADASYN
X, y = make_classification(n_classes=2, class_sep=2,
                           weights=[0.1, 0.9], n_informative=3, n_redundant=1, flip_y=0,
                           n_features=20, n_clusters_per_class=1, n_samples=1000,
                           random_state=10)
print('Original dataset shape %s' % Counter(y))
ada = ADASYN(random_state=42)
X_res, y_res = ada.fit_resample(X, y)
print('Resampled dataset shape %s' % Counter(y_res))

adasyn.png

参考:不平衡数据处理之SMOTE、Borderline SMOTE和ADASYN详解及Python使用

SMOTE改进

smote_compare.png

参考:SMOTE过采样处理不均衡数据(imbalanced data)

5. 基于聚类的过采样

先对数据进行聚类,然后对聚类后的数据分别进行过采样。这种方法能够降低类间和类内的不平衡

6. 神经网络中的过采样

SGD训练时,保证每个batch内部样本均衡

二、 欠采样

对不均衡数据中样本较多的一类进行采样,使其约等于样本量较少的一类。主要是移除数据量较多类别中的部分数据。

1. Prototype generation(原型生成)

算法即对多数类样本生成新的样本去替代原样本,使得样本数目减少,且新样本是生成的而不是选取的

from imblearn.under_sampling import ClusterCentroids
cc = ClusterCentroids(random_state=0)
X_resampled, y_resampled = cc.fit_resample(X,y)

2. Prototype selection (原型选择)

算法即从原数据集(original set)中选取一些样本,根据选取思路主要分为以下两类

2.1 the controlled under-sampling techniques

会严格控制下采样后正例的样本量
有如下几种方法:

1. RandomUnderSampler 直接随机选取删除法

from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=0)
X_resampled, y_resampled = rus.fit_resample(X, y)
print(sorted(Counter(y_resampled).items())

注意1:当设置replacement=True时,采用bootstrap
注意2: 允许非结构化数据,例如数据中含字符串

2.NearMiss 基于NN启发式算法

from imblearn.under_sampling import NearMiss
nm1 = NearMiss(version=1)
X_resampled_num1, y_resampled = nm1.fit_resample(X, y)

version=1:选取正例样本中与N个最近邻负样本平均距离最短的样本
version=2:选取正例样本中与N个最远邻负样本平均距离最短的样
version=3:2-steps 算法,首先对于每个负类样本,他们的M近邻正样本保留。然后,选取到N近邻负平均聚类最大。

2.2 Cleaning under-sampling techniques

采取启发式算法删除正例样本,不严格控制下采样后正例的样本量
有如下几种方法:
1.Tomek’s link (TomeLinks)
2.Edited data set using neareast neighbours(EditeNearestNeighbours)
运用一个NN算法并通过移除与他们的近邻not agree "enough"的方式来’edit’数据集。

from imblearn.under_sampling import EditedNearestNeighbours
enn = EditedNearestNeighbours()
X_resampled, y_resampled = enn.fit_resample(X, y)

目前有两个准则:: kind_sel='mode’和 kind_sel=‘all’
这个算法只执行一次

变体:RepeatedEditedNearestNeighbours
算法比起EditeNearestNeighbours的改进为:自动重复ENN算法多次。

from imblearn.under_sampling import RepeatedEditedNearestNeighbours
renn = RepeatedEditedNearestNeighbours()

变体:ALLKNN
算法比起RepeatedEditedNearestNeighbours,改进为:在每次迭代会KNN中邻居的数目都会增多。

from imblearn.under_sampling import RepeatedEditedNearestNeighbours
renn = RepeatedEditedNearestNeighbours()

3.Condensed(浓缩的) nearest neighbors and derived algorithms(CondensedNearestNeighbour)
使用一个1近邻原则迭代地决定是否移除一个样本,缺点是对噪声太敏感。

from imblearn.under_sampling import CondensedNearestNeighbour
cnn = CondensedNearestNeighbour(random_state=0)

Step1:把所有负类样本放到集合C
Step2:从要进行下采样的类中选取一个元素加入C,该类其它集合加入S
Step3:遍历S,对每个元素进行采样,采用1-NN算法进行分类,将分类错误的加入C
Step4:迭代S直到没有元素要加入C

变体:OneSideSelection
与CondensedNearestNeighbour相比,使用TomeLinks来remove noisy samples.

from imblearn.under_sampling import OneSidedSelection
oss = OneSidedSelection(random_state=0)

变体:NeighbourhoodCleaningRule
use the nnion of samples to be rejected between the ENN and the output a 3-NN分类.

from imblearn.under_sampling import NeighbourhoodCleaningRule
ncr = NeighbourhoodCleaningRule()

4.Instance hardness threshold(InstanceHardnessThreshold)
在数据集中训练一个分类器,并且样本带有低概率会被移除。

from sklearn.linear_model import LogisticRegression
from imblearn.under_sampling import InstanceHardnessThreshold
iht = InstanceHardnessThreshold(random_state=0,
                                 estimator=LogisticRegression(
                                     solver='lbfgs', multi_class='auto')

estimator可以接受任何有一个method predict_proba的scikit-learn分类

欠采样部分转载自:python imblearn toolbox 解决数据不平衡问题(三)——under-sampling下采样

5. K-近邻(KNN)

基于给定数据的分布特征,有四种 KNN 欠抽样方法:

1. NearMiss-1
选择到最近的三个少数类样本平均距离最小的那些多数类样本

2. NearMiss-2
选择到最远的三个少数类样本平均距离最小的那些多数类样本

3. NearMiss-3
为每个少数类样本选择给定数目的最近多数类样本,目的是保证每个少数类样本都被一些多数类样本包围

4. 最远距离
选择到最近的三个少数类样本平均距离最大的那些多数类样本

Note:实验结果表明 NearMiss-2 方法的不均衡分类性能最优

转自:不均衡学习的抽样方法

3 改变原数据权值

【机器学习】处理样本不均衡问题的方法,样本权重的处理方法及代码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351