特征工程(二)
0.1 离群值识别和处理
离群值是指数据集的每个变量中孤立于其他数据点的对象。在数据的收集中,由于各种因素的影响,离群点是很难避免的。尤其在人工输入数据的时候,经常会出现小数点输入错误的问题,比如123.12误输入为1231.2。
离群点同样会对数据挖掘产生一定的影响,如果不做离群点的处理,那么模型的输入就是存在偏差的。可想而知,一个有偏差的输入,很难得出无偏差的输出。
0.1.1 离群点识别
在 R 中识别离群点的方法同样有很多,比如可视化方向的箱线图、统计学方向的高杠杆值点、dffits值、学生化残差、cook距离等。不过统计学方向的识别方法是基于回归的,现在学习这个有些吃力,所以在此我就只简单的介绍通用的可视化方法。
绘制箱线图也有很多种函数,比如boxplot()、geom_boxplot()、plot_ly()等。箱线图会让我们方便的了解某个变量的分布情况,并且会把离群点(上边缘以上和下边缘以下)标记出来。不过对于含有较多离群点的变量来说,其返回的结果不能清晰的看到离群点的具体个数。
boxplot(iris$Sepal.Width) # 绘制箱线图
从上面的两个箱线图可以看出,第一个箱线图可以看到Sepal.Width中存在4个离群点。
0.1.2 离群点处理
针对于离群点的处理方法主要是:直接剔除含有异常值的观测、视为缺失值处理、均值修正(前后两个观测的均值替换)、用特定值替换(一般用于知道离群点出现的原因)。同样,处理的方法也是各有千秋。
需要注意的是,并不是说离群点必须要做处理。如果说离群点是一个正确的数据,比如说公司中不同职位的员工的工资汇总表就会出现很多离群点,所以说在很多情况下则可以直接进行挖掘。由于这个离群点的处理大都是由业务需求决定的,所以后面只演示剔除某个值以上的离群点。
后面的代码中会出现%>%,这个是dplyr包里面的管道函数。这个函数就是把前面的数据作为一个参数,传入后面的函数中,默认作为第一个参数,当然也可以自定义参数的位置。
注:%>%非常好用,在R中可以说是至关重要的一个函数,强烈建议大家多去使用此函数!
# install.packages("dplyr")
library(dplyr) # filter()
## 假设需要剔除Sepal.Width的长度大于4的观测
iris.new <- iris %>% filter(Sepal.Width <= 4) # 筛选出Sepal.Width小于等于4的观测
# 绘制箱线图验证是否处理成功
boxplot(iris.new$Sepal.Width) # 绘制箱线图
0.2 无量纲化
无量纲化就是消除量纲影响,量纲是表征物理量的性质(类别),如时间、长度、质量等。那么不同的量纲又有什么影响呢?举个例子:若是研究成年男性的身高、年龄对于体重的影响,那么身高一般是150-190cm,而年龄则是18-100岁。若是直接将此数据对体重就行拟合,那么则很容易去强化某一变量而弱化另一变量的作用。
消除量纲最常用的两种方法是就是标准化和归一化。以下进行无量纲化操作使用的数据是R自带的Puromycin数据集。因为在此只为了进行单纯的无量纲化处理,所以就不去详细解释此数据集了,有兴趣的可以在R中输入?Puromycin
命令去查看数据的详细信息。
# install.packages("DT")
library(DT)
data("Puromycin")
datatable(Puromycin)
0.2.1 标准化
简单的说,标准化就是按照特征矩阵的列处理数据,通过使用z-score的方法,转换为标准正态分布。在R中使用scale()函数就可以简单的将数据进行标准化,该函数使用的是z-score标准化方法,该方法原理如下: \[X_{new}=\frac{X-\mu}{\sigma}=\frac{X-Mean(X)}{StdDev(X)}\]
## 对数据的第一列和第二列进行标准化,并把处理后的数据赋值给Puromycin.sacle
Puromycin.scale <- scale(Puromycin[, 1:2])
datatable(Puromycin.scale)
0.2.2 归一化
与标准化不同的是,归一化只是将样本的特征值转换到同一量纲下把数据映射到[0,1]区间内,却没有使数据标准化的作用。在R中最常用的归一化就是min-max方法,其原理如下: \[X_{new}=\frac{X-min(X)}{max(X)-min(X)}\]
## 笨方法——封装函数
# 封装归一化函数
normalize <- function(x) {
return((x - min(x)) / (max(x) - min(x)))
}
## 对数据的前两列进行归一化
Puromycin.nor <-
lapply(Puromycin[1:2], normalize) %>% # 进行标准化,返回列表
data.frame() # 将列表转换为数据框
datatable(Puromycin.nor)
## 好方法
# install.packages("caret")
library(caret)
data("Puromycin") # 获取数据
standard <- preProcess(Puromycin, method = 'range') # 针对数据设定归一化方法
datatable(predict(standard, Puromycin)) # 对数据进行归一化
心细的同学们肯定发现两种方法代入的数据有所不同,笨方法中指定对前两列进行归一化,而好方法中则不需指定。这正是笨方法与好方法的区别:好方法可以自动识别数值进行标准化,避免繁琐的操作。
0.3 特征重编码
特征重编码就是把数据集中的变量值进行重塑,无论是定量特征还是定性特征都可以进行重编码。比如说把“性别”这个定性变量中的“男”、“女”重塑为“0”、“1”。这样做的目的主要就是为了让数据适应不同的算法要求,因为不同的算法对数据类型的要求不同。
0.3.1 定量特征重塑
针对于定量特征的重编码主要就是二值化。常用于概率模型中,将概率小于等于0.5的转换为0,否则转换为1。
下面我们随机生成10个0-1之间的随机数,然后进行二值化变换。
set.seed(45)
mydata <- runif(10, 0, 1) # 生成10个0-1之间的随机数
# 对其进行二值化变换,小于等于0.5的赋值为0,否则赋值为1
mydata.new <- ifelse(mydata <= 0.5, 0, 1)
0.3.2 定性特征重塑
针对于定性特征的重编码主要就是构建独热(One-Hot)编码。简而言之,就是将一个包含n个特征的变量转换为n个变量,转换后的变量中只会出现0、1两个特征。
下面我们构建一个拥有三个特征的变量,然后进行独热编码。
# 构建一个数据框,赋值为mydata,并展示数据集
mydata <- data.frame(letters = c("A", "B", "C", "A", "C")); mydata
## letters
## 1 A
## 2 B
## 3 C
## 4 A
## 5 C
# install.packages("dummies")
library(dummies)
# 对mydata进行独热编码,赋值为mydata.oh,并展示数据
mydata.oh <- dummy.data.frame(mydata, names = c('letters'), sep = '.'); mydata.oh
## letters.A letters.B letters.C
## 1 1 0 0
## 2 0 1 0
## 3 0 0 1
## 4 1 0 0
## 5 0 0 1