zoukankan      html  css  js  c++  java
  • 正负样本比率失衡SMOTE

    正负样本比率失衡SMOTE

    背景

    这几天测试天池的优惠券预测数据在dnn上面会不会比集成树有较好的效果,但是正负样本差距太大,而处理这种情况的一般有欠抽样和过抽样,这里主要讲过抽样,过抽样有一种简单的方法叫随机过抽样,但是随机过抽样只是随机的复制,很容易过拟合,所以SMOTE比较好,SMOTE还有一些改进版本,更好用,这里讲一般的SMOTE即可

    公式

    (x) : 任意一个样本
    ( ilde{x}) : (x)最临近的(K)个样本的随机一个,(x ot= ilde{x})

    [x_{new}=x+rand(0,1) imes( ilde{x}-x) ]

    python实现

    import random
    from sklearn.neighbors import NearestNeighbors
    import numpy as np
    class Smote:
        def __init__(self,N=1,k=5):
            self.__shape=None
            self.__N=N
            self.__k=k
        
        def fit(self, samples):
            self.__shape=samples.shape #源样本的shape
            # 塑形为两位度才可以用KNN
            self.__samples=samples.reshape((self.__shape[0],-1)) 
            self.__tmp_shape=self.__samples.shape
            # 返回值的维度
            self.__ret_shape=(self.__shape[0]*self.__N,)+self.__shape[1:]
    
        def transform(self):
            # 如果没有喂给数据,则直接返回None
            if self.__shape == None:
                return None
            self.__index=0 # 清零新增数据的索引
            self.__X = np.zeros((self.__tmp_shape[0] * self.__N, self.__tmp_shape[1])) # 构造返回的数据,具体数据待填充
            neighbors=NearestNeighbors(n_neighbors=self.__k).fit(self.__samples)
            for i in range(self.__shape[0]): # 根据每一个样本产生一个新样本
                # nnarray当前样本最近k个的样本的索引
                nnarray=neighbors.kneighbors(self.__samples[i].reshape(1,-1),return_distance=False)[0]
                # 根据当前样本索引和,最近k和样本生成一个新样本
                self.__new_one_sample(i,nnarray)
            return self.__X.reshape(self.__ret_shape) # 重新塑形并返回
    
        def fit_transform(self, samples):
            self.fit(samples)
            return self.transform()
        
        # 根据当前样本索引和,最近k和样本生成一个新样本
        def __new_one_sample(self,i,nnarray):
            for _ in range(self.__N):
                #从K个最近的样本随机挑选不同于当前样本的一个样本
                nn_idx=random.choice(nnarray)
                while (nn_idx==i):
                    nn_idx=random.choice(nnarray)
                gap=self.__samples[nn_idx]-self.__samples[i]
                prob=random.random()
                # 根据公式生成新样本
                self.__X[self.__index]=self.__samples[i]+prob*gap
                self.__index+=1
    
    if __name__ == '__main__':
        a=np.array([[1,3,4],[2,5,6],[4,1,2],[5,1,4],[3,2,4],[5,3,5]])
        print("
    "*2, "测试维度为" , a.shape)
        print("*"*100)
        s=Smote()
        s.fit(a)
        print (s.transform())
        
        # 测试多维度支持
        b=np.zeros((10,)+a.shape)
        print("
    "*2, "测试维度为" , b.shape)
        print("*"*100)
        for i in range(10):
            b[i,:]=s.fit_transform(a)
        print (s.fit_transform(b))
    

    代码的使用方法

    假设你已经有label很少的数据 data (不包括label列)

    s=Smote()
    s.fit(data)
    s.transform()
    

    上面的实例是默认参数,可根据情况选择参数N和k
    数据扩增N被,从最近的k个样本选择一个样本参考(这里 参考 这个词可能不太准确,想不出其他词)来生成样本

    s=Smote(N=2, k=4)
    s.fit(data)
    s.transform()
  • 相关阅读:
    CodeForces 659F Polycarp and Hay
    CodeForces 713C Sonya and Problem Wihtout a Legend
    CodeForces 712D Memory and Scores
    CodeForces 689E Mike and Geometry Problem
    CodeForces 675D Tree Construction
    CodeForces 671A Recycling Bottles
    CodeForces 667C Reberland Linguistics
    CodeForces 672D Robin Hood
    CodeForces 675E Trains and Statistic
    CodeForces 676D Theseus and labyrinth
  • 原文地址:https://www.cnblogs.com/paiandlu/p/8081763.html
Copyright © 2011-2022 走看看