R语言第八讲 评估模型之交叉验证法分析案例
題目
? ? ? 評估Auto數據集上擬合多個線性模型所產生的測試錯誤率。Auto數據集是存在與ISLR程序包中的一個摩托車相關數據的數據集,讀者可自行下載ISLR程序包,并將Auto數據集加載。
相關資料
? ? ? 交叉驗證是在機器學習建立模型和驗證模型參數時常用的辦法。交叉驗證,顧名思義,就是重復的使用數據,把得到的樣本數據進行切分,組合為不同的訓練集和測試集,用訓練集來訓練模型,用測試集來評估模型預測的好壞。在此基礎上可以得到多組不同的訓練集和測試集,某次訓練集中的某樣本在下次可能成為測試集中的樣本,即所謂“交叉”。
那么什么時候才需要交叉驗證呢?交叉驗證用在數據不是很充足的時候。比如在我日常項目里面,對于普通適中問題,如果數據樣本量小于一萬條,我們就會采用交叉驗證來訓練優化選擇模型。如果樣本大于一萬條的話,我們一般隨機的把數據分成三份,一份為訓練集(Training Set),一份為驗證集(Validation Set),最后一份為測試集(Test Set)。用訓練集來訓練模型,用驗證集來評估模型預測的好壞和選擇模型及其對應的參數。把最終得到的模型再用于測試集,最終決定使用哪個模型以及對應參數。
回到交叉驗證,根據切分的方法不同,交叉驗證分為下面三種:
第一種是簡單交叉驗證,所謂的簡單,是和其他交叉驗證方法相對而言的。首先,我們隨機的將樣本數據分為兩部分(比如: 70%的訓練集,30%的測試集),然后用訓練集來訓練模型,在測試集上驗證模型及參數。接著,我們再把樣本打亂,重新選擇訓練集和測試集,繼續訓練數據和檢驗模型。最后我們選擇損失函數評估最優的模型和參數。
第二種是S折交叉驗證(S-Folder Cross Validation)。和第一種方法不同,S折交叉驗證會把樣本數據隨機的分成S份,每次隨機的選擇S-1份作為訓練集,剩下的1份做測試集。當這一輪完成后,重新隨機選擇S-1份來訓練數據。若干輪(小于S)之后,選擇損失函數評估最優的模型和參數。
第三種是留一交叉驗證(Leave-one-out Cross Validation),它是第二種情況的特例,此時S等于樣本數N,這樣對于N個樣本,每次選擇N-1個樣本來訓練數據,留一個樣本來驗證模型預測的好壞。此方法主要用于樣本量非常少的情況,比如對于普通適中問題,N小于50時,我一般采用留一交叉驗證。
通過反復的交叉驗證,用損失函數來度量得到的模型的好壞,最終我們可以得到一個較好的模型。那這三種情況,到底我們應該選擇哪一種方法呢?一句話總結,如果我們只是對數據做一個初步的模型建立,不是要做深入分析的話,簡單交叉驗證就可以了。否則就用S折交叉驗證。在樣本量少的時候,使用S折交叉驗證的特例留一交叉驗證。
此外還有一種比較特殊的交叉驗證方式,也是用于樣本量少的時候。叫做自助法(bootstrapping)。比如我們有m個樣本(m較小),每次在這m個樣本中隨機采集一個樣本,放入訓練集,采樣完后把樣本放回。這樣重復采集m次,我們得到m個樣本組成的訓練集。當然,這m個樣本中很有可能有重復的樣本數據。同時,用沒有被采樣到的樣本做測試集。這樣接著進行交叉驗證。由于我們的訓練集有重復數據,這會改變數據的分布,因而訓練結果會有估計偏差,因此,此種方法不是很常用,除非數據量真的很少,比如小于20個。
? ? ? ? 隨機抽樣函數sample介紹:
?
> x=1:10> sample(x=x) [1] 3 5 9 6 10 7 2 1 8 4? ? ? ? 第一行代碼表示給x向量x賦值,第二行代碼表示對x向量進行隨機抽樣。結果輸出為每次抽樣抽得的結果,可以看出該抽樣為無放回抽樣-最多抽n次,n為向量中元素的個數。
? ? ? ?如果想指定在該向量中抽取元素的個數,需要加一個參數size:
> x=1:1000> sample(x=x,size=20)[1] 66 891 606 924 871 374 879 573 284 305 914 792 398 497 721 897 324 437[19] 901 33? ? ? ?這是在1~1000的正整數中抽樣,其中size指定抽樣的次數,抽了20次,結果如上所示。
? ? ? ?這些都是無放回抽樣。所謂無放回抽樣,也就是說某個元素一旦被選擇,該總體中就不會再有該元素。如果是有放回抽樣,則需添加一個參數repalce=T:
> x=1:10> sample(x=x,size=5,replace=T)[1] 4 7 2 4 8? ? ? ?“replace”就是重復的意思。即可以重復對元素進行抽樣,也就是所謂的有放回抽樣。我們看上面的結果,元素4在5次隨機抽樣的過程中被抽取了兩次。
? ? ? ?如果我們輸入代碼的位置與某個函數中參數的位置一一對應的話,我們可以不寫該函數的參數,如:
> x=1:10> sample(x,20,T)[1] 1 2 2 1 5 5 5 9 9 5 2 9 8 3 4 8 8 8 1 1? ? ? 簡單運用:對于擲骰子,投硬幣(這可能是介紹抽樣必介紹的內容),都屬于有放回抽樣。
? ? ? ?這里要說明,對于sample函數,參數x可以是數值,也可以是字符,實際上參數x代表任意一個向量:
> a=c("A","B")> sample(x=a,size=10,replace=T)[1] "B" "A" "A" "A" "B" "A" "A" "B" "A" "A"? ? ? 上述代碼可以理解為擲硬幣,拋了10次,其中正面(A)與反面(B)出現的次數是可以重復的。
? ? ?上述抽樣過程,每一個元素被抽取的概率相等,稱為隨機抽樣。
? ? ?有時候我們的抽取元素的概率未必相等(如常見的二項分布概率問題),此時我們需要添加一個參數prob,即:“probability”(概率)的縮寫。假設一名醫生給患者做某手術成功的概率是80%,那么現在他給20例病人做手術,可能有哪幾次是成功的呢?代碼如下:
> x=c("S","F")> sample(x,size=20,replace=T,prob=c(0.8,0.2))[1] "F" "S" "S" "S" "S" "S" "S" "S" "S" "S" "S" "S" "F" "S" "S" "F" "S" "S"[19] "F" "S"? ? ?其中“S”代表成功,“F”代表失敗。
> x=c(1,3,5,7)> sample(x,size=20,replace=T,prob=c(0.1,0.2,0.3,0.9))[1] 3 5 7 3 7 3 7 5 3 7 7 7 1 5 7 5 7 7 3 7? ? ? 這些代碼告訴我們,對每一個元素都可以給定一個概率,且每個概率是獨立的,即在參數prob中,不一定所有元素的概率加起來等于1,它只代表某元素被抽取的概率而已。
? ? ?對于sample函數,其參數x可以是R中任意一個對象(如上述對字符的抽樣)。其中還有一個功能相同的函數sample.int,“int”即“intger”的縮寫,也就是“整數”。它的參數n必須是正整數:
> x=-10.5:7.5> sample(x=x,size=3)> sample.int(n=x,size=3)[1] -5.5 -7.5 0.5Error in sample.int(x, size = 3) : invalid first argument? ? ? ? 第一行代碼生成了-10.5到7.5的等差數列,結果輸出的第一行是sample的結果;第二行是sample.int的結果,提示錯誤:“第一個自變量無效”,因為它不是正整數。其余的用法與ample是一樣的。
?
實驗
? ? ??在開始之前,用 set. seed ()函數來為 R 的隨機數生成器設定一個種子 (seed) .這樣就就可以得到與下面展示的完全相同的結果。通常來說,使用一種如同交叉驗證法這樣包含隨機性的分析方法時,可以設定一個隨機種子,這樣下次就可以得到完全相同的結果。
? ? ? ?首先用 sample()函數把觀測集分為兩半,從原始的 392 個觀測中隨機地選取一個有 196 個觀測的子集,作為訓練集。
> library(ISLR) > set.seed(1) #產生從1-392中抽樣出196個數。 > train=sample(392,196) [1] 324 167 129 299 270 187 307 85 277 362 330 263 329 79 213 37 105 [18] 217 366 165 290 383 89 289 340 326 382 42 111 20 44 343 70 121 [35] 40 172 25 248 198 39 298 280 160 14 130 45 22 206 230 193 104 [52] 367 255 341 342 103 331 13 296 375 176 279 110 84 29 141 252 221 [69] 108 304 33 347 149 287 102 145 118 323 107 64 224 337 51 325 372 [86] 138 390 389 282 143 285 170 48 204 295 24 181 214 225 163 43 1 [103] 328 78 284 116 233 61 86 374 49 242 246 247 239 219 135 364 363 [120] 310 53 348 65 376 124 77 218 98 194 19 31 174 237 75 16 358 [137] 9 50 92 122 152 386 207 244 229 350 355 391 223 373 309 140 126 [154] 349 344 319 258 15 271 388 195 201 318 17 212 127 133 41 384 392 [171] 159 117 72 36 315 294 157 378 313 306 272 106 185 88 281 228 238 [188] 368 80 30 93 234 220 240 369 164? ? ? ? ?用 lm() 函數中的 subset 選項,只用訓練集中的觀測來擬合一個線性回歸模型。
> lm.fit=lm(mpg~horsepower,data=Auto,subset=train)? ? ? ?現在用 predict ()函數來估計全部?392 個觀測的響應變量,再用 mean() 函數來計算驗證集中 196 個觀測的均方誤差。注意一下,下面的 -train 指標意味著只選取不在訓練集中的觀測。(說明:‘-’就是subset)
> attach(Auto) > mean((mpg-predict(lm.fit,Auto))[-train]^2) [1] 23.26601? ? ?從以上數據可以看出用線性回歸擬合模型所產生的測試的均方誤差估計為 23.26601。下面用 poly ()函數來估計用二次和三次多項式回歸所產生的測試誤差。
> lm.fit2=lm(mpg~poly(horsepower,2),data=Auto,subset=train)#poly函數估計二次 > mean((mpg-predict(lm.fit2,Auto))[-train]^2) [1] 18.71646 > lm.fit3=lm(mpg~poly(horsepower,3),data=Auto,subset=train)#和三次 > mean((mpg-predict(lm.fit3,Auto))[-train]^2) [1] 18.79401? ? ? ?這兩個錯誤率分別為 18.71646?和 18.79401。如果選擇了一個不同的訓練集的話,那就會在驗證集上 得到一個不同的誤差。
> set.seed(2) > train=sample(392,196) > lm.fit=lm(mpg~horsepower,subset=train) > mean((mpg-predict(lm.fit,Auto))[-train]^2) [1] 25.72651 > lm.fit2=lm(mpg~poly(horsepower,2),data=Auto,subset=train) > mean((mpg-predict(lm.fit2,Auto))[-train]^2) [1] 20.43036 > lm.fit3=lm(mpg~poly(horsepower,3),data=Auto,subset=train) > mean((mpg-predict(lm.fit3,Auto))[-train]^2) [1] 20.38533? ? ? ? 案例分析完畢,小伙伴們學到了沒有(*^_^*)
?
總結
以上是生活随笔為你收集整理的R语言第八讲 评估模型之交叉验证法分析案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux chmod修改权限失败,【L
- 下一篇: 朴素贝叶斯算法-分类算法