最近在处理特征,有点拙见,分享出来,欢迎各路神仙拍砖指正。
在此以 iris 数据集为例子来说明问题:
# 加载数据集到全局环境
data(iris)
# 加载rpart来构建一颗决策树
library(rpart)
my_tree <- rpart(Species~., data = iris)
# n= 150
#
# node), split, n, loss, yval, (yprob)
# * denotes terminal node
# 1) root 150 100 setosa (0.33333333 0.33333333 0.33333333)
# 2) Petal.Length< 2.45 50 0 setosa (1.00000000 0.00000000 0.00000000) *
# 3) Petal.Length>=2.45 100 50 versicolor (0.00000000 0.50000000 0.50000000)
# 6) Petal.Width< 1.75 54 5 versicolor (0.00000000 0.90740741 0.09259259) *
# 7) Petal.Width>=1.75 46 1 virginica (0.00000000 0.02173913 0.97826087) *
将构建的树打印出来,发现 Petal.Length 是树的第一个划分点,下面来验证一下特征的重要性
print(my_tree$variable.importance)
# Petal.Width Petal.Length Sepal.Length Sepal.Width
# 88.96940 81.34496 54.09606 36.01309
发现 Petal.Width 与 Petal.Length 特征重要性得分相对都比较高,再看看这些特征在相应分类变量(响应变量)下的数据分布情况
# 加载绘图包
library(ggplot2)
- Petal.Width
ggplot(data = iris) + geom_density(mapping = aes(x = Petal.Width, col = Species))
- Petal.Length
ggplot(data = iris) + geom_density(mapping = aes(x = Petal.Length, col = Species))
- Sepal.Length
ggplot(data = iris) + geom_density(mapping = aes(x = Sepal.Length, col = Species))
- Sepal.Width
ggplot(data = iris) + geom_density(mapping = aes(x = Sepal.Width , col = Species))
如图示,可清晰的看到特征得分较高的特征在分类变量条件下数据分布间的差异性较大,下面我们构造一个对分类变量划分很明确的特征,来看看效果。
iris2 <- cbind(iris, V = c(rnorm(50), runif(50, 2, 3), rpois(50, 10)))
my_tree2 <- rpart(Species~., data = iris2)
print(my_tree2$variable.importance)
# V Petal.Width Petal.Length Sepal.Length Sepal.Width
# 100 94 93 61 38
# 绘制数据分布图
ggplot(data = iris2) + geom_density(mapping = aes(x = V, col = Species))
构造的特征数据分别来自三个不同分布,这里特征重要性得分到达了满分,说明了以该特征为划分,可以百分之百将分类变量划分,当然这里是在预先知道分类变量类型下有意去构造能划分出分类变量的数据,以此特征来进行预测必然会产生过拟合的现象。这里只是为了说明特征在分类变量下的数据分布的差异是划分特征的一个重要原则。
这里延伸一个观点,不管什么模型(这里针对树型模型),模型本身只识别数据,而数据的现实意义是我们人工赋予的,如果该具备现实意义的数据恰好符合模型做分类很好的划分,那么该具备现实意义的数据就成为模型的一个重要的特征,比如男女的划分,可以以头发长短来划分,这里可以划分大部分,少部分也会被误判,当然男女最好的划分当然是生殖器,因为本身就是以这个特征来定义男女的,这里就相当于用响应变量来进行划分,自然是百分之百区分。
现实环境中,特征是随着时间在不断变化的,因此任何模型都有它的适用范围,超出这个范围自然会失去其中效用。