点击“阅读原文”直接打开【北京站 | GPU CUDA 进阶课程】报名链接

沙韬伟,苏宁易购高级算法工程师。
曾任职于Hewlett-Packard、滴滴出行。
数据学院特邀讲师。
主要研究方向包括风控、推荐和半监督学习。目前专注于基于深度学习及集成模型下的用户行为模式的识别。

之前一直没有用过python,最近做了一些数量级比较大的项目,觉得有必要熟悉一下python,正好用到了smote,网上也没有搜到,所以就当做一个小练手来做一下。

首先,看下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

下面定义距离计算的方式,所有算法中,涉及到距离的地方都需要标准化去除冈量,也同时加快了计算的速度。

这边采取了欧式距离的方式,更多计算距离的方式参考:
多种距离及相似度的计算理论介绍(http://www.jianshu.com/p/1417fcb06797)

# 统计所有检验距离样本个数 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训练的初始少类样本集合中去抽样。

所以,剔除左侧的青色新增点,只保留右边的新增数据如下:

参考文献

1、https://www.jair.org/media/953/live-953-2037-jair.pdf;

2、https://github.com/fmfn/UnbalancedDataset;

3、Batista, G. E., Bazzan, A. L., & Monard, M. C. (2003, December). Balancing Training Data for Automated Annotation of Keywords: a Case Study. In WOB (pp. 10-18);

4、Batista, G. E., Prati, R. C., & Monard, M. C. (2004). A study of the behavior of several methods for balancing machine learning training data. ACM Sigkdd Explorations Newsletter, 6(1), 20-29。

原文链接:http://www.jianshu.com/p/ecbc924860af

   BY  简书

往期精彩回顾

深度学习视频(一) | 免费放送—深度学习的应用场景和数学基础

深度学习视频(二) | 免费放送—卷积神经网络(一)

深度学习视频(三) | 免费放送—卷积神经网络(二)

深度学习视频(四) | 免费放送—深度学习的具体模型和方法

深度学习视频(五) | 免费放送—上机实操(一)

点击“阅读原文”直接打开【北京站 | GPU CUDA 进阶课程】报名链接

当常规的算法都山穷水尽之后,你可以试试python中的SMOTE算法相关推荐

  1. 在python中使用FP-growth算法

    在 Python 中使用 FP-growth 算法可以使用第三方库 PyFIM.PyFIM 是一个 Python 的实现频繁项集挖掘算法库,它提供了多种频繁项集挖掘算法,其中包括 FP-growth. ...

  2. gbdt 算法比随机森林容易_用Python实现随机森林算法

    CDA数据分析师 出品 拥有高方差使得决策树(secision tress)在处理特定训练数据集时其结果显得相对脆弱.bagging(bootstrap aggregating 的缩写)算法从训练数据 ...

  3. python中值滤波算法_Python扩展库scipy中值滤波算法的应用

    中值滤波是数字信号处理.数字图像处理中常用的预处理技术,特点是将信号中每个值都替换为其邻域内的中值,即邻域内所有值排序后中间位置上的值.下面的代码演示了scipy库中signal模块的中值滤波算法的用 ...

  4. python中难的算法_Python算法很难吗?python神书《算法图解》PDF电子版分享给你

    许多小伙伴后台私信说,python算法让自己很头疼,有没有可以让算法像小说一样有趣的书籍资料呢?看这里吧!小宋为大家找到了这本<算法图解>的PDF电子版!让你在学习python的路上变得轻 ...

  5. matlab中基于十字形窗口的滤波算法,#215;字形滤波窗口在Matlab自适应中值滤波算法中的应用 - 21ic中国电子网...

    由于种种原因,图像在生成.传输.变换等过程中往往会受到各种噪声的污染,从而导致图像质量退化.噪声信号的滤波是图像处理的基本任务之一,主要有线性滤波和非线性滤波两种方法.线性滤波方法一般具有低通特性,而 ...

  6. python中的一些算法

    两个基础知识点:递归和时间复杂度 递归 递归函数的特点:自己调用自己,有结束条件,看下面例子: def fun1(x):"""无结束条件,报错""&q ...

  7. python中什么是算法_python自动开发之(算法)第二十七天

    1.什么是算法? 算法(Algorithm):一个计算过程,解决问题的方法 2.复习:递归 递归的两个特点:(1) 调用自身 (2)结束条件 deffunc1(x):print(x) func1(x- ...

  8. python中难的算法_一个python的比较难的算法,有懂的人可以进来一下

    问 题 我的需求: 结构数据是这样的: 要求按照这样的公式: 组合一: 时间词+地方词+动词+等级+名词+价格词: 比如 2016年深圳大鹏新区给健康全身检查要多少钱 就是按照这样的公式组合出来的关键 ...

  9. knn算法python代码_在python中使用KNN算法处理缺失的数据

    处理缺失的数据并不是一件容易的事. 方法的范围从简单的均值插补和观察值的完全删除到像MICE这样的更高级的技术. 解决问题的挑战性是选择使用哪种方法. 今天,我们将探索一种简单但高效的填补缺失数据的方 ...

最新文章

  1. 使用pg_stat_statement监控pgsql遇到的问题
  2. 趣谈网络协议笔记-二(第十九讲)
  3. redis持久化实现原理
  4. 明智地选择数据中心的五个注意事项
  5. WinSock服务程序
  6. 华为芯片设计面试题_未来想去华为海思做芯片设计,应该做哪些努力?
  7. 【python 9】python注册器
  8. GatewayMetricsFilter网关度量过滤器(服务监控)
  9. 根因分析初探:一种报警聚类算法在业务系统的落地实施 1
  10. HTML多选mysql,html多选下拉框 | 学步园
  11. python partition只能切割一次吗_Python3的字符串方法
  12. 抖音同款表白神器(按钮漂移)
  13. Kubernetes kubectl The connection to the server localhost:8080 was refused - did you specify the rig
  14. Jupyter Notebook 作图显示中文
  15. CentOS下安裝iRedMail
  16. 万字攻略,详解腾讯面试(T1-T9)核心技术点,面试题整理
  17. narwal机器人_首款全自动扫拖一体机器人Narwal云鲸,彻底解放双手
  18. linux 处理匹配文本的前后行
  19. Freeman链码及其某些变化
  20. android21是什么手机,三星S21成安卓新王者?详细对比发现,OPPO小米才是真厚道...

热门文章

  1. java中简单的if语句_java中if语句的写法
  2. python属于私有属性_Python私有属性和受保护的属性原理解析
  3. HTML文档的三大构成元素,构成基础结课小结 为什么三大构成是设计的基础课程...
  4. python是基于什么的内存管理方式_python的内存管理机制是什么?
  5. python颜色相关系数_python相关系数 - osc_w6qmyr6s的个人空间 - OSCHINA - 中文开源技术交流社区...
  6. 制作自己的linux内核,打造属于你自己的Linux系统
  7. 添加mysql库路径_修改MySQL数据库存放路径
  8. iis php的mime类型,IIS MIME类型介绍、MIME大全
  9. linux(cat,more,less,head)——对文件显示进行查看操作
  10. 算法导论 第十三章 红黑树(python)-1插入