天天看點

K-近鄰算法以及圖像分類應用

以下均為自己看視訊做的筆記,自用,侵删!

K最近鄰(k-Nearest Neighbor,KNN)分類算法,該方法的思路是:如果一個樣本在特征空間中的k個最相似(即特征空間中最鄰近)的樣本中的大多數屬于某一個類别,則該樣本也屬于這個類别。

K-近鄰算法以及圖像分類應用

K-近鄰算法步驟:

對于未知類别屬性資料集中的點:

  1. 計算已知類别資料集中的點與目前點的距離
  2. 按照距離依次排序
  3. 選取與目前點距離最小的K個點
  4. 确定前K個點所在類别的出現機率
  5. 傳回前K個點出現頻率最高的類别作為目前點預測分類。

概述:

  • KNN 算法本身簡單有效,它是一種 lazy-learning 算法。
  • 分類器不需要使用訓練集進行訓練,訓練時間複雜度為0。
  • KNN 分類的計算複雜度和訓練集中的文檔數目成正比,也就是說,如果訓練集中文檔總數為 n,那麼 KNN 的分類時間複雜度為O(n)。

K 值的選擇,距離度量和分類決策規則是該算法的三個基本要素。

問題 該算法在分類時有個主要的不足是,當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導緻當輸入一個新樣本時,該樣本的 K 個鄰居中大容量類的樣本占多數。

解決 不同的樣本給予不同權重項

K-近鄰算法以及圖像分類應用

如何計算:

K-近鄰算法以及圖像分類應用

結果 利用K-近鄰(距離為矩陣差異值累加和),不理想。

K-近鄰算法以及圖像分類應用

最近鄰代碼:

import numpy as np

class NearestNeighbor(object):
  def __init__(self):
    pass

  def train(self, X, y):
    #X是NXD的數組,其中每一行代表一個樣本,Y是N行的一維數組,對應X的标簽
    # 最近鄰分類器就是簡單的記住所有的資料
    self.Xtr = X
    self.ytr = y

  def predict(self, X):
    #X是NXD的數組,其中每一行代表一個圖檔樣本
    #看一下測試資料有多少行
    num_test = X.shape[0]
    # 确認輸出的結果類型符合輸入的類型
    Ypred = np.zeros(num_test, dtype = self.ytr.dtype)

    # 循環每一行,也就是每一個樣本
    for i in xrange(num_test):
      # 找到和第i個測試圖檔距離最近的訓練圖檔
      # 計算他們的L1距離
      distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
      min_index = np.argmin(distances) # 拿到最小那個距離的索引
      Ypred[i] = self.ytr[min_index] # 預測樣本的标簽,其實就是跟他最近的訓練資料樣本的标簽
    return Ypred
           

上一個是用L1:曼哈頓距離,絕對值裡兩個樣本相減, L2:計算歐氏距離

K-近鄰算法以及圖像分類應用

distances = np.sqrt(np.sum(np.square(self.Xtr - X[i,:]), axis = 1))

超參數的選取

問題:

1.對于距離如何設定?

2.對于K近鄰的K該如何選擇?

3.如果有的話,其它的超參數該怎麼設定呢?

K-近鄰算法以及圖像分類應用

測試集非常寶貴,隻能最終的時候才能使用(所有模型的參數都确定下來之後)。(不能每次訓練完之後,用測試集來調一下參數)

# 假設我們之前有 Xtr_rows, Ytr, Xte_rows, Yte 這幾份資料
#  Xtr_rows 是 50,000 x 3072 的矩陣
Xval_rows = Xtr_rows[:1000, :] # 抽取前1000張作為評估集
Yval = Ytr[:1000]
Xtr_rows = Xtr_rows[1000:, :] # 其餘的4900張作為訓練集
Ytr = Ytr[1000:]

# 找到在評估集上表現做好的超參數
validation_accuracies = []
for k in [1, 3, 5, 10, 20, 50, 100]:

  # 使用确定的k值作用在評估集上
  nn = NearestNeighbor()
  nn.train(Xtr_rows, Ytr)
  # 這裡假設我們有一個最近鄰的類,可以把k值作為輸入
  Yval_predict = nn.predict(Xval_rows, k = k)
  acc = np.mean(Yval_predict == Yval)
  print 'accuracy: %f' % (acc,)

  # 記錄在評估集上每個k對應的準确率
  validation_accuracies.append((k, acc))
           

交差驗證

K-近鄰算法以及圖像分類應用

(将訓練集再分成兩部分:一部分當作訓練集,另一部分當作驗證集,測試集最後用!),通過5次疊代的結果求平均,交差驗證可以消除一些偏高或偏低的結果。

不同交差驗證次數,得到的結果:

K-近鄰算法以及圖像分類應用

背景主導:

因為背景的作用,導緻圖像分類的不準确,是以我們不能用K-近鄰來完成圖像分類。因為不同的變化和原圖具有相同的L2距離。

使用K-近鄰:

  1. 選取超參數調優的正确方法是:将原始訓練集分為 訓練集和 驗證集 ,我們在驗證集上嘗試不同的超參數,最後保留表現最好那個。
  2. 如果訓練資料量不夠: 使用交叉驗證 交叉驗證方法,它能幫助我們在選取最優超參數的時候減少噪音。
  3. 一旦找到最優的超參數: 就讓算法以該參數在測試集跑且隻跑一次,并根據測試結果評價算法。
  4. 最近鄰分類器能夠在CIFAR-10上得到将近40%的準确率。該算法簡單易實作,但需要存儲所有訓練資料,并且在測試的時候過于耗費計算能力。
  5. 最後,我們知道了僅僅使用L1和L2範數來進行像素比較是不夠的,圖像更多的是按照背景和顔色被分類,而不是語義主體分身。

使用注意:

  1. 預處理你的資料:對你資料中的 特征進行歸一化(normalize),讓其具有 零平均值(zero mean)和 機關方差(unit variance)。
  2. 如果資料是高維資料,考慮使用降維方法,比如PCA。
  3. 将資料随機分入訓練集和驗證集。按照一般規律,70%-90% 資料作為訓練集。
  4. 在驗證集上調優,嘗試足夠多的k值,嘗試L1和L2兩種範數計算方式。

本文參考:https://www.cnblogs.com/douzujun/p/9035923.html