python 利用KNN分析商戶是否續約
之前寫過一個利用LR回歸做的二分類問題,是關於華南區商戶是否續約的問題,這次改用KNN正好也是想比較一下兩種方法和進行簡單的調參,使得對KNN能有更深入一些的了解。
原華南區商戶續約問題的鏈接在這,數據也可以從這裡進行獲取:python做logistic分類預測嘗試
當時做的總體預測正確率在73%左右,理論上來說二分類的問題是非常適合LR進行分類的,對於KNN有必要在鞏固一下基本原理和優缺點。
KNN全稱K-Nearest-Neighbor,給定一個訓練數據集(其中的類別已定),對新的輸入實例,在訓練數據集中找到與該實例最接近的k個實例,這k個實例的多數屬於某個類,就把該輸入實例分為這個類。
引用維基百科上的圖更為直觀,如果說綠色是一個新的實例:
當K取3時即參考離他最近的三個樣本分別是什麼,顯然是兩個三角,一個方塊,我們取多數的情況,則將綠色的圓圈判為是三角類,當K取5時,則會判為是方塊類。那顯然K的取值會影響到後續的分類的準確度,所以後續需要通過交叉驗證的方法來確定最佳的K值。另外一點是由於K近鄰法的距離是通過歐氏距離來進行計算的,所以自變數本身的大小會很影響最後的結果,具體可以參考這個網站中舉的男女身高與鞋子尺碼的量綱不同,會使得計算時會偏向於數值較大的特徵-------
一文搞懂k近鄰
基於這樣的認識,我們把原始數據在沒有標準化,和在標準化後分別使用KNN進行預測做一個對比,看看實際情況是否真的如此。
import pandas as pdnfrom sklearn import neighborsnfrom sklearn.model_selection import cross_val_scorenimport numpy as npndf=pd.read_csv(D:huanan.csv,encoding=utf-8)ndf.sample(10)nfeatures=[u註冊時長,u營業收入,u成本]nX=df[features]ny=df[續約]nknn=neighbors.KNeighborsClassifier(5,weights=uniform) #k取值為5,權重都一樣,也可以改為distance(即k個近鄰點的權重為距離的倒數)nscore=cross_val_score(knn,X,y,cv=5,scoring=accuracy)nprint(np.mean(score)) n
與上篇相同都是用的5折交叉驗證,這一次用KNN分類的結果顯示為0.6833,下一步嘗試進行調參,首先觀察到三個維度的數據,註冊時長,營業收入基本是一個量級的,但成本數值上明顯偏小一些,看是否可以通過歸一化解決。
關於歸一化常用的有兩種方法,一種是Max-Min方法,另一種是Z-score方法。
Max-Min方法:也叫離差標準化,是對原始數據的線性變換,使結果落到[0,1]區間,轉換函數如下:
其中max為樣本數據的最大值,min為樣本數據的最小值。
z-score方法:x?=(x?μ)/σ
其中μ為所有樣本數據的均值,σ為所有樣本數據的標準差。
我們分別進行嘗試,在python sklearn中有preprocessing包可供調用,z-score標準化:
from sklearn import preprocessingnnfeatures=preprocessing.scale(df[features])nX=nfeaturesn
array([[-0.43535216, -0.200308 , 0.26110203],
[ 2.2192342 , 0.75374495, 1.4693353 ], [ 0.20541006, -0.0547745 , -0.37275092],...,
[-0.70996455, -0.66924928, -0.68785148], [ 0.20541006, -0.24881917, 0.02073351], [-0.52688962, -0.53988617, -0.57307975]])這時候我們看到原本的註冊時長,營業收入和成本都進行了歸一化,這個時候仍然採用k=5的KNN方法和5折交叉驗證,結果仍然是0.6833。
我又嘗試了用0-1歸一化(即Min-Max方法):
from sklearn import preprocessingnmin_max_scaler = preprocessing.MinMaxScaler()nnfeatures=min_max_scaler.fit_transform(df[features])nX=nfeaturesn
這個時候仍然採用k=5的KNN方法和5折交叉驗證,結果是0.6933,略好於未作歸一化的情況,總體而言,這三個特徵的數據量級差的不是特別大,所以是否做歸一化影響並不是特別大,由於使用0-1歸一化效果較好,我們繼續探究取什麼樣的K值結果準確率最高,我們可以對k值進行迭代,來觀察輸出的結果:
import matplotlib.pyplot as pltn%matplotlib inline #這一句是因為我要在juypter notebook中畫圖需要使用naccuracy=[]nfor k in range(1,30):n knn=neighbors.KNeighborsClassifier(k,weights=uniform)n score=cross_val_score(knn,X,y,cv=5,scoring=accuracy)n accuracy.append(np.mean(score))nk=range(1,30)nplt.plot(k,accuracy)nplt.xlabel("Value of K for KNN")nplt.ylabel("Testing Accuracy")n
隨著K的變化,準確率變化如圖所示,所以取k=15應該是比較好的一個選擇,準確率可以達到74%,與LR的結果基本上相同。
推薦閱讀: