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

article/2025/11/11 2:38:30

一、SMOTE原理

SMOTE的全称是Synthetic Minority Over-Sampling Technique 即“人工少数类过采样法”,非直接对少数类进行重采样,而是设计算法来人工合成一些新的少数样本。

SMOTE步骤__1.选一个正样本

红色圈覆盖
在这里插入图片描述

SMOTE步骤__2.找到该正样本的K个近邻(假设K = 3

在这里插入图片描述

SMOTE步骤__3.随机从K个近邻中选出一个样本

绿色的
在这里插入图片描述

SMOTE步骤__4.在正样本和随机选出的这个近邻之间的连线上,随机找一点。这个点就是人工合成的新正样本了在这里插入图片描述

二、调包实现

2.1 R调包实现_SMOTE

主要参数解释:
perc.over = a 需要生成的正样本:最后正样本数 ( 1 + a /100) * N : N 为目前有的正样本数量
perc.under = a 需要从负样本抽样的个数:最后负样本数 (a / 100 * b / 10) * N
K = x 用相近的 x 个样本(中的一个)生成正样本
library(DMwR)#  pos = (1 + perc.over/100) * N (N original pos sample)#  neg = (perc.over/100 * perc.under/100) * N# SMOT oversamplenewdata <- SMOTE(tp~., data_in, perc.over = 300, k = 5, perc.under = 200)

2.2 Python 调包实现_SMOTE

imblearn.over_sampling.SMOTE(
sampling_strategy = ‘auto’,
random_state = None, ## 随机器设定
k_neighbors = 5, ## 用相近的 5 个样本(中的一个)生成正样本
m_neighbors = 10, ## 当使用 kind={'borderline1', 'borderline2', 'svm'}
out_step = ‘0.5’, ## 当使用 kind = 'svm'
kind = 'regular', ## 随机选取少数类的样本
borderline1: 最近邻中的随机样本b与该少数类样本a来自于不同的类
borderline2: 随机样本b可以是属于任何一个类的样本;
svm:使用支持向量机分类器产生支持向量然后再生成新的少数类样本
svm_estimator = SVC(), ## svm 分类器的选取
n_jobs = 1, ## 使用的例程数,为-1时使用全部CPU
ratio=None
)
from imblearn.over_sampling import SMOTE
sm = SMOTE(random_state = 42, n_jobs = -1)
x, y = sm.fit_sample(x_val, y_val)

仅用正样本的K近邻生成新正样本是正是SMOTE方法,考虑到(SMOTE的最终目的是分清正负样本的边界),所以需要对样本生成进行优化

2.2.1 SMOTE优化 borderline1 方法简述

Dgr = [] # 危险集
for i in 正样本:1) 计算点 i 在训练集 D 上的 m 个最近邻。x =  i 的最近邻中属于负样本的数量2) 如果 x  = m,则 p 是一个噪声next3) 如果 0 ≤ x ≤ m/2, 则说明p很安全next4) 如果 m/2 ≤ x ≤ m, 那么点p就很危险了,我们需要在这个点附近生成一些新的少数类点Dgr.append(x)
最后,对于每个在危险集(Dgr)中的点,使用SMOTE算法生成新的样本

2.2.2 SMOTE优化 borderline2 方法简述

前面1-4步骤均同 borderline1 方法
在最后进行SMOTE的时候:
采用了 比例分配 生成新样本
for i in Dgr:1) 正样本 K 个近邻2) 负样本 K 个近邻3) 正样本 K 个近邻选取 alpha 比例的样本点 和 i 作随机的线性插值 ==>> 新正样本点4) 负样本K个近邻选取 (1 - alpha) 比例的样本点 和 i 作随机的线性插值 ==>> 新正样本点

三、算法实现

