通過交叉驗證尋找K近鄰算法的最優K值

問題引出

之前我們使用K近鄰算法嘗試尋找用戶年齡與預估薪資之間的某種相關性,以及他們是否有購買SUV的決定。主要代碼如下:

通過交叉驗證尋找K近鄰算法的最優K值

在有一個問題,上面的n_neighbors(k值)為什麼是5,其他值可不可以?效果會怎麼樣?如何知道哪個k值的效果相對較好?這就需要用到交叉驗證。

交叉驗證有什麼用,為什麼要用它?

關於它有什麼用,經過瀏覽相關網頁獲得了以下兩點總結:

  • 在數據集很小的時候防止過擬合。
  • 找到合適的模型參數。

看到這裡,不知道你對為什麼要用交叉驗證有沒有明白一點點,說白了就是我們手頭上的數據量太小,直接對數據量小的數據集進行訓練集和測試集的劃分,最後的效果即使很好,也不能確定後面部署上線的結果會一樣好,因為模型效果表現僅僅侷限於我們那少得可憐的數據集上。

假如我們有很多很多的數據,不要問多少,反正就是很多的那種,我個人覺得我們可以直接暴力的通過下面方式來找到KNN的最優k值:

通過交叉驗證尋找K近鄰算法的最優K值

通過交叉驗證尋找K近鄰算法的最優K值

這樣,在我們有大量數據前提下,我們就可以大致確定哪個k值最優了,或者直接做深度學習。

但是,現實中,我們往往很難收集到大量的數據,這種情況下,我們只好從我們那少得可憐的數據集下手了,也就是說,我們要在數據量少的情況下,儘量通過交叉驗證來找到一組好的模型參數,讓其在看到未知參數的情況也一樣好,這樣也就防止了模型訓練的效果好,看到未知數據不好的過擬合情況。

如何交叉驗證?

簡單來說就是對數據集進行重新劃分,不再像之前那樣只是簡單將數據集劃分訓練集和測試集。關於如何重新劃分數據集,網上主要有兩種方式。

1、先將數據集劃分為訓練集和測試集,再對訓練集劃分為子訓練集和子測試集,如下圖:

通過交叉驗證尋找K近鄰算法的最優K值


2、直接將數據集劃分如下所示:

通過交叉驗證尋找K近鄰算法的最優K值

關於上面的兩個方法,看到網絡上絕大多數都是第一種方式,我是這麼認為的,既然交叉驗證只是用來找到合適的模型參數,到最後我們要驗證找的合適的模型參數是否合適,那麼我們還是需要通過給模型看看它沒有看過的數據來驗證,所以我也支持第一種方法。

還有一點要說明的是,從上面的圖中可以看出,交叉驗證的時候同時訓練十個模型(訓練集和測試集都不一樣),然後將結果取求和平均。到這裡我又有一個疑惑,為什麼是10個,不是5個,接著我又瀏覽一些網站,發現一點:大家普遍用5個或者是10個。我後面會選5個的。不要問為什麼,因為如果我用10個你也會問我同意的問題。

動手擼代碼

又到開心又快樂的擼代碼(我信你鬼)環節,對了,上面和接下來要做的都是基於sklearn的K近鄰算法做的。為了更加深刻了解機器學習的敲代碼步驟,下面將盡量從頭開始做起。

案例描述

一家汽車公司剛剛推出了他們新型的豪華SUV,我們嘗試預測哪些用戶會購買這種全新SUV。數據集是從某社交網絡中收集的用戶信息。這些信息涉及用戶ID、性別、年齡以及預估薪資,最後一列用來表示用戶是否購買。我們將建立一種模型來預測用戶是否購買這種SUV,該模型基於兩個變量,分別是年齡和預計薪資。我們嘗試尋找用戶年齡與預估薪資之間的某種相關性,以及他們是否有購買SUV的決定。

通過交叉驗證尋找K近鄰算法的最優K值

導入常用相關庫

通過交叉驗證尋找K近鄰算法的最優K值

導入數據集

通過交叉驗證尋找K近鄰算法的最優K值

將數據集劃分成為訓練集和測試集

通過交叉驗證尋找K近鄰算法的最優K值

數據標準化

通過交叉驗證尋找K近鄰算法的最優K值

運用訓練集來做交叉驗證,從而找到最優k值

我們因為要同時觀察訓練集的子訓練集和測試集效果隨著k的增加而變化情況,所以這裡直接用 sklearn.model_selection 中的 vlidation_curve 來完成。

通過交叉驗證尋找K近鄰算法的最優K值


通過交叉驗證尋找K近鄰算法的最優K值

通過交叉驗證尋找K近鄰算法的最優K值


通過交叉驗證尋找K近鄰算法的最優K值


從上圖我們可以看到最優的k值在7。

用找到的k值做模型訓練

通過交叉驗證尋找K近鄰算法的最優K值

用測試集測試結果

通過交叉驗證尋找K近鄰算法的最優K值


到這裡就結束了。最後要記住交叉驗證不是用來提高模型準確率的,而是用來找到合適的模型參數,在數據集很小的時候防止過擬合。


分享到:


相關文章: