Python:SMOTE算法

article/2025/11/11 9:30:15

17.11.28更新一下:最近把这个算法集成到了数据预处理的python工程代码中了,不想看原理想直接用的,有简易版的python开发:特征工程代码模版
,进入页面后ctrl+F搜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是样本类别判别标签,0:1=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.5return 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训练的初始少类样本集合中去抽样
所以,剔除左侧的青色新增点,只保留右边的新增数据如下:

 


欢迎大家关注我的个人bolg,更多代码内容欢迎follow我的个人Github,如果有任何算法、代码疑问都欢迎通过公众号发消息给我哦。

少年,扫一下嘛

 

参考文献:

  • https://www.jair.org/media/953/live-953-2037-jair.pdf
  • https://github.com/fmfn/UnbalancedDataset
  • 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).
  • 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.



作者:slade_sal
链接:https://www.jianshu.com/p/ecbc924860af
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


http://chatgpt.dhexx.cn/article/T6uganCs.shtml

相关文章

探索SMOTE算法

摘要 SMOTE是一种综合采样人工合成数据算法&#xff0c;用于解决数据类别不平衡问题(Imbalanced class problem)&#xff0c;以Over-sampling少数类和Under-sampling多数类结合的方式来合成数据。本文将以Nitesh V. Chawla&#xff08;2002&#xff09;的论文为蓝本&#xff0…

不均衡数据集采样1——SMOTE算法(过采样)

SMOTE: Synthetic Minority Over-sampling Technique 论文地址:https://www.jair.org/index.php/jair/article/download/10302/24590 SMOTE的算法思路是&#xff1a; 使用K近邻&#xff0c;在附近&#xff08;最少选附近5个点&#xff09;随便找一个同一类别的点&#xff0c;然…

数据不平衡问题——SMOTE算法赏析

春节前后好久没有总结问题了&#xff0c;这一段时间一直在做NLP的文本分类&#xff08;二分类&#xff09;问题&#xff0c;遇到了各种问题 。分别如下&#xff1a; 1、数据打标问题。运营人手不够可把兄弟们累坏了&#xff0c;是我给兄弟们分的任务&#xff0c;别打我嘿嘿。 …

SMOTE算法代码实现

类别不平衡问题 类别不平衡问题&#xff0c;顾名思义&#xff0c;即数据集中存在某一类样本&#xff0c;其数量远多于或远少于其他类样本&#xff0c;从而导致一些机器学习模型失效的问题。例如逻辑回归即不适合处理类别不平衡问题&#xff0c;例如逻辑回归在欺诈检测问题中&a…

有关不平衡学习与SMOTE算法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言因为最近的任务中运用到了Smote算法&#xff0c;但是我找了网上好多帖子都没有解决问题&#xff0c;因此去阅读了imblearn库的User guide。然后在这边写下所得到…

Borderline-SMOTE算法介绍及Python实现【内附源代码】

&#x1f496;作者简介&#xff1a;大家好&#xff0c;我是车神哥&#xff0c;府学路18号的车神&#x1f947; ⚡About—>车神&#xff1a;从寝室到实验室最快3分钟&#xff0c;最慢3分半&#xff08;那半分钟其实是等红绿灯&#xff09; &#x1f4dd;个人主页&#xff1a;…

SMOTE算法原理及Python代码实现

SMOTE算法原理及Python代码实现 文章目录 SMOTE算法原理及Python代码实现预备知识SMOTE算法内容的简单复习SMOTE算法的详细分析创建类对象和初始化构建训练函数构建合成样本函数 SMOTE算法的完整代码示例代码 预备知识 向量代数的知识&#xff1a;对于点 x 1 \mathbf{x}_1 x1​…

smote算法_海量样本无从下手?这五种抽样算法分分钟搞定

全文共 1854字&#xff0c;预计学习时长 4分钟 数据科学是研究算法的学科。本文介绍了一些常见的用于处理数据的抽样技术。 图片来源&#xff1a;unsplash.com/gndclouds 简单随机抽样 假设要从一个群体中选出一个集合&#xff0c;该集合中的每个成员选中的概率相等。 下列代码…

smote算法_探索SMOTE算法

SMOTE是一种综合采样人工合成数据算法,用于解决数据类别不平衡问题(Imbalanced class problem),以Over-sampling少数类和Under-sampling多数类结合的方式来合成数据。本文将以 Nitesh V. Chawla(2002) 的论文为蓝本,阐述SMOTE的核心思想以及实现其朴素算法,在传统分类器(贝…

[12]机器学习_smote算法

1、smote原理介绍 在两个点连线中间取点 2、smote算法实现 import random from sklearn.neighbors import NearestNeighbors import numpy as np import matplotlib.pyplot as pltclass Smote(object):def __init__(self, N50, k5, r2):# 初始化self.N, self.k, self.r, sel…

过采样:SMOTE算法

前言&#xff1a;在比赛中遇到关于样本不均衡问题&#xff0c;特地过来补补知识点&#xff01; 1、smote原理 过采样的技术有非常多,最常见的就是随机过采样和SMOTE过采样。 随机过采样就是从少的类中进行随机进行采样然后拼接上去,这种效果很多时候和加权差不大。还有一种较…

SMOTE算法

SMOTE算法的思想是合成新的少数类样本&#xff0c;合成的策略是对每个少数类样本a&#xff0c;从它的最近邻中随机选一个样本b&#xff0c;然后在a、b之间的连线上随机选一点作为新合成的少数类样本。 如图所示&#xff1a; 算法流程&#xff1a; 1、对于少数类中每一个样本a&…

SMOTE算法及其python实现

SMOTE&#xff08;Synthetic Minority Oversampling Technique&#xff09;&#xff0c;合成少数类过采样技术&#xff0e;它是基于随机过采样算法的一种改进方案&#xff0c;由于随机过采样采取简单复制样本的策略来增加少数类样本&#xff0c;这样容易产生模型过拟合的问题&a…

SMOTE算法(人工合成数据)

SMOTE全称是Synthetic Minority Oversampling Technique即合成少数类过采样技术&#xff0c;它是基于随机过采样算法的一种改进方案&#xff0c;由于随机过采样采取简单复制样本的策略来增加少数类样本&#xff0c;这样容易产生模型过拟合的问题&#xff0c;即使得模型学习到的…

SMOTE算法原理 易用手搓小白版 数据集扩充 python

前言 为啥要写这个呢&#xff0c;在做课题的时候想着扩充一下数据集&#xff0c;尝试过这个过采样降采样&#xff0c;交叉采样&#xff0c;我还研究了一周的对抗生成网络&#xff0c;对抗生成网络暂时还解决不了我要生成的信号模式崩塌的问题&#xff0c;然后就看着尝试一下别…

机器学习_SMOTE:简单原理图示_算法实现及R和Python调包简单实现

一、SMOTE原理 SMOTE的全称是Synthetic Minority Over-Sampling Technique 即“人工少数类过采样法”&#xff0c;非直接对少数类进行重采样&#xff0c;而是设计算法来人工合成一些新的少数样本。 SMOTE步骤__1.选一个正样本 红色圈覆盖 SMOTE步骤__2.找到该正样本的K个近…

Hash碰撞(冲突)

2019独角兽企业重金招聘Python工程师标准>>> 什么是哈希&#xff08;哈希算法&#xff09; 哈希算法是将任意长度的二进制值映射为较短的固定长度的二进制值&#xff0c;这个小的二进制值称为哈希值。 哈希值是一段数据唯一且极其紧凑的数值表示形式。如果散列一段明…

Hash 碰撞是什么?如何解决(开放寻址法和拉链法)?hash链表和红黑树知识扩展?

一、什么是Hash碰撞 hash碰撞指的是&#xff0c;两个不同的值&#xff08;比如张三、李四的学号&#xff09;经过hash计算后&#xff0c;得到的hash值相同&#xff0c;后来的李四要放到原来的张三的位置&#xff0c;但是数组的位置已经被张三占了&#xff0c;导致冲突 二、Ha…

hash碰撞解决方法

Hash碰撞冲突 我们知道&#xff0c;对象Hash的前提是实现equals()和hashCode()两个方法&#xff0c;那么HashCode()的作用就是保证对象返回唯一hash值&#xff0c;但当两个对象计算值一样时&#xff0c;这就发生了碰撞冲突。如下将介绍如何处理冲突&#xff0c;当然其前提是一…

Java 集合深入理解 (十一) :HashMap之实现原理及hash碰撞

文章目录 前言哈希表原理实现示例HashMap实现原理全篇注释分析实现注意事项默认属性分析属性分析构造方法分析重要的put方法总结 前言 哈希表&#xff08;hashMap&#xff09;又叫散列表 是一种非常重要的数据结构基于map接口实现应用场景及其丰富&#xff0c;本地临时缓存&a…