R语言:SMOTE - Supersampling Rare Events in R:用R对非平衡数据的处理方法

SMOTE - Supersampling Rare Events in R:用R对稀有事件进行超级采样

在这个例子中将用到以下三个包

{DMwR} - Functions and data for the book “Data Mining with R” and SMOTE algorithm:SMOTE算法

{caret} - modeling wrapper, functions, commands:模型封装、函数、命令

{pROC} - Area Under the Curve (AUC) functions:曲线下面积(ACU)函数

SMOTE算法是为了解决不平衡的分类问题。也就是说,它可以产生一个新的“SMOTEd”数据,解决类不平衡问题集。或者,它也可以运行在这个新的数据集的分类算法,并返回所得到的模型。

我们利用 Thyroid Disease 数据来进行研究。

让我们清洗一些数据

# 加载数据,删除冒号和句号,并追加列名

hyper <-read.csv(‘http://archive.ics.uci.edu/ml/machine-learning-databases/thyroid-disease/hypothyroid.data‘, header=F)

names <- read.csv(‘http://archive.ics.uci.edu/ml/machine-learning-databases/thyroid-disease/hypothyroid.names‘, header=F, sep=‘\t‘)[[1]]

names <- gsub(pattern =":|[.]", replacement="", x = names)

colnames(hyper)<-names

# 我们将第一列的列名从 hypothyroid, negative改成target,并将negative变成0,其他值变成1.

colnames(hyper)[1]<-"target"

colnames(hyper)

##  [1] "target"                    "age"

##  [3] "sex"                       "on_thyroxine"

##  [5] "query_on_thyroxine"        "on_antithyroid_medication"

##  [7] "thyroid_surgery"           "query_hypothyroid"

##  [9] "query_hyperthyroid"        "pregnant"

## [11] "sick"                      "tumor"

## [13] "lithium"                   "goitre"

## [15] "TSH_measured"              "TSH"

## [17] "T3_measured"               "T3"

## [19] "TT4_measured"              "TT4"

## [21] "T4U_measured"              "T4U"

## [23] "FTI_measured"              "FTI"

## [25] "TBG_measured"              "TBG"

hyper$target<-ifelse(hyper$target=="negative",0,1)

# 检查下阳性和阴性的结果

table(hyper$target)

##

##    0    1

## 3012  151

prop.table(table(hyper$target))

##

##       0       1

## 0.95226 0.04774

# 可见,1仅有5%。这显然是一个扭曲的数据集,也是罕见事件。

head(hyper,2)

##   target age sex on_thyroxine query_on_thyroxine on_antithyroid_medication

## 1      1  72   M            f                  f                         f

## 2      1  15   F            t                  f                         f

##   thyroid_surgery query_hypothyroid query_hyperthyroid pregnant sick tumor

## 1               f                 f                  f        f    f     f

## 2               f                 f                  f        f    f     f

##   lithium goitre TSH_measured TSH T3_measured   T3 TT4_measured TT4

## 1       f      f            y  30           y 0.60            y  15

## 2       f      f            y 145           y 1.70            y  19

##   T4U_measured  T4U FTI_measured FTI TBG_measured TBG

## 1            y 1.48            y  10            n   ?

## 2            y 1.13            y  17            n   ?

# 这数据都是因子型变量(字符型的值),这些都需要转换成二值化的数字,以方便建模:

ind<-sapply(hyper,is.factor)

hyper[ind]<-lapply(hyper[ind],as.character)

hyper[hyper=="?"]=NA

hyper[hyper=="f"]=0

hyper[hyper=="t"]=1

hyper[hyper=="n"]=0

hyper[hyper=="y"]=1

hyper[hyper=="M"]=0

hyper[hyper=="F"]=1

hyper[ind]<-lapply(hyper[ind],as.numeric)

replaceNAWithMean<-function(x) {replace(x,is.na(x),mean(x[!is.na(x)]))}

hyper<-replaceNAWithMean(hyper)

模型研究

我们利用caret包中的createDataPartition(数据分割功能)函数将数据随机分成相同的两份。

library(caret)

## Loading required package: lattice

## Loading required package: ggplot2

set.seed(1234)

splitIndex<-createDataPartition(hyper$target,time=1,p=0.5,list=FALSE)

trainSplit<-hyper[splitIndex,]

testSplit<-hyper[-splitIndex,]

prop.table(table(trainSplit$target))

##

##       0       1

## 0.95006 0.04994

prop.table(table(testSplit$target))

##

##       0       1

## 0.95446 0.04554

两者的分类结果是平衡的,因此仍然有5%左右的代表,我们仍然处于良好的水平。

我们利用caret包中的treebag模型算法,对训练集数据建立模型,并对测试集数据进行预测。

ctrl<-trainControl(method="cv",number=5)

tbmodel<-train(target~.,data=trainSplit,method="treebag",

trControl=ctrl)

## Loading required package: ipred

## Loading required package: plyr

predictors<-names(trainSplit)[names(trainSplit)!=‘target‘]

pred<-predict(tbmodel$finalModel,testSplit[,predictors])

为了评估模型,我们用pROC包的roc函数算auc得分和画图

library(pROC)

## Type ‘citation("pROC")‘ for a citation.

##

## Attaching package: ‘pROC‘

##

## 下列对象被屏蔽了from ‘package:stats‘:

##

##     cov, smooth, var

auc<-roc(testSplit$target,pred)

print(auc)

##

## Call:

## roc.default(response = testSplit$target, predictor = pred)

##

## Data: pred in 1509 controls (testSplit$target 0) < 72 cases (testSplit$target 1).

## Area under the curve: 0.985

plot(auc,ylim=c(0,1),print.thres=TRUE,main=paste(‘AUC‘,round(auc$auc[[1]],2)))

##

## Call:

## roc.default(response = testSplit$target, predictor = pred)

##

## Data: pred in 1509 controls (testSplit$target 0) < 72 cases (testSplit$target 1).

## Area under the curve: 0.985

abline(h=1,col="blue",lwd=2)

abline(h=0,col="red",lwd=2)

auc得分是0.98,已经是非常不错的结果了(因为它的范围是在0.5到1之间)。

很难想象SMOTE对此能再有提高了,但接下来我们利用SMOTE对数据处理后再建模,看看auc结果

在R中,SMOTE算法是DMwR软件包的一部分,主要参数有如下三个:perc.over:过采样时,生成少数类的样本个数;k:过采样中使用K近邻算法生成少数类样本时的K值,默认是5;perc.under:欠采样时,对应每个生成的少数类样本,选择原始数据多数类样本的个数。例如,perc.over=500表示对原始数据集中的每个少数样本,都将生成5个新的少数样本;perc.under=80表示从原始数据集中选择的多数类的样本是新生的数据集中少数样本的80%。

library(DMwR)

## Loading required package: grid

##

## Attaching package: ‘DMwR‘

##

## 下列对象被屏蔽了from ‘package:plyr‘:

##

##     join

trainSplit$target<-as.factor(trainSplit$target)

trainSplit<-SMOTE(target~.,trainSplit,perc.over=100,perc.under=200)

trainSplit$target<-as.numeric(trainSplit$target)

# 我们再次用prop.table()函数检查结果的平衡性,确定我们已经让阴性、阳性数据达到相同。

prop.table(table(trainSplit$target))

##

##   1   2

## 0.5 0.5

# 再次建立treebag模型

tbmodel<-train(target~.,data=trainSplit,method="treebag",

trControl=ctrl)

predictors<-names(trainSplit)[names(trainSplit)!=‘target‘]

pred<-predict(tbmodel$finalModel,testSplit[,predictors])

auc<-roc(testSplit$target,pred)

print(auc)

##

## Call:

## roc.default(response = testSplit$target, predictor = pred)

##

## Data: pred in 1509 controls (testSplit$target 0) < 72 cases (testSplit$target 1).

## Area under the curve: 0.99

哇,达到0.99,比之前的0.985有提高

plot(auc,ylim=c(0,1),print.thres=TRUE,main=paste(‘AUC‘,round(auc$auc[[1]],2)))

##

## Call:

## roc.default(response = testSplit$target, predictor = pred)

##

## Data: pred in 1509 controls (testSplit$target 0) < 72 cases (testSplit$target 1).

## Area under the curve: 0.99

abline(h=1,col="blue",lwd=2)

abline(h=0,col="red",lwd=2)

时间: 2024-10-31 12:21:10

R语言:SMOTE - Supersampling Rare Events in R:用R对非平衡数据的处理方法的相关文章

《R语言入门》如何在Windows下安装R语言编程环境

R语言开发环境下载安装地址:http://ftp.ctex.org/mirrors/CRAN/index.html 有Linux版本,Mac版本,Windows版本,这里点击Download R for Windows,打开的页面又有几个选项,点击"install R for the first time."进入真正的下载页面, 点击"Download R 3.1.2 for Windows"开始下载. 运行安装程序,开始安装:一路下一步就可以了. 安装完成后会在桌

R语言基础知识学习(四):R中的画图函数--plot()函数

plot()函数是R中基本的画x-y两个变量的函数,其用法如下为:plot(x, y, ...) 例如:首先我用runif()函数产生了两列随机数:x1,y1,然后用plot()函数直接画图: > x1 <- round(runif(20,min = 0 ,max = 100))> x1 [1] 90 84 86 86 28 43 86 76 90 76 14 62 40 52 87 57 88 17[19] 10 27> y1 <- round(runif(20,min =

R语言基础知识学习(一):R中的数据类型和数据结构

R中数据类型有:数值型,字符型,逻辑型和复数型等. R 中存储数据的结构有:向量,数组,因子,数据框,矩阵和列表等. 向量是用于存储数值型.字符型或逻辑型数据的一维数组. 用函数c()可以来创建一个向量,如: > a <- c(1,2,3,4)> b <- c('china','america','japan')> c <- c(TRUE,FALSE,TRUE,FALSE)> ls()[1] "a" "b" "c&

R语言基础知识学习(五):R中的线性回归分析

在R中线性回归分析的函数是lm(). (1)一元线性回归 我们可以根据以上数据来分析合金的强度是否与碳含量有关系. 首用以下命令把数据读取到R中: x <- c(seq(0.10,0.18,by = 0.01),0.20,0.21,0.23)y <- c(42.0,43.5,45.0,45.5,45.0,47.5,49.0,53.0,50.0,55.0,55.0,60.0)plot(x,y) 通过画图得到想x,y两个变量之间存在某种线性关系 所以,就可以用lm()函数来拟合直线,通过回归函数l

R语言快速上手入门

R语言快速上手入门 课程学习网址:http://www.xuetuwuyou.com/course/196 课程出自学途无忧网:http://www.xuetuwuyou.com 课程简介 本教程深入浅出地讲解如何使用R语言玩转数据.课程中涵盖R语言编程的方方面面,内容涉及R对象的类型.R的记号体系和环境系统.自定义函数.if else语句.for循环.S3类R的包系统以及调试工具等.本课程还通过示例演示如何进行向量化编程,从而对代码进行提速并尽可能地发挥R的潜能.本课程适合立志成为数据科学家的

R语言入门

向量是 R 语言中最基本的数据类型,在 R 中没有单独的标量(例如 1 本质上是 c(1)) 注意 R 语言的下标是从 1 开始的 负数下标表示不选这个这些下标,例如: > a <- c(2,5,8)> a[-2][1] 2 8 循环补齐 向量有个比较有趣的性质,当两个向量进行操作时,如果长度不等,长度比较短的一个会复制自己直到自己和长的一样长. > a <- c(3,4)> b <- c(1,2,5,6)> a+b[1]  4  6  8 10 新建一个矩

基于R语言的数据分析和挖掘方法总结——均值检验

2.1 单组样本均值t检验(One-sample t-test) 2.1.1 方法简介 t检验,又称学生t(student t)检验,是由英国统计学家戈斯特(William Sealy Gosset, 1876-1937)所提出,student则是他的笔名.t检验是一种检验总体均值的统计方法,当数据中仅含单组样本且样本数较大时(通常样本个数≧30的样本可视为样本数较大),可用这种方法来检验总体均值是否大于.小于或等于某一特定数值.当数据中仅含单组样本但样本数较小时(通常样本个数<30的样本可视为

R语言学习笔记2——绘图

R语言提供了非常强大的图形绘制功能.下面来看一个例子: > dose <- c(20, 30, 40, 45, 60)> drugA <- c(16, 20, 27, 40, 60)> drugB <- c(15, 18, 25, 31, 40) > plot(dose, drugA, type="b") > plot(dose, drugB, type="b") 该例中,我们引入了R语言中第一个绘图函数plot.pl

R语言字符串处理包stringr

前言 用R语言处理字符串,总觉得很麻烦,即不能用向量的方法进行分割,也不能用循环遍历索引.grep()家族函数常常记不住,paste()函数默认以空格分割,各种不顺手啊!随着使用R语言的场景越来越多,字符串处理是必不可少的.给大家推荐一个由 Hadley Wickham 开发的一个灵活的字符串处理包stringr. 目录 stringr介绍 stringr安装 stringr的API介绍 整体文章:http://blog.fens.me/r-stringr/