KNN——圖像分類


內容參考自:https://zhuanlan.zhihu.com/p/20894041?refer=intelligentunit

 

用像素點的rgb值來判斷圖片的分類准確率並不高,但是作為一個練習knn的題目,還是挺不錯的。

 

1. CIFAR-10

CIFAR-10是一個圖像分類數據集。數據集包含60000張32*32像素的小圖片,每張圖片都有一個類別標注(總共有10類),分成了50000張的訓練集和10000張的測試集。

然后下載后得到的並不是實實在在的圖片(不然60000張有點可怕...),而是序列化之后的,需要我們用代碼來打開來獲得圖片的rgb值。

1 import pickle
2 
3 def unpickle(file):
4    with open(file, 'rb') as f:
5    dict = pickle.load(f, encoding='latin1')
6    return dict 

由此得到的是一個字典,有data和labels兩個值。

data:

一個10000*3072的numpy數組,這個數組的每一行存儲了32*32大小的彩色圖像。前1024個數是red,然后分別是green,blue。

labels:
一個范圍在0-9的含有10000個數的一維數組。第i個數就是第i個圖像的類標。

 

2. 基於曼哈頓距離的1NN分類

這個訓練文件很大,如果全部讀的話會占據很多內存...第一次全部讀直接內存爆炸直接死機。所以這里我就讀了一個文件的內容。

 1 #! /usr/bin/dev python
 2 # coding=utf-8
 3 import os
 4 import sys
 5 import pickle
 6 import numpy as np
 7 
 8 def load_data(file):
 9     with open(file, 'rb') as f:
10         datadict = pickle.load(f, encoding='latin1')
11         X = datadict['data']
12         Y = datadict['labels']
13         X = X.reshape(10000, 3, 32, 32).transpose(0, 2, 3, 1).astype('float')
14         Y = np.array(Y)
15         return X, Y
16 
17 def load_all(root):
18     xs = []
19     ys = []
20     for n in range(1, 2):
21         f = os.path.join(root, 'data_batch_%d' %(n,))
22         X, Y = load_data(f)
23         xs.append(X)
24         ys.append(Y)
25     X_train = np.concatenate(xs)   #轉換為行向量 26     Y_train = np.concatenate(ys)
27     del X, Y
28     X_test, Y_test = load_data(os.path.join(root, 'test_batch'))
29     return X_train, Y_train, X_test, Y_test
30 
31 
32 def classTest(Xtr_rows, Xte_rows, Y_train):
33     count = 0
34     numTest = Xte_rows.shape[0]
35     result = np.zeros(numTest)   #構造一維向量的結果
36     for i in range(numTest):
37         distance = np.sum(np.abs(Xtr_rows - Xte_rows[i,:]), axis=1)
38         min_dis = np.argmin(distance)
39         result[i] = Y_train[min_dis]
40         print('%d:  %d' %(count, result[i]))
41         count += 1
42     return result
43 
44 if __name__ == '__main__':
45     X_train, Y_train, X_test, Y_test = load_all('D:\學習資料\機器學習\cifar-10-python\\')
46     Xtr_rows = X_train.reshape(X_train.shape[0], 32 * 32 * 3)
47     Xte_rows = X_test.reshape(X_test.shape[0], 32 * 32 * 3)
48     result = classTest(Xtr_rows, Xte_rows, Y_train)
49     print('accuracy: %f' % (np.mean(result == Y_test)))

 最后測試結果如下:(跑了很久...)

 

3. KNN

有了上面的基礎,接下來要實現最KNN就很簡單了,保存與測試數據最接近的k個數據,最后選出最多的即可。

 1 def classTest(Xtr_rows, Xte_rows, Y_train, k):
 2     count = 0
 3     numTest = Xte_rows.shape[0]
 4     result = np.zeros(numTest)   #構造一維向量的結果
 5     for i in range(numTest):
 6         classCount = {}
 7         distance = np.sum(np.abs(Xtr_rows - Xte_rows[i,:]), axis=1)
 8         distance = distance.argsort()
 9         for j in range(k):
10             votelabel = Y_train[distance[j]]
11             classCount[votelabel] = classCount.get(votelabel, 0) + 1
12             sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
13         result[i] = sortedClassCount[0][0]
14         print('%d:  %d' % (count, result[i]))
15         count += 1
16     return result

 

4. 驗證

對於如何確定一個最佳的k值,我們就需要去做驗證,需要注意的是測試集不能作為驗證集去驗證。一般來說就是將訓練數據分為兩部分,一部分作為驗證集去確定最佳的k值,最后再去用該k值去測試。

如果數據不是很多的話,那么就可以用交叉驗證來尋找最佳的k值,交叉驗證就是將數據分為多份,依次選一份作為驗證集,比如將訓練數據分為5分,然后進行5次訓練,每次將其中一份作為驗證集,另外四份作為訓練集。

 


免責聲明!

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



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