"""
(2) 準備資料:編寫函式classify0,將影象格式轉換為分類器使用的list格式
(3) 分析資料:在python命令提示符中檢查資料,確保它符合要求
(4) 訓練演算法:此步驟不適合用於k-近鄰演算法
(5) 測試演算法:編寫函式使用提供的部分資料集作為測試樣本,測試樣本與非測試樣本的
區別在於測試眼gv恩是已經完成分類的資料,如果**分類與實際類別不同則標記為乙個錯誤
(6) 使用演算法:本例沒有完成此步驟,若你感興趣可以構建完整的應用程式,從影象中提取數字
完成數字識別,美國的郵件分揀系統就是乙個實際執行的類似系統
"""from numpy import *
import os
import operator
def classify0(inx, dataset, labels, k):
"""共有四個輸入引數:用於分類的輸入向量是inx,輸入的訓練樣本集為dataset
標籤向量為labels, 最後的引數k表示用於選擇最鄰近的數目,其中標籤向量的元素數目和
矩陣dataset的行數相同。計算的距離為歐氏距離
:param inx:
:param dataset:
:param labels:
:param k:
:return:
"""# 計算歐氏距離
datasetsize = dataset.shape[0] # dataset.shape[0]輸出的是資料集的行數,shape[1]輸出的是資料集的列數
diffmat = tile(inx, (datasetsize, 1)) - dataset # tile函式共有兩個引數,tile(a, reps), a指待輸入陣列,reps決定a重複的次數,整個函式用於重複陣列a來構建新的陣列
sqdiffmat = diffmat ** 2 # 計算歐氏距離
sqdistances = sqdiffmat.sum(axis=1) # 按行求和,
distance = sqdistances ** 0.5 # 開根號,結果為該未知資料集到每乙個已知資料集的歐氏距離
# 選擇距離最小的k個點
sorteddistindicies = distance.argsort() # argsort()方法返回陣列值從小到大的索引
classcount = {}
for i in range(k):
voteilabel = labels[sorteddistindicies[i]] # 獲取所屬類別
classcount[voteilabel] = classcount.get(voteilabel, 0) + 1 # get方法返回指定鍵的值,如果不存在則返回預設值(0:設定預設值為0)
sortedclasscount = sorted(classcount.items(), key=operator.itemgetter(1), reverse=true) # items()返回字典列表操作後的迭代 sorted(可迭代物件, 自定義的比較函式, 順序預設為fslse,正序)
return sortedclasscount[0][0]
def img2vector(filename):
"""將影象格式化處理為乙個向量,我們將把乙個32* 32的二進位制影象矩陣轉換為乙個1*1024的向量
這兩前兩節使用的分類器就可以處理數字影象資訊了
該函式主要功能是將影象轉換為向量,哈數建立乙個1*1024的numpy陣列,然後開啟給定的檔案,迴圈
讀出檔案的前32行,並將每行的頭32個字元儲存z在numpy陣列中,最後返回乙個二維陣列陣列
:param filename:
:return: returnvect
"""returnvect = zeros((1, 1024)) # 返回乙個一行1024列的全0陣列
fr = open(filename) # 開啟檔案
for i in range(32):
linestr = fr.readline()
for j in range(32):
returnvect[0, 32*i+j] = int(linestr[j]) # 1*1024陣列
return returnvect
def handwritingclasstest():
"""將資料輸入到分類器,檢測分類器的執行效果,該函式是測試分類器的**
主要功能是從os模組中匯入函式listdir,它可以列出給定目錄的檔名
:return:
"""hwlabels =
# 獲取目錄內容以及目錄的長度 訓練集
trainingfilelist = os.listdir("data/trainingdigits") # 指定目錄中的檔名列表
# print(trainingfilelist)
m = len(trainingfilelist) # 返回列表的長度
trainingmat = zeros((m, 1024)) # 建立乙個m行,1024列的矩陣
for i in range(m):
# 從檔名解析分類數字
filenamestr = trainingfilelist[i] # 取出每乙個檔案的檔名
filestr = filenamestr.split(".")[0] # 切分檔名和字尾,去掉字尾
classnumstr = int(filestr.split("_")[0]) # 切分檔名前的數字
# print(hwlabels)
trainingmat[i, :] = img2vector("data/trainingdigits/%s" % filenamestr) # 二維陣列
# 測試集
testfilelist = os.listdir("data/testdigits")
errorcount = 0.0
mtest = len(testfilelist)
for i in range(mtest):
filenamestr = testfilelist[i]
filestr = filenamestr.split(".")[0]
classnumstr = int(filestr.split("_")[0])
vectorundertest = img2vector("data/testdigits/%s" % filenamestr)
classifierresult = classify0(vectorundertest, trainingmat, hwlabels, 3)
print("the classifier came back with: %d, the real answer is: %d" % (classifierresult, classnumstr))
if(classifierresult != classnumstr):
errorcount += 1.0
print("the total number of errors is : %d" % errorcount)
print("the total error rate is :%f" %(errorcount/float(mtest)))
if __name__ == '__main__':
filename = "data/testdigits/0_13.txt"
returnvect = img2vector(filename)
handwritingclasstest()
# print(returnvect[0, 32:1023])
手寫識別系統(k 近鄰演算法)
k 近鄰演算法 knn 是機器學習中乙個相對比較簡單的演算法。該演算法在訓練集中資料和標籤已知的情況下,輸入測試資料,將測試資料的特徵與訓練集中對應的特徵進行相互比較 比如通過歐氏距離 找到訓練集中與之最為相似的前k個資料,則該測試資料對應的類別就是k個資料中出現次數最多的那個分類,其演算法的描述為...
k 近鄰演算法 手寫識別系統
手寫數字是32x32的黑白影象。為了能使用knn分類器,我們需要把32x32的二進位制影象轉換為1x1024 from numpy import 匯入科學計算包numpy和運算子模組operator import operator from os import listdir def img2vec...
機器學習 使用k 近鄰演算法實現手寫識別系統
knn概述 k 近鄰演算法就是通過計算不同特徵值之間的距離來進行分類的演算法。假設我們現在有乙個樣本集,每個樣本都有幾個特徵用來描述這個樣本,以及乙個它所屬分類的標籤。當我們拿到乙個沒有標籤的樣本時,該如何判斷它屬於哪個樣本呢?我們將這個樣本與每乙個已知標籤的樣本做比較,找到相似度最大的k個樣本,記...