前一周學習了一些理論的知識,雖然懂了原理,但感覺真要寫起**來還是摸不著頭腦,所以接下來的幾天都打算在**方面下一番功夫。由於接觸python不久,且能力有限,難免有些錯誤的或者理解不到位的地方,希望讀者不吝指正!
k-近鄰演算法(k-nn)的基本原理:存在乙個樣本資料集合,也叫訓練樣本集,並且樣本集中的每個資料都存在標籤,就是我們知道每個資料與所屬分類的對應關係。輸入沒有標籤的新資料後,我們將新資料的特徵跟樣本集中每個資料對應的特徵進行比較,選擇特徵最相似的(最近鄰)的分類標籤認為是新資料的標籤。一般來說我們只選擇樣本資料集中前k個最相似的資料,這就是k-近鄰的出處。
接下來我們進入**實戰,首先用乙個簡單的knn的例子來上手:
第一步,我們建立乙個小的資料集,python**如下。這是帶有標籤的四個資料點
有了資料集之後,我們接著來對新資料進行分類,看**
def這個函式classify0有四個輸入引數,inx表示分類的輸入向量,dataset表示訓練資料集,labels表示標籤向量,k表示取前k個最相似(最相近)的向量。這個函式是計算輸入向量與訓練資料集的歐式距離,然後對距離進行排序並選擇前k個最小的距離,對這些類別進行統計,返回類別多的標籤作為新資料的標籤。classdict是定義的乙個空的儲存字典,.argsort()函式是對距離進行排序並返回從小到大排列的序號,注意,這裡返回的序號就是已經排列好的(從小到大),所以在後面取sortdis[i]的時候就是前k個最小距離了。這個問題要注意一下,我這裡想了很久才想明白,所以有必要提醒一下。之後的sorted()函式是按統計的標籤數的多少降序排列,所以sortclassdict[0][0]就是統計標籤數最多的類別了。classify0(inx,dataset,labels,k):
datasetsize = dataset.shape[0] #
.shape[0]表示dataset的行數
diffmat = tile(inx,(datasetsize,1))-dataset #
某個點與資料集中點的x和y的座標差
sqdiffmat = diffmat**2sumdiffmat = sqdiffmat.sum(axis=1) #
對sqdiffmat的行求和即(x-x1)^2+(y-y1)^2
dis = sumdiffmat**0.5 #
求平方根即距離
sortdis =dis.argsort()
classdict = {} #
定義乙個儲存字典
for i in
range(k):
keylabels =labels[sortdis[i]]
classdict[keylabels] = classdict.get(keylabels,0)+1sortclassdict = sorted(classdict.items(),key = operator.itemgetter(1),reverse =true)
#.items()方法是將classdict這個儲存字典轉化為list,operator.itemgetter(1)是按classdict的第一項排序
#reverse = true表示降序排列即從大到小
return sortclassdict[0][0]
有了這兩個程式我們就可以進行測試啦,結果如圖,測試(1,1)這點屬於'a'類
做完這個小例子,接下來我們就要對檔案資料進行操作,首先需要從文字中解析資料,這樣的乙個文字dataset_knn.txt中存在1000行、4列資料,前三列為特徵向量,最後一列為標籤。我們需要將特徵向量和標籤分開放入兩個矩陣中,**如下:
def一些函式的功能我注發布來了,可以自己先new乙個短的txt檔案去測試這些函式,確保功能正常。執行結果如下:file2mat(filename):
fr =open(filename)
listoffile = fr.readlines() #
一次性讀取文字的所有內容並以list形式返回
numoflines = len(listoffile) #
得到檔案的行數
newfacmat = zeros((numoflines,3))#
建立乙個行數*3的零矩陣
newclassvec = #
建立乙個類的向量
index=0
for line in
listoffile:
line = line.strip() #
strip函式用來截斷所有的回車符
listfromline = line.split('
\t')#
以'\t'進行分割
newfacmat[index,:] = listfromline[0:3]
index+=1
return newfacmat,newclassvec
我們可以根據特徵向量畫出散點圖,這裡是特徵向量第0列和第1列。
下面進行資料的歸一化。這裡就是我們之前在理論部分說的歸一化是乙個道理,不能讓特徵向量之間的差值太大而影響我們的結果,所以要進行歸一化,公式也跟之前一樣:newvalue=(value-min)/(max-min)。**如下:
def到這裡我們的knn演算法需要的函式就完了,下面介紹乙個評價該演算法的方法。這裡將樣本資料分為訓練資料集和測試資料集(8:2),錯誤率定義為 **錯誤的總數/測試樣本總數autonorm(dataset):
valuemax =dataset.max(0)
valuemin =dataset.min(0)
value_range = valuemax-valuemin
normdataset =zeros(shape(dataset))
m =dataset.shape[0]
normdataset = dataset-tile(valuemin,(m,1))
normdataset = normdataset/tile(value_range,(m,1))
return normdataset,value_range,valuemin
def前百分之二十的資料作為測試樣本,當然這裡的測試樣本是需要隨機選取的,由於文字檔案中就是隨機的,我們這裡取前20%,剩下的作為訓練樣本。k取5。如果**的標籤跟實際的標籤不符合,就令**錯誤的總數+1。datingsettest():
h = 0.2newfacmat,newclassvec = file2mat(r'
dataset_knn.txt')
normmat,value_range,value_min =autonorm(newfacmat)
m =normmat.shape[0]
numtestdata = int(m*h) #
測試向量的總數
error_cnt=0
for i in
range(numtestdata):
result = classify0(normmat[i,:],normmat[numtestdata:m,:],newclassvec[numtestdata:m],5)
print('
the result is %d,the real answer is %d\n
'%(result,newclassvec[i]))
if result!=newclassvec[i]:
error_cnt+=1
print('
the error rate is %f\n
'%(error_cnt/float(numtestdata)))
結果為這裡的錯誤率為8.6%。
k-nn演算法到這裡就介紹的差不多了,說簡單也不簡單,說複雜好像也沒多少步驟,最關鍵的是自己要去想,要去做,才能更好的掌握!
《機器學習實戰》 K 近鄰演算法
基本原理 通過計算新資料與給定的樣本資料之間的距離,來確定相似度排名 然後取前k個最相似的樣本,統計這k 一般不大於20 個樣本中出現最多的分類,設為新資料的分類。新資料,訓練樣本集,樣本資料標籤 即分類 最近鄰 前k個最相似資料 最近鄰標籤 演算法實施 首先提取要比較的特徵,確定各特徵的權重,進行...
機器學習實戰 K 近鄰演算法
簡單的說,k 近鄰演算法採用測量不同特徵值之間的距離辦法進行分類.收集資料 可以使用任何方法。準備資料 距離計算所需要的數值,最好是結構化的資料格式。分析資料 可以使用任何方法。訓練演算法 此步驟不適用於k 近鄰演算法。測試演算法 計算錯誤率。使用演算法 首先需要輸入樣本資料和結構化的輸出結果,然後...
機器學習實戰 k 近鄰演算法
本系列是基於 機器學習實戰 這本書做的讀書筆記,原書採用python2作為工具,我則將原書 改為用python3編寫並記錄在此系列中。我將把書中對這些機器學習演算法的定義謄上,然後寫下自己對該演算法的通俗理解,之後貼出書中演算法清單中的 本書講解的第乙個機器學習演算法是k 近鄰演算法 knn 它的工...