Python:SMOTE算法

直接用python的库,

imbalanced-learn

imbalanced-learn is a python package offering a number of re-sampling techniques commonly used in datasets showing strong between-class imbalance. It is compatible with scikit-learn and is part of scikit-learn-contrib projects.

---------------------

http://contrib.scikit-learn.org/imbalanced-learn/stable/auto_examples/over-sampling/plot_smote.html#sphx-glr-auto-examples-over-sampling-plot-smote-py

http://contrib.scikit-learn.org/imbalanced-learn/stable/over_sampling.html#from-random-over-sampling-to-smote-and-adasyn 入门

SMOTE

An illustration of the SMOTE method and its variant.

# Authors: Fernando Nogueira
# Christos Aridas
# Guillaume Lemaitre <g.lemaitre58@gmail.com>
# License: MIT import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.decomposition import PCA from imblearn.over_sampling import SMOTE print(__doc__) def plot_resampling(ax, X, y, title):
c0 = ax.scatter(X[y == 0, 0], X[y == 0, 1], label="Class #0", alpha=0.5)
c1 = ax.scatter(X[y == 1, 0], X[y == 1, 1], label="Class #1", alpha=0.5)
ax.set_title(title)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.get_xaxis().tick_bottom()
ax.get_yaxis().tick_left()
ax.spines['left'].set_position(('outward', 10))
ax.spines['bottom'].set_position(('outward', 10))
ax.set_xlim([-6, 8])
ax.set_ylim([-6, 6]) return c0, c1 # Generate the dataset
X, y = make_classification(n_classes=2, class_sep=2, weights=[0.3, 0.7],
n_informative=3, n_redundant=1, flip_y=0,
n_features=20, n_clusters_per_class=1,
n_samples=80, random_state=10) # Instanciate a PCA object for the sake of easy visualisation
pca = PCA(n_components=2)
# Fit and transform x to visualise inside a 2D feature space
X_vis = pca.fit_transform(X) # Apply regular SMOTE
kind = ['regular', 'borderline1', 'borderline2', 'svm']
sm = [SMOTE(kind=k) for k in kind]
X_resampled = []
y_resampled = []
X_res_vis = []
for method in sm:
X_res, y_res = method.fit_sample(X, y)
X_resampled.append(X_res)
y_resampled.append(y_res)
X_res_vis.append(pca.transform(X_res)) # Two subplots, unpack the axes array immediately
f, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(3, 2)
# Remove axis for second plot
ax2.axis('off')
ax_res = [ax3, ax4, ax5, ax6] c0, c1 = plot_resampling(ax1, X_vis, y, 'Original set')
for i in range(len(kind)):
plot_resampling(ax_res[i], X_res_vis[i], y_resampled[i],
'SMOTE {}'.format(kind[i])) ax2.legend((c0, c1), ('Class #0', 'Class #1'), loc='center',
ncol=1, labelspacing=0.)
plt.tight_layout()
plt.show()

Total running time of the script: ( 0 minutes 0.704 seconds)

Python:SMOTE算法

from:https://www.jianshu.com/p/ecbc924860af

首先,看下Smote算法之前,我们先看下当正负样本不均衡的时候,我们通常用的方法:

  • 抽样
    常规的包含过抽样、欠抽样、组合抽样
    过抽样:将样本较少的一类sample补齐
    欠抽样:将样本较多的一类sample压缩
    组合抽样:约定一个量级N,同时进行过抽样和欠抽样,使得正负样本量和等于约定量级N

这种方法要么丢失数据信息,要么会导致较少样本共线性,存在明显缺陷

  • 权重调整
    常规的包括算法中的weight,weight matrix
    改变入参的权重比,比如boosting中的全量迭代方式、逻辑回归中的前置的权重设置

这种方式的弊端在于无法控制合适的权重比,需要多次尝试

  • 核函数修正
    通过核函数的改变,来抵消样本不平衡带来的问题

