圖片分類-最近鄰分類(1)

作爲我們學習的第一個方法,我們會開發一個叫最近鄰分類器的東西。這個分類器與卷積神經網絡(CNN)沒有什麼關係並且在實際中很少用到。但是他會讓我們對圖片分類問題的基礎算法有一個初步的瞭解。
如圖,分類數據集爲:CIFAR-10。一個非常有趣的圖片分類數據集是CIFAR-10數據集。這個數據集包含60000個32*32像素的小圖片。每個圖片都被標記成十種類別中的一種(例如“airplane, automobile, bird, etc”)。這60000個圖片被分爲訓練集和測試集。訓練集有50000個圖片,測試集有10000個圖片。在如下的圖片中我們可以看到10個從十種類型中選取的隨機圖片樣本:
這裏寫圖片描述
左圖:從CIFAR-10數據集中獲取的樣本圖片。右圖:第一行展示了一些測試圖片並且他們最相近鄰的類型由於像素不同。
假如現在我們有50000個CIFAR-10數據集的訓練集(每個種類5000張圖片),並且我們希望編輯剩餘的10000張圖片。最近鄰算法就會拿一個測試圖片,然後讓他與訓練集中的每一張圖片對比。並且預測和他最相近的訓練集。在如上的圖片中右圖你可以看到一個樣本經過這樣處理後的結果。請注意,在10個示例中,只有3個示例中檢索了同一個類的圖像,而在其他7個示例中,情況並非如此。例如,在第八列中最近鄰馬頭的圖片是一個紅色的車,大概是因爲黑色背景吧。在這種情況下,這個馬的圖片將被歸在汽車類中。
你可能注意到了我們留了很多不明確的細節例如我們怎麼比較這兩個有32*32*3的圖片數據。最簡單的比較方式就是一個像素一個像素的疊加並且添加所有不同。其他方面,有兩個圖片並且表現他們的向量I1,I2,一個很合理的選擇就是比較他們的L1距離

這裏總和可以包含所有元素。以下是過程的可視化:
這裏寫圖片描述
一個兩個圖片像素比較轉化爲L1距離的比較(對於每一個顏色來說)。這兩個圖片用減法運算並且把所有的不同都相加到一個數上。如果兩個圖片是相等的那麼他們的結果會是0。但是如果不同他們的值會非常大。
讓我們來看看我們怎麼實現分類器的代碼。首先,我們把CIFAR-10數據以4個數組到內存中:訓練集/訓練標記和測試集/測試標記。在以下的代碼中,Xtr(大小:50000*32*32*3)把所有的圖片都保存着並且會有一個一維的數組Ytr分配(長度50000)保存訓練集(從0到9):

import pickle
import  NearestNeighbor as NN
import numpy as np
def unpickle(file):
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='bytes')
        #print (dict)
        X = dict[b'data']
        Y = dict[b'labels']
        Y = np.array(Y)
    return X,Y
def load_CIFAR10(dir):
    Xtr = []
    Ytr = []
    for i in range(1, 6):
        x, y = unpickle("%sdata_batch_%d" % (dir,i))
        Xtr.extend(x)
        Ytr.extend(y.tolist())
    Xtr = np.array(Xtr)
    Ytr = np.array(Ytr)
    Xte, Yte = unpickle("%stest_batch"%(dir))
    return Xtr, Ytr, Xte, Yte
if __name__ == '__main__':
    Xtr, Ytr, Xte, Yte = load_CIFAR10('data/')
    # flatten out all images to be one-dimensional
    Xtr_rows = Xtr.reshape(Xtr.shape[0], 32 * 32 * 3)  # Xtr_rows becomes 50000 x 3072
    Xte_rows = Xte.reshape(Xte.shape[0], 32 * 32 * 3)  # Xte_rows becomes 10000 x 3072

現在我們把全部圖片伸展成列,這裏是我們怎麼訓練和評估一個分類器:

nn = NearestNeighbor() # create a Nearest Neighbor classifier class
nn.train(Xtr_rows, Ytr) # train the classifier on the training images and labels
Yte_predict = nn.predict(Xte_rows) # predict labels on the test images
# and now print the classification accuracy, which is the average number
# of examples that are correctly predicted (i.e. label matches)
print 'accuracy: %f' % ( np.mean(Yte_predict == Yte) )

注意到作爲一個評價標準,用精確度(通過記錄錯誤的預測所佔比例)是很常見的。注意所有的飛雷奇我們都會創建成滿足這個通用API:他們有一個函數train(X,y)函數來學習數據和標記。本質上來說,這個類應該建立一些種類的標記模型並且提供他們如何從數據中預測。當然,我們遺忘了一些事情,例如真實的分類器。這裏有一個肩帶的基於L1距離的最近鄰算法分類器的代碼:

import numpy as np

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

  def train(self, X, y):
    """ X is N x D where each row is an example. Y is 1-dimension of size N """
    # the nearest neighbor classifier simply remembers all the training data
    self.Xtr = X
    self.ytr = y

  def predict(self, X):
    """ X is N x D where each row is an example we wish to predict label for """
    num_test = X.shape[0]
    # lets make sure that the output type matches the input type
    Ypred = np.zeros(num_test, dtype = self.ytr.dtype)

    # loop over all test rows
    for i in xrange(num_test):
      # find the nearest training image to the i'th test image
      # using the L1 distance (sum of absolute value differences)
      distances = np.sum(np.abs(self.Xtr - X[i,:]), axis = 1)
      min_index = np.argmin(distances) # get the index with smallest distance
      Ypred[i] = self.ytr[min_index] # predict the label of the nearest example

    return Ypred

如果你可以跑起來這個代碼,你會發現這個分類器在CIFAR-10上只有38.6%的準確度。這比隨機選取好的到了(隨機選取只有10%的準確度由於只有十類),但是離人類還差得遠(評估的有94%)或者通過狀態集藝術卷積神經網絡與95%的準確率(最近kaggle的leaderboard
距離選擇.
這裏有很多其他的計算兩個向量之間的距離函數。一個比較公認的就是L2距離。它在集合論中解釋維歐氏距離。距離函數爲

換一句話說,目前我們可以計算像素之間的差異,但是這次是以平方的方式,把他們加起來再求他們的平方根。再numpy中,用代碼可以表示如下:

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

注意:這裏我們用了np.sqrt函數,但是再實際中最近鄰函數我們會省略平方根操作,因爲它是一個單調函數。這樣的話,它只是計算了絕對距離並且保留了排序,所以有沒有用平方根都一樣。如果你用這個距離再數據集上跑可以獲得35.4%的準確率(略低於L1距離)。
L1 vs L2.
考慮兩種方法的對比還是很有趣。特別的,L2距離相比L1距離來說再計算兩個向量距離方面更加的斤斤計較。因此,L2距離再中等規模的分期上表現的比大規模上更好。L1和L2距離(L1/L2規則再比較圖片上有相同的效應)是最常用的p-norm特殊方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章