
知識(shí)要點(diǎn):
lubridate包拆解時(shí)間 | POSIXlt
利用決策樹(shù)分類(lèi),利用隨機(jī)森林預(yù)測(cè)
利用對(duì)數(shù)進(jìn)行fit,和exp函數(shù)還原
訓(xùn)練集來(lái)自Kaggle華盛頓自行車(chē)共享計(jì)劃中的自行車(chē)租賃數(shù)據(jù),分析共享自行車(chē)與天氣、時(shí)間等關(guān)系。數(shù)據(jù)集共11個(gè)變量,10000多行數(shù)據(jù)。
https://www.kaggle.com/c/bike-sharing-demand
首先看一下官方給出的數(shù)據(jù),一共兩個(gè)表格,都是2011-2012年的數(shù)據(jù),區(qū)別是Test文件是每個(gè)月的日期都是全的,但是沒(méi)有注冊(cè)用戶(hù)和隨意用戶(hù)。而Train文件是每個(gè)月只有1-20天,但有兩類(lèi)用戶(hù)的數(shù)量。
求解:補(bǔ)全Train文件里21-30號(hào)的用戶(hù)數(shù)量。評(píng)價(jià)標(biāo)準(zhǔn)是預(yù)測(cè)與真實(shí)數(shù)量的比較。

首先加載文件和包
library(lubridate)
library(randomForest)
library(readr)
setwd("E:")
data<-read_csv("train.csv")
head(data)
這里我就遇到坑了,用r語(yǔ)言缺省的read.csv死活讀不出來(lái)正確的文件格式,換成xlsx更慘,所有時(shí)間都變成43045這樣的怪?jǐn)?shù)字。本來(lái)之前試過(guò)as.Date可以正確轉(zhuǎn)換,但這次因?yàn)橛袝r(shí)分秒,就只能用時(shí)間戳,但結(jié)果也不行。
最后是下載了"readr"包,用read_csv語(yǔ)句,順利解讀。
因?yàn)閠est比train日期完整,但缺少用戶(hù)數(shù),所以要把train和test合并。
test$registered=0
test$casual=0
test$count=0
data<-rbind(train,test)
摘取時(shí)間:可以用時(shí)間戳,這里的時(shí)間比較簡(jiǎn)單,就是小時(shí)數(shù),所以也可以直接截字符串。
data$hour1<-substr(data$datetime,12,13)
table(data$hour1)
統(tǒng)計(jì)一下每個(gè)小時(shí)的使用總數(shù),是這樣(為什么介么整齊):

接下來(lái)是運(yùn)用箱線圖,看一下使用者和時(shí)間,周幾這些的關(guān)系。為什么用箱線圖而不用hist直方圖,因?yàn)橄渚€圖有離散點(diǎn)表達(dá),下面也因此運(yùn)用對(duì)數(shù)求fit
從圖中可以看出,在時(shí)間方面,注冊(cè)用戶(hù)和非注冊(cè)用戶(hù)的使用時(shí)間有很大不同。



接下來(lái)用相關(guān)系數(shù)cor檢驗(yàn)用戶(hù),溫度,體感溫度,濕度,風(fēng)速的關(guān)系。
相關(guān)系數(shù):變量之間的線性關(guān)聯(lián)度量,檢驗(yàn)不同數(shù)據(jù)的相關(guān)程度。
取值范圍[-1,1],越接近0越不相關(guān)。
從運(yùn)算結(jié)果可以看出,使用人群與風(fēng)速呈負(fù)相關(guān),比溫度影響還大。

接下來(lái)就是將時(shí)間等因素用決策樹(shù)分類(lèi),然后用隨機(jī)森林來(lái)預(yù)測(cè)。隨機(jī)森林和決策樹(shù)的算法。聽(tīng)起來(lái)很高大上,其實(shí)現(xiàn)在也很常用了,所以一定要學(xué)會(huì)。
決策樹(shù)模型是 一種簡(jiǎn)單易用的非參數(shù)分類(lèi)器。它不需要對(duì)數(shù)據(jù)有任何的先驗(yàn)假設(shè),計(jì)算速度較快,結(jié)果容易解釋?zhuān)曳€(wěn)健性強(qiáng),不怕噪聲數(shù)據(jù)和缺失數(shù)據(jù)。
決策樹(shù)模型的基本計(jì) 算步驟如下:先從n個(gè)自變量中挑選一個(gè),尋找最佳分割點(diǎn),將數(shù)據(jù)劃分為兩組。針對(duì)分組后數(shù)據(jù),將上述步驟重復(fù)下去,直到滿(mǎn)足某種條件。
在決策樹(shù)建模中需要解決的重要問(wèn)題有三個(gè):
如何選擇自變量
如何選擇分割點(diǎn)
確定停止劃分的條件
做出注冊(cè)用戶(hù)和小時(shí)的決策樹(shù),
train$hour1<-as.integer(train$hour1)
d<-rpart(registered~hour1,data=train)
rpart.plot(d)