这种使用场景局限,前置的知识学习代价高,核函数调整代价高,黑盒优化

  • 模型修正
    通过现有的较少的样本类别的数据,用算法去探查数据之间的特征,判读数据是否满足一定的规律
    比如,通过线性拟合,发现少类样本成线性关系,可以新增线性拟合模型下的新点

实际规律比较难发现,难度较高

SMOTE(Synthetic minoritye over-sampling technique,SMOTE)是Chawla在2002年提出的过抽样的算法,一定程度上可以避免以上的问题

下面介绍一下这个算法:

正负样本分布

很明显的可以看出,蓝色样本数量远远大于红色样本,在常规调用分类模型去判断的时候可能会导致之间忽视掉红色样本带了的影响,只强调蓝色样本的分类准确性,这边需要增加红色样本来平衡数据集

Smote算法的思想其实很简单,先随机选定n个少类的样本,如下图

找出初始扩展的少类样本

再找出最靠近它的m个少类样本,如下图

再任选最临近的m个少类样本中的任意一点,

在这两点上任选一点,这点就是新增的数据样本


R语言上的开发较为简单,有现成的包库,这边简单介绍一下:

rm(list=ls())
install.packages(“DMwR”,dependencies=T)
library(DMwR)#加载smote包
newdata=SMOTE(formula,data,perc.over=,perc.under=)
#formula:申明自变量因变量
#perc.over:过采样次数
#perc.under:欠采样次数

效果对比:

简单的看起来就好像是重复描绘了较少的类
这边的smote是封装好的,直接调用就行了,没有什么特别之处


这边自己想拿刚学的python练练手,所有就拿python写了一下过程:

# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from numpy import *
import matplotlib.pyplot as plt #读数据
data = pd.read_table('C:/Users/17031877/Desktop/supermarket_second_man_clothes_train.txt', low_memory=False) #简单的预处理
test_date = pd.concat([data['label'], data.iloc[:, 7:10]], axis=1)
test_date = test_date.dropna(how='any')

数据大致如下:

test_date.head()
Out[25]:
label max_date_diff max_pay cnt_time
0 0 23.0 43068.0 15
1 0 10.0 1899.0 2
2 0 146.0 3299.0 21
3 0 30.0 31959.0 35
4 0 3.0 24165.0 98
test_date['label'][test_date['label']==0].count()/test_date['label'][test_date['label']==1].count()
Out[37]: 67

label是样本类别判别标签,1:0=67:1,需要对label=1的数据进行扩充


# 筛选目标变量
aimed_date = test_date[test_date['label'] == 1]
# 随机筛选少类扩充中心
index = pd.DataFrame(aimed_date.index).sample(frac=0.1, random_state=1)
index.columns = ['id']
number = len(index)
# 生成array格式
aimed_date_new = aimed_date.ix[index.values.ravel(), :]

随机选取了全量少数样本的10%作为数据扩充的中心点



