1. 程式人生 > 其它 >常見機器學習方法的優缺點及適用場景:K近鄰(KNN)

常見機器學習方法的優缺點及適用場景:K近鄰(KNN)

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()

輸出結果: