欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

機(jī)器學(xué)習(xí)之KNN算法原理及Python實(shí)現(xiàn)方法詳解

 更新時(shí)間:2018年07月09日 12:13:16   作者:荔枝童鞋  
這篇文章主要介紹了機(jī)器學(xué)習(xí)之KNN算法原理及Python實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了機(jī)器學(xué)習(xí)KNN算法原理以及Python相關(guān)實(shí)現(xiàn)步驟、操作技巧與注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了機(jī)器學(xué)習(xí)之KNN算法原理及Python實(shí)現(xiàn)方法。分享給大家供大家參考,具體如下:

文中代碼出自《機(jī)器學(xué)習(xí)實(shí)戰(zhàn)》CH02,可參考本站:

機(jī)器學(xué)習(xí)實(shí)戰(zhàn) (Peter Harrington著) 中文版

機(jī)器學(xué)習(xí)實(shí)戰(zhàn) (Peter Harrington著) 英文原版 [附源代碼]

KNN算法介紹

KNN是一種監(jiān)督學(xué)習(xí)算法,通過計(jì)算新數(shù)據(jù)與訓(xùn)練數(shù)據(jù)特征值之間的距離,然后選取K(K>=1)個(gè)距離最近的鄰居進(jìn)行分類判(投票法)或者回歸。若K=1,新數(shù)據(jù)被簡(jiǎn)單分配給其近鄰的類。

KNN算法實(shí)現(xiàn)過程

(1)選擇一種距離計(jì)算方式, 通過數(shù)據(jù)所有的特征計(jì)算新數(shù)據(jù)與已知類別數(shù)據(jù)集中的數(shù)據(jù)點(diǎn)的距離;

(2)按照距離遞增次序進(jìn)行排序,選取與當(dāng)前距離最小的k個(gè)點(diǎn);

(3)對(duì)于離散分類,返回k個(gè)點(diǎn)出現(xiàn)頻率最多的類別作預(yù)測(cè)分類;對(duì)于回歸則返回k個(gè)點(diǎn)的加權(quán)值作為預(yù)測(cè)值;

算法關(guān)鍵

(1)數(shù)據(jù)的所有特征都要做可比較的量化

若是數(shù)據(jù)特征中存在非數(shù)值的類型,必須采取手段將其量化為數(shù)值。例如樣本特征中包含顏色,可通過將顏色轉(zhuǎn)換為灰度值來實(shí)現(xiàn)距離計(jì)算。

(2)樣本特征要做歸一化處理

樣本有多個(gè)參數(shù),每一個(gè)參數(shù)都有自己的定義域和取值范圍,他們對(duì)距離計(jì)算的影響不一樣,如取值較大的影響力會(huì)蓋過取值較小的參數(shù)。所以樣本參數(shù)必須做一些scale處理,最簡(jiǎn)單的方式就是所有特征的數(shù)值都采取歸一化處置。

(3)需要一個(gè)距離函數(shù)以計(jì)算兩個(gè)樣本之間的距離

距離的定義:歐氏距離、余弦距離、漢明距離、曼哈頓距離等,一般選歐氏距離作為距離度量,但是這是只適用于連續(xù)變量。在文本分類這種非連續(xù)變量情況下,漢明距離可以用來作為度量。通常情況下,如果運(yùn)用一些特殊的算法來計(jì)算度量的話,K近鄰分類精度可顯著提高,如運(yùn)用大邊緣最近鄰法或者近鄰成分分析法。

(4)確定K的值

K值選的太大易引起欠擬合,太小容易過擬合。交叉驗(yàn)證確定K值。

KNN分類

分類算法常采用多數(shù)表決決定。一個(gè)缺點(diǎn)是出現(xiàn)頻率較多的樣本將會(huì)主導(dǎo)測(cè)試點(diǎn)的預(yù)測(cè)結(jié)果。解決這個(gè)缺點(diǎn)的方法之一是在進(jìn)行分類時(shí)將K個(gè)鄰居到測(cè)試點(diǎn)的距離考慮進(jìn)去。若樣本到測(cè)試點(diǎn)距離d,則選1/d為該鄰居的權(quán)重,統(tǒng)計(jì)k個(gè)鄰居所有類標(biāo)簽的權(quán)重和,值最大的就是新數(shù)據(jù)點(diǎn)的預(yù)測(cè)類標(biāo)簽。

