Kaggle Titanic Data Analysis(Top 1.6%)經驗分享

該題目來自於Kaggle:Titanic: Machine Learning from Disaster,也是Kaggle上最受關注的題目之一,不僅因為它浪漫的背景故事,更因為數據集的一些feature也蠻耐人琢磨。最近struggle出一個模型,在此跟大家分享,其中kaggle上的一些演算法也給予了我一些啟發。

分析語言採用的R,特徵工程的靈感主要來自於畫圖和統計檢驗,最終模型用的randomforest,比賽嘛,模型肯定是要用ensembling models的,你拿個logistic reg、Decision Tree不是說就一定做出不好結果,局限性還是有的,擬合特別好的模型像Adaboost、GBDT,調不好容易造成overfitting,某次訓練集準確率奇高(%99),然而並無卵用,妥妥過擬合,下次kaggle準備再用用XGBoost。個人覺得如果feature造的好、代表性強的話,boosting模型比較好,否則為了防止over fitting或者模型調不熟練,還是bagging放心一些。

嗯,話說數據預處理和探索佔到整個分析過程的%70~80,可我居然用了%95。不管怎麼說,我相信好模型是賴於好feature,好演算法只是挖掘出feature本該有的價值而已,再好的演算法,配上爛feature也是無濟於事,這點和吹噓後期技術忽略原片的攝影領域是一樣一樣滴。

至於特徵工程,其實各種方法差別並不多(Pclass、Sex、Child、GroupSize、Embarked、Fare),而最終提升的關鍵個人認為在於稱呼和組識別,僅在這兩個feature上沒有眉目的同學可以跳過前面大部分直接到Title和組識別(death Chain)的章節。對整個分析過程感興趣的話就可以向下面看啦。

嗯,我們開始

本文分為以下及部分

1 Exploration

2 Feature Engineering

3 Model and Access

1 Exploration

A. 載入與導入

導入數據時先不要讓R把字元特性作為因子,我們後續還要對其進行操作,最後再轉成因子不遲,然後我們將訓練集和測試集合併,隨後處理時我們一併處理,簡化操作,順便將完整數據集轉換成dplyr::tbl_df對象(個人習慣把數據集變為增強型Data.Frame,在使用head函數查看數據集簡要時顯示特徵類型),不知道的同學可以忽略這個轉換,對接下來的處理沒有影響哦

library(ggplot2)library(dplyr)library(randomForest)library(plyr)library(grid)library(RColorBrewer)train <- read.csv(G:/下載/train.csv)test <- read.csv(G:/下載/test.csv)comp <- bind_rows(train, test) comp <- dplyr::tbl_df(comp)comp$Set <- NAcomp$Set[1:nrow(train)] <- "Train"comp$Set[(nrow(train)+1):nrow(comp)] <- "Test"

B. 特徵查看

View(comp)str(comp)

summary(comp)

apply(comp,2,FUN=function(x) round(sum(x==|is.na(x))/nrow(comp),4))

拿到數據先別急著處理,讓我們來過一遍,並且產生一些猜想。

1) PassengerId(乘客ID),有用嗎,肯定沒有用~

2) Survived(生存情況),目標變數,兩類,生還、死亡

3) Pclass(船艙等級),講道理,船艙級別越高,越靠近甲板,人少一些逃生快,可以快速到達甲板。這個應該比較重要。

4) Name(姓名),姓名看上去應該和生還沒有什麼關係,但是仔細觀察姓名,裡面有稱呼信息,這個信息也許對我們有一些幫助。

5) Sex(性別),common sense是女人和孩子應該是重點保護對象,理論上女性生還幾率應該會比較高。

6) Age(年齡),猜想年邁的人應該不太容易生還,但是萬一老人優先上救生艇呢?嗯,這個我們先存疑,小孩應該沒有問題,該是存活率較高的。

7) SibSp(姐妹和配偶數),該乘客在船上的姐妹和配偶總共有幾人。

