解决R语言 数据不平衡的问题

 更新时间:2021年03月11日 14:36:39   作者:Y_Wolf  
这篇文章主要介绍了解决R语言 数据不平衡的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

R语言解决数据不平衡问题

一、项目环境

开发工具:RStudio

R:3.5.2

相关包:dplyr、ROSE、DMwR

二、什么是数据不平衡?为什么要处理数据不平衡?

首先我们要知道的第一个问题就是“什么是数据不平衡”,从字面意思上进行解释就是数据分布不均匀。在我们做有监督学习的时候,数据中有一个类的比例远大于其他类,或者有一个类的比值远小于其他类时,我们就可以认为这个数据存在数据不平衡问题。

那么这样的一个问题会对我们后续的分析工作带来怎样的影响呢?我举个简单的例子,或许大家就明白了。

假设我们现在需要训练一个模型来分辨人群中那个人是恐怖分子。那么现在给到我们1万个人员的数据,在做分析之前其实我们就很清楚,一群人中恐怖分子的比例肯定是要远小于普通人的比例的。

那么假如在这1万个人中只有一个是恐怖分子,那么恐怖分子与正常人的比例就是 9999 : 1 。

那么如果我们不进行任何处理就直接进行有监督学习的话,那么模型只需要将所有人数据都分类为正常人,模型的准确率就能达到99.99%。而这样的模型显然是没有意义的。

因为基本上说有可能存在的恐怖分子的特征基本都被模型给忽略了,这也就说明了为什么要处理数据不平衡问题。

三、 常见的数据不平衡处理方法

以下是几种比较常见的处理数据不平衡的方法:

1、欠采样法(Undersampling)

2、过采样法(Oversampling)

3、人工数据合成法(Synthetic Data Generation)

4、代价敏感学习法(Cose Sensitive Learning)

【注】:本文主要以实现为主,因此不对上述方法进行过多的讲解。

​ 在处理数据之前,我们先看一下需要处理的数据分布的情况。

load("C:/Users/User/Desktop/data.RData")
table(data$classification)
prop.table(table(data$classification))

> table(data$classification)

-8 1 2 3 4 5

12 104 497 1158 4817 1410

> prop.table(table(data$classification))

-8 1 2 3 4 5

0.001500375 0.013003251 0.062140535 0.144786197 0.602275569 0.176294074

1、 欠采样

######### 方法一 #########
library(ROSE)
# 由于是多分类问题,我们先提取数据中比例最大的类和比例最小的类
# 进行平衡(转化为二分类问题)
test <- data[which(data$classification == -8 | data$classification == 4),]
# 将分类结果转化为因子型(不然会报错)
test$classification <- as.factor(test$classification)
# 进行欠采样
# 其中 method = "under" 表示采用的方法为“欠采样”
# N = 40 表示最终整个数据集的数量
# seed 随机种子,为了保留对样本的追踪
under <- ovun.sample(classification ~ ., test, method = "under", N = 40, seed = 1)$data
# 查看结果
table(under$classification)

> table(under$classification)

4 -8

28 12

######### 方法二 #########
library(dplyr)
# 由于是多分类问题,我们先提取数据中比例最大的类和比例最小的类
# 进行平衡(转化为二分类问题)
test <- data[which(data$classification == -8 | data$classification == 4),]
# 提取大比例类
test1 <- test[which(test$classification == 4),]
# 将大比例类的数量降为12个
down <- sample_n(test1, 12, replace = TRUE)
# 将欠采样后的类进行合并
down <- rbind(test[which(test$classification == -8), ],down)
table(down$classification)

> table(down$classification)

-8 4

12 12

【注】:欠采样是无放回的采样。

2、 过采样

######### 方法一 #########
library(ROSE)
test <- data[which(data$classification == -8 | data$classification == 4),]
test$classification <- as.factor(test$classification)
# 实现上大致与欠采样相同,只有类型 method 改成了 "over",同时没有限制总数量
under <- ovun.sample(classification ~ ., test, method = "over", seed = 1)$data
table(under$classification)

> table(under$classification)

4 -8

4817 4785

