特徵工程總結:R與Python的比較實現

文前提要

  1. 特徵工程概述

  2. 特徵選擇的一般步驟

  3. 特徵工程的主要包含的內容框架

  4. 特徵選擇的主要方法和python與R的比較實現

目錄

1.特徵工程概述

2.特徵工程知識框架

3.特徵工程的一般步驟

4.特徵選擇的python與R實現比較

4.1 導入數據

4.2 數據預處理

4.2.1 標準化

4.2.2 區間放縮法

4.2.3 歸一化

4.2.4 對定量特徵二值化

4.2.5 對定性特徵啞編碼

4.2.6 缺失值填補

4.2.7 數據變換

4.3 特徵選擇

4.3.1 Filter法(過濾法)

4.3.2 Wrapper法(封裝法)

4.3.3 Embedded(集成法)

4.4降維

4.4.1PCA

4.4.2LDA

1.特徵工程概述

特徵工程其實是一個偏工程的術語,在資料庫領域可能叫做屬性選擇,而在統計學領域叫變數選擇,其實是一個意思:即最大限度地從原始數據中提取有用信息以供演算法和模型使用,通過尋求最優特徵子集等方法使模型預測性能最高。當然,網路上對特徵工程的總結已經非常成熟了(詳見jasonfreak的知乎問答:使用sklearn做單機特徵工程<https://www.zhihu.com/question/29316149>。但本人將依據python代碼的實習,總結用R來實現,以方便對特徵工程全面的總結和理解。本文總結主要依據jasonfreak的「使用sklearn做單機特徵工程」總結,在此對其的深刻總結表示感謝。n

2.特徵工程知識框架

jasonfreak總結出了特徵工程的主要知識框架,如下圖:n

Alt text

3.特徵工程的一般步

  1. 子集產生:按照一定搜索策略產生候選特徵子集;

  2. 子集評估:通過某個評價函數評估子集的優劣;

  3. 停止條件:決定特徵選擇演算法什麼時候停止;

  4. 子集驗證:驗證最終所選子集的有效性。

Alt text

4.特徵選擇的python與R實現比較

4.1導入數據

我們以經典的鳶尾花數據iris為例,分別根據已有的特徵選擇的框架圖,本人結合網路上給出的python代碼總結,添加了運用R實現特徵選擇的方法,來對比兩種語言的差異。n

python:

from sklearn.datasets import load_irisnn#導入數據集niris = load_iris()n#特徵矩陣niris.datan#目標向量niris.targetn

R:

data("iris")n# 特徵矩陣niris.data <- iris[, -length(iris)]n# 目標向量niris.targer <- iris[, length(iris)]n

4.2數據預處理

4.2.1標準化(要求數據符合正態性)

python:

from sklearn.preprocessing import StandardScalernStandardScaler().fit_transform(iris.data)n

R:

scale(iris.data, center = TRUE, scale = TRUE)n# 或者運用BBmisc包中的normalize函數nnormalize(iris.data)n

4.2.2區間放縮法

python:

from sklearn.preprocessing import MinMaxScalernMinMaxScaler().fit_transform(iris.data)n

R:

# 依據公式構建區間放縮函數nmaxmin <- function(col) {n maxmin <- (col - min(col))/(max(col) - min(col))n return(maxmin)}nmaxmin(iris.data)n

4.2.3歸一化

此處的歸一化是指依照特徵矩陣的行處理數據,其目的在於樣本向量在點乘運算或其他核函數計算相似性時,擁有統一的標準,也就是說都轉化為「單位向量」.歸一化後樣本各屬性的平方和為1.n

python:

from sklearn.preprocessing import NormalizernNormalizer().fit_transform(iris.data)n

R:

norm <- function(data) {n norm = apply(data, 1, function(x) {n x/sqrt(sum(x^2))n })n norm = t(norm)n return(norm)}norm(iris.data)n

標準化與歸一化的區別:

標準化是依照特徵矩陣的列處理數據,其通過求z-score的方法,轉換為標準正態分布。而歸一化是將樣本的特徵值轉換到同一量綱下把數據映射到[0,1]區間內,因此區間放縮法是歸一化的一種。n

4.2.4對定量特徵二值化

以某個值為閾值,轉換為0,1變數。n

python:

from sklearn.preprocessing import BinarizernBinarizer(threshold=3).fit_transform(iris.data)n

R:

bina <- function(data, threshold) {n ifelse(data > threshold, 1, 0)}nbina(iris.data, threshold = 3)n

4.2.5對定性特徵啞編碼

python:

from sklearn.preprocessing import OneHotEncodernOneHotEncoder().fit_transform(iris.target.reshape((-1,1)))n

R:

library(caret)nvar <- dummyVars(~Species, data = iris)npredict(var, iris["Species"])n

4.2.6缺失值填補

新增一個樣本,缺失值為NAN,並對缺失值進行填補。n

python:

from numpy import vstack, array, nannfrom sklearn.preprocessing import Imputernn#參數strategy為缺失值填充方式,默認為mean(均值)nImputer().fit_transform(vstack((array([nan, nan, nan, nan]), iris.data)))n

R:

new = rep(NA, 4)niris.data <- rbind(new, iris.data)nlibrary(Hmisc)nimpute(iris.data, mean)n

4.2.7數據變換

常見的數據變換有基於多項式的、基於指數函數的、基於對數函數等.n

python:

#多項式轉換nfrom sklearn.preprocessing import PolynomialFeaturesn#參數degree為度,默認值為2nPolynomialFeatures().fit_transform(iris.data)n#對數函數轉換nfrom numpy import log1pnfrom sklearn.preprocessing import FunctionTransformernFunctionTransformer(log1p).fit_transform(iris.data)n

R:

# 多項式轉換nlibrary(dplyr)niris.data <- iris.data %>% n mutate(x3 = Sepal.Length * Sepal.Width)# 對數函數轉換niris.data <- iris.data %>% n mutate_each(funs(log1p))n

4.3特徵選擇

4.3.1Filter法(過濾法)

按照變數內部特徵或者相關性對各個特徵進行評分,設定閾值或者待選擇閾值的個數選擇特徵.與特定的學習演算法無關,因此具有較好的通用性,作為特徵的預篩選器非常合適。缺點主要是由於演算法的評價標準獨立於特定的學習演算法,所選的特徵子集在分類準確率方面通常低於Wrapper方法。n

1.方差選擇法

計算各個特徵的方差,然後根據閾值,選擇方差大於閾值的特徵.n

python:

from sklearn.feature_selection import VarianceThresholdn#參數threshold為方差的閾值nVarianceThreshold(threshold=3).fit_transform(iris.data)n

R:

library(mlr)n# 創建taskntrain.task <- makeClassifTask(data = iris, target = "Species")n# 查看變數選擇可選方法listFilterMethods()n# 選擇計算方差,進行特徵選擇nvar_imp <- generateFilterValuesData(train.task, method = "variance", nselect = 3)nvar_impn# 對衡量特徵指標進行繪圖nplotFilterValues(var_imp, feat.type.cols = TRUE, n.show = 3)n

2.相關係數法

計算各個特徵對目標值的相關係數以及相關係數的P值.n

python:

from sklearn.feature_selection import SelectKBestnfrom scipy.stats import pearsonrn#選擇K個最好的特徵,返回選擇特徵後的數據n#第一個參數為計算評估特徵是否好的函數,該函數輸入特徵矩陣和目標向量,n#輸出二元組(評分,P值)的數組,數組第i項為第i個特徵的評分和P值。在此定義為計算相關係數n#參數k為選擇的特徵個數nSelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)n

R:

library(mlr)n# 創建taskntrain.task <- makeRegrTask(data = iris.data, target = "Sepal.Width")n# 查看變數選擇可選方法nlistFilterMethods()n# 選擇pearson相關係數,進行特徵選擇 也可以選擇秩相關係數(method =# rank.correlation)nvar_imp <- generateFilterValuesData(train.task, method = "linear.correlation")nvar_impn# 對相關係數進行繪圖nlibrary(corrplot)ncorrplot(cor(iris.data), order = "hclust")n

3.計算卡方值

經典的卡方檢驗是檢驗定性自變數對定性因變數的相關性,考慮自變數等於i且因變數等於j的樣本頻數的觀察值與期望的差距,這個統計量的含義簡而言之就是自變數對因變數的相關性.n

python:

from sklearn.feature_selection import SelectKBestnfrom sklearn.feature_selection import chi2nn#選擇K個最好的特徵,返回選擇特徵後的數據nSelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)n

R:

library(mlr)n# 創建taskntrain.task <- makeClassifTask(data = iris, target = "Species")n# 查看變數選擇可選方法nlistFilterMethods()n# 選擇計算卡方值,進行特徵選擇nvar_imp <- generateFilterValuesData(train.task, method = "chi.squared")nvar_impn# 對衡量特徵指標進行繪圖nplotFilterValues(var_imp, feat.type.cols = TRUE)n

4.互信息

經典的互信息也是評價定性自變數對定性因變數的相關性的,可以看成是一個隨機變數中包含的關於另一個隨機變數的信息量.n

python:

from sklearn.feature_selection import SelectKBestnfrom minepy import MINEnn#由於MINE的設計不是函數式的,定義mic方法將其為函數式的,n#返回一個二元組,二元組的第2項設置成固定的P值0.5ndef mic(x, y):n m = MINE()n m.compute_score(x, y)n return (m.mic(), 0.5)nn#選擇K個最好的特徵,返回特徵選擇後的數據nSelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)n

R:

library(mlr)n# 創建taskntrain.task <- makeClassifTask(data = iris, target = "Species")n# 查看變數選擇可選方法nlistFilterMethods()# 選擇計算信息增益,進行特徵選擇nvar_imp <- generateFilterValuesData(train.task, method = "information.gain")nvar_impn# 對衡量特徵指標進行繪圖nplotFilterValues(var_imp, feat.type.cols = TRUE)n

4.3.2 Wrapper法(封裝法)

封裝式特徵選擇是利用學習演算法的性能來評價特徵子集的優劣。因此,對於一個待評價的特徵子集,Wrapper方法需要訓練一個分類器,根據分類器的性能對該特徵子集進行評價,學習演算法包括決策樹、神經網路、貝葉斯分類器、近鄰法以及支持向量機等。Wrapper方法缺點主要是特徵通用性不強,當改變學習演算法時,需要針對該學習演算法重新進行特徵選擇。n

1.遞歸特徵消除法

遞歸消除特徵法使用一個模型來進行多輪訓練,每輪訓練後,消除若干權值係數的特徵,再基於新的特徵集進行下一輪訓練。Logistic回歸的R實現詳見本微信公眾號歷史文章:Logistic回歸詳解(三)——變數選擇部分。n

python:

from sklearn.feature_selection import RFEnfrom sklearn.linear_model import LogisticRegressionnn#遞歸特徵消除法,返回特徵選擇後的數據n#參數estimator為基模型n#參數n_features_to_select為選擇的特徵個數nRFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)n

R:

# 構建Logistic回歸模型nlibrary(MASS)nm <- glm(Species ~ ., data = iris, family = "binomial")n# 運用step函數進行變數選擇nselecting <- step(m, direction = "backward")n

4.3.3 Embedded(集成法)

在集成法特徵選擇中,特徵選擇演算法本身作為組成部分嵌入到學習演算法里。最典型的即決策樹演算法。包括基於懲罰項的特徵選擇法和基於樹模型的特徵選擇法。n

1.基於懲罰項的特徵選擇法

其中R實現詳見本微信公眾號歷史文章:正則化及其R實現。n

python:

from sklearn.feature_selection import SelectFromModelnfrom sklearn.linear_model import LogisticRegressionnn#帶L1懲罰項的邏輯回歸作為基模型的特徵選擇(lasso回歸)nSelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target)n

R:

# 轉換變數類型niris.matrix <- as.matrix(iris.data)ntarget <- as.numeric(iris.targer)n# Lasso回歸nlibrary(glmnet)n# alpha = 1為Lasso回歸,alpha=0為嶺回歸nr2 <- glmnet(iris.matrix, target, family = "multinomial", alpha = 1)n# 通過10fold交叉驗證獲得最優lambda參數nr2.cv <- cv.glmnet(iris.matrix, target, family = "multinomial", alpha = 1, nfolds = 10)nplot(r2.cv)n# 根據獲得的lambda.min值,擬合最優模型r2.minnr2.min <- glmnet(iris.matrix, target, family = "multinomial", alpha = 1, lambda = r2.cv$lambda.min)nr2.min_coef <- coef(r2.min)n

2.基於樹模型的特徵選擇法

python:

from sklearn.feature_selection import SelectFromModelnfrom sklearn.ensemble import GradientBoostingClassifiern#GBDT作為基模型的特徵選擇nSelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)n

R:

library(mlrn)train.task <- makeClassifTask(data = iris, target = "Species")n# 查看可選模型參數nlistLearners("classif", "multiclass")[c("class", "package")]n# 創建機器學習模型ngbm_learner <- makeLearner("classif.gbm", predict.type = "response")n# 設定模型參數ngbm_learner$par.vals <- list(laplace = 1)n# 訓練和預測nnB_models <- mlr::train(gbm_learner, train.task)nnB_predict <- predict(nB_models, train.task)n# 模型評估nnB_prediction <- nB_predict$data$responsen# 混淆矩陣ndCM <- confusionMatrix(iris$Species, nB_prediction)n

4.4降維

降維方法除了以上提到的基於L1懲罰項的模型以外,另外還有主成分分析法(PCA)和線性判別分析(LDA),線性判別分析本身也是一個分類模型。PCA和LDA有很多的相似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標不一樣:PCA是為了讓映射後的樣本具有最大的發散性;而LDA是為了讓映射後的樣本有最好的分類性能。所以說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法。n

4.4.1主成分分析(PCA)

python:

from sklearn.decomposition import PCAn#主成分分析法,返回降維後的數據n#參數n_components為主成分數目nPCA(n_components=2).fit_transform(iris.data)n

R:

# 主成分分析niris.pc <- prcomp(iris.data)summary(iris.pc)n# 主成分分析陡坡圖nplot(iris.pc, type = "l", main = "PCA陡坡圖")n

4.4.2線性判別分析(LDA)

python:

from sklearn.lda import LDAn#線性判別分析法,返回降維後的數據n#參數n_components為降維後的維數nLDA(n_components=2).fit_transform(iris.data, iris.target)n

R:

library(MASS)n# 以公式格式進行線性判別nfit_lda = lda(Species ~ ., data = iris)nnames(fit_lda)nfit_lda$meansn

要想獲取分析代碼,可查看原文,進入本人的GitHubgithub.com/Alven8816查看下載,或通過本人郵箱yuwenhuajiayou@sina.cn與本人聯繫

------------------------------------------

作者:余文華

專欄:樂享數據DataScientists的博客專欄

公眾號:樂享數據DataScientists

大家也可以加小編微信:tsbeidou (備註:知乎),進R語言中文社區 交流群,可以跟各位老師互相交流

推薦閱讀:

Python 初學者最容易犯的幾個錯誤。
markdown for academia
Python 字母行轉序號應該怎麼做?
python 括弧檢測是否匹配?
如何理解Python裝飾器?

TAG:R编程语言 | Python | 数据分析 |