最近在做一个分类问题,结果样本分布不均衡,因此查阅了一些资料,大家共勉
Python库中Imblearn是专门用于处理不平衡数据
安装参考:anaconda上面安装imblearn包
引言
样本类别分布不均衡,即数据集中存在某一类样本,其数量远多于或远少于其他类样本,从而导致一些机器学习模型失效的问题。
样本类别不均衡将导致样本量少的分类所包含的特征过少,并很难从中提取规律;即使得到分类模型,也容易产生过度依赖与有限的数据样本而导致过拟合问题,当模型应用到新的数据上时,模型的准确性会很差。
解决方法
常见的解决方法有
一、 过采样(over-sampling)
对不均衡数据中样本减少的一类重复采样,通过增加分类中少数类样本的数量来实现样本均衡
1. 随机过采样
随机的复制、重复少数类样本(从少数类样本集中随机重复抽取样本(有放回)以得到更多的样本),最终使得少数类与多数类的个数相同从而得到一个新的均衡的数据集。
这种方法实现简单,但会由于数据较为单一而容易造成过拟合
from imblearn.over_sampling import RandomOverSampler
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的时候出现了一个报错:
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
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))
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))
参考:不平衡数据处理之SMOTE、Borderline SMOTE和ADASYN详解及Python使用
SMOTE改进
参考: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 方法的不均衡分类性能最优
转自:不均衡学习的抽样方法