機器學習:k-NN算法(也叫k近鄰算法)


一、kNN算法基礎

# kNN:k-Nearest Neighboors

# 多用於解決分類問題

 1)特點:

  1. 是機器學習中唯一一個不需要訓練過程的算法,可以別認為是沒有模型的算法,也可以認為訓練數據集就是模型本身;
  2. 思想極度簡單;
  3. 應用數學知識少(近乎為零);
  4. 效果少;
  5. 可以解釋機械學習算法使用過程中的很多細節問題
  6. 更完整的刻畫機械學習應用的流程;

 2)思想:

  • 根本思想:兩個樣本,如果它們的特征足夠相似,它們就有更高的概率屬於同一個類別;
  • 問題:根據現有訓練數據集,判斷新的樣本屬於哪種類型
  • 方法/思路
  1. 求新樣本點在樣本空間內與所有訓練樣本的歐拉距離;
  2. 對歐拉距離排序,找出最近的k個點;
  3. 對k個點分類統計,看哪種類型的點數量最多,此類型即為對新樣本的預測類型;

 3)代碼實現過程:

  • 示例代碼:
    import numpy as np
    import matplotlib.pyplot as plt
    
    raw_data_x = [[3.3935, 2.3312],
                  [3.1101, 1.7815],
                  [1.3438, 3.3684],
                  [3.5823, 4.6792],
                  [2.2804, 2.8670],
                  [7.4234, 4.6965],
                  [5.7451, 3.5340],
                  [9.1722, 2.5111],
                  [7.7928, 3.4241],
                  [7.9398, 0.7916]]
    raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
    
    # 訓練集樣本的data
    x_train = np.array(raw_data_x)
    # 訓練集樣本的label
    y_train = np.array(raw_data_y)
    
    # 1)繪制訓練集樣本與新樣本的散點圖
    # 根據樣本類型(0、1兩種類型),繪制所有樣本的各特征點
    plt.scatter(x_train[y_train == 0, 0], x_train[y_train == 0, 1], color = 'g')
    plt.scatter(x_train[y_train == 1, 0], x_train[y_train == 1, 1], color = 'r')
    # 新樣本
    x = np.array([8.0936, 3.3657])
    # 將新樣本的特征點繪制在訓練集的樣本空間
    plt.scatter(x[0], x[1], color = 'b')
    plt.show()
    
    
    # 2)在特征空間中,計算訓練集樣本中的所有點與新樣本的點的歐拉距離
    from math import sqrt
    # math模塊下的sqrt函數:對數值開平方sqrt(number)
    distances = []
    for x_train in x_train:
        d = sqrt(np.sum((x - x_train) ** 2))
        distances.append(d)
    
    # 也可以用list的生成表達式實現:
    # distances = [sqrt(np.sum((x - x_train) ** 2)) for x_train in x_train]
    
    
    # 3)找出距離新樣本最近的k個點,並得到對新樣本的預測類型
    nearest = np.argsort(distances)
    k = 6
    # 找出距離最近的k個點的類型
    topK_y = [y_train[i] for i in nearest[:k]]
    
    # 根據類別對k個點的數量進行統計
    from collections import Counter
    votes = Counter(topK_y)
    
    # 獲取所需的預測類型:predict_y
    predict_y = votes.most_common(1)[0][0]

 

  • 封裝好的Python代碼
    import numpy as np
    from math import sqrt
    from collections import Counter
    
    def kNN_classify(k, X_train, y_train, x):
    
        assert 1 <= k <= X_train.shape[0],"k must be valid"
        assert X_train.shape[0] == y_train.shape[0], \
            "the size of X_train nust equal to the size of y_train"
        assert X-train.shape[1] == x.shape[0],\
            "the feature number of x must be equal to X_train"
    
        distances = [sprt(np.sum((x_train - x) ** 2)) for x_train in X_train]
        nearest = np.argsort(distances)
        topK_y = [y_train[i] for i in nearest[:k]]
        vates = Counter(topK_y)
        return votes.most_common(1)[0][0]

    # assert:表示聲明;此處對4個參數進行限定;

  • 代碼中的其它Python知識:
  1. math模塊下的sprt()方法:對數開平方;

    from math import sqrt
    print(sprt(9))
    # 3
  2. collections模塊下的Counter()方法:對列表中的數據進行分類統計,生產一個Counter對象;
    from collections import Counter
    
    my_list = [0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3]
    print(Counter(my_list))
    # 一個Counter對象:Counter({0: 2, 1: 3, 2: 4, 3: 5})
  3. Counter對象的most_common()方法:Counter.most_common(n),返回Counter對象中數量最多的n種數據,返回一個list,list的每個元素為一個tuple;
    from collections import Counter
    
    my_list = [0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3]
    votes = Counter(my_list)
    print(votes.most_common(2))
    # [(3, 5), (2, 4)]

 

