实操来了!轻松搞定预测模型类别不平衡问题

文摘   科学   2024-07-06 20:30   湖南  

大家好,我是北游。

我们在做风险预测模型的时候,经常会遇到数据不平衡问题,关于什么是不平衡以及它可能导致的影响,前面已经有过一期分享,这里不赘述:预测模型小白入门:不平衡数据与处理方法文章发布后,有网友留言说想学习具体操作方法,于是这期就专门来聊聊如何具体如何去做smote。

提示:本期会用到R软件,如果你还不会使用,请提前学习相关基础知识,这些知识在我们护理统计随笔平台上都有分享,随着现在原创文章达到了三百余篇,想要找过去的文章会不太容易,所以我们设置了一些菜单页面,可以方便去查找想要的内容,大家不妨去看看。在此之前,特意跟大家求一个关注、点赞和转发,谢谢支持


一、SMOTE的基本介绍

SMOTE(Synthetic Minority Over-sampling Technique)算法是一种用于处理不平衡数据集的过采样方法,由Nitesh V. Chawla等人于2002年提出。其主要目的是通过生成新的合成样本来增加少数类(即数据中较少的类别)的样本数量,从而改善模型训练过程中的类别不平衡问题。

SMOTE算法的底层原理:

  1. 选择少数类样本:从少数类中随机选择一个样本点,称为“种子样本”(Seed Sample)。

  2. 确定K近邻:计算该种子样本点的K个最近邻(K-Nearest Neighbors,KNN),通常使用欧氏距离来衡量。

  3. 选择近邻样本:从K个最近邻中随机选择一个样本点,称为“邻居样本”。

  4. 生成新样本在种子样本和邻居样本之间的连线上,根据随机选择的缩放因子(在0到1之间均匀分布),生成一个新的合成样本点。

  5. 重复过程:重复上述过程,直到生成足够数量的合成样本,使得少数类的样本数量达到预期的平衡状态。

SMOTE算法的特点:

  • 合成样本:SMOTE通过合成新样本而不是简单地复制现有样本,这有助于增加数据的多样性,减少过拟合的风险。

  • 基于最近邻:通过考虑种子样本的K个最近邻,SMOTE能够较好地捕捉到少数类样本的局部特征。

  • 可调整性:用户可以根据需要调整K值和合成样本的数量,以适应不同的数据集和问题。

SMOTE算法的局限性:

  • 对噪声敏感:如果数据中存在噪声或异常值,SMOTE可能会生成质量不高的合成样本。

  • 依赖参数选择:K值的选择可能会影响算法的效果,需要根据具体情况进行调整。

  • 计算成本:对于大规模数据集,计算K近邻可能会带来较高的计算成本。

  • 补充一点(个人亲测):适用于数值变量,如果是分类变量,可能某些工具就无法使用或者需要做点调整。

尽管存在一些局限性,SMOTE算法由于其简单有效性,在处理不平衡数据问题时仍然被广泛使用。此外,还有许多SMOTE的变体,如Borderline-SMOTE、SVM-SMOTE等,旨在解决原始SMOTE的一些不足。

最后,处理类别不平衡问题也不一定要做smote,rose等方法也是很棒的,大家不妨去学习下。鉴于smote比较常用,所以本期以它为例子,分享实操方法。

图片来源:见参考文献

二、R语言实操

这里用几个我自己写的例子来分别展示下数值型变量的处理方法,以及如果既有数值又有分类,该如何处理。

1、预测变量是数值型

这个将会用到smotefamily包。在此之前,我们需要先做点预处理:不能有缺失值,不要对测试集进行平衡处理,确保自变量是数值型的。

library(tidyverse)library(tidymodels)library(MASS)
md1 = biopsy[,-1]md1 = na.omit(md1) #smote不能有缺失值str(md1)
# 分割数据集set.seed(123)md_split = initial_split(md1)md_train = training(md_split)md_test = testing(md_split)
# 查看类别比例table(md_train$class)

这是一个分类任务的预测模型,现在正式执行smote处理:

library(DMwR2)library(smotefamily)
#少数类别增加1倍,只能处理数值变量list = SMOTE(md_train[,-10],md_train[,10],dup_size=1)
# 查看平衡后的类别比例table(list$data$class)

可以看到,平衡后的类别比例相对合理了。

2、预测变量是混合类型

在护理研究领域,我们做风险预测模型时基本不会出现纳入变量全是数值的情况,如果有分类变量,在R语言体系中,是必须进行处理的(比如因子化、设置哑变量等)。在此背景下,如果是混合类型的数据(既有因子、又有数值),怎么处理呢?前面的方法能用吗?答:不行,会报错(个人亲测结果)。这里分享另一种方法。


# 导入数据,后台回复“泰坦尼克”即可获取data = read_csv('train.csv')
# 剔除缺失值data = na.omit(data)
# 选取几个变量,并对分类变量进行因子化varname = colnames(data)data = data %>% dplyr::select(Survived,Pclass,Sex,Age,SibSp,Embarked) %>% mutate( across(c('Survived','Pclass','Sex','Embarked'),factor) )str(data)
# 分割数据集set.seed(123)data_split = initial_split(data)data_train = training(data_split)data_test = testing(data_split)
# 查看类别比例table(data_train$Survived)str(data_train)library(UBL)smote_train = SmoteClassif(Survived~., as.data.frame(data_train), dist = "HEOM")table(smote_train$Survived)

这份数据源于kaggel竞赛平台,有需要的朋友可以回复关键词自动获取。

其实,不光是smote能处理这些类别不平衡问题,还有一些可能更好用的算法。且,对于smote,也有一些更为方便的方法去实现。比如说,mlr3(R语言机器学习的集大成者)、tidymodel(没那么强大,但个人很喜欢),这些框架也集成了多种类别不平衡的处理方法,可能会在后续分享,所以还没有关注公众号的朋友可以关注下哦。

另外,我们也可能会在新开的同名视频号中,以视频的形式分享更多新知识,大家不妨关注下。这期就写到这里了,我们下期再见!



主要参考来源:

Lee YW, Choi JW, Shin EH. Machine learning model for predicting malaria using clinical information. Comput Biol Med. 2021 Feb;129:104151. doi: 10.1016/j.compbiomed.2020.104151. Epub 2020 Nov 28. PMID: 33290932.

相关R包的帮助文档;

本期第一部分内容由AI参与创作。

免责声明:仅供科研学习和分享,不做商业用途,如有侵权,请联系我们删除,谢谢。

补充:护理统计随笔平台的内容现在已经非常丰富,很多方面都有涉及到,如果你觉得你没有看到往期的相关文章,不妨打开公众号的菜单页,在各级目录中查找你想要的内容。如果你在科研学习中遇到了疑问,恰好也想跟网友们交流,可以加入我们建立的“护理科研交流群”。这是一个完全自由、开放、没有套路的纯交流群。入群方式:私信发送关键词“加群”。


护理统计随笔
未来是精准护理的时代,护理研究的发展不仅在于基于证据的理论创新及实践,更在于大数据和人工智能。这里是一个从0到1的学习平台,关注我们,不但可以夯实科研基础,更可以开阔研究视野,让你的护理科研之路走得更远、更广。
 最新文章