基於SVM和KNN的手寫數字的識別(分類)——小試牛刀篇
阿新 • • 發佈:2019-01-06
下面分別採用的是k近鄰演算法(KNN)和SVM實現的手寫數字識別。
python實現程式碼:
# -*- coding: utf-8 -*- import os import numpy as np def img2vector(filename, label): #影象資料轉為向量 f = open(filename,'r') row_data = f.read() row_data = row_data.replace('\n','') #換行符轉為空格 row_data = row_data + label row_data = np.array(map(int, list(row_data))) #將string轉為np.array return row_data #k緊鄰(KNN)分類演算法 def classify0(rowX, dataSet, k): ''' rowX是待分類的向量, dataSet是標記好的訓練集, k表示選擇最近鄰居的數目 ''' #距離計算:絕對值距離 dataSetSize = dataSet.shape[0] #print dataSetSize rowMat = np.zeros((dataSetSize, 1025), np.int) for i in range(dataSetSize): rowMat[i] = rowX diffMat = rowMat - dataSet label0 = dataSet[:,1024] #取出訓練集label diffMat2 = diffMat[:,0:1024] #差分矩陣去除label列 diffMat3 = diffMat2**2 #差分矩陣的平方,即是絕對值 dis = diffMat3.sum(axis = 1) #沿行求和,即是該待分類向量與訓練集中每條資料的距離 #選擇距離最小的k個點 sortedIndice = dis.argsort() #print sortedIndice vote_label = np.zeros((1,10), np.int) for i in range(k): label= label0[sortedIndice[i]] #獲取第i小距離的label vote_label[0,label] = vote_label[0,label] + 1 sorted_vote = vote_label.argsort() #print sorted_vote return sorted_vote[0,9] #將訓練集資料儲存到np陣列train_data中 train_dir = 'trainingDigits\\' train_filename = os.listdir(train_dir) #獲取trainingDigits目錄下的檔名 m = len(train_filename) train_data = np.zeros((m,1025), np.int) for i in range(0, m): label = train_filename[i].split('_')[0] row = img2vector(train_dir + train_filename[i], label) train_data[i] = row #將測試集資料儲存到np陣列test_data中 test_dir = 'testDigits\\' test_filename = os.listdir(test_dir) #獲取trainingDigits目錄下的檔名 m = len(test_filename) test_data = np.zeros((m,1025), np.int) test_result = np.zeros((m,1),np.int) for i in range(0, m): label = test_filename[i].split('_')[0] test_result[i] = int(label) #儲存測試集正確的分類 row = img2vector(test_dir + test_filename[i], '0') #測試集初始分類設定為0 test_data[i] = row cc = 0 for i in range(m): ll = classify0(test_data[i], train_data, 5) #print ll,test_result[i] if ll == test_result[i]: cc = cc + 1 else: print i,ll,test_result[i] print '正確率是:%f' %(float(cc)/float(m))
執行結果如下圖:
輸出的每一行表示分類錯誤的資料,每一行的第1列是測試集的id,第2列是KNN演算法分類的結果,第三列是正確的分類結果。
svm實現手寫字型分類,程式碼如下:
執行結果:# -*- coding: utf-8 -*- import os from sklearn import svm def img2vector(filename): #影象資料轉為list f = open(filename,'r') row_data = f.read() row_data = row_data.replace('\n','') #換行符轉為空格 row_data = list(row_data) for i in range(len(row_data)): row_data[i] = int(row_data[i]) return row_data train_dir = 'trainingDigits\\' train_filename = os.listdir(train_dir) #獲取trainingDigits目錄下的檔名 m = len(train_filename) X = [] Y = [] for i in range(0, m): label = train_filename[i].split('_')[0] Y.append(int(label)) row = img2vector(train_dir + train_filename[i]) X.append( row ) clf = svm.SVC(decision_function_shape='ovo') clf.fit(X, Y) test_dir = 'testDigits\\' test_filename = os.listdir(test_dir) #獲取trainingDigits目錄下的檔名 m = len(test_filename) X_test = [] Y_test = [] for i in range(0, m): label = test_filename[i].split('_')[0] Y_test.append(int(label)) #儲存測試集正確的分類 row = img2vector(test_dir + test_filename[i]) X_test.append(row) ans = clf.predict(X_test) cc = 0 ll = len(ans) for i in range(ll): if Y_test[i] == ans[i]: cc +=1 else: print "分錯的檔案為%s,被分類為%d" %(test_filename[i],ans[i]) print '正確率是:%f' % (1.0*cc/ll)
參考資料:
1、機器學習實戰
2、http://scikit-learn.org/stable/modules/svm.html#svm