SMOTE 解决正负样本数不平衡
2018-07-20 本文已影响0人
蓝绿黄红
SMOTE(Synthetic Minority Oversampling Technique),合成少数类过采样技术.它是基于随机过采样算法的一种改进方案,由于随机过采样采取简单复制样本的策略来增加少数类样本,这样容易产生模型过拟合的问题,即使得模型学习到的信息过于特别(Specific)而不够泛化(General),SMOTE算法的基本思想是对少数类样本进行分析并根据少数类样本人工合成新样本添加到数据集中。简单来说,SMOTE 算法是基于“插值”来为少数类合成新的样本。具体如下图所示,算法流程如下。
- 首先从该少数类的全部 T 个样本中找到样本 xi 的 k 个近邻(例如用欧氏距离),记为 xi(near),near∈{1,...,k};
- 然后从这 k 个近邻中随机选择一个样本 xi(nn) ,再生成一个 0 到 1 之间的随机数 ζ1 ,从而合成一个新样本 xi1 :(相当于在xi和xi(nn)之间“插入”了一个新的样本)
image
image - 将步骤2重复进行 N 次,从而可以合成 N 个新样本:xi new, new∈1,...,N;
那么,对全部的 T 个少数类样本进行上述操作,便可为该少数类合成 NT 个新样本。
Python 实现
import random
from sklearn.neighbors import NearestNeighbors
import numpy as np
class Smote(object):
def __init__(self,samples, N = 10, K=5):
self.n_samples = samples.shape[0]
self.n_attrs = samples.shape[1]
self.samples = samples
self.N = N
self.K = K
self.newindex=0
def run(self):
self.synthetic = np.zeros((self.N * self.n_samples, self.n_attrs))
neighbors = NearestNeighbors(n_neighbors=self.K).fit(self.samples)
for i in range(self.n_samples):
nnarray = neighbors.kneighbors(self.samples[i].reshape(1,-1),return_distance=False)[0]
xi = self.samples[i]
for i in range(self.N):
xn = self.samples[nnarray[random.randint(1, self.K-1)]]
dif=xn-xi
gap=random.random()
xnew = xi + gap*dif
self.synthetic[self.newindex] = xnew
self.newindex +=1
return self.synthetic
if __name__ == "__main__":
# 定义假数据
s = np.random.randn(100, 5)
# 根据每个样本最近的5个样本 合成 5 倍的数据
smote = Smote(s,N = 5, K = 5)
m = smote.run()
# 打印出假数据
print(len(m),m)
改进思路,有些正样本在空间的分布上为异常点。此时在和它的中间生成样本可能不是很合适。这是可以做一个判断。如果两个样本之间距离过远。他们之间就不要生成样本。应该重新生成。