Feature Engineering


介紹如何在R語(yǔ)言中進(jìn)行特征工程(未完待續(xù))
建議在R語(yǔ)言中親自實(shí)踐


總述

特征工程可以幫助我們提升模型的表現(xiàn),但是這是一個(gè)有些玄學(xué)的東西,因?yàn)闆]有一種具體的、結(jié)構(gòu)性強(qiáng)的處理方法。很多人都有一些秘而不宣的小技巧。我的體會(huì)是,對(duì)于數(shù)據(jù)比賽和發(fā)論文來(lái)說(shuō),這是一個(gè)利器。但是對(duì)于商業(yè)應(yīng)用來(lái)說(shuō)有些雞肋,因?yàn)椴惶铣杀臼找娣治觥?/p>

有一點(diǎn)要特別強(qiáng)調(diào),當(dāng)你的數(shù)據(jù)量不夠多時(shí),特征工程非常重要。一旦數(shù)據(jù)量足夠大以后,它就不那么重要了,這是因?yàn)橄裆窠?jīng)網(wǎng)等模型充分訓(xùn)練以后可以充分提取特征。

盡管這是一個(gè)玄之又玄的東西,我們還是要掌握一些常規(guī)的方法。通常情況下,特征工程總是伴隨著可視化,于是我們的ggplot2可以派上用場(chǎng)了。

數(shù)據(jù)準(zhǔn)備

我們的數(shù)據(jù)來(lái)源于kaggle競(jìng)賽https://www.kaggle.com/c/mercedes-benz-greener-manufacturing/data,可以自由下載。

我們觀察數(shù)據(jù),會(huì)發(fā)現(xiàn)這個(gè)數(shù)據(jù)集由0-1數(shù)據(jù)和類別數(shù)據(jù)(x0-x8)構(gòu)成。把他們分離。

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格式,此時(shí)文件路徑不能含有中文,否則會(huì)報(bào)錯(cuò)。而傳統(tǒng)的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

這個(gè)數(shù)據(jù)集很完整,不需要處理數(shù)據(jù)缺失,我們將在另外的文檔中展示這一功能。為保證特征工程的完整性,我們暫且加上它。

One-hot encoding

首先說(shuō)一說(shuō)什么是熱獨(dú)碼。這是一種把種類數(shù)據(jù)轉(zhuǎn)換為0-1矩陣的方法,很常見。

使用one-hot encoding前:

代碼實(shí)現(xiàn)如下:

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),]

成果:

同時(shí),我們還可以給0-1矩陣畫圖,以下代碼實(shí)現(xiàn)了這一功能:

image(as.matrix(ohe_features), col=c("white", "black"))
# 主要的畫圖函數(shù),橫坐標(biāo)是樣本,縱坐標(biāo)是所有的類別。被映射到[0,1]上。
n_levels <- apply(categorical_df, 2, function(x){length(unique(x))}) 
# 計(jì)算類的數(shù)量
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")
# 標(biāo)定類
abline(v=0.5, col="darkgreen")
# 0.5表示訓(xùn)練集和測(cè)試集五五開,應(yīng)視實(shí)際情況選取
text(0.22, 0.025, "Train", col="darkgreen")
text(0.72, 0.025, "Test", col="darkgreen")

圖像示例

解讀:在這個(gè)例子中,X5值得我們關(guān)注。這表明觀察結(jié)果也許不是隨機(jī)選擇的。X5可能是一個(gè)測(cè)試參數(shù),在幾次連續(xù)的測(cè)試運(yùn)行中保持不變。這表明觀察的時(shí)間順序。
這樣,我們完成了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) }))
# 聚類的信息都儲(chǔ)存在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))
聚類結(jié)果

這樣,我們把類作為新的特征即可。有關(guān)聚類的更多細(xì)節(jié),我們會(huì)專題學(xué)習(xí)。

Principal Component Analysis (PCA)

PCA也是爛大街的一種方法,具體說(shuō)來(lái)就是把高維度特征精華一下,濃縮到相對(duì)低維,而又不損失太多信息。這種方法聽起來(lái)不錯(cuò),用起來(lái)就差強(qiáng)人意。不過(guò)還是比沒有強(qiáng)那么一些。

# 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

結(jié)果如下:


可以畫成這種,用ggplot2自己完成即可。



注:
參數(shù)的意義依次為標(biāo)準(zhǔn)差、方差貢獻(xiàn)率、累計(jì)方差貢獻(xiàn)率。

Logistic PCA

用于0-1數(shù)據(jù)降維的更合適的方法稱為L(zhǎng)ogistic PCA。與普通PCA不同,Logistic PCA最大化伯努利對(duì)數(shù)似然函數(shù)而不是變量線性組合的方差。

對(duì)Logistic PCA更詳細(xì)的解釋在“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)

這個(gè)算法計(jì)算量比較大,速度慢一些。

ICA

MCA

總結(jié)

最后我們把做好的特征組合起來(lái),喂給我們的模型。這樣,通常來(lái)說(shuō)你會(huì)得到一個(gè)好于直接把數(shù)據(jù)丟給模型更好的結(jié)果。當(dāng)然,有一點(diǎn)需要銘記:這是經(jīng)驗(yàn)占據(jù)主導(dǎo)地位的一個(gè)領(lǐng)域。

參考文獻(xiàn)

https://www.kaggle.com/msp48731/feature-engineering-and-visualization/notebook

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容