機器學習python實戰 k近鄰演算法

2022-08-24 05:33:08 字數 4300 閱讀 4857

前一周學習了一些理論的知識,雖然懂了原理,但感覺真要寫起**來還是摸不著頭腦,所以接下來的幾天都打算在**方面下一番功夫。由於接觸python不久,且能力有限,難免有些錯誤的或者理解不到位的地方,希望讀者不吝指正!

k-近鄰演算法(k-nn)的基本原理:存在乙個樣本資料集合,也叫訓練樣本集,並且樣本集中的每個資料都存在標籤,就是我們知道每個資料與所屬分類的對應關係。輸入沒有標籤的新資料後,我們將新資料的特徵跟樣本集中每個資料對應的特徵進行比較,選擇特徵最相似的(最近鄰)的分類標籤認為是新資料的標籤。一般來說我們只選擇樣本資料集中前k個最相似的資料,這就是k-近鄰的出處。

接下來我們進入**實戰,首先用乙個簡單的knn的例子來上手:

第一步,我們建立乙個小的資料集,python**如下。這是帶有標籤的四個資料點

有了資料集之後,我們接著來對新資料進行分類,看**

def

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]

這個函式classify0有四個輸入引數,inx表示分類的輸入向量,dataset表示訓練資料集,labels表示標籤向量,k表示取前k個最相似(最相近)的向量。這個函式是計算輸入向量與訓練資料集的歐式距離,然後對距離進行排序並選擇前k個最小的距離,對這些類別進行統計,返回類別多的標籤作為新資料的標籤。classdict是定義的乙個空的儲存字典,.argsort()函式是對距離進行排序並返回從小到大排列的序號,注意,這裡返回的序號就是已經排列好的(從小到大),所以在後面取sortdis[i]的時候就是前k個最小距離了。這個問題要注意一下,我這裡想了很久才想明白,所以有必要提醒一下。之後的sorted()函式是按統計的標籤數的多少降序排列,所以sortclassdict[0][0]就是統計標籤數最多的類別了。

有了這兩個程式我們就可以進行測試啦,結果如圖,測試(1,1)這點屬於'a'類

做完這個小例子,接下來我們就要對檔案資料進行操作,首先需要從文字中解析資料,這樣的乙個文字dataset_knn.txt中存在1000行、4列資料,前三列為特徵向量,最後一列為標籤。我們需要將特徵向量和標籤分開放入兩個矩陣中,**如下:

def

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

一些函式的功能我注發布來了,可以自己先new乙個短的txt檔案去測試這些函式,確保功能正常。執行結果如下:

我們可以根據特徵向量畫出散點圖,這裡是特徵向量第0列和第1列。

下面進行資料的歸一化。這裡就是我們之前在理論部分說的歸一化是乙個道理,不能讓特徵向量之間的差值太大而影響我們的結果,所以要進行歸一化,公式也跟之前一樣:newvalue=(value-min)/(max-min)。**如下:

def

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

到這裡我們的knn演算法需要的函式就完了,下面介紹乙個評價該演算法的方法。這裡將樣本資料分為訓練資料集和測試資料集(8:2),錯誤率定義為 **錯誤的總數/測試樣本總數

def

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)))

前百分之二十的資料作為測試樣本,當然這裡的測試樣本是需要隨機選取的,由於文字檔案中就是隨機的,我們這裡取前20%,剩下的作為訓練樣本。k取5。如果**的標籤跟實際的標籤不符合,就令**錯誤的總數+1。

結果為這裡的錯誤率為8.6%。

k-nn演算法到這裡就介紹的差不多了,說簡單也不簡單,說複雜好像也沒多少步驟,最關鍵的是自己要去想,要去做,才能更好的掌握!

《機器學習實戰》 K 近鄰演算法

基本原理 通過計算新資料與給定的樣本資料之間的距離,來確定相似度排名 然後取前k個最相似的樣本,統計這k 一般不大於20 個樣本中出現最多的分類,設為新資料的分類。新資料,訓練樣本集,樣本資料標籤 即分類 最近鄰 前k個最相似資料 最近鄰標籤 演算法實施 首先提取要比較的特徵,確定各特徵的權重,進行...

機器學習實戰 K 近鄰演算法

簡單的說,k 近鄰演算法採用測量不同特徵值之間的距離辦法進行分類.收集資料 可以使用任何方法。準備資料 距離計算所需要的數值,最好是結構化的資料格式。分析資料 可以使用任何方法。訓練演算法 此步驟不適用於k 近鄰演算法。測試演算法 計算錯誤率。使用演算法 首先需要輸入樣本資料和結構化的輸出結果,然後...

機器學習實戰 k 近鄰演算法

本系列是基於 機器學習實戰 這本書做的讀書筆記,原書採用python2作為工具,我則將原書 改為用python3編寫並記錄在此系列中。我將把書中對這些機器學習演算法的定義謄上,然後寫下自己對該演算法的通俗理解,之後貼出書中演算法清單中的 本書講解的第乙個機器學習演算法是k 近鄰演算法 knn 它的工...