######### 方法二 #########
library(dplyr)
test <- data[which(data$classification == -8 | data$classification == 4),]
# 提取小比例类
test1 <- test[which(test$classification == -8),]
# 将小比例类的数量降为4817个(与大比例类相同)
# 这里使用的过采样方法是随机复制小比例类中的数据,将其扩充到指定数量
down <- sample_n(test1, 4817, replace = TRUE)
down <- rbind(test[which(test$classification == 4), ],down)
table(down$classification)

> table(down$classification)

-8 4

4817 4817

3、人工数据合成法(Synthetic Data Generation)

######### 方法一 #########
library(ROSE)
# 由于是多分类问题,我们先提取数据中比例最大的类和比例最小的类
# 进行平衡(转化为二分类问题)
test <- data[which(data$classification == -8 | data$classification == 4),]
# 将分类结果转化为因子型(不然会报错)
test$classification <- as.factor(test$classification)
# ROSE提供了ROSE()函数来合成人工数据
rose <- ROSE(classification ~ ., test, seed = 1)$data
# 查看结果
table(rose$classification)

> table(rose$classification)

4 -8

2483 2346

######### 方法二 #########
library(DMwR)
test <- data[which(data$classification == -8 | data$classification == 4),]
test$classification <- as.factor(test$classification)
# perc.over: 如 perc.over = n,小比例类的个数变为 (n/100)a + a 个数据(a为小比例类原始数量)
# perc.under: 如 perc.under = m,大比例类的个数变为((nm)/100)a个
# 因此本次案例中,小比例类的个数变为(3500/100)*12 + 12 = 432个
# 大比例类的个数变为((3500*300)/100^2)*12 = 1260个
down <- SMOTE(classification ~ ., test, perc.over = 3500, perc.under = 300)
table(down$classification)

> table(down$classification)

-8 4

432 1260

【注】:相较于前两种方法而言,人工合成法既不会像过采样容易导致过拟合问题,也不会出现欠采样大量丢失信息的问题。

4、代价敏感学习法(Cose Sensitive Learning)

【注】:还没想好怎么写。。。。。

三、 结语

本文之所以都只拿两个分类在进行分析,是因为上面提到的用于解决数据不平衡问题的函数,基本上都是针对二分类问题的。当导入的数据中有大于两个分类时,函数就会报错。

但是在实际分析的过程中,其实我们更经常遇到的时多分类问题,这是我们就需要将多分类问题转化为二分类问题,将各个分类两两进行比较才能更好的解决数据不平衡的问题。

相关文章

  • R语言学习RcppEigen进行矩阵运算

    R语言学习RcppEigen进行矩阵运算

    这篇文章主要为大家介绍了R语言学习如何利用RcppEigen进行矩阵运算的实现方式,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • R语言seq()函数的调用方法

    R语言seq()函数的调用方法

    这篇文章主要介绍了R语言seq()函数的调用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • R语言初学者的一些常见报错指南

    R语言初学者的一些常见报错指南

    在使用R的时候,偶尔也会遇到一些糟心的报错,本文把运行过程中遇到的一些报错和解决方案进行总结归纳,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • R语言学习笔记缺失数据的Bootstrap与Jackknife方法

    R语言学习笔记缺失数据的Bootstrap与Jackknife方法

    这篇文章主要为大家介绍了R语言学习笔记关于缺失数据的Bootstrap与Jackknife的方法,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • 使用ggsignif优雅添加显著性标记详解

    使用ggsignif优雅添加显著性标记详解

    这篇文章主要为大家介绍了使用ggsignif优雅添加显著性标记详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • R语言可视化开发forestplot根据分组设置不同颜色

    R语言可视化开发forestplot根据分组设置不同颜色

    这篇文章主要为大家介绍了R语言可视化开发使用forestplot根据分组设置不同颜色的实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • R语言关于多重回归知识点总结

    R语言关于多重回归知识点总结

    在本篇内容里小编给大家整理了一篇关于R语言关于多重回归知识点总结,有兴趣的朋友们可以学习下。
    2021-05-05
  • 用R语言绘制ROC曲线的实例讲解

    用R语言绘制ROC曲线的实例讲解

    这篇文章主要介绍了用R语言绘制ROC曲线的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 基于R语言中的各种更新方法分享

    基于R语言中的各种更新方法分享

    这篇文章主要介绍了基于R语言中的各种更新方法分享,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • R语言-计算频数和频率的操作

    R语言-计算频数和频率的操作

    这篇文章主要介绍了R语言-计算频数和频率的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论