#! /user/bin/python 3
# -*- coding: utf-8 -*-
# author: Scc_hy
# 2018-11-17
# SMOTE
from sklearn.neighbors import NearestNeighbors
import numpy as np 
import pandas as pd 
import copy
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifierclass TWO_SMOTE():"""不平二分类人工插值法采样"""def __init__(self, K_neighbors = 5,N_need = 200,random_state = 42):self.K_neighbors = K_neighborsself.N_need = N_needself.random_state = 42def get_param_describe(self):print("算法参数: \n"+'K_neighbors: 和正样本相近的随机样本数' + "\n" +"N_need: 需要增加的正样本数 (N_need // 100 * a)" + "\n" +"random_state: 随机器设定" + "\n""\nover_sample 参数:\n" +"x_data: 需要进行过采样的全部数据集(非文本DataFrame)" + "\n" +"y_label: 类别标签(非文本DataFrame.Series)"+ "\n" )def div_data(self, x_data, y_label):"""将数据依据类分开"""tp = set(y_label)tp_less = [a for a in tp if sum(y_label == a) < sum(y_label != a)][0]data_less = x_data.iloc[y_label == tp_less, :]data_more = x_data.iloc[y_label != tp_less, :]tp.remove(tp_less)return data_less, data_more, tp_less, list(tp)[0]def get_SMOTE_sample(self, x_data, y_label):"""获取需要抽样的正样本"""sample = []data_less, data_more, tp_less, tp_more = self.div_data(x_data, y_label)n_integ = self.N_need // 100data_add = copy.deepcopy(data_less)if n_integ == 0 :print('WARNING: PLEASE RE-ENTER N_need')else:for i in range(n_integ-1):data_out =  data_less.append(data_add)data_out.reset_index(inplace = True, drop = True)return data_out, tp_lessdef over_sample(self, x_data, y_label):"""SMOTE算法简单实现"""sample, tp_less = self.get_SMOTE_sample(x_data, y_label)knn = NearestNeighbors(n_neighbors = self.K_neighbors ,n_jobs = -1).fit(sample)n_atters = x_data.shape[1]label_out = copy.deepcopy(y_label)new = pd.DataFrame(columns = x_data.columns)for i in range(len(sample)): # 1. 选择一个正样本# 2.选择少数类中最近的K个样本k_sample_index = knn.kneighbors(np.array(sample.iloc[i, :]).reshape(1, -1),n_neighbors = self.K_neighbors + 1,return_distance = False)# 计算插值样本# 3.随机选取K中的一个样本np.random.seed(self.random_state)choice_all = k_sample_index.flatten()choosed = np.random.choice(choice_all[choice_all != 0])# 4. 在正样本和随机样本之间选出一个点diff = sample.iloc[choosed,] - sample.iloc[i,]gap = np.random.rand(1, n_atters)new.loc[i] = [x for x in sample.iloc[i,] + gap.flatten() * diff]label_out = np.r_[label_out, tp_less]new_sample = pd.concat([x_data, new])new_sample.reset_index(inplace = True, drop = True)return new_sample, label_outif __name__ == '__main__':iris = load_iris()irisdf = pd.DataFrame(data = iris.data, columns = iris.feature_names)     y_label = iris.target# 生成不平二分类数据iris_1 = irisdf.iloc[y_label == 1,]iris_2 = irisdf.iloc[y_label == 2,]iris_2imb = pd.concat([iris_1, iris_2.iloc[:10, :]])label_2imb =np.r_[y_label[y_label == 1], y_label[y_label == 2][:10]]iris_2imb.reset_index(inplace = True, drop = True)smt  = TWO_SMOTE()x_new, y_new = smt.over_sample(iris_2imb, label_2imb)

以上就是SMOTE的简单实现,尚未有考虑到仅有 0 1变量,后期会更新


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

相关文章

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…

java基础篇 - HashMap 理解Hash碰撞

HashMap是大家都在用&#xff0c;面试的时候也经常会被考的考点&#xff0c;在这篇文章中说下HashMap的hash碰撞和减轻碰撞的优化。 1、什么是hash碰撞 在解释Hash碰撞之前先说一下hashmap的存储结构、添加和检索是怎么实现的 1.1HashMap的存储结构 HashMap的存储结构是En…

大白话解释hash碰撞是什么以及如何解决

一、Hash如何存数据 hash表的本质其实就是数组&#xff0c;hash表中通常存放的是键值对Entry。 这里的id是个key&#xff0c;哈希表就是根据key值来通过哈希函数计算得到一个值&#xff0c;这个值就是下标值&#xff0c;用来确定这个Entry要存放在哈希表中哪个位置。 二、Ha…

hash碰撞的概率推导(生日攻击生日问题)

1.关于hash碰撞 哈希碰撞是指&#xff0c;两个不同的输入得到了相同的输出&#xff1b; hash碰撞不可避免&#xff0c;hash算法是把一个无限输入的集合映射到一个有限的集合里&#xff0c;必然会发生碰撞&#xff1b; 2.碰撞概率的问题描述的其他形式 n个球&#xff0c;&…

Hash碰撞(冲突)的解决方案

hash算法就是&#xff0c;用同一个哈希函数计算&#xff1a; 两个相同的值&#xff0c;计算出的hash值一定相同&#xff0c; 两个不同的值&#xff0c;计算出的hash值可能不同&#xff0c;也可能相同&#xff0c;当相同时就是hash冲突 一、链式寻址法 也叫“拉链法”&#…

MD5 hash碰撞实现解密