KNN回歸

KNN回歸是取K個(gè)鄰居類標(biāo)簽值得加權(quán)作為新數(shù)據(jù)點(diǎn)的預(yù)測(cè)值。

優(yōu)缺點(diǎn)

(1)KNN算法的優(yōu)點(diǎn)

  • 1.簡(jiǎn)單、有效。
  • 2.重新訓(xùn)練的代價(jià)較低(類別體系的變化和訓(xùn)練集的變化,在Web環(huán)境和電子商務(wù)應(yīng)用中是很常見的)。
  • 3.計(jì)算時(shí)間和空間線性于訓(xùn)練集的規(guī)模(在一些場(chǎng)合不算太大)。
  • 4.由于KNN方法主要靠周圍有限的鄰近的樣本,而不是靠判別類域的方法來確定所屬類別的,因此對(duì)于類域的交叉或重疊較多的待分樣本集來說,KNN方法較其他方法更為適合。
  • 5.該算法比較適用于樣本容量比較大的類域的自動(dòng)分類,而那些樣本容量較小的類域采用這種算法比較容易產(chǎn)生誤分。

(2)KNN算法缺點(diǎn)

  • 1.KNN算法是懶散學(xué)習(xí)方法(lazy learning,基本上不學(xué)習(xí)),一些積極學(xué)習(xí)的算法要快很多。
  • 2.類別評(píng)分不是規(guī)格化的(不像概率評(píng)分)(???)。
  • 3.輸出的可解釋性不強(qiáng),例如決策樹的可解釋性較強(qiáng)。
  • 4.該算法在分類時(shí)有個(gè)主要的不足是,當(dāng)樣本不平衡時(shí),如一個(gè)類的樣本容量很大,而其他類樣本容量很小時(shí),有可能導(dǎo)致當(dāng)輸入一個(gè)新樣本時(shí),該樣本的K個(gè)鄰居中大容量類的樣本占多數(shù)。該算法只計(jì)算最近的鄰居樣本,某一類的樣本數(shù)量很大,那么或者這類樣本并不接近目標(biāo)樣本,或者這類樣本很靠近目標(biāo)樣本。無論怎樣,數(shù)量并不能影響運(yùn)行結(jié)果??梢圆捎脵?quán)值的方法(和該樣本距離小的鄰居權(quán)值大)來改進(jìn)。
  • 5.計(jì)算量較大。目前常用的解決方法是事先對(duì)已知樣本點(diǎn)進(jìn)行剪輯,事先去除對(duì)分類作用不大的樣本。

KNN實(shí)現(xiàn)

import numpy as np
import operator
import matplotlib
import matplotlib.pyplot as plt
from os import listdir
def Create_DataSet():
 group = np.array([[1.0, 1.1],[1.0,1.0],[0,0],[0,0.1]])
 labels = ['A','A','B','B']
 return group,labels

函數(shù)Create_DataSet創(chuàng)建一個(gè)數(shù)據(jù)集,坐標(biāo)軸左下角分類為B,右上角分類為A。

下面函數(shù)classify0,計(jì)算向量inX與數(shù)據(jù)集中各點(diǎn)的距離,計(jì)算n_estimators個(gè)近鄰中l(wèi)abel頻率最高的分類號(hào)并返回作為向量inX的分類號(hào)。

def classify0(inX, dataSet, labels, n_estimators=3):
 dataSetSize = dataSet.shape[0]
 #print 'in classify0,dataSetSize = \n',dataSetSize
 #轉(zhuǎn)變向量inx格式為datasize行,1列;并計(jì)算與dataset元素距離
 diffMat = np.tile(inX, (dataSetSize,1)) - dataSet
 #計(jì)算歐氏距離((x0-x1)^2 + (y0-y1)^2 )^(1/2)
 sqDiffMat = diffMat**2 #diffMat每個(gè)元素取平方
 sqDistances = sqDiffMat.sum(axis=1)
 distances = sqDistances**0.5
 #排序,將值從小到大排列,返回索引
 sortedDistIndicies = distances.argsort()
 #print 'in classify0,sortedDistIndicies:\n',sortedDistIndicies
 #求與距離最近的k個(gè)點(diǎn)的label統(tǒng)計(jì)
 classCount={}
 for i in range(n_estimators):
  voteIlabel = labels[sortedDistIndicies[i]] #獲取對(duì)應(yīng)label號(hào)
  classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
 #對(duì)字典排序,按value值降序排列
 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
 #print 'sortedClassCount[0][0]:\n',sortedClassCount[0][0]
 return sortedClassCount[0][0]