二、總結

 1)k近鄰算法的作用

  1、解決分類問題,而且天然可以解決多分類問題;

  2、也可以解決回歸問題,其中scikit-learn庫中封裝的KNeighborsRegressor,就是解決回歸問題;

 2)缺點

  • 缺點1:效率低下
  1. 原因:如果訓練集有m個樣本,n個特征,預測每一個新樣本,需要計算與m個樣本的距離,每計算一個距離,要使用n個時間復雜度,則計算m個樣本的距離,使用m * n個時間復雜度;
  2. 算法的時間復雜度:反映了程序執行時間隨輸入規模增長而增長的量級,在很大程度上能很好反映出算法的優劣與否。
  3. 算法的時間復雜度與空間復雜度,參考:算法的時間復雜度和空間復雜度
  4. 可以通過樹結構對k近鄰算法優化:KD-Tree、Ball-Tree,但即便進行優化,效率依然不高;

 

  • 缺點2:高度數據相關
  1. 機器學習算法,就是通過喂給數據進行預測,理論上所有機器學習算法都是高度數據相關;
  2. k近鄰算法對outlier更加敏感:比如三近鄰算法,在特征空間中,如果在需要預測的樣本周邊,一旦有兩個樣本出現錯誤值,就足以使預測結果錯誤,哪怕在更高的范圍里,在特征空間中有大量正確的樣本;

 

  • 缺點3:預測的結果不具有可解釋性
  1. 按k近鄰算法的邏輯:找到和預測樣本比較近的樣本,就得出預測樣本和其最近的這個樣本類型相同;
  2. 問題:為什么預測的樣本類型就是離它最近的樣本的類型?
  3. 很多情況下,只是拿到預測結果是不夠的,還需要對此結果有解釋性,進而通過解釋推廣使用,或者制作更多工具,或者以此為基礎發現新的理論/規則,來改進生產活動中的其它方面——這些是kNN算法做不到的;

 

  • 缺點4:維數災難
  1. 維數災難:隨着維度的增加,“看似相近”的兩個點之間的距離越來越大;
  2. 例:[0, 0, 0, ...0]和[1, 1, 1,...1],按歐拉定理計算,元素個數越多,兩點距離越大;
  3. 方案:降維(PCA);

 

三、使用機器學習算法的流程

  • 獲取原始數據——數據分割——數據歸一化——訓練模型——預測
  1. 獲取原始數據:一般可從scikit-learn庫中調用——# 調用數據集的操作流程  機器學習:scikit-learn中算法的調用、封裝並使用自己所寫的算法
  2. 數據分割:一般按2 :8進行分割——# 分割數據的代碼實現過程、通過scikit-learn庫分割數據的操作流程  機器學習:訓練數據集、測試數據集
  3. 數據歸一化:參見  機器學習:數據歸一化(Scaler)
  4. 訓練模型、模型預測:  機器學習:scikit-learn中算法的調用、封裝並使用自己所寫的算法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM