机器学习——样本不均衡学习

news2024/9/17 7:14:42

1、样本不均衡定义

一般在分类机器学习中,每种类别的样本是均衡的,也就是不同目标值的样本总量是接近的,但是在很多场景下的样本没有办法做到理想情况,甚至部分情况本身就是不均衡情况:
(1)很多场景下,数据集本身不平和,部分类别的数据多于其他数据;
(2)固定场景下,例如风控的场景,负样本的比例远远小于正样本的占比;
(3)梯度下降过程中,不同类别的样本量比较大时,模型本身很难做到收敛最优解。

2、解决方案

不同场景下,对样本不均衡的解决方案侧重点不同,下面以金融风控举例:
(1)下探法:将被拒绝的用户放进来,充当负样本。缺点也很明显,容易风险高,成本也较高;
(2)代价敏感:对少数样本进行加权处理,让模型进行均衡训练;
(3)采样法:通过多正样本进行欠采样,或者负样本进行过采样的方式平衡样本;
(4)半监督学习

2.1 代价敏感

通过改变少数样本的权重,从而让模型得到一定的均衡训练。但是代价敏感加权增大了负样本在模型中的贡献度,但本身并没有为模型增加额外的信息,这就没有办法解决选择偏误的问题,也没办法带来负面影响。
在逻辑回归中就可以通过参数class_weight='balanced’来调整正负样本的权重,我们以逻辑回归评分卡为例,调整逻辑回归的class_weight的参数,看看结果,该例子链接:逻辑回归评分卡

# 导入模块
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_auc_score,roc_curve,auc

data = pd.read_csv('Bcard.txt')
feature_lst = ['person_info','finance_info','credit_info','act_info']
# 划分数据
train = data[data.obs_mth != '2018-11-30'].reset_index().copy()
val = data[data.obs_mth == '2018-11-30'].reset_index().copy()
x = train[feature_lst]
y = train['bad_ind']
val_x = val[feature_lst]
val_y = val['bad_ind']

# 查看正负样本的数量
print('训练集:\n',y.value_counts())
print('跨时间验证集:\n',val_y.value_counts())

# 训练模型
lr_model = LogisticRegression(C=0.1)
lr_model.fit(x,y)

# 训练集
print('参数调整前的ks值')
y_pred = lr_model.predict_proba(x)[:,1] #取出训练集预测值
fpr_lr_train,tpr_lr_train,_ = roc_curve(y,y_pred) #计算TPR和FPR
train_ks = abs(fpr_lr_train - tpr_lr_train).max() #计算训练集KS
print('train_ks : ',train_ks)

#验证集
y_pred = lr_model.predict_proba(val_x)[:,1] #计算验证集预测值
fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred) #计算验证集预测值
val_ks = abs(fpr_lr - tpr_lr).max() #计算验证集KS值
print('val_ks : ',val_ks)


# 调整逻辑回归中的class_weight参数
print('参数调整后的ks值')
lr_model = LogisticRegression(C=0.1,class_weight = 'balanced')
lr_model.fit(x,y)
y_pred = lr_model.predict_proba(x)[:,1] #取出训练集预测值
fpr_lr_train,tpr_lr_train,_ = roc_curve(y,y_pred) #计算TPR和FPR
train_ks = abs(fpr_lr_train - tpr_lr_train).max() #计算训练集KS
print('train_ks : ',train_ks)
y_pred = lr_model.predict_proba(val_x)[:,1] #计算验证集预测值
fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred) #计算验证集预测值
val_ks = abs(fpr_lr - tpr_lr).max() #计算验证集KS值
print('val_ks : ',val_ks)

在这里插入图片描述
从上面可以看出,调整参数后的训练集合验证集的ks值都有了一定的提升。

2.2 过采样

代价敏感有用,但效果不一定,通过对负样本进行过采样能够达到更好的效果,即为模型引入更多的负样本。一般过采样的方法如下:

  • 随机过采样:直接复制负样本,模型的泛化能力较差。
  • SMOTE算法:少数类别过采样技术(Synthetic Minority Oversampling Technique)

SMOTE过采样

