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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,776评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,527评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,361评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,430评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,511评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,544评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,561评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,315评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,763评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,070评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,235评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,911评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,554评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,173评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,424评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,106评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,103评论 2 352

推荐阅读更多精彩内容