然后就是根據(jù)決策樹(shù)的結(jié)果手動(dòng)分類(lèi),所以還滿(mǎn)占代碼的...
train$hour1<-as.integer(train$hour1)
data$dp_reg=0
data$dp_reg[data$hour1<7.5]=1
data$dp_reg[data$hour1>=22]=2
data$dp_reg[data$hour1>=9.5 & data$hour1<18]=3
data$dp_reg[data$hour1>=7.5 & data$hour1<8.5]=4
data$dp_reg[data$hour1>=8.5 & data$hour1<9.5]=5
data$dp_reg[data$hour1>=20 & data$hour1<22]=6
data$dp_reg[data$hour1>=18 & data$hour1<20]=7
同理,做出 (小時(shí) | 溫度) X (注冊(cè) | 隨意用戶(hù)) 等決策樹(shù),繼續(xù)手動(dòng)分類(lèi)....

年份月份,周末假日等手動(dòng)分類(lèi)
data$year_part=0
data$month<-month(data$datatime)
data$year_part[data$year=='2011']=1
data$year_part[data$year=='2011' & data$month>3]=2
data$year_part[data$year=='2011' & data$month>6]=3
data$year_part[data$year=='2011' & data$month>9]=4
data$day_type=""
data$day_type[data$holiday==0 & data$workingday==0]="weekend"
data$day_type[data$holiday==1]="holiday"
data$day_type[data$holiday==0 & data$workingday==1]="working day"
data$weekend=0
data$weekend[data$day=="Sunday"|data$day=="Saturday"]=1
接下來(lái)用隨機(jī)森林語(yǔ)句預(yù)測(cè)
在機(jī)器學(xué)習(xí)中,隨機(jī)森林是一個(gè)包含多個(gè)決策樹(shù)的分類(lèi)器, 并且其輸出的類(lèi)別是由個(gè)別樹(shù)輸出的類(lèi)別的眾數(shù)而定。
隨機(jī)森林中的子樹(shù)的每一個(gè)分裂過(guò)程并未用到所有的待選特征,而是從所有的待選特征中隨機(jī)選取一定的特征,再在其中選取最優(yōu)的特征。這樣決策樹(shù)都能夠彼此不同,提升系統(tǒng)的多樣性,從而提升分類(lèi)性能。
ntree指定隨機(jī)森林所包含的決策樹(shù)數(shù)目,默認(rèn)為500,通常在性能允許的情況下越大越好;
mtry指定節(jié)點(diǎn)中用于二叉樹(shù)的變量個(gè)數(shù),默認(rèn)情況下數(shù)據(jù)集變量個(gè)數(shù)的二次方根(分類(lèi)模型)或三分之一(預(yù)測(cè)模型)。一般是需要進(jìn)行人為的逐次挑選,確定最佳的m值—摘自datacruiser筆記。這里我主要學(xué)習(xí),所以雖然有10000多數(shù)據(jù)集,但也只定了500。就這500我的小電腦也跑了半天。
#train<-data[as.integer(day(data$datetime))>20,]
train<-data
set.seed(421)
train$logreg<-log(train$registered+1)
train$logcas<-log(train$casual+1)
#fit1<-randomForest(logreg~hour1+workingday+day+holiday+day_type+
temp_reg+humidity+atemp+windspeed+season+weather
+dp_reg+weekend+year+year_part,
train,importance=TRUE,ntree=250)
fit1<-randomForest(logreg~hour1+workingday+holiday+temp_reg+atemp+humidity
+windspeed+season+weather+weekend+year+year_part
+dp_reg,train,importance=TRUE,ntree=500)
pred1<-predict(fit1,train)
train$logreg<-pred1
set.seed(421)
fit2<-randomForest(logcas~hour1+workingday+holiday+temp_cas+atemp+humidity
+windspeed+season+weather+weekend+year+year_part
+dp_cas,train,importance=TRUE,ntree=500)
pred2<-predict(fit2,train)
train$logcas<-pred2
這里不知道怎么回事,我的day和day_part加進(jìn)去就報(bào)錯(cuò),只有刪掉這兩個(gè)變量計(jì)算,還要研究修補(bǔ)。
然后用exp函數(shù)還原
train$registered<-exp(train$logreg)-1
train$casual<-exp(train$logcas)-1
train$count<-test$casual+train$registered
最后把20日后的日期截出來(lái),寫(xiě)入新的csv文件上傳。
train2<-train[as.integer(day(data$datetime))>=20,]
submit_final<-data.frame(datetime=train2$datetime,count=train2$count)
write.csv(submit_final,"submit_final.csv",row.names=F)
大功告成!
github的代碼在此
原來(lái)的示例是煉數(shù)成金網(wǎng)站的kaggle課程第二節(jié),基本按照視頻的思路。因?yàn)檎n程沒(méi)有源代碼,所以要自己修補(bǔ)運(yùn)行完整。總算把這個(gè)功課做完了。下面要修正的有:
好好理解三個(gè)知識(shí)點(diǎn)(lubridate包/POSIXlt,log線性,決策樹(shù)和隨機(jī)森林);
用WOE和IV代替cor函數(shù)分析相關(guān)關(guān)系;
用其他圖形展現(xiàn)的手段分析
隨機(jī)樹(shù)變量重新測(cè)試
完成了一個(gè)“浩大完整”的數(shù)據(jù)分析,還是很有成就感的!