8) Parch(父母孩子數),該乘客在船上的父母和孩子總共有幾人,暫時這個兩個變數還沒什麼感覺,但這兩個加一起基本就是一個家庭的成員數,具體和生還有沒有關係我們再看。

9) Ticket(票號),感覺上與生還率沒什麼關係,但…船票上會不會有什麼信息呢?

10) Fare(船票價格),猜想船票價格越高,應該是生還越高。

11) Cabin(客艙號),猜想客艙的位置也許跟生還有關,畢竟船是頭撞冰上上的。

12) Embarked(登船地點):這個應該和生還沒什麼關係吧,至少先作這樣的假定。

可以看到除目標特徵外,Age、Fare、Embarked、Cabin存在缺失值,其中Cabin大量缺失

C. 相關關係

  • Sex,Pclass VS Survived

p <- ggplot(comp %>% filter(Set==Train))+scale_fill_brewer(palette = "Pastel1")p1 <- p+geom_bar(aes(x=Sex,fill=as.factor(Survived)),position="fill")+labs(title="Sex VS Survived")p2 <- p+geom_bar(aes(x=Pclass,fill=as.factor(Survived)),position="fill")+labs(title="Pclass VS Survived")p3 <- p+geom_jitter(aes(x=as.factor(Sex),y=as.factor(Pclass),color=as.factor(Survived)))+labs(title="Sex+Pclass VS Survived")+scale_colour_brewer(palette=Set1)grid.newpage()pushViewport(viewport(layout = grid.layout(2, 2)))print(p1, vp = viewport(layout.pos.row=1, layout.pos.col =1))print(p2, vp = viewport(layout.pos.row=1, layout.pos.col =2))print(p3, vp = viewport(layout.pos.row=2, layout.pos.col =c(1:2)))

從這三幅圖中,顯而易見我們可以得出最基本也是最重要的結論:性別、船艙等級與生還率相關,女性生存率明顯高於男性,船艙等級越高生存率越高。從Sex+Pclass vs Survived圖中,我們可以看到,在1、2等艙的女性幾乎全部都活了下來,2、3等艙的男性基本都沒有生還,而1等艙中的男性和3等艙中的女性,將成為擾亂我們分類準確率的區域。

  • Embarked VS Survived

p <- ggplot(comp %>% filter(Set==Train,Embarked!=))+scale_fill_brewer(palette = "Pastel1")p1 <- p+geom_bar(aes(x=as.factor(Embarked),fill=as.factor(Survived)),position="fill")+labs(title="Embarked VS Survived")p2 <- p+geom_bar(aes(x=as.factor(Pclass),fill=as.factor(Survived)))+labs(title="Embarked VS Pclass VS Survived")+facet_grid(.~Embarked)p3 <- p+geom_bar(aes(x=as.factor(Sex),fill=as.factor(Survived)))+labs(title="Embarked VS Sex VS Survived")+facet_grid(.~Embarked)grid.newpage()pushViewport(viewport(layout = grid.layout(3, 1)))vplayout = function(x, y) viewport(layout.pos.row = x, layout.pos.col = y)print(p1, vp = viewport(layout.pos.row =1))print(p2, vp = viewport(layout.pos.row =2))print(p3, vp = viewport(layout.pos.row =3))

理論上登船地點應該和生還並沒有關係,但從圖中我們看到,C地,一等艙比例很高,男女比例正常,而S地中,男性和三等艙比例很高,而Q地雖然三等艙比例高,但男女比例適中,因此便導致生還率C>Q>S,說明顯點三地登船的生還率有差別歸根結底是船艙等級和性別決定的,所以,Embarked這個特徵我們先作保留。

  • Age VS Survived

ggplot(comp %>% filter(Set==Train))+geom_density(aes(x=Age,fill=as.factor(Survived)),alpha=0.7)+labs(title="Age VS Survived")+scale_fill_brewer(palette = "Pastel1")

從不同生還情況的密度圖可以看出,在年齡15歲的左側,生還率有明顯差別,密度圖非交叉區域面積非常大,但在其他年齡段,則差別不是很明顯,認為是隨機所致,因此可以考慮將此年齡偏小的區域分離出來。

  • SibSp+Parch+1 VS Survived

