SMOTE原理及實現

Smote算法原理:
這裏寫圖片描述
python2.7 算法實現: 原算法只能針對N採樣率小於100%或者N爲100%整數的參數進行採樣。我實現的代碼可對任意N>0的採樣率從進行SMOTE。詳情見源碼

#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from sklearn.neighbors import NearestNeighbors
import numpy as np
import warnings
from sklearn.datasets import load_iris
warnings.filterwarnings("ignore")

class Smote(object):
    """data爲少數類"""
    def __init__(self,data,N=100,k=5):
        self.data = data
        self.N = N 
        self.k = k+1
        self.n_attrs = data.shape[1]

    def oversample(self):

        # 1.獲取要插值的對象 sample 
        index = set()          #當插值的倍率<1時 存儲用來存儲smote的樣本序列 
        sample = list()        #用來存儲進行smote的樣本
        newsample = list()     #用來存儲插值的樣本

        N_inter = int(self.N/100)            #N大於100%的部分(整數的採樣倍數)
        N_decimal = self.N- 100*N_inter      #N小於100%的部分

        #N小於100的部分 隨機選擇N*len(data)進行插值
        while(len(index)<int(len(self.data)*N_decimal/100.0)):
            term = np.random.randint(len(self.data))
            if term in index:
                continue
            else:
                index.add(term)
                sample.append(self.data[term])

        #N大於100%的部分 (整數的採樣倍數)        
        if N_inter>0:
                for i in xrange(N_inter):
                    sample.extend(self.data)  
        #2進行插值
        knn = NearestNeighbors(n_neighbors=self.k).fit(self.data)
        for j in sample:
            nnarray = knn.kneighbors(j, return_distance=False)[0][1:] #選擇少數類中最近的K個樣本 【1:】表示去除自己
            #根據公式  xnew = x +rand(0,1)*(x近鄰-x) 計算插值樣本 並將其存儲在newsample中
            select = np.random.choice(nnarray)
            dif = self.data[select] - j
            gap = np.random.rand(1,self.n_attrs)
            newsample.append(j + gap.flatten() * dif)

        return newsample

if __name__ == "__main__":
    #隨機生成100個高斯分佈數據
    iris = load_iris()
    data = iris.data
    i_label = iris.target
    data = np.random.randn(100,2)
    i_label = np.ones(100)
    i_label[0:50] = 0
    data = np.column_stack([data,i_label])
    #初始化smote的參數
    K= 3
    N =120
    smote = Smote(data=data[:50],N=N,k=K)
    new = smote.oversample()    #new 爲新生成的樣本
    print len(new)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章