目录 1.前言 2.MD5 hash单个碰撞解密 3.MD5 hash批量碰撞解密 1.前言 在日常渗透中,获取到后台密码往往是加密的,常见的就是MD5加密,常见的做法我们会使用在线网站去解密,常用的有cmd5,somd5,cmd5对于一些密文是要收费的,有时我们就想白嫖。 这时我们会用so…

哈希碰撞+mysql_HashMap之Hash碰撞冲突解决方案及未来改进

HashMap位置决定与存储 通过前面的源码分析可知&#xff0c;HashMap 采用一种所谓的“Hash 算法”来决定每个元素的存储位置。当程序执行put(String,Obect)方法 时&#xff0c;系统将调用String的 hashCode() 方法得到其 hashCode 值——每个 Java 对象都有 hashCode() 方法&am…

Hash碰撞概率

计算Hash冲突的概率 虽然已经很多可以选择的Hash函数,但创建一个好的Hash函数仍然是一个活跃的研究领域。一些Hash函数是快的,一些是慢的,一些Hash值均匀地分布在值域上,一些不是。对于我们的目的,让我们假设这个Hash函数是非常好的。它的Hash值均匀地分布在值域上。 在这…

HashMap之Hash碰撞

详细理解了Hash碰撞及处理方法 为什么会出现hash碰撞 在hash算法下,假设两个输入串的值不同,但是得到的hash值相同, 即会产生hash碰撞 一个很简单的例子: 假设你自己设计了一个计算hash的算法toHashValue(String). 是取的输入值的Unicode编码值(当然实际的情况会比这复杂很…

hashmap存储方式 hash碰撞及其解决方式

1.Map 的存储特点 在 Map 这个结构中&#xff0c;数据是以键值对&#xff08;key-value&#xff09;的形式进行存储的&#xff0c;每一个存储进 map 的数据都是一一对应的。 创建一个 Map 结构可以使用 new HashMap() 以及 new TreeMap() 两种方式&#xff0c;两者之间的区别…

Java Hash 碰撞

散列函数&#xff08;英语&#xff1a;Hash function&#xff09;又称散列算法、哈希函数&#xff0c;是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要&#xff0c;使得数据量变小&#xff0c;将数据的格式固定下来。 该函数将数据打乱混合…

通俗解释hash碰撞是什么以及如何解决

Hash如何存数据 hash表的本质其实就是数组&#xff0c;hash表中通常存放的是键值对Entry。 如下图: 这里的学号是个key&#xff0c;哈希表就是根据key值来通过哈希函数计算得到一个值&#xff0c;这个值就是下标值&#xff0c;用来确定这个Entry要存放在哈希表中哪个位置。 H…

Hash碰撞

Hash碰撞 什么是Hash碰撞 Hash碰撞是指两个不同的输入值&#xff0c;经过哈希函数的处理后&#xff0c;得到相同的输出值&#xff0c;这种情况被称之为哈希碰撞。 例如&#xff1a;两个不同的对象&#xff08;object1和object2的值&#xff09;经过Hash函数计算后的&#xf…

浅谈“越权访问”

一&#xff1a;漏洞名称&#xff1a; 越权访问漏洞 描述&#xff1a; 越权访问&#xff0c;这类漏洞是指应用在检查授权&#xff08;Authorization&#xff09;时存在纰漏&#xff0c;使得攻击者在获得低权限用户帐后后&#xff0c;可以利用一些方式绕过权限检查&#xff0c;访…

逻辑越权——垂直、水平越权

水平越权&#xff1a;通过更换的某个ID之类的身份标识&#xff0c;从而使A账号获取&#xff08;修改、删除等&#xff09;B账号数据。 垂直越权&#xff1a;使用低权限身份的账号&#xff0c;发送高权限账号才能有的请求&#xff0c;获得其高权限的操作。 未授权访问&#xff1…

横向越权和纵向越权(水平越权、垂直越权)

越权&#xff1a;顾名思义&#xff0c;就是获得了本不应该有的权限。 我们都喜欢创造一些复杂的词汇&#xff0c;而实际上这些词就是一个代词&#xff0c;根本没有那么复杂。 越权漏洞往往是基于业务逻辑的漏洞&#xff0c;这样的漏洞很难被WAF保护。 越权的分类 按照方向…

越权访问

目录 概念 分类 pikachu--水平越权 源码分析 pikachu---垂直越权 源码分析 概念 越权访问&#xff08;Broken Access Control,BAC&#xff09;是web中一种常见的漏洞&#xff0c;且越权漏洞属于逻辑漏洞&#xff0c;是由于权限校验的逻辑不够严谨导致的&#xff0c;所以越…