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

之前一直没有用过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。

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-11-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ATYUN订阅号

解决多标签分类问题(包括案例研究)

由于某些原因,回归和分类问题总会引起机器学习领域的大部分关注。多标签分类在数据科学中是一个比较令人头疼的问题。在这篇文章中,我将给你一个直观的解释,说明什么是多...

4956
来自专栏Python中文社区

ALI的Tensorflow炼成与GAN科普

專 欄 ❈那只猫,Python中文社区专栏作者,Python中文社区新Logo设计人,纯种非CS科班数据分析人,沉迷Keras。在Cambridge做了点小事...

19610
来自专栏AI科技大本营的专栏

测试数据科学家聚类技术的40个问题(能力测验和答案)(下)

【AI100 导读】本次测试的重点主要集中在概念、聚类基本原理以及各种技术的实践知识等方面。本文为下部,包括21-40题。上部请查看: 测试数据科学家聚类技术的...

3204
来自专栏大数据挖掘DT机器学习

数据挖掘18大算法实现以及其他相关经典DM算法

算法使用方法在每个算法中给出了3大类型,主算法程序,调用程序,输入数据,调用方法如下: 将需要数据的测试数据转化成与给定的输入格式相同,然后以Client类...

3519
来自专栏数据派THU

一文读懂支持向量机SVM(附实现代码、公式)

支持向量机(SVM),一个神秘而众知的名字,在其出来就受到了莫大的追捧,号称最优秀的分类算法之一,以其简单的理论构造了复杂的算法,又以其简单的用法实现了复杂的问...

1703
来自专栏闪电gogogo的专栏

OMP算法代码学习

正交匹配追踪(OMP)算法的MATLAB函数代码并给出单次测试例程代码 测量数M与重构成功概率关系曲线绘制例程代码 信号稀疏度K与重构成功概率关系曲线绘制例程代...

2176
来自专栏AI研习社

Must Know! 数据科学家们必须知道的 5 种聚类算法

聚类是一种关于数据点分组的机器学习技术。给出一组数据点,我们可以使用聚类算法将每个数据点分类到特定的组中。理论上,同一组中的数据点应具有相似的属性或特征,而不同...

3818
来自专栏机器学习算法与理论

《白话深度学习与Tensorflow》学习笔记(1)

刚入手一本《白话深度学习与Tensorflow》,哈哈,一直看深度学习很火,其实自己一知半解,都没有对这个领域进行一点系统的学习,现在准备看看这本书,开始入门。...

3598
来自专栏PPV课数据科学社区

百度校园招聘数据挖掘工程师面试题集锦(2013)

一、简答题(30分) 1、简述数据库操作的步骤(10分) 步骤:建立数据库连接、打开数据库连接、建立数据库命令、运行数据库命令、保存数据库命令、关闭数据库连接。...

3545
来自专栏数说工作室

最重要的一集 | 【SAS Says·扩展篇】IML:6.作业

咱们的SAS矩阵交互语言IML就要完结了,本文将会用IML编一个回归程序。无论你需要一元的还是多元的回归模型,该程序都能计算出模型的系数、t检验以及t检验的p值...

3338

扫码关注云+社区