Cs231n-2017課程作業(assignment 1)之KNN
KNN算法理解:(百度百科)
KNN也即k-Nearest Neighbor,K(最)近鄰分類算法,即是給定一個訓練數據集,對新的輸入實例,在訓練數據集中找到與該實例最鄰近的K個實例(也即是K個鄰居,可根據一定的距離計算公式尋找鄰居,如曼哈頓距離,歐式距離等), 這K個實例的多數屬於某個類,就把該輸入實例分類到這個類中。
更形象的理解如下:圖中有兩個不同的類,分別是藍色的正方形所屬的一類和紅色的三角所屬的一類,我們的目的是預測出綠色的圓屬於他們中的那一類?
- 如果K=3,綠色圓點的最近的3個鄰居是2個紅色小三角形和1個藍色小正方形,少數從屬於多數,基於統計的方法,判定綠色的這個待分類點屬於紅色的三角形一類
- 如果K=5,綠色圓點的最近的5個鄰居是2個紅色三角形和3個藍色的正方形,還是少數從屬於多數,基於統計的方法,判定綠色的這個待分類點屬於藍色的正方形一類
於此我們看到,當無法判定當前待分類點是從屬於已知分類中的哪一類時,我們可以依據統計學的理論看它所處的位置特徵,衡量它周圍鄰居的權重,而把它歸爲(或分配)到權重更大的那一類。這就是K近鄰算法的核心思想。
KNN算法中,所選擇的鄰居都是已經正確分類的對象。該方法在定類決策上只依據最鄰近的一個或者幾個樣本的類別來決定待分樣本所屬的類別。KNN 算法本身簡單有效,它是一種 lazy-learning 算法,分類器不需要使用訓練集進行訓練,訓練時間複雜度爲0。KNN 分類的計算複雜度和訓練集中的文檔數目成正比,也就是說,如果訓練集中文檔總數爲 n,那麼 KNN 的分類時間複雜度爲O(n)。
參考:
作業代碼下載:https://github.com/Burton2000/CS231n-2017
參考理解博客:https://blog.csdn.net/u014485485/article/details/79433514
環境配置:
Window7 64位 + Jupyter notebook (通過anaconda安裝,python3.6)
數據下載:
下載CIFAR-10數據庫:http://www.cs.toronto.edu/~kriz/cifar.html,下載CIFAR-10 python version解壓到cs231n/datasets目錄下。
開始做作業:
點開 knn.ipynb對每一個cell,shift+enter運行。
首先是加載數據
可以看出訓練集含有50000張32*32的圖片,測試集含有10000張。
可視化數據集,cifar-10中共有10個分類,每一個類隨機選取7張圖片:
代碼內 函數分析:
numpy.flatnonzero(a):返回非0元素的索引,a可以是一個表達式
x.ravel()[np.flatnonzero(x)]可以使用它來提取非0元素
np.arange(-2, 3) # 從-2 開始,到3結束,不包含3的數組 [-2,-1,0,1,2]
numpy.random.choice(a, size=None, replace=True, p=None):對一維數組a產生一個隨機採樣。size指的是輸出形狀,replace表示放回還是不放回,p可代表a中樣本被採樣的概率情況,即自定義取樣概率。
爲了後面減少計算量,隨機採樣數據集,訓練集採樣5000張,測試集採樣500張,並將32*32*3的圖片reshape成一行:
函數解析:
numpy.reshape(a, newshape, order='C')
np.reshape(a, (a.shape[1], a.shape[0])):轉置等同於np.transpose(a)
當數據的形狀不確定時,如果想轉換爲1行,列數不確定的話,newshape可以傳入(1, -1);如果想轉換爲1列,行數不確定的話,newshape可以傳入(-1, 1);同理如果是2列或者2行的話,就是(-1, 2)或者(2,-1)。 -1代表不確定
導入k近鄰分類器模塊:
(A) 利用兩層循環計算L2距離:即
其中兩層循環是指從原始訓練集(50000)中分兩次抽取截取的訓練集數(5000)進行L2計算。
可視化距離矩陣:(本人沒看懂是什麼意思)
knn不需要訓練,直接進行預測,k=1:
Got 137 / 500 correct => accuracy: 0.274000
函數解析:argsort(a, axis=-1, kind='quicksort', order=None)排序,得到前k個近鄰的標籤,然後得到投票結果
numpy.bincount(x, weights=None, minlength=0)對一維數組x統計各值出現的次數,x裏必須是非負整數
numpy.argmax(a, axis=None, out=None)返回最大值
再令k=5預測:
Got 139 / 500 correct => accuracy: 0.278000 精度比k=1時稍高。
結果驗證,驗證結果爲:
(B)在一個loop中完成L2距離計算,並用F範數與兩個loop時的結果比較
驗證正確性:(用numpy數組運算的特性(broadcast),自動進行維數擴展),其中,F範數代表:
(C)不使用loop計算L2距離就是將距離函數拆開,完成各個單項後再合併
(x - y)^2 = x^2 - 2*x*y + y^2
比較三種方法的優劣,高下立現:
交叉驗證:
將訓練集分成5等分,同時觀察不同的k下的分類精度,執行5次kNN算法,將其中一份數據作爲驗證集,其他作爲測試集,取測試集的精度:
取平均精度,畫出k-精度圖:
可以看出,kNN的分類精度高也就30%,不實用。最佳k咱們取10:
Got 141 / 500 correct => accuracy: 0.282000 度28.2%.
總結:
KNN 即K-Nearest Neighbor在圖像分類中一半不做使用,引起效率低,而且是對像素級的計算,對於圖像來說計算量太大,效率慢,且對於對圖像做輕微的改變,比如部分像素塊遮蓋,圖像下移,背景渲染等做一小部分的改變可能不會改變L2的值,KNN的檢測結果則是相同的圖片。通過這個例子可以熟悉圖像分類的一般過程,訓練,測試;以及對數據集進行交叉驗證的方法,很值得學習。