# 自变量标准化
sc = StandardScaler().fit(aimed_date_new)
aimed_date_new = pd.DataFrame(sc.transform(aimed_date_new))
sc1 = StandardScaler().fit(aimed_date)
aimed_date = pd.DataFrame(sc1.transform(aimed_date)) # 定义欧式距离计算
def dist(a, b):
a = array(a)
b = array(b)
d = ((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2 + (a[3] - b[3]) ** 2) ** 0.5
return d

下面定义距离计算的方式,所有算法中,涉及到距离的地方都需要标准化去除冈量,也同时加快了计算的速度
这边采取了欧式距离的方式,更多计算距离的方式参考:
多种距离及相似度的计算理论介绍


# 统计所有检验距离样本个数
row_l1 = aimed_date_new.iloc[:, 0].count()
row_l2 = aimed_date.iloc[:, 0].count()
a = zeros((row_l1, row_l2))
a = pd.DataFrame(a)
# 计算距离矩阵
for i in range(row_l1):
for j in range(row_l2):
d = dist(aimed_date_new.iloc[i, :], aimed_date.iloc[j, :])
a.ix[i, j] = d
b = a.T.apply(lambda x: x.min())

调用上面的计算距离的函数,形成一个距离矩阵


# 找到同类点位置
h = []
z = []
for i in range(number):
for j in range(len(a.iloc[i, :])):
ai = a.iloc[i, j]
bi = b[i]
if ai == bi:
h.append(i)
z.append(j)
else:
continue
new_point = [0, 0, 0, 0]
new_point = pd.DataFrame(new_point)
for i in range(len(h)):
index_a = z[i]
new = aimed_date.iloc[index_a, :]
new_point = pd.concat([new, new_point], axis=1) new_point = new_point.iloc[:, range(len(new_point.columns) - 1)]

再找到位置的情况下,再去原始的数据集中根据位置查找具体的数据


import random
r1 = []
for i in range(len(new_point.columns)):
r1.append(random.uniform(0, 1))
new_point_last = []
new_point_last = pd.DataFrame(new_point_last)
# 求新点 new_x=old_x+rand()*(append_x-old_x)
for i in range(len(new_point.columns)):
new_x = (new_point.iloc[1:4, i] - aimed_date_new.iloc[number - 1 - i, 1:4]) * r1[i] + aimed_date_new.iloc[
number - 1 - i, 1:4]
new_point_last = pd.concat([new_point_last, new_x], axis=1)
print new_point_last

最后,再根据smote的计算公式new_x=old_x+rand()*(append_x-old_x),计算出新的点即可,python练手到此就结束了

其实,在这个结果上,我们可以综合Tomek link做一个集成的数据扩充的算法,思路如下:
假设,我们利用上述的算法产生了两个青色方框的新数据点:

我们认为,对于新产生的青色数据点与其他非青色样本点距离最近的点,构成一对Tomek link,如下图框中的青蓝两点

我们可以定义规则:
当以新产生点为中心,Tomek link的距离为范围半径,去框定一个空间,空间内的少数类的个数/多数类的个数<最低阀值的时候,认为新产生点为“垃圾点”,应该剔除或者再次进行smote训练;空间内的少数类的个数/多数类的个数>=最低阀值的时候,在进行保留并纳入smote训练的初始少类样本集合中去抽样
所以,剔除左侧的青色新增点,只保留右边的新增数据如下:

参考文献:

Python:SMOTE算法——样本不均衡时候生成新样本的算法的更多相关文章

  1. Bert文本分类实践(三):处理样本不均衡和提升模型鲁棒性trick

    目录 写在前面 缓解样本不均衡 模型层面解决样本不均衡 Focal Loss pytorch代码实现 数据层面解决样本不均衡 提升模型鲁棒性 对抗训练 对抗训练pytorch代码实现 知识蒸馏 防止模 ...

  2. 【小白学AI】八种应对样本不均衡的策略

    文章来自:微信公众号[机器学习炼丹术] 目录 1 什么是非均衡 2 8种解决办法 2.1 重采样(四种方法) 2.2 调整损失函数 2.3 异常值检测框架 2.4 二分类变成多分类 2.5 EasyE ...

  3. 思科恶意加密TLS流检测论文记录——由于样本不均衡,其实做得并不好,神马99.9的准确率都是浮云啊,之所以思科使用DNS和http一个重要假设是DGA和HTTP C&C(正常http会有图片等)。一开始思科使用的逻辑回归,后面17年文章是随机森林。

    论文记录:Identifying Encrypted Malware Traffic with Contextual Flow Data from:https://songcoming.github. ...

  4. Consistent Hashing算法-搜索/负载均衡

    在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括:  轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法(Respons ...

  5. 用Caffe生成对抗样本

    同步自我的知乎专栏:https://zhuanlan.zhihu.com/p/26122612 上篇文章 瞎谈CNN:通过优化求解输入图像 - 知乎专栏 中提到过对抗样本,这篇算是针对对抗样本的一个小 ...

  6. One Class SVM 对于样本不均衡处理思路——拿出白样本建模,算出outlier,然后用黑去检验效果

    One Class SVM 是指你的training data 只有一类positive (或者negative)的data, 而没有另外的一类.在这时,你需要learn的实际上你training d ...

  7. JavaScript算法题之–随机数的生成

    JavaScript算法题之–随机数的生成 需求描述:从一组有序的数据中生成一组随机并且不重复的数,类似于简单的抽奖程序的实现. 先来生成一个有序的数组: 1 var arr = [], 2      ...

  8. c# Hash一致算法实现负载均衡

    开篇吹牛..... 不吹了,因为我不擅长算法,就不胡说八道了. 现在一般的实现负载均衡,主要采用2种方法: 1.轮训    2.负载均衡算法 轮训就不说了,负载均衡现在一般采用HASH一致算法 不多说 ...

  9. 为什么ROC曲线不受样本不均衡问题的影响

    转自:https://blog.csdn.net/songyunli1111/article/details/82285266 在对分类模型的评价标准中,除了常用的错误率,精确率,召回率和F1度量外, ...

随机推荐

  1. vue项目中添加百度地图功能及解决遇到的问题详解

    第一步,在百度地图开放平台 申请密钥 (如果有密钥可以省略此步骤,朋友有也可以借) 地址:http://lbsyun.baidu.com/ 第二步,创建应用并填写表单(下面链接可参考) http:// ...

  2. Spring Boot 与ElasticSearch

    一.ElasticSearch 介绍 ​ 开源的 ElasticSearch 是目前全文搜索引擎的首选,它是一个分布式搜索服务,提供Restful API,它可以快速地存储.搜索和分析海量数据.底层基 ...

  3. 王垠:写给支持和反对《完全用Linux工作》的人们

    王垠:写给支持和反对<完全用Linux工作>的人们 在一阵阵唾骂和欢呼声中,<完全用linux工作>被转载到了天涯海角.很多人支持我,也有很多人唾骂我.我不知道它是怎样流传到那 ...

  4. c/c++编程排坑(1)-- 数据类型的“安静”转换

    这里主要介绍ANSI C的特性:当执行算术运算时,操作数的类型如果不同,就会发生转换.数据类型一般朝着精度更高.长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则 ...

  5. UVA - 1611 Crane (思路题)

    题目: 输入一个1~n(1≤n≤300)的排列,用不超过96次操作把它变成升序.每次操作都可以选一个长度为偶数的连续区间,交换前一半和后一半.输出每次操作选择的区间的第一个和最后一个元素. 思路: 注 ...

  6. Tampermonkey脚本安装问题及自用脚本推荐

    对于高手来说,chrome浏览器中即使没有其他任何chrome插件,可能都无关紧要.但是有一个插件必不可少, 那就是Tampermonkey油猴插件.Tampermonkey是Chrome上最流行的用 ...

  7. dstat系统分析工具的使用

    1.安装 方法一:yum #yum install -y dstat 方法二:rpm 官网下载地址: http://dag.wieers.com/rpm/packages/dstat #wget ht ...

  8. JavaScript 面向对象的编程(三) 类的继承

    定义父类和子类的继承关系 //声明父类 function SuperClass(){ this.superValue = true; } //为父类添加共有方法 SuperClass.prototyp ...

  9. java中List遍历删除元素-----不能直接 list.remove()

    https://blog.csdn.net/github_2011/article/details/54927531 这是List接口中的方法,List集合调用此方法可以得到一个迭代器对象(Itera ...

  10. Meanshift,聚类算法

    记得刚读研究生的时候,学习的第一个算法就是meanshift算法,所以一直记忆犹新,今天和大家分享一下Meanshift算法,如有错误,请在线交流. Mean Shift算法,一般是指一个迭代的步骤, ...