SMOTE是通过合成少数样本的过采样技术,它是通过对少数样本进行分析,然后在现有少数样本之间进行插值,人工合成新样本,合并样本到模型中训练。基本步骤如下:
(1)采用knn算法,计算出每个少数样本的k个近邻;
(2)从k个近邻中随机挑选N个样本进行随机线性插值;
(3)构造新的少数样本;
(4)将新样本和原本数据合并,产生新的训练集。
在这里插入图片描述

SMOTETomek综合采样

先使用过采样,扩大样本后再对处在胶着状态的点用 Tomek Link 法进行删除,有时候甚至连 Tomek Link 都不用,直接把离得近的对全部删除,因为在进行过采样后,0 和 1 的样本量已经达到了 1:1。
在这里插入图片描述

随机过采样、SMOTE采样和综合采样的示例代码

以上面的评分卡数据为例,读取数据的代码省略。
导入模块

from imblearn.over_sampling import RandomOverSampler,SMOTE
from imblearn.combine import SMOTETomek

使用三种过采样方法进行采样

# 随机过采样
ros = RandomOverSampler(random_state=0, sampling_strategy='auto')
x_ros, y_ros = ros.fit_resample(x,y)
print('随机过采样后分类情况:',y_ros.value_counts())

# SMOTE过采样
sot = SMOTE(random_state=0)
x_sot,y_sot = sot.fit_resample(x,y)
print('smote过采样后情况:',y_sot.value_counts())

# SMOTETomek综合采样
sttk = SMOTETomek(random_state=0)
x_sttk,y_sttk = sttk.fit_resample(x,y)
print('综合采样后情况:',y_sttk.value_counts())

在这里插入图片描述
比较三种采样后的ks值、recall值和auc值

data = [['原始数据',x,y],['随机过采样',x_ros,y_ros],['SMOTE过采样',x_sot,y_sot],['综合过采样',x_sttk,y_sttk]]

# 使用逻辑回归分别对过采样后的数据进行训练,看看情况
lr = LogisticRegression(C=0.1)
for text,train_X, train_y in data:
    lr.fit(train_X, train_y)
    y_pred = lr.predict_proba(val_x)[:,1] #计算验证集预测值
    pred_y = lr.predict(val_x)
    rc_score = recall_score(val_y,pred_y)
    fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred) #计算验证集预测值
    val_ks = abs(fpr_lr - tpr_lr).max() #计算验证集KS值
    auc_score = auc(fpr_lr,tpr_lr)
    print(text,'ks',val_ks,'auc',auc_score,'recall',rc_score)

在这里插入图片描述
以上可以看出三种方法过采样可以提升模型的评分,但没有一定要采用哪种过采样方法,不同的数据会有不同的情况。

机器学习与过采样

我们还能使用机器学习先对训练集的数据进行拟合,将预测结果较差的样本排除,不参与过采样,具体代码如下:
这里我们使用lightGBM算法,数据还是使用上面数据

 # 使用lightGBM进行数据拟合,去掉预测结果较差的数据,再进行smote过采样
import lightgbm as lgb
import numpy as np
lgb_clf = lgb.LGBMClassifier(learning_rate=0.05,n_estimators=100)
lgb_clf.fit(x, y, eval_set=[(x, y), (val_x, val_y)], eval_metric='auc')
temp = x.copy()
temp['bad_ind'] = y
temp['pred'] = lgb_clf.predict_proba(x)[:,1]
temp=temp.sort_values(by=['pred'], ascending=False).reset_index()
temp['rank'] = np.array(temp.index)/len(temp)
temp

在这里插入图片描述
我们定义一个weight函数,将预测不准的前后各20%数据排除

def weight(x,y):
    if x==0 and y<0.2:
        return 0.1
    elif x==1 and y>0.8:
        return 0.1
    else:
        return 1
    
temp['weight'] = temp.apply(lambda x:weight(x.bad_ind,x['rank']), axis=1)
smote_sample = temp[temp.weight==1]
print(smote_sample.shape)
train_X_smote = smote_sample[feature_lst]
train_y_smote = smote_sample['bad_ind']

在这里插入图片描述
同样进行三种采样,跟没有采样数据进行对比

# 随机过采样
ros = RandomOverSampler(random_state=0, sampling_strategy='auto')
x_ros, y_ros = ros.fit_resample(train_X_smote,train_y_smote)
print('随机过采样后分类情况:',y_ros.value_counts())

# SMOTE过采样
sot = SMOTE(random_state=0)
x_sot,y_sot = sot.fit_resample(train_X_smote,train_y_smote)
print('smote过采样后情况:',y_sot.value_counts())

# SMOTETomek综合采样
sttk = SMOTETomek(random_state=0)
x_sttk,y_sttk = sttk.fit_resample(train_X_smote,train_y_smote)
print('综合采样后情况:',y_sttk.value_counts())

data = [['原始数据',x,y],['随机过采样',x_ros,y_ros],['SMOTE过采样',x_sot,y_sot],['综合过采样',x_sttk,y_sttk]]

# 使用逻辑回归分别对过采样后的数据进行训练,看看情况
lr = LogisticRegression(C=0.1)
for text,train_X, train_y in data:
    lr.fit(train_X, train_y)
    y_pred = lr.predict_proba(val_x)[:,1] #计算验证集预测值
    pred_y = lr.predict(val_x)
    rc_score = recall_score(val_y,pred_y)
    fpr_lr,tpr_lr,_ = roc_curve(val_y,y_pred) #计算验证集预测值
    val_ks = abs(fpr_lr - tpr_lr).max() #计算验证集KS值
    auc_score = auc(fpr_lr,tpr_lr)
    print(text,'ks',val_ks,'auc',auc_score,'recall',rc_score)

在这里插入图片描述
可以看到将预测结果较差的样本排除,再进行过采样,得到的模型会比更好一些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/803020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[洛谷]P2052 [NOI2011] 道路修建(dfs)

在递归过程中也把子节点的贡献&#xff08;以及左右国家数记录下来了&#xff09;。 void dfs(int u,int fa) {d[u]1;//当前节点也算一个 for(int ih[u]; i; ine[i]) {int toe[i];//子节点if(tofa) continue;//防止重复搜索&#xff0c;即防止从下往上搜dfs(to,u);//子节点 //…

基于SSM+JSP+LayUI的宿舍管理系统

修正初始账号密码 默认账号&#xff1a;admin&#xff0c;默认密码&#xff1a;123456修复后台管理头像消失功能相对简单些&#xff0c;可能需要添加一些功能&#xff0c;需要源码免费提供需要运行服务、添加功能等联系我

springboot开放实验室管理系统【纯干货分享,免费领源码03361】

摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是使用动态网页开发技术java作为系统的开发语言&#xff0c;M…

如何挑选滚珠螺杆的润滑油脂?

滚珠螺杆在日常使用中&#xff0c;出现卡顿或者噪音等问题&#xff0c;不用担心&#xff0c;不是你的滚珠螺杆出了问题&#xff0c;而是润滑系统出了问题&#xff0c;提醒你应该更换润滑油了。那么&#xff0c;我们应该怎样挑选滚珠螺杆的润滑油呢&#xff1f; 一般建议用轴承润…

hive整合es,详细过程。

参考官网 Apache Hive integration | Elasticsearch for Apache Hadoop [7.17] | Elastic 官网的介绍很简单&#xff0c;我看了很多博客&#xff0c;写的也很简单&#xff0c;但是我搞了半天才勉强成功&#xff0c;分享下&#xff0c;免得各位多走弯路。 环境准备 官网也很…

K8S暴露pod内多个端口

K8S暴露pod内多个端口 一、背景 公司统一用的某个底包跑jar服务&#xff0c;只暴露了8080端口 二、需求 由于有些服务在启动jar服务后&#xff0c;会启动多个端口&#xff0c;除了8080端口&#xff0c;还有别的端口需要暴露&#xff0c;我这里就还需要暴露9999端口。 注&a…

mysql常用时间相关函数

在我们平常开发的工作中&#xff0c;我们在数据库中经常会用到时间相关的函数&#xff0c;比如格式化当前时间&#xff0c;求当前时间或者计算某个特定间隔后的时间&#xff0c;那么我们主要会用到哪些函数呢&#xff1f; 1&#xff1a;求当前时间&#xff1a; select now();…

Gradle build 失败后提示.lock文件,解决办法

在Gradle build失败之后时&#xff0c;有时候强制关闭AndroidStudio&#xff0c;再次打开build时&#xff0c;会提示各种.lock 文件问题&#xff0c;删除了一个还有下一个&#xff0c;而且路径不一样。 一般情况下是这两个文件夹下的lockfile影响继续build %GRADLE_HOME%/ca…

YoLoV7做图像分类/目标检测过程(附代码+详细操作说明)

一、准备数据 图像在my_1imgs中&#xff0c;一个是原图jpg&#xff0c;一个是用labelimg画的标签xml文件。&#xff08;这个画的是一个矩形框&#xff09; 把自己的数据集&#xff08;原图和标签准备好后&#xff09;&#xff0c;这两个文件复制到VOCdevkit中,ImageSets为空。 …

EtherNet/IP转CAN网关can协议标准

生产管理设备中&#xff0c;会有设备与其他设备的协议不同&#xff0c;数据无法互通&#xff0c;让你的工作陷入困境。这时&#xff0c;一款神奇的产品出现了——远创智控YC-EIP-CAN通讯网关&#xff01; 1, 这款通讯网关采用ETHERNET/IP从站功能&#xff0c;可以将各种CAN总线…

vue-simple-uploader的fileAdded方法不支持异步的解决办法,autoStart 设置

每日鸡汤&#xff1a;悲观者可能正确&#xff0c;但是乐观者往往成功 假设有一个需求&#xff0c;上传的pdf文档不得大于10M 使用 vue-simple-uploader 这个插件&#xff0c;我们需要在 fileAdded 事件里面进行校验&#xff0c;在1.0.0版本以后&#xff0c;如果想停止上传&…

如何快速用Python获取短信验证码

在Python中获取短信验证码需要通过调用短信服务接口或者使用短信网关来实现。具体实现方式取决于你使用的短信服务提供商或者短信网关的API。 一般来说&#xff0c;你需要以下步骤来获取短信验证码&#xff1a; 选择短信服务提供商或者短信网关 你需要选择一个合适的短信服务…

vue利用echarts简单实现具有中心节点的知识图谱

效果展示 边缘节点可拖动&#xff0c;其大小可以根据传入的值而变化&#xff08;比如我更喜欢芒果&#xff0c;所以给了芒果更大的权值&#xff0c;在显示的时候芒果所在的节点显示的比例更大&#xff09; 代码下载 https://download.csdn.net/download/David_house/881151…

汉明距离,两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。

题记&#xff1a; 两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y&#xff0c;计算并返回它们之间的汉明距离。 示例 1&#xff1a; 输入&#xff1a;x 1, y 4 输出&#xff1a;2 解释&#xff1a; 1 (0 0 0 1) 4 (0 1 0 0…

家用取暖器北美UL 1278测试要求内容

取暖器是指用于取暖的设备&#xff0c;取暖设备根据加热介质不同、加热原不同&#xff0c;大体可以分为&#xff1a;燃气取暖设备、电加热取暖设备、锅炉取暖设备、电壁挂炉取暖。但一般这类产品要上架美国亚马逊平台都必须要办理UL1278测试报告。 适用产品范围&#xff1a; …

苍穹外卖-day02

苍穹外卖-day02 本项目学自黑马程序员的《苍穹外卖》项目&#xff0c;是瑞吉外卖的Plus版本 功能更多&#xff0c;更加丰富。 结合资料&#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频&#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…

机器学习|分类入门

顾名思义&#xff0c;分类就是把事物“分类”成子类别的任务。但是&#xff0c;被一台机器&#xff01;如果这听起来并不多&#xff0c;想象一下你的电脑能够区分你和陌生人。在土豆和西红柿之间。在A和F之间。现在听起来很有趣。分类是监督机器学习的一部分&#xff0c;我们将…

Linux内核中的链表、红黑树和KFIFO

lLinux内核代码中广泛使用了链表、红黑树和KFIFO。 一、 链表 linux内核代码大量使用了链表这种数据结构。链表是在解决数组不能动态扩展这个缺陷而产生的一种数据结构。链表所包含的元素可以动态创建并插入和删除。链表的每个元素都是离散存放的&#xff0c;因此不需要占用连…

红黑树深入剖析【C++】

目录 一、红黑树概念 二、红黑树节点结构设计 三、插入操作 处理情况1 处理情况2 处理情况3 插入总结&#xff1a; 四、插入操作源码 五、红黑树验证 一、红黑树概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0…