組隊出發的人數由SibSp+Parch+1得出,表明一家子出發時是多少人

ggplot(comp %>% filter(Set==Train))+geom_bar(aes(x=(SibSp+Parch+1),fill=as.factor(Survived)),position="fill")+facet_grid(.~Pclass)+labs(title="Fare VS Survived")+scale_fill_brewer(palette = "Pastel1")

觀察到有趣的現象,單個人的生存率並不高,以小組為結構的乘客生存率比較高,但組內人數一旦多起來,生還率便開始下降,這使得我們應該小心謹慎地處理該特徵,一來我們若把組隊出發人數不作處理直接扔進模型(二分類樹模型),勢必造成模型將該特徵小於某值作為一類,大於某值作為一類,然而我們的特徵是在兩邊應該是一類,中間是一類,所以我們不能直接把該特徵不作處理直接扔進模型,這提示我們也許接下來要將組與非組分開,大組與小組分開,這樣才有可能讓模型將大組和無組分成一類,小組成為另一類。另外,為了看的清晰一些,我們使用不帶填充選項的條形圖,可以看到三等艙的人數偏多,大組數也明顯偏多,這提示我們後面應當以三等艙乘客的生存轉折處進行劃分(也許在4或5)

  • Fare VS Survived

p1 <- ggplot(comp %>% filter(Set==Train,Fare<300))+geom_density(aes(x=Fare,fill=as.factor(Survived)),alpha=0.85)+labs(title="Fare VS Survived")+scale_fill_brewer(palette = "Pastel1")+guides(fill=FALSE)p2 <- ggplot(comp %>% filter(Set==Train,Pclass==1,Fare<300))+geom_density(aes(x=Fare,fill=as.factor(Survived)),alpha=0.85)+labs(title="Fare for class1 VS Survived")+scale_fill_brewer(palette = "Pastel1")p3 <- ggplot(comp %>% filter(Set==Train,Pclass==2,Fare<300))+geom_density(aes(x=Fare,fill=as.factor(Survived)),alpha=0.85)+labs(title="Fare for class2 VS Survived")+scale_fill_brewer(palette = "Pastel1")+guides(fill=FALSE)p4 <- ggplot(comp %>% filter(Set==Train,Pclass==3,Fare<300))+geom_density(aes(x=Fare,fill=as.factor(Survived)),alpha=0.85)+labs(title="Fare for class3 VS Survived")+scale_fill_brewer(palette = "Pastel1")+guides(fill=FALSE)grid.newpage()pushViewport(viewport(layout = grid.layout(2, 2)))print(p1, vp = viewport(layout.pos.row=1, layout.pos.col =1))print(p2, vp = viewport(layout.pos.row=1, layout.pos.col =2))print(p3, vp = viewport(layout.pos.row=2, layout.pos.col =1))print(p4, vp = viewport(layout.pos.row=2, layout.pos.col =2))

很明顯,單看票價和生存的話,票價越低,生存越渺茫,但別忘了票價可是受客艙等級影響的,真正要看票價能否影響生存,還應該固定住船艙等級來看,因此再次觀察下各個船艙等級下票價對生存的影響。由密度圖結果看,票價對生存的影響似乎沒有那麼明顯,這個特徵我們先保留,到最後時放進模型看看效果再決定。

  • Name、Ticket、Cabin VS Sruvived?

暫時我們還無法使用這些變數,不過名字中的稱呼信息,似乎可以建立一個分類變數,而且我們對這個稱呼信息也比較感興趣,同時票的號碼和船艙號的中的數字及字母也比較感興趣,那麼我們先進入Feature Engineering,再來探索這部分信息。

2 Feature Engineering

Name->Title、Surname

我們先來處理之前我們最感興趣的特徵:姓名,姓名中會有什麼信息呢,同一家庭的人的姓大部分是一樣的,因此我們不如把姓名提取出來,此外名字中的稱呼我們也提取出來。此處需要正則表達式

#把,及,開始的任意個單字元替換成comp$Surname <- gsub(,.*, , comp$Name)#把, 及, 之前的任意個單字元替換成、且把.及.開始的任意個單字元替換成comp$Title <- gsub((.*, )|(\..*), , comp$Name)ggplot(comp %>% filter(Set==Train))+geom_bar(aes(x=Title,fill=as.factor(Survived)),position="fill")+scale_fill_brewer(palette = "Pastel1")

提取出了稱呼信息,我們來仔細研究一下這個,這些稱呼中除了正常的Mr、Mrs、Miss外,還有哪些信息呢。經過百度我們知道

Miss(未婚女子都叫Miss,包括小孩,Miss可以0歲也可以27歲)

Master少爺(普通人家也可以叫少爺,僅限小孩,Master只可能0歲到十來歲)

Mlle=Mademoiselle小姐(法語)

Ms=Miss小姐

Mme=Madame女士(法語)

Capt=Captain上校

Col=Colonel中校

Dr=Doctor醫生

Major=Major少校

Rev=Reverend牧師

Dona夫人(西班牙語)

Lady夫人(爵士夫人)

Sir爵士

the Countess夫人(爵士夫人)

Don未知

#Jonkheer未知

因此我們可以知道,稱呼中除了不同語言下的稱呼外,還有軍銜、牧師、及上流社會的稱呼(比如夫人Lady,在英國不是什麼人都叫夫人,地位顯赫的女人才能叫夫人,比如撒切爾夫人),從條形圖中,我們大概可以將高生還率的特別地稱呼為貴族,低生還率的特別地稱呼為公僕,並且將意思相同的稱呼合併(Jonkheer和Don的含義沒有查到,鑒於只有蛋疼的顯赫人士才有這麼多講究而嫌棄使用Mr、Mrs,我們把它踢到貴族中)。

comp$Title[comp$Title == Mlle]<- Miss comp$Title[comp$Title == Ms]<- Misscomp$Title[comp$Title == Mme]<- Mrs pubServ <- c(Capt, Col, Don, Dr, Major, Rev,Jonkheer)noble <- c(Dona, Lady, Sir, the Countess)comp$Title[comp$Title %in% noble] <- Noblecomp$Title[comp$Title %in% pubServ] <- PublicServantggplot(comp %>% filter(Set==Train))+geom_bar(aes(x=Title,fill=as.factor(Survived)),position="fill")+labs(title="Title VS Survived")+scale_fill_brewer(palette = "Pastel1")

我們再來查看一下特徵構造後的Title在水平上縮減了很多,而且在生還率差別上也體現出了區別。

View(comp[which(comp$Title== Noble),])View(comp[which(comp$Title== PubicServant),])

再來看一看新構造出的貴族和公僕的具體情況,可以看到貴族和公僕水平基本都分布在一等艙和二等艙,而且公僕中很多男性,這對我們之前提到的一等艙男性的生還率分類難點提供了一些幫助。

  • Age->Child

按照之前的約定,我們需要把小孩子變數提取出來,作為年齡分類化的一個特徵。但年齡有很多的缺失值,我們先填補缺失值再來進行分類。填補的缺失值為每個稱呼組的年齡中位數

byTitle<-group_by(comp,Title)titleAge <- data.frame(dplyr:::summarise(byTitle,disp=median(Age,na.rm=T)))comp[is.na(comp$Age), "Age"] <- apply(comp[is.na(comp$Age), ] , 1, function(x) titleAge[titleAge[, 1]==x["Title"], 2])comp$Child=NAcomp$Child=ifelse(comp$Age < 18,Child,Others)

  • SibSp、Parch->GroupSize

小組的成員數由乘客的姐妹配偶父母兒女和自己加和

根據探索組隊出發人數時得出的結論,將組內人數大於等於5的作為大組,組內人數小於5的組作為小組。