dataSet.shape()函數(shù)用于獲取矩陣dataSet的大小,shape[0]返回對(duì)應(yīng)行數(shù),shape[1]返回對(duì)應(yīng)列數(shù)。

因?yàn)樾枰獙?duì)每列屬性做距離運(yùn)算,所以需要將輸入inX轉(zhuǎn)換為和dataSet相同行數(shù)和列數(shù)的矩陣,因?yàn)閕nX列數(shù)與dataSet中每個(gè)元素列數(shù)相同,所以需要將其行數(shù)進(jìn)行擴(kuò)展,np.tile(inX, (dataSetSize,1))將inX行數(shù)拓展為dataSetSize行,1表示縱向復(fù)制1次,即列不變。

距離公式采用歐式距離計(jì)算,得到的距離值為一維列表,分別對(duì)應(yīng)dataSet中每個(gè)元素和inX的距離。distances.argsort() 將距離按從小到大排列,并返回索引。例如distance = [0.1,0.5,0.3],distance.argsort()返回[1,3,2] 。返回索引是為了找到對(duì)應(yīng)的label值,并進(jìn)行統(tǒng)計(jì)。

下面for循環(huán)用于建立字典并統(tǒng)計(jì)前n_estimators個(gè)label的個(gè)數(shù)。key對(duì)應(yīng)label,key_value對(duì)應(yīng)個(gè)數(shù)。

operator.itemgetter函數(shù),operator模塊提供的itemgetter函數(shù)用于獲取對(duì)象的哪些維的數(shù)據(jù),參數(shù)為一些序號(hào),即需要獲取的數(shù)據(jù)在對(duì)象中的序號(hào);例如a = [1,2,3] ,定義函數(shù)b=operator.itemgetter(1),獲取對(duì)象的第1個(gè)域的值,則 b(a)=2;若定義函數(shù)b,獲取對(duì)象的第1個(gè)域和第0個(gè)的值b=operator.itemgetter(1,0),則b(a)=(2, 1) 。注意operator.itemgetter函數(shù)獲取的不是值,而是定義了一個(gè)函數(shù),通過該函數(shù)作用到對(duì)象上才能獲取值;

sorted函數(shù):Python內(nèi)置的排序函數(shù)sorted可以對(duì)list或者iterator進(jìn)行排序;第一個(gè)參數(shù)iterable指定要排序的list或者iterable,第二個(gè)參數(shù)指定排序時(shí)進(jìn)行比較的函數(shù),可以指定一個(gè)函數(shù)或者lambda函數(shù)。例如students為類對(duì)象的list,每個(gè)成員有三個(gè)域,用sorted進(jìn)行比較時(shí)可以自己定cmp函數(shù),例如這里要通過比較第三個(gè)數(shù)據(jù)成員來排序,students = [(‘john', ‘A', 15), (‘jane', ‘B', 12), (‘dave', ‘B', 10)],sorted(students, key=lambda student : student[2]),key為函數(shù),指定取待排序元素的哪一項(xiàng)進(jìn)行排序,key指定的lambda函數(shù)功能是去元素student的第三個(gè)域(student[2]),因此sorted排序時(shí)會(huì)以students所有元素的第三個(gè)域來進(jìn)行排序;也可以這么寫sorted(students, key=operator.itemgetter(2)) ,sorted函數(shù)也可以進(jìn)行多級(jí)排序,例如要根據(jù)第二個(gè)域和第三個(gè)域進(jìn)行排序;sorted(students, key=operator.itemgetter(1,2))即先跟句第二個(gè)域排序,再根據(jù)第三個(gè)域排序;第三個(gè)參數(shù)reverse是一個(gè)bool變量,表示升序還是降序排列,默認(rèn)為false升序排列,定義為True時(shí)將按降序排列。

此處sort函數(shù)用于對(duì)字典進(jìn)行排序。按key_value降序排列,即對(duì)應(yīng)label個(gè)數(shù)從大到小排列。返回值為列表,列表元素為元組,元組第一個(gè)元素對(duì)應(yīng)label,第二個(gè)元素對(duì)應(yīng)label個(gè)數(shù)。sortedClassCount[0][0]即返回label次數(shù)最多的類標(biāo)號(hào),為inX的label。

