使用KNN对MNIST数据集进行实验
之前使用SVM對MNIST數據集進行了分類實驗,得到了98.46%的分類正確率(見:使用libsvm對MNIST數據集進行實驗)。
今天用python寫了個小程序,來測試一下KNN的分類效果。
由于KNN的計算量太大,還沒有使用KD-tree進行優化,所以對于60000訓練集,10000測試集的數據計算比較慢。這里只是想測試觀察一下KNN的效果而已,不調參。
K選擇之前看過貌似最好不要超過20,因此,此處選擇了K=10,距離為歐式距離。如果需要改進,可以再調整K來選擇最好的成績。
先跑了一遍不經過scale的,也就是直接使用像素灰度值來計算歐式距離進行比較。發現開始基本穩定在95%的正確率上,嚇了一跳。因為本來覺得KNN算是沒有怎么“學習”的機器學習算法了,猜測它的特點可能會是在任何情況下都可以用,但都表現的不是最好。所以估計在60%~80%都可以接受。沒想到能基本穩定在95%上,確定算法和代碼沒什么問題后,突然覺得是不是這個數據集比較沒挑戰性。。。
去MNIST官網(http://yann.lecun.com/exdb/mnist/),上面掛了以該數據集為數據的算法的結果比較。查看了一下KNN,發現有好多,而且錯誤率基本都在5%以內,甚至能做到1%以內。唔。
跑的結果是,正確率:96.687%。也就是說,錯誤率error rate為3.31%左右。
再跑一下經過scale的數據,即對灰度數據歸一化到[0,1]范圍內。看看效果是否有所提升。
經過scale,最終跑的結果是,正確率:竟然也是96.687%! 也就是說,對于該數據集下,對KNN的數據是否進行歸一化并無效果!
在跑scale之前,個人猜測:由于一般對數據進行處理之前都進行歸一化,防止高維詛咒(在784維空間中很容易受到高維詛咒)。因此,預測scale后會比前者要好一些的。但是,現在看來二者結果相同。也就是說,對于K=10的KNN算法中,對MNIST的預測一樣的。
對scale前后的正確率相同的猜測:由于在訓練集合中有60000個數據點,因此0-9每個分類平均都有6000個數據點,在這樣的情況下,對于測試數據集中的數據點,相臨近的10個點中大部分都是其他分類而導致分類錯誤的概率會比較地(畢竟10相對與6000來說很小),所以,此時,KNN不僅可以取得較好的分類效果,而且對于是否scale并不敏感,效果相同。
代碼如下:
#KNN for MNIST from numpy import * import operatordef line2Mat(line):line = line.strip().split(' ')label = line[0]mat = []for pixel in line[1:]:pixel = pixel.split(':')[1]mat.append(float(pixel))return mat, label#matrix should be type: array. Or classify() will get error. def file2Mat(fileName):f = open(fileName)lines = f.readlines()matrix = []labels = []for line in lines:mat, label = line2Mat(line)matrix.append(mat)labels.append(label)print 'Read file '+str(fileName) + ' to matrix done!'return array(matrix), labels#classify mat with trained data: matrix and labels. With KNN's K set. def classify(mat, matrix, labels, k):diffMat = tile(mat, (shape(matrix)[0], 1)) - matrix#diffMat = array(diffMat)sqDiffMat = diffMat ** 2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances ** 0.5sortedDistanceIndex = distances.argsort()classCount = {}for i in range(k):voteLabel = labels[sortedDistanceIndex[i]]classCount[voteLabel] = classCount.get(voteLabel,0) + 1sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1),reverse=True)return sortedClassCount[0][0]def classifyFiles(trainMatrix, trainLabels, testMatrix, testLabels, K):rightCnt = 0for i in range(len(testMatrix)):if i % 100 == 0:print 'num '+str(i)+'. ratio: '+ str(float(rightCnt)/(i+1))label = testLabels[i]predictLabel = classify(testMatrix[i], trainMatrix, trainLabels, K)if label == predictLabel:rightCnt += 1return float(rightCnt)/len(testMatrix)trainFile = 'train_60k.txt' testFile = 'test_10k.txt' trainMatrix, trainLabels = file2Mat(trainFile) testMatrix, testLabels = file2Mat(testFile) K = 10 rightRatio = classifyFiles(trainMatrix, trainLabels, testMatrix, testLabels, K) print 'classify right ratio:' +str(right)總結
以上是生活随笔為你收集整理的使用KNN对MNIST数据集进行实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 'takes exactl
- 下一篇: 使用Decision Tree对MNIS