comp$GroupSize <- comp$SibSp+comp$Parch+1comp$GroupStyle[comp$GroupSize == 1] <- Alonecomp$GroupStyle[comp$GroupSize < 5 & comp$GroupSize > 1] <- Smallcomp$GroupStyle[comp$GroupSize >= 5] <- Big

  • Filling Embarked

由於登船地點只有兩個缺失值,因此直接用眾數替代

comp$Embarked[which(comp$Embarked==)]=median(comp$Embarked)

  • Filling Fare and->FareSingle

用各個艙位的票價中位數去填補票價

byPclass<-group_by(comp,Pclass)farePclass <- data.frame(dplyr:::summarise(byPclass,disp=median(Fare,na.rm=T)))comp[is.na(comp$Fare), "Fare"] <- apply(comp[is.na(comp$Fare), ] , 1, function(x) farePclass[farePclass[, 1]==x["Pclass"], 2])

  • Ticket-> TicketStyle

接下來討論的Ticket和後面的Cabin的特徵工程,出發點都是希望通過船票或者船艙號來得出一些與生存率相關的信息,以此來試探我們的猜想:即乘客所處的位置對最終的生存率是有影響的,為了不至於使得船票信息水平過多,我們構造船票首字母特徵。

船票號多少會和艙位有關,因此我們剔開艙位的因素,看看各個艙位下船票對生存率的影響,由於船票引起的差別不是很容易用肉眼觀察,我們採用非參檢驗來趟這灘渾水。

comp$TicketLett <- sapply(comp$Ticket,function(x) substr(x,1,1))ggplot(comp %>% filter(Set==Train))+geom_bar(aes(x=TicketLett,fill=as.factor(Survived)),position=fill)+facet_grid(.~Pclass)+labs(title="TicketLett+Pclass VS Survived")+scale_fill_brewer(palette = "Pastel1")cTable <- xtabs(~as.factor(TicketLett)+as.factor(Survived),data=comp %>% filter(Set==Train,Pclass==1))chisq.test(cTable)cTable <- xtabs(~as.factor(TicketLett)+as.factor(Survived),data=comp %>% filter(Set==Train,Pclass==2))chisq.test(cTable)cTable <- xtabs(~as.factor(TicketLett)+as.factor(Survived),data=comp %>% filter(Set==Train,Pclass==3))chisq.test(cTable)

可以看到一等艙二等艙段,船票並沒有對生存率產生影響,但是在三等艙艙段,船票對生存率的影響是顯著的。我們繼續向下探索,看看在三等艙中、不同性別下船票對生存率的影響情況。

ggplot(comp %>% filter(Set==Train,Pclass==3))+geom_bar(aes(x=TicketLett,fill=as.factor(Survived)))+labs(title="TicketLett for Pclass3 VS Survived")cTable <- xtabs(~as.factor(TicketLett)+as.factor(Survived),data=comp %>% filter(Set==Train,Pclass==3,Sex==female))chisq.test(cTable)cTable <- xtabs(~as.factor(TicketLett)+as.factor(Survived),data=comp %>% filter(Set==Train,Pclass==3,Sex==male))chisq.test(cTable)

可以看出若再把三等艙下的乘客繼續按性別分類,則船票的影響就不顯著了,而今檢驗結果顯示,在三等艙不同性別下,船票的影響處於我們可相信的邊緣(%99置信度),而本身船票的水平就有很多,而對於乘客數量少的水平(『5』,』6』,』8』,』9』,』F』),其中的乘客生存率會產生較大的方差使得某一水平下的生存率不能反映其真實的生存率,這將容易使得檢驗結果偏向顯著,在這種情況下,處於顯著邊緣的檢驗我們應更加保守,所以我得出的結論是,拋棄掉票號這一特徵。

  • Cabin->CabinLett、CabinNo

接下來我們看看船艙中有沒有什麼信息,先分離出船艙的首字母和其後的數字