下面測(cè)試一個(gè)簡(jiǎn)單的向量:

group,labels = Create_DataSet()
sortedClassCount = classify0([0,0.5],group,labels,3)

輸出為

sortedClassCount:[(‘B', 2), (‘A', 1)]
sortedClassCount[0][0]:
B

下面函數(shù)file2matrix用于從txt中讀取原始數(shù)據(jù)并轉(zhuǎn)化為矩陣。

test.txt格式為

40920 8.326976 0.953952 largeDoses
14488 7.153469 1.673904 smallDoses
26052 1.441871 0.805124 didntLike
75136 13.147394 0.428964 didntLike
……

最后一列為label,值為largeDoses、smallDoses或didntLike。每行元素用\t隔開。轉(zhuǎn)換后label分別對(duì)應(yīng)3、2、1。

轉(zhuǎn)換函數(shù)如下:

def file2matrix(filename):
 fr = open(filename)
 numberOfLines = len(fr.readlines())
 print 'in file2matrix,numberOfLines:\n',numberOfLines
 returnMat = np.zeros((numberOfLines,3))
 classLabelVector = []
 fr = open(filename)
 index = 0
 for line in fr.readlines(): #遍歷每一行
  line = line.strip() #strip用于刪除字符,此處刪除空白字符,回車
  listFromLine = line.split('\t') #獲取每行的元素列表,元素用\t分開
  returnMat[index,:] = listFromLine[0:3]#取前3個(gè)元素,對(duì)應(yīng)屬性集
  if(listFromLine[-1] == 'largeDoses'):#有什么有效的方法 將屬性值和類標(biāo)號(hào)分開,相互對(duì)應(yīng)
   classLabelVector.append(3)
  elif(listFromLine[-1] == 'smallDoses'):
   classLabelVector.append(2)
  elif(listFromLine[-1] == 'didntLike'):
   classLabelVector.append(1)
  elif(listFromLine[-1] == 3):
   classLabelVector.append(3)
  elif(listFromLine[-1] == 2):
   classLabelVector.append(2)
  elif(listFromLine[-1] == 1):
   classLabelVector.append(1)
  index += 1
 #print 'returnMat = ',returnMat
 #print 'classLabelVector = ',classLabelVector
 return returnMat,classLabelVector #得到屬性集和類標(biāo)號(hào)

首先打開文件并獲取行數(shù),建立一個(gè)相同大小的空矩陣,用于存儲(chǔ)轉(zhuǎn)換后的屬性集,并新建一個(gè)一維列表,用于存放類標(biāo)號(hào)。fr.readlines()讀取所有行,得到一個(gè)行列表,列表元素為每行內(nèi)容;readline只讀取1行,獲取該行元素的列表。
上述函數(shù)即返回屬性集矩陣和類標(biāo)號(hào)列表。

因?yàn)閷傩灾挡罹噍^大,為了減少值太大的屬性對(duì)值小的屬性的影響,分類之前還需要進(jìn)行歸一化。歸一化方程為(datain-min_val) / (max_val - min_val),輸出值都介于0-1。

def autoNorm(dataSet):
 minVals = dataSet.min(0) #獲取每列最大值與最小值,(0)指定列,而不是行
 print 'in autoNorm,minVals:',minVals
 maxVals = dataSet.max(0)
 print 'in autoNorm,maxVals:',maxVals
 ranges = maxVals - minVals
 print 'in autoNorm,ranges:',ranges
 normDataSet = np.zeros(np.shape(dataSet))
 m = dataSet.shape[0] #獲取行數(shù)
 #特征值矩陣為1000x3,minVals值為1x3,使用tile函數(shù)擴(kuò)展為相同大小的矩陣
 #np.tile(minVals, (m,1))矩陣minval,橫向復(fù)制m次,縱向復(fù)制1次
 normDataSet = dataSet - np.tile(minVals, (m,1)) # (data - minval)/(maxval - minval)
 normDataSet = normDataSet/np.tile(ranges, (m,1)) #element wise divide
 print 'in autoNorm,normDataSet = ',normDataSet
 return normDataSet, ranges, minVals

返回歸一化以后的屬性集。即可進(jìn)行距離運(yùn)算并分類。

