常見機器學習方法的優缺點及適用場景:K近鄰(KNN)
阿新 • • 發佈:2022-04-18
K近鄰(KNN)
1. KNN建立過程:
a. 給定測試樣本,計算它與訓練集中的每個樣本的距離;
b. 找到距離最近的K個訓練樣本,作為測試樣本的K近鄰;
c. 根據K近鄰歸屬的類別來確定該測試樣本的類別(少數服從多數)。
2. 類別的判定
a. 投票決定,少數服從多數,取樣本數最對的類別最為測試樣本的類別
b. 加權投票法:依據計算得出距離的函式作為權重,對不同近鄰的投票進行加權;一般函式取距離平方的倒數
3. 應用:即能做分類又能做迴歸, 還能用來做資料預處理的缺失值填充
4. 原理:
分類問題進行表決投票;
迴歸問題使用加權平均或者直接平均的方法。
knn演算法中我們最需要關注兩個問題:k值的選擇和距離的計算。 kNN中的k是一個超引數,需要我們進行指定,一般情況下這個k和資料有很大關係,都是交叉驗證進行選擇,但是建議使用交叉驗證的時候,k∈[2,20],使用交叉驗證得到一個很好的k值。
k值還可以表示我們的模型複雜度,當k值越小意味著模型複雜度變大,更容易過擬合,(用極少數的樣例來絕對這個預測的結果,很容易產生偏見,這就是過擬合)。我們有這樣一句話,k值越大學習的估計誤差越小,但是學習的近似誤差就會增大。
近似誤差:可以理解為對現有訓練集的訓練誤差,太小更容易過擬合。
估計誤差:可以理解為對測試集的測試誤差。
5. 實戰(sklearn)
馬絞痛資料--kNN資料預處理+kNN分類pipeline
# ipython下載 # 下載需要用到的資料集 !wget https://tianchi-media.oss-cn-beijing.aliyuncs.com/DSW/3K/horse-colic.csv # 下載資料集介紹 !wget https://tianchi-media.oss-cn-beijing.aliyuncs.com/DSW/3K/horse-colic.names
"step1:庫匯入" import numpy as np import pandas as pd # KNN分類器 from sklearn.neighbors import KNeighborsClassifier # 用kNN對資料空值填充 from sklearn.impute import KNNImputer # 計算帶有空值的歐式距離 from sklearn.metrics.pairwise import nan_euclidean_distances # 交叉驗證 from sklearn.model_selection import cross_val_score # kFlod的函式 from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.pipeline import Pipeline import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split "step2:資料匯入&分析" # 資料中有”?“值,沒辦法分析,需要先使用KNNImputer進行空值填充 "Step4: KNNImputer空值填充--歐式距離的計算" # load dataset, 將?變成空值 input_file = './horse-colic.csv' df_data = pd.read_csv(input_file, header=None, na_values='?') # 得到訓練資料和label, 第23列表示是否發生病變, 1: 表示Yes; 2: 表示No. data = df_data.values ix = [i for i in range(data.shape[1]) if i != 23] X, y = data[:,ix], data[:,23] # numpy可以用列表當切片 # 檢視所有特徵的缺失值個數和缺失率 for i in range(df_data.shape[1]): n_miss = df_data[[i]].isnull().sum() # df_data[[i]]:表示pd中完整一列 perc = n_miss / df_data.shape[0] * 100 if n_miss.values[0] > 0: print('>Feat: %d, Missing: %d, Missing ratio: (%.2f%%)' % (i, n_miss, perc)) # 檢視總的空值個數 print('KNNImputer before Missing: %d' % sum(np.isnan(X).flatten())) # 定義 knnimputer imputer = KNNImputer() # 填充資料集中的空值 imputer.fit(X) # 轉換資料集 Xtrans = imputer.transform(X) # 列印轉化後的資料集的空值 print('KNNImputer after Missing: %d' % sum(np.isnan(Xtrans).flatten()))
輸出結果:
"step5: 基於pipeline模型訓練&視覺化" "K折交叉驗證的選擇" # 什麼是Pipeline, 我這裡直接翻譯成資料管道。任何有序的操作有可以看做pipeline results = list() strategies = [str(i) for i in [1,2,3,4,5,6,7,8,9,10,15,16,18,20,21]] for s in strategies: # create the modeling pipeline pipe = Pipeline(steps=[('imputer', KNNImputer(n_neighbors=int(s))), ('model', KNeighborsClassifier())]) # 資料多次隨機劃分取平均得分 scores = [] for k in range(20): # 得到訓練集合和驗證集合, 8: 2 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) pipe.fit(X_train, y_train) # 驗證model score = pipe.score(X_test, y_test) scores.append(score) # 保持result results.append(np.array(scores)) print('>k: %s, Acc Mean: %.3f, Std: %.3f' % (s, np.mean(scores), np.std(scores))) # print(results) # plot model performance for comparison plt.boxplot(results, labels=strategies, showmeans=True) plt.show()
輸出結果: