十八、R语言特征工程实战
特征工程是機器學習過程中和模型訓練同樣重要的部分,特征如何提取、如何處理、如何選擇、如何使用都是特征工程的范疇,特征工程需要具備數據分析的能力,那些稱為數據科學家的人一定是有很強的特征工程能力的人。R語言是大數據領域的主流語言之一,本文主要介紹用R語言的圖形工具做特征工程的實戰方法
請尊重原創,轉載請注明來源網站www.shareditor.com以及原始鏈接地址
R語言介紹
熟悉R語言的朋友請直接略過。R語言是貝爾實驗室開發的S語言(數據統計分析和作圖的解釋型語言)的一個分支,主要用于統計分析和繪圖,R可以理解為是一種數學計算軟件,可編程,有很多有用的函數庫和數據集。
?
R的安裝和使用
在https://mirrors.tuna.tsinghua.edu.cn/CRAN/下載對應操作系統的安裝包安裝。安裝好后單獨創建一個目錄作為工作目錄(因為R會自動在目錄里創建一些有用的隱藏文件,用來存儲必要的數據)
執行
R即可進入R的交互運行環境
簡單看一個實例看一下R是如何工作的:
[root@centos:~/Developer/r_work $] RR version 3.3.1 (2016-06-21) -- "Bug in Your Hair" Copyright (C) 2016 The R Foundation for Statistical Computing Platform: x86_64-apple-darwin13.4.0 (64-bit)> x <- c(1,2,3,4,5,6,7,8,9,10) > y <- x*x > plot(x,y,type="l") >以上看得出我們畫了y = x^2的曲線
R語言的語法和C類似,但是稍有不同,R語言里向量和矩陣的操作和python的sci-learn類似,但是稍有不同:
1. R的賦值語句的符號是"<-"而不是"="
2. R里的向量用c()函數定義,R里沒有真正的矩陣類型,矩陣就是一系列向量組成的list結構
有時候如果我們想要加載一個庫發現沒有安裝,就像這樣:
> library(xgboost) Error in library(xgboost) : 不存在叫‘xgboost’這個名字的程輯包那么就這樣來安裝:
> install.packages("xgboost")輸入后會提示選擇下載鏡像,選擇好后點ok就能自動安裝完成,這時就可以正常加載了:
> library(xgboost) >想了解R語言的全部用法,推薦《權威的R語言入門教程《R導論》-丁國徽譯.pdf》,請自行下載閱讀,也可以繼續看我下面的內容邊用邊學
?
特征工程
按我的經驗,特征工程就是選擇和使用特征的過程和方法,這個說起來容易,做起來真的不易,想要對實際問題設計一套機器學習方法,幾乎大部分時間都花在了特征工程上,相反最后的模型開發花不了多長時間(因為都是拿來就用了),再有需要花一點時間的就是最后的模型參數調優了。花費時間排序一般是:特征工程>模型調參>模型開發
?
Titanic數據集特征工程實戰
Titanic數據集是這樣的數據:Titanic(泰坦尼克號)沉船災難死亡了很多人也有部分人成功得救,數據集里包括了這些字段:乘客級別、姓名、性別、年齡、船上的兄弟姐妹數、船上的父母子女數、船票編號、票價、客艙編號、登船港口、是否得救。
我們要做的事情就是把Titanic數據集中部分數據作為訓練數據,然后用來根據測試數據中的字段值來預測這位乘客是否得救
?
數據加載
訓練數據可以在https://www.kaggle.com/c/titanic/download/train.csv下載,測試數據可以在https://www.kaggle.com/c/titanic/download/test.csv下載
下面開始我們的R語言特征工程,創建一個工作目錄r_work,下載train.csv和test.csv到這個目錄,看下里面的內容:
[root@centos:~/Developer/r_work $] head train.csv PassengerId,Survived,Pclass,Name,Sex,Age,SibSp,Parch,Ticket,Fare,Cabin,Embarked 1,0,3,"Braund, Mr. Owen Harris",male,22,1,0,A/5 21171,7.25,,S 2,1,1,"Cumings, Mrs. John Bradley (Florence Briggs Thayer)",female,38,1,0,PC 17599,71.2833,C85,C 3,1,3,"Heikkinen, Miss. Laina",female,26,0,0,STON/O2. 3101282,7.925,,S 4,1,1,"Futrelle, Mrs. Jacques Heath (Lily May Peel)",female,35,1,0,113803,53.1,C123,S 5,0,3,"Allen, Mr. William Henry",male,35,0,0,373450,8.05,,S 6,0,3,"Moran, Mr. James",male,,0,0,330877,8.4583,,Q 7,0,1,"McCarthy, Mr. Timothy J",male,54,0,0,17463,51.8625,E46,S 8,0,3,"Palsson, Master. Gosta Leonard",male,2,3,1,349909,21.075,,S 9,1,3,"Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg)",female,27,0,2,347742,11.1333,,S我們看到文件內容是用逗號分隔的多個字段,第一行是schema,第二行開始是數據部分,其中還有很多空值,事實上csv就是Comma-Separated Values,也就是用“逗號分隔的數值”,它也可以用excel直接打開成表格形式
R語言為我們提供了加載csv文件的函數,如下:
> train <- read.csv('train.csv', stringsAsFactors = F) > test <- read.csv('test.csv', stringsAsFactors = F)如果想看train和test變量的類型,可以執行:
> mode(train) [1] "list"我們看到類型是列表類型
如果想預覽數據內容,可以執行:
> str(train) 'data.frame': 891 obs. of 12 variables:$ PassengerId: int 1 2 3 4 5 6 7 8 9 10 ...$ Survived : int 0 1 1 1 0 0 0 0 1 1 ...$ Pclass : int 3 1 3 1 3 3 1 3 3 2 ...$ Name : chr "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...$ Sex : chr "male" "female" "female" "female" ...$ Age : num 22 38 26 35 35 NA 54 2 27 14 ...$ SibSp : int 1 1 0 1 0 0 0 3 0 1 ...$ Parch : int 0 0 0 0 0 0 0 1 2 0 ...$ Ticket : chr "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...$ Fare : num 7.25 71.28 7.92 53.1 8.05 ...$ Cabin : chr "" "C85" "" "C123" ...$ Embarked : chr "S" "C" "S" "S" ...可以看到其實train和test變量把原始的csv文件解析成了特定的數據結構,train里有891行、12列,每一列的字段名、類型以及可能的值都能預覽到
因為test數據集也是真實數據的一部分,所以在做特征工程的時候可以把test和train合并到一起,生成full這個變量,后面我們都分析full:
> library('dplyr') > full <- bind_rows(train, test)?
頭銜特征的提取
因為并不是所有的字段都應該用來作為訓練的特征,也不是只有給定的字段才能作為特征,下面我們開始我們的特征選擇工作,首先我們從乘客的姓名入手,我們看到每一個姓名都是這樣的結構:"名字, Mr/Mrs/Capt等. 姓",這里面的"Mr/Mrs/Capt等"其實是一種稱謂(Title),雖然人物的姓名想必和是否得救無關,但是稱謂也許和是否得救有關,我們把所有的Title都篩出來:
> table(gsub('(.*, )|(\\..*)', '', full$Name))Capt Col Don Dona Dr Jonkheer1 4 1 1 8 1Lady Major Master Miss Mlle Mme1 2 61 260 2 1Mr Mrs Ms Rev Sir the Countess757 197 2 8 1 1解釋一下,這里面的full$Name表示取full里的Name字段的內容,gsub是做字符串替換,table是把結果做一個分類統計(相當于group by title),得出數目
通過結果我們看到不同Title的人數目差別比較大
我們把這個Title加到full的屬性里:
> full$Title <- gsub('(.*, )|(\\..*)', '', full$Name)這時我們可以按性別和title分兩級統計(相當于group by sex, title):
> table(full$Sex, full$Title)Capt Col Don Dona Dr Jonkheer Lady Major Master Miss Mlle Mme Mr Mrsfemale 0 0 0 1 1 0 1 0 0 260 2 1 0 197male 1 4 1 0 7 1 0 2 61 0 0 0 757 0Ms Rev Sir the Countessfemale 2 0 0 1male 0 8 1 0?
為了讓這個特征更具有辨別性,我們想辦法去掉那些稀有的值,比如總次數小于10的,我們都把title改成“Rare Title”
> rare_title <- c('Dona', 'Lady', 'the Countess','Capt', 'Col', 'Don', 'Dr', 'Major', 'Rev', 'Sir', 'Jonkheer') > full$Title[full$Title %in% rare_title] <- 'Rare Title'同時把具有相近含義的title做個歸一化
> full$Title[full$Title == 'Mlle'] <- 'Miss' > full$Title[full$Title == 'Ms'] <- 'Miss' > full$Title[full$Title == 'Mme'] <- 'Mrs'這回我們看下title和是否得救的關系情況
> table(full$Title, full$Survived)0 1Master 17 23Miss 55 130Mr 436 81Mrs 26 100Rare Title 15 8請尊重原創,轉載請注明來源網站www.shareditor.com以及原始鏈接地址
還不夠直觀,我們可以通過馬賽克圖來形象的看:
> mosaicplot(table(full$Sex, full$Title), shade=TRUE)這回看出比例情況的差異了,比如title為Mr的死亡和得救的比例比較明顯,說明這和是否得救關系密切,title作為一個特征是非常有意義的
這樣第一個具有代表意義的特征就提取完了
?
家庭成員數特征的提取
看過電影的應該了解當時的場景,大家是按照一定秩序逃生的,所以很有可能上有老下有小的家庭會被優先救援,所以我們統計一下一個家庭成員的數目和是否得救有沒有關系。
為了計算家庭成員數目,我們只要計算父母子女兄弟姐妹的數目加上自己就可以,所以:
> full$Fsize <- full$SibSp + full$Parch + 1下面我們做一個Fsize和是否得救的圖像
> library("ggplot2") > library('ggthemes') > ggplot(full[1:891,], aes(x = Fsize, fill = factor(Survived))) + geom_bar(stat='count', position='dodge') + scale_x_continuous(breaks=c(1:11)) + labs(x = 'Family Size') + theme_few()我們先解釋一下上面的ggplot語句
第一個參數full[1:891,]表示我們取全部數據的前891行的所有列,取891是因為train數據一共有891行
aes(x = Fsize, fill = factor(Survived))表示坐標軸的x軸我們取Fsize的值,這里的fill是指用什么變量填充統計值,factor(Survived)表示把Survived當做一種因子,也就是只有0或1兩種“情況”而不是數值0和1,這樣才能分成紅綠兩部分統計,不然如果去掉factor()函數包裹就會像這個樣子(相當于把0和1加了起來):
這里的“+”表示多個圖層,是ggplot的用法
geom_bar就是畫柱狀圖,其中stat='count'表示統計總數目,也就是相當于count(*) group by factor(Survived),position表示重疊的點放到什么位置,這里設置的是“dodge”表示規避開的展示方式,如果設置為"fill"就會是這樣的效果:
scale_x_continuous(breaks=c(1:11))就是說x軸取值范圍是1到11,labs(x = 'Family Size')是說x軸的label是'Family Size',theme_few()就是簡要主題
下面我們詳細分析一下這個圖說明了什么事情。我們來比較不同家庭成員數目里面成功逃生的和死亡的總數的比例情況可以看出來:家庭人數是1或者大于4的情況下紅色比例較大,也就是死亡的多,而人數為2、3、4的情況下逃生的多,因此家庭成員數是一個有意義的特征,那么把這個特征總結成singleton、small、large三種情況,即:
> full$FsizeD[full$Fsize == 1] <- 'singleton' > full$FsizeD[full$Fsize < 5 & full$Fsize > 1] <- 'small' > full$FsizeD[full$Fsize > 4] <- 'large'再看下馬賽克圖:
> mosaicplot(table(full$FsizeD, full$Survived), main='Family Size by Survival', shade=TRUE)從圖中可以看出差異明顯,特征有意義
?
模型訓練
處理好特征我們就可以開始建立模型和訓練模型了,我們選擇隨機森林作為模型訓練。首先我們要把要作為factor的變量轉成factor:
> factor_vars <- c('PassengerId','Pclass','Sex','Embarked','Title','FsizeD') > full[factor_vars] <- lapply(full[factor_vars], function(x) as.factor(x))然后我們重新提取出train數據和test數據
> train <- full[1:891,] > test <- full[892:1309,]接下來開始訓練我們的模型
> library('randomForest') > set.seed(754) > rf_model <- randomForest(factor(Survived) ~ Pclass + Sex + Embarked + Title + FsizeD, data = train)下面畫出我們的模型誤差變化:
> plot(rf_model, ylim=c(0,0.36)) > legend('topright', colnames(rf_model$err.rate), col=1:3, fill=1:3)圖像表達的是不同樹個數情況下的誤差率,黑色是整體情況,綠色是成功獲救的情況,紅色是死亡的情況,可以看出通過我們給定的幾個特征,對死亡的預測誤差更小更準確
我們還可以利用importance函數計算特征重要度:
> importance(rf_model) MeanDecreaseGini Pclass 40.273719 Sex 53.240211 Embarked 8.566492 Title 85.214085 FsizeD 23.543209可以看出特征按重要程度從高到底排序是:Title > Sex > Pclass > FsizeD > Embarked
?
數據預測
有了訓練好的模型,我們可以進行數據預測了
> prediction <- predict(rf_model, test)這樣prediction中就存儲了預測好的結果,以0、1表示
為了能輸出我們的結果,我們把test數據中的PassengerId和prediction組合成csv數據輸出
> solution <- data.frame(PassengerID = test$PassengerId, Survived = prediction) > write.csv(solution, file = 'solution.csv', row.names = F)最終的solution.csv的內容如下:
[root@centos:~/Developer/r_work $] head solution.csv "PassengerID","Survived" "892","0" "893","1" "894","0" "895","0" "896","1" "897","0" "898","1" "899","0" "900","1"本文部分內容參考:https://www.kaggle.com/mrisdal/titanic/exploring-survival-on-the-titanic/comments
總結
以上是生活随笔為你收集整理的十八、R语言特征工程实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nginx配置多域名跳转到不同的Tomc
- 下一篇: gulp详细入门教程