下面函數(shù)即對(duì)文件中所有輸入的行向量屬性進(jìn)行分類

def datingClassTest(n_estimators=3):
 hoRatio = 0.50
 #(1)讀取文件
 datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
 #(2)歸一化
 normMat, ranges, minVals = autoNorm(datingDataMat)
 m = normMat.shape[0]
 numTestVecs = int(m*hoRatio)
 errorCount = 0.0
 for i in range(numTestVecs):
  classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],n_estimators=n_estimators)
  if (classifierResult != datingLabels[i]): errorCount += 1.0
 print "in datingClassTest,the total error rate is: %f" % (errorCount/float(numTestVecs))
 print 'in datingClassTest,errorCount:',errorCount

將測(cè)試文件分為數(shù)據(jù)集和用于測(cè)試的向量2部分。前一半用于測(cè)試,后一半作為數(shù)據(jù)集,并定義errorCount用于統(tǒng)計(jì)出錯(cuò)個(gè)數(shù)。經(jīng)過歸一化以后的數(shù)據(jù)集和驗(yàn)證通過for循環(huán)計(jì)算分類結(jié)果,并與實(shí)際結(jié)果進(jìn)行對(duì)比,得到總出錯(cuò)數(shù)和出錯(cuò)率。

執(zhí)行該函數(shù),結(jié)果顯示:

in datingClassTest,the total error rate is: 0.064000
in datingClassTest,errorCount: 32.0

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python數(shù)學(xué)運(yùn)算技巧總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》及《Python文件與目錄操作技巧匯總

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • python實(shí)現(xiàn)支持目錄FTP上傳下載文件的方法

    python實(shí)現(xiàn)支持目錄FTP上傳下載文件的方法

    這篇文章主要介紹了python實(shí)現(xiàn)支持目錄FTP上傳下載文件的方法,適用于windows及Linux平臺(tái)FTP傳輸文件及文件夾,需要的朋友可以參考下
    2015-06-06
  • tensorflow自定義激活函數(shù)實(shí)例

    tensorflow自定義激活函數(shù)實(shí)例

    今天小編就為大家分享一篇tensorflow自定義激活函數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • 用Python實(shí)現(xiàn)隨機(jī)森林算法的示例

    用Python實(shí)現(xiàn)隨機(jī)森林算法的示例

    這篇文章主要介紹了用Python實(shí)現(xiàn)隨機(jī)森林算法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • pyCharm 實(shí)現(xiàn)關(guān)閉代碼檢查

    pyCharm 實(shí)現(xiàn)關(guān)閉代碼檢查

    這篇文章主要介紹了pyCharm 實(shí)現(xiàn)關(guān)閉代碼檢查,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • Python matplotlib可視化繪圖詳解

    Python matplotlib可視化繪圖詳解

    這篇文章主要介紹了Python matplotlib繪圖可視化知識(shí)點(diǎn)整理(小結(jié)),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2021-09-09
  • Python中的生成器和yield詳細(xì)介紹

    Python中的生成器和yield詳細(xì)介紹

    這篇文章主要介紹了Python中的生成器和yield詳細(xì)介紹,本文講解了列表推導(dǎo)與生成器表達(dá)式、斐波那契數(shù)列、生成器Generator、協(xié)程與yield表達(dá)式、使用生成器與協(xié)程等內(nèi)容,需要的朋友可以參考下
    2015-01-01
  • Python枚舉類定義和使用方法

    Python枚舉類定義和使用方法

    這篇文章主要介紹了Python枚舉類定義和使用方法,文章圍繞主題的相關(guān)資料展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-05-05
  • windows系統(tǒng)下Python環(huán)境搭建教程

    windows系統(tǒng)下Python環(huán)境搭建教程

    這篇文章主要為大家詳細(xì)介紹了windows系統(tǒng)下Python環(huán)境搭建教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • python模塊中判斷全局變量的賦值的實(shí)例講解

    python模塊中判斷全局變量的賦值的實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于python模塊中判斷全局變量的賦值的實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-03-03
  • 基于python-opencv3實(shí)現(xiàn)圖像顯示和保存操作

    基于python-opencv3實(shí)現(xiàn)圖像顯示和保存操作

    這篇文章主要介紹了基于python opencv3的圖像顯示和保存操作方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-06-06

最新評(píng)論