1.1 簡介
knn演算法即k最近鄰分類演算法,是機器學習的一種。從訓練樣本集中選取k個與測試樣本「距離」最近的樣本,這k個樣本中出現頻率最高的類別作為該測試樣本的類別。
1.2 要求
目標:分類未知類別的案例。
輸入:待分類未知類別案例專案(測試集),已知類別案例集合d(訓練集)。
輸出:未知類別案例的可能分類。
1.3 步驟
下面是乙個常見的乙個二分類示意圖。
其中已知類別為三角形與正方形,圓點為待分類的案例。
分類過程如下:
1.首先確定k值,即待分類樣本用多少鄰居進行估計。以上述問題為例,分別選取k為3和5 。
2.確定合適的距離度量公式(如:歐氏距離),然後根據乙個待分類樣本點與所有已知類別的樣本點中,找出待分類樣本點中最近的k個鄰居。
3.統計這k個樣本點的類別,選取類別最多的一類作為待分類樣本點的類別。以上述問題為例,當k=3時圓點為三角形,當k=5時,圓點為正方形。
1.4 優缺點
優點:演算法實現簡單,不需要引數估計,不需要事先訓練模型。
缺點:直到分類時才開始訓練,運算量大,而且訓練樣本儲存在本地,記憶體開銷大。
1.5 注意點
k的選取一般不大於20.
2.1 numpy庫介紹
numpy庫中有兩種基本資料型別,分別是矩陣和陣列array。
shape()檢視矩陣或者陣列的維度
>>>shape(array) 若矩陣有m行n列,返回(m,n)
>>>array.shape[0] 返回m,若下標為1,返回n
tile()構造陣列
>>>tile(a,(m,n)) 將陣列a作為元素構造乙個m行n列的陣列
sum()
>>>array.sum(axis=1)按行累加,axis=0為按列累加
argsort() 返回矩陣中每乙個元素原來的下標號
>>>a=array.argsort() a[0]表示排序後 排在第乙個的那個數在原來陣列中的下標
min()、max()
>>>array.min(0) 返回乙個陣列,陣列中每個數都是它所在列的所有數的最小值
>>>array.min(1) 返回乙個陣列,陣列中每個數都是它所在行的所有數的最小值
split()切割字串
>>>string.split(『str』)以字元str為分隔符切片,返回list
2.2 實現「手寫識別
每乙個數字都預先被處理為32*32二進位制檔案。
1.將每乙個(即txt文字)轉化為乙個向量,即將32*32的陣列轉換為1 *1024的陣列。這個1*1024的陣列在ml中即乙個特徵向量。
2.訓練資料中一共有10*10個檔案,將其合併為10*1024的矩陣,每一行對應乙個。(這是為了方便計算,很多機器學習演算法在計算的時候採用矩陣運算,可以簡化**,有時還可以減少計算複雜度)。
3.測試樣本中有10*5個,我們要讓程式自動判斷每個所表示的數字。同樣的,對於測試,將其轉化為1*1024的向量,然後計算它與訓練樣本中各個的「距離」(這裡兩個向量的距離採用歐式距離),然後對距離排序,選出較小的前k個,因為這k個樣本來自訓練集,是已知其代表的數字的,所以被測試所代表的數字就可以確定為這k個中出現次數最多的那個數字。
2.3 **實現
第一步,轉化特徵向量
#輸入二進位制檔案
defimg2vector
(filename):
returnvect = zeros((1,1024))
with open(filename) as file:
for i in range(32):
line = file.readline()
for j in range(32):
returnvect[1,32*i+j] = int(line[j])
return returnvect
第二步,組合所有的訓練集,同時對測試集進行樣本分類。
def
handwritingclasstest
():#組合所有的訓練集
#所有已有的類別集合
handlabels =
#將每乙個檔案的檔名儲存在乙個列表中
trainingfilelist = listdir('traingdigits')
m = len(trainingfilelist)
trainingmat = zeros((m,1024))
#迴圈對每乙個數字檔案進行處理
for i in range(m):
filenamestr = trainingfilelist[i]
#切除字尾名
filename = filenamestr.split('.')[0]
#提取類別名
classnumstr = int(filename.split('_')[0])
#採用格式化引數
trainingmat[i,:] = img2vector('traindigits/%s' % filenamestr)
#對測試集進行分類
testfilelist = listdir('testdigits')
errorcount = 0.0
mtest = len(testfilelist)
for i in range(mtest):
filenamestr = testfilelist[i]
filename = filenamestr.split('.')[0]
classnumstr = int(filename.split('_')[0])
vectorundertest = img2vector('testdigits/%s' % filenamestr)
classifierresult = classify(vectorundertest, trainingmat, handlabels, 3)
print
"the classifier came back with: %d, and the real answer is: %d" % (classifierresult,classnumstr)
if(classifierresult != classnumstr ):
errorcount += 1.0
print
"\nthe total number of errors is: %d" % errorcount
print
"\nthe total error rate is %f" % (errorcount/float(mtest))
分類函式:
#testdata為測試向量;traindata為訓練資料;label為訓練資料對應的標籤;k為近鄰數
defclassify
(testdata, traindata, label, k):
#記錄訓練集資料個數
trainnum = traindata.shape[0]
#diffmat的每一行為該測試向量與訓練資料的差異值,每一行中的每乙個元素對應乙個維度上的差異
diffmat = tile(testdata,(trainnum,1)) - traindata
sqdiffmat = diffmat ** 2
#axis=1為按行累加,然後開方,即最終的歐式距離
sqdistances = sqdiffmat.sum(axis=1)
distances = sqdistances ** 0.5
#獲取排序後元素在原陣列中的下標列表,即sortdistindicies[0]為排序後第乙個元素在原來的序列中的下標
sortdistindicies = distances.argsort()
#統計k個相似值中的類別數
classcount = {}
for i in range(k):
getlabel = label(sortdistindicies[i])
classcount[getlabel] = classcount.get(getlabel,0)+1
sortedclasscount = sorted(classcount.iteritems(), key=operator.itemgetter(1), reverse=true)
#返回最多的label
return sortedclasscount[0][0]
機器學習實戰 knn 手寫識別
這個是 機器學習實戰 的第二個例項,用knn演算法實現手寫識別,識別0 9這幾個數字 要實現手寫識別功能,首先將影象資料轉換為矩陣或者向量形式,本例使用32 32的二值影象,轉化成1 1024的陣列,具體 如下 def img2vector filename returnvect zeros 1,1...
機器學習(二) kNN手寫數字識別
一 knn演算法 1 knn演算法是機器學習的入門演算法,其中不涉及訓練,主要思想是計算待測點和參照點的距離,選取距離較近的參照點的類別作為待測點的的類別。2,距離可以是歐式距離,夾角余弦距離等等。3,k值不能選擇太大或太小,k值含義,是最後選取距離最近的前k個參照點的類標,統計次數最多的記為待測點...
KNN演算法識別手寫數字
前言 從現在開始博主要開始學習機器學習了,歡迎有共同興趣的人一起學習。廢話不多說了,開始上 一 將資料集csv檔案匯入到python中,並將csv格式轉為list格式 def dataset 讀取訓練集檔案路徑 path trains1.csv os.path.abspath machinelear...