smote算法

平时很多分类问题都会面对样本不均衡的问题,很多算法在这种情况下分类效果都不够理想。针对不均衡问题,一般有采样和代价敏感学习两种策略,采样的话又分为over-sampling和under-sampling。其中,smote算法算是over-sampling中比较常用的一种。

smote算法的思想是合成新的少数类样本,合成的策略是对每个少数类样本a,从它的最近邻中随机选一个样本b,然后在a、b之间的连线上随机选一点作为新合成的少数类样本。
论文地址:https://www.jair.org/media/953/live-953-2037-jair.pdf
下图是论文中给出的smote伪代码。

smote算法_第1张图片

#encoding=gbk
from sklearn.neighbors import NearestNeighbors
import numpy as np
import random
class Smote:
    #samples的最后一列是类标,都是1
    def __init__(self, samples, N=10,k=5):
        self.n_samples, self.n_attrs=samples.shape
        self.N=N
        self.k=k
        self.samples=samples

    def over_sampling(self):
        if self.N<100:
            old_n_samples=self.n_samples
            print "old_n_samples", old_n_samples
            self.n_samples=int(float(self.N)/100*old_n_samples)
            print "n_samples", self.n_samples
            keep=np.random.permutation(old_n_samples)[:self.n_samples]
            print "keep", keep
            new_samples=self.samples[keep]
            print "new_samples", new_samples
            self.samples=new_samples
            print "self.samples", self.samples
            self.N=100

        N=int(self.N/100) #每个少数类样本应该合成的新样本个数
        self.synthetic=np.zeros((self.n_samples*N, self.n_attrs))
        self.new_index=0

        neighbors=NearestNeighbors(n_neighbors=self.k).fit(self.samples)
        print "neighbors", neighbors
        for i in range(len(self.samples)):
            nnarray=neighbors.kneighbors(self.samples[i],return_distance=False)[0]
            #存储k个近邻的下标
            self.__populate(N, i, nnarray )
        return self.synthetic

    #从k个邻居中随机选取N次,生成N个合成的样本
    def __populate(self, N, i, nnarray):
        for i in range(N):
            nn = np.random.randint(0, self.k)
            dif=self.samples[nnarray[nn]]-self.samples[i]    #包含类标
            gap=np.random.rand(1,self.n_attrs)
            self.synthetic[self.new_index]=self.samples[i]+gap.flatten()*dif
            self.new_index+=1

你可能感兴趣的:(机器学习,不平衡问题)