comp$CabinNo <- as.integer(ldply(strsplit(comp$Cabin,([A-Z]| )+),rbind)[[2]])comp$CabinLett <- sapply(comp$Cabin,function(x) substr(x,1,1))ggplot(comp %>% filter(Set==Train,!is.na(CabinNo)))+geom_density(aes(x=CabinNo,fill=as.factor(Survived)),alpha=0.6)+labs(title="Cabin Number VS Survived")

觀察密度圖,暫時沒什麼感覺,由於客艙信息大量缺失,唯一比較完整的也集中在一等艙中,那我們可以忽略客艙對二等三等艙的影響,由於一等艙的女性不是我們分類的重點(幾乎全部生還),那問題就集中在一等艙中的男性這一難題上,我們直接檢驗一等艙男性中客艙數字對生還情況的影響。

data1 <- comp %>% filter(Set==Train,Pclass==1,Sex==male)hetcor(data1$CabinNo,as.factor(data1$Survived))

很顯然,P-values不顯著,我們無法拒絕不相關。

再來看看客艙首字母與生存的關係,我們仍然只關注一等艙男性的情況。

ggplot(comp %>% filter(Set==Train,Pclass==1))+geom_bar(aes(x=CabinLett,fill=as.factor(Survived)),alpha=0.6)+labs(title="CabinLett+Pclass1 VS Survived")+scale_fill_brewer(palette = "Pastel1")kruskal.test(Survived~as.factor(CabinLett),data=comp %>% filter(Set==Train,Pclass==1,Sex==male))

很顯然,也並沒有什麼關係。

  • Identify death chain

在不斷提升準確率的過程中,我堅信船艙船票位置和結隊出發這兩個要素中一定有一個能夠成為影響最終生存結果的隱藏boss,但很遺憾,船艙船票位置要素被檢驗結果拍的一無是處,而組隊出發也沒那麼盡如人意,然而在多次嘗試與觀察數據之後,發現組隊出發要素中有更深的東西在隱藏。在組內人數2~4的組中,存在相互拖累與相互扶持的情況,但這種情況僅限於女人與孩子們!先建立組名,再按每一組算出組內人數、組內女人小孩人數,組內女人小孩死亡人數,和組內女人小孩生存情況缺失人數。並統計每一組(訓練集中的組,不包含缺失值)中的女人小孩生存率。

comp$GroupName=NAcomp$GroupName <- apply(comp,1,function(x) ifelse((as.numeric(x[SibSp])+as.numeric(x[Parch]))>0,paste0(x[Surname],x[Fare]),NotGroup))groupSurInfo <- comp %>% dplyr:::group_by(GroupName) %>% dplyr:::summarize(len = length(Survived), wmChdLen = sum(as.numeric((Sex==female|Child==Child))),wmChdDthLen = sum(as.numeric((Sex==female|Child==Child)&(Survived==0)),na.rm=T),wmChdNaLen = sum(is.na(Survived)&(Sex==female|Child==Child)))groupSurInfo <- groupSurInfo %>% mutate(wmChdDthRate=wmChdDthLen/wmChdLen)viewGroup <- groupSurInfo %>% filter(len<=4,len>1,wmChdLen>1,wmChdNaLen==0)ggplot(viewGroup)+geom_bar(aes(x=wmChdDthRate))+labs(title="Surviving rate of female and Children in every family ")+facet_grid(.~wmChdLen)

可以觀察到,每一組中的女人小孩要麼生存率是1要麼是0,幾乎沒有(0,1)的情況,這就說明在每一小規模組(2~4)中,女人小孩要麼全部存活要麼全部死亡。因此我標識出在測試集中的、小規模組中的、同組有女人小孩死亡的女人小孩,這句話有點繞,用一段數據說明一下:

該972號被標記,是因為它是測試集中的小孩,處於一個三人組,並且和他同組的人有女人或小孩死亡,事實上一個是他的媽媽一個是他的姐姐…。那麼我認為他也會死亡,原因也很明顯,在女人和小孩優先登船的情況下,女人和小孩一定會抱成一團出發,要麼救生艇有限,抱緊緊的母子母女排在了僅有的救生艇之外,要麼他們根本由於船艙的傾斜或破壞沒有到達救生艇…。那麼有的同學會問,為什麼不在訓練集中加入同組有否女人小孩死亡的特徵,來懲罰同組有死和獎勵同組無死的情況呢,我也這樣考慮過,但我決定不在訓練集加入此特徵,因為該特徵僅能應對極個別的一些觀測,雖然該特徵是影響死亡率的最後內在邏輯之一,但加入此特徵勢必給整個模型帶來不小的雜訊,甚至出現與預期相反的情況出現。所以直接修改入測試集是比較好的方法,我的做法是直接懲罰他們的性別、是否是小孩、稱呼,讓他們的觀測變為一個成年男人,事實證明,這樣的方法確實能夠達到最佳效果。

targetGroup <- groupSurInfo %>% filter(len<=4,len>1,wmChdLen>1,wmChdDthLen>0,wmChdNaLen>0)comp$Sex[comp$GroupName %in% targetGroup$GroupName & is.na(comp$Survived)] <- malecomp$Child[comp$GroupName %in% targetGroup$GroupName & is.na(comp$Survived)] <- Adultcomp$Title[comp$GroupName %in% targetGroup$GroupName & is.na(comp$Survived)] <- Mr

  • Conversion

comp$Child <- factor(comp$Child)comp$Sex <- factor(comp$Sex)comp$Embarked <- factor(comp$Embarked)comp$Title <- factor(comp$Title)comp$Pclass <- factor(comp$Pclass)comp$GroupStyle <- factor(comp$GroupStyle)train<- comp %>% filter(Set==Train)test <- comp %>% filter(Set==Test)

將該轉換成因子的特徵轉換為因子,或者特徵工程後的訓練集和測試集

3 Model and Access

set.seed(123)model <- randomForest(factor(Survived) ~ Pclass + Sex + Fare +Embarked + Title + GroupStyle + Child , data = train)print(model)varImpPlot(model, main = "variables importance of random forest")plot(model, main = Error of model)legend(topright, colnames(model$err.rate), col=1:3, fill=1:3)prdct <- predict(model, test)write.csv(data.frame(PassengerID = test$PassengerId,Survived = prdct ), file = G:/下載/resultbase818.8test.csv, row.names = F)

在變數的選擇上,Pclass、Sex、Title、GroupSize、Child為首選,Fare、Embarked為備選,個人認為Fare和Embarked中的信息全部體現在Pclass、Sex、GroupSize中,理應不加入模型,但事實證明,加入該兩個特徵卻能使準確率提高兩個percent,這點也是我一直到現在的疑惑所在,我選擇接收這個事實,將二者也加入模型。

從圖中看到隨著樹的增多,袋外誤差在趨於穩定,我們的模型默認值,nTree=500完全能夠滿足我們的要求,由於Title中暗藏了男人和女人,還有貴族、公僕、男性小孩(Master),使得Title卻成為最重要的變數,但我們也能夠理解,畢竟其蘊含的信息已然是最多,按照Title劃分,不純度理應降的最多,剩下的Sex和Pclass排在前列也是預料之中,單單Fare能排這麼高確實有點令我驚訝,這點也是我一直不理解的。

最後上傳至kaggle準確率為83.732%。

總體來講,個人認為分類的基礎還是在Pclass,Sex、Child上,單純用該三個特徵也能預測出還可以的結果,而模型準確率的提升還依賴於GroupSize、Fare、Embarked,最終獲得的競爭力提升在於組的識別和稱呼Title上,我相信好的準確率的模型必然要挖掘出Title這個特徵並在組識別上下一些功夫,而本文從組中提取出了部分女人小孩之所以未生還的原因,如果各位還有其他有意思的邏輯也請多多分享啦。


推薦閱讀:

IMDB Movie :Python數據分析報告
吳恩達deep learning中實現CNN的小作業
《BI程序猿——2017年總結》
重走數據分析之路 R In Action

TAG:數據分析 | 數據挖掘 | Kaggle |