Feature Engineering
介绍如何在R语言中进行特征工程(未完待续)
建议在R语言中亲自实践
总述
特征工程可以帮助我们提升模型的表现,但是这是一个有些玄学的东西,因为没有一种具体的、结构性强的处理方法。很多人都有一些秘而不宣的小技巧。我的体会是,对于数据比赛和发论文来说,这是一个利器。但是对于商业应用来说有些鸡肋,因为不太符合成本收益分析。
有一点要特别强调,当你的数据量不够多时,特征工程非常重要。一旦数据量足够大以后,它就不那么重要了,这是因为像神经网等模型充分训练以后可以充分提取特征。
尽管这是一个玄之又玄的东西,我们还是要掌握一些常规的方法。通常情况下,特征工程总是伴随着可视化,于是我们的ggplot2可以派上用场了。
数据准备
我们的数据来源于kaggle竞赛https://www.kaggle.com/c/mercedes-benz-greener-manufacturing/data,可以自由下载。
我们观察数据,会发现这个数据集由0-1数据和类别数据(x0-x8)构成。把他们分离。
library(tidyverse)
dir_train <- 'F:/Mine/R/FE/test.csv'
dir_test <- 'F:/Mine/R/FE/test.csv'
train <- read_csv(dir_train)
test <- read_csv(dir_test)
# 我们用read_csv()读入tibble格式,此时文件路径不能含有中文,否则会报错。而传统的read.csv()则是可以的。
data_all <- rbind(train, test)
categorical_vars = paste0('X', c(0,1,2,3,4,5,6,8))
categorical_data <- df_all %>% select(one_of(categorical_vars))
# one_of(): variables in character vector ; select(): choose columns
binary_data <- data_all %>% select(-one_of(categorical_vars))
Missing Data
这个数据集很完整,不需要处理数据缺失,我们将在另外的文档中展示这一功能。为保证特征工程的完整性,我们暂且加上它。
One-hot encoding
首先说一说什么是热独码。这是一种把种类数据转换为0-1矩阵的方法,很常见。
使用one-hot encoding前:代码实现如下:
library(caret)
# perform one-hot encoding
dmy <- dummyVars(~., data = categorical_data)
ohe_features <- data.frame(predict(dmy, newdata = categorical_data))
data_all <- cbind(data_all, ohe_features)
binary_data <- cbind(binary_data, ohe_features)
binary_data_train <- binary_data[1:nrow(train), ]
binary_data_test <- binary_data[(nrow(train)+1):nrow(binary_data),]
成果:
同时,我们还可以给0-1矩阵画图,以下代码实现了这一功能:
image(as.matrix(ohe_features), col=c("white", "black"))
# 主要的画图函数,横坐标是样本,纵坐标是所有的类别。被映射到[0,1]上。
n_levels <- apply(categorical_df, 2, function(x){length(unique(x))})
# 计算类的数量
n_levels <- n_levels/sum(n_levels)
# 归一化
abline(h=cumsum(n_levels), col="red")
text(0.05, cumsum(n_levels)-.025, names(n_levels), col="red")
# 标定类
abline(v=0.5, col="darkgreen")
# 0.5表示训练集和测试集五五开,应视实际情况选取
text(0.22, 0.025, "Train", col="darkgreen")
text(0.72, 0.025, "Test", col="darkgreen")
图像示例
解读:在这个例子中,X5值得我们关注。这表明观察结果也许不是随机选择的。X5可能是一个测试参数,在几次连续的测试运行中保持不变。这表明观察的时间顺序。
这样,我们完成了one-hot encoding。
Hierarchical Clustering(分层聚类)
这里聚合0-1变量并使用不同聚类索引作为新特征。使用Jaccard的距离。
library(proxy)
# compute distance matrix
jdist <- proxy::dist(binary_data, method = "Jaccard")
# perform hierarchical clustering
hc <- hclust(jdist)
# get all clusterings with 2 up to max_k clusters
max_k <- 50
clusters <- data.frame(sapply(2:max_k, function(k){ cutree(hc,k) }))
# 聚类的信息都储存在clusters中
colnames(clusters) <- paste0("hc_group_", 2:max_k)
# add lines for each cut in the dendrogram
plot(hc, hang = -1, labels = FALSE, xlab = "", ann=FALSE)
cuts <- sort(hc$height, decreasing = TRUE)[2:max_k]
abline(h=cuts, col=alpha("red",0.3))
聚类结果
这样,我们把类作为新的特征即可。有关聚类的更多细节,我们会专题学习。
Principal Component Analysis (PCA)
PCA也是烂大街的一种方法,具体说来就是把高维度特征精华一下,浓缩到相对低维,而又不损失太多信息。这种方法听起来不错,用起来就差强人意。不过还是比没有强那么一些。
# perform pca
res_pca <- prcomp(binary_data_train)
pca_features <- predict(res_pca, newdata = binary_data)
# proportion of explained variance
importance_pca <- summary(res_pca)$importance
结果如下:
可以画成这种,用ggplot2自己完成即可。
注:
参数的意义依次为标准差、方差贡献率、累计方差贡献率。
Logistic PCA
用于0-1数据降维的更合适的方法称为Logistic PCA。与普通PCA不同,Logistic PCA最大化伯努利对数似然函数而不是变量线性组合的方差。
对Logistic PCA更详细的解释在“Dimensionality Reduction for Binary Data through the Projection of Natural Parameters”这篇论文中,下载地址为https://arxiv.org/pdf/1510.06112.pdf或者参照https://cran.r-project.org/web/packages/logisticPCA/vignettes/logisticPCA.html。
library(logisticPCA)
library(rARPACK)
# Find the appropriate values for k and m.
# > logsvd_model = logisticSVD(binary_data, k = 20)
# 8418 rows and 368 columns
# Rank 20 solution
# 95.6% of deviance explained
# 397 iterations to converge
#
# > logpca_cv = cv.lpca(binary_data, ks = 20, ms = 1:10)
# m
# k 1 2 3 4 5 6 7 8 9 10
# 20 400428 261586.6 185985 143663.3 118547.4 102668.9 92638.51 85579.33 80440.14 76707.54
k <- 20
m <- 12
logpca_model = logisticPCA(binary_df_train, k = k, m = m)
logpca_features <- predict(logpca_model, newdata=binary_df)
colnames(logpca_features) <- paste0("LPC", 1:k)
这个算法计算量比较大,速度慢一些。
ICA
MCA
总结
最后我们把做好的特征组合起来,喂给我们的模型。这样,通常来说你会得到一个好于直接把数据丢给模型更好的结果。当然,有一点需要铭记:这是经验占据主导地位的一个领域。
参考文献
https://www.kaggle.com/msp48731/feature-engineering-and-visualization/notebook