日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

k近邻法(k-nearest neighbor, k-NN)

發(fā)布時(shí)間:2024/8/26 47 生活家
生活随笔 收集整理的這篇文章主要介紹了 k近邻法(k-nearest neighbor, k-NN) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一種基本分類與回歸方法

工作原理是:1、訓(xùn)練樣本集+對應(yīng)標(biāo)簽

      2、輸入沒有標(biāo)簽的新數(shù)據(jù),將新的數(shù)據(jù)的每個(gè)特征與樣本集中數(shù)據(jù)對應(yīng)的特征進(jìn)行比較,然后算法提取樣本最相似數(shù)據(jù)(最近鄰)的分類標(biāo)簽。

      3、一般來說,我們只選擇樣本數(shù)據(jù)集中前k個(gè)最相似的數(shù)據(jù)。

      4、選擇k個(gè)最相似數(shù)據(jù)中出現(xiàn)次數(shù)最多的分類,作為新數(shù)據(jù)的分類。

k-近鄰算法沒有進(jìn)行數(shù)據(jù)的訓(xùn)練,直接使用未知的數(shù)據(jù)與已知的數(shù)據(jù)進(jìn)行比較,得到結(jié)果。因此,可以說k-鄰近算法不具有顯式的學(xué)習(xí)過程。

距離度量:歐氏距離

工作流程:

收集數(shù)據(jù):可以使用爬蟲進(jìn)行數(shù)據(jù)的收集,也可以使用第三方提供的免費(fèi)或收費(fèi)的數(shù)據(jù)。一般來講,數(shù)據(jù)放在txt文本文件中,按照一定的格式進(jìn)行存儲(chǔ),便于解析及處理。
準(zhǔn)備數(shù)據(jù):使用Python解析、預(yù)處理數(shù)據(jù)。
分析數(shù)據(jù):可以使用很多方法對數(shù)據(jù)進(jìn)行分析,例如使用Matplotlib將數(shù)據(jù)可視化。
測試算法:計(jì)算錯(cuò)誤率。
使用算法:錯(cuò)誤率在可接受范圍內(nèi),就可以運(yùn)行k-近鄰算法進(jìn)行分類。

KNN算法原理代碼:

 1 import numpy as np
 2 import operator
 3 
 4 def classify0(inx,dataset,labels,k):  #定義一個(gè)分類函數(shù),測試數(shù)據(jù),數(shù)據(jù)集,標(biāo)簽集,k個(gè)
 5     datasetsize = dataset.shape[0]  #獲取數(shù)據(jù)集的第一維個(gè)數(shù),為了計(jì)算測試數(shù)據(jù)與數(shù)據(jù)集中每個(gè)數(shù)據(jù)的距離
 6     diffmat = np.tile(inx,(datasetsize,1)) - dataset #將測試數(shù)據(jù)在行上重復(fù)多次,列上重復(fù)一次,也就是不重復(fù),
 7                                                      # 這樣可以與每個(gè)數(shù)據(jù)計(jì)算距離
 8     sqdiffmat = diffmat**2 #距離的平方
 9     sqdistance = sqdiffmat.sum(axis=1) # 行里的所有元素都加起來,1是行,0是列
10     distance = sqdistance**0.5  #距離的平方再開方
11     sorteddisindeces = distance.argsort() #距離進(jìn)行從小到大的排序,返回的是排序后的索引值
12     classcount = {} #這個(gè)是用來記錄取得前k個(gè)值后,進(jìn)行排序的字典, 鍵:距離對應(yīng)的標(biāo)簽,值:標(biāo)簽出現(xiàn)的次數(shù)
13     for i in range(k):
14         voteilabel = labels[sorteddisindeces[i]] #鍵 = 標(biāo)簽(前k個(gè)索引值)  鍵=前k個(gè)標(biāo)簽
15         classcount[voteilabel] = classcount.get(voteilabel,0) + 1 #        #計(jì)算前k個(gè)便簽出現(xiàn)的次數(shù),次數(shù)就是值
16     sortedclasscount = sorted(classcount.items(),key=operator.itemgetter(1),reverse=True) #key=operator.itemgetter(1)定義函數(shù),獲取對象1值
17                                                                                           #按照值進(jìn)行倒序排,元素格式是
18                        #{ [標(biāo)簽,次數(shù)],[標(biāo)簽,次數(shù)].......}
19     return sortedclasscount[0][0] #排完值后,將排行老一的也就是最近距離的標(biāo)簽
20 
21 def createDataSet():
22     #四組二維特征
23     group = np.array([[1,101],[5,89],[108,5],[115,8]])
24     #四組特征的標(biāo)簽
25     labels = ['愛情片','愛情片','動(dòng)作片','動(dòng)作片']
26     return group, labels
27 
28 if __name__ == '__main__':
29     #創(chuàng)建數(shù)據(jù)集
30     group, labels = createDataSet()
31     #測試集
32     test = [101,20]
33     #kNN分類
34     test_class = classify0(test, group, labels, 3)
35     #打印分類結(jié)果
36     print(test_class)

View Code

使用sklearn運(yùn)用KNN(鳶尾花數(shù)據(jù)集)

 1 from sklearn import datasets
 2 #導(dǎo)入內(nèi)置的數(shù)據(jù)集
 3 from sklearn.neighbors import KNeighborsClassifier
 4 #導(dǎo)入sklearn.neighbors 里的KNN算法模塊
 5 import numpy as np
 6 
 7 np.random.seed(0)
 8 #設(shè)置隨機(jī)種子,這樣每次調(diào)用隨機(jī)模塊時(shí)產(chǎn)生的隨機(jī)數(shù)就是一樣的了
 9 
10 iris=datasets.load_iris()
11 #導(dǎo)入鳶尾花數(shù)據(jù)集(data數(shù)據(jù),target標(biāo)簽)
12 
13 iris_x=iris.data
14 #獲取樣本數(shù)據(jù)    type:nadarry
15 #是150*4二維數(shù)據(jù),代表150個(gè)樣本,
16 # 一共三類花 Iris-Setosa 山鳶尾,Iris-Versicolour 變色鳶尾,Iris-Virginica 維吉尼亞鳶尾
17 # 每類有50個(gè)樣本,每個(gè)樣本4個(gè)屬性分別為花萼和花瓣的長、寬
18 
19 iris_y = iris.target
20 #獲取樣本標(biāo)簽,是150*1的一維數(shù)組, type:nadarry
21 
22 indices = np.random.permutation(len(iris_x))
23 #permutation接收一個(gè)數(shù)作為參數(shù)(150),產(chǎn)生一個(gè)0-149一維數(shù)組,只不過是隨機(jī)打亂的,當(dāng)然她也可以接收一個(gè)一維數(shù)組作為參數(shù),結(jié)果是直接對這個(gè)數(shù)組打亂
24 #函數(shù)shuffle與permutation都是對原來的數(shù)組進(jìn)行重新洗牌(即隨機(jī)打亂原來的元素順序);區(qū)別在于shuffle直接在原來的數(shù)組上進(jìn)行操作,改變原來數(shù)組的順序,無返回值。而permutation不直接在原來的數(shù)組上進(jìn)行操作,而是返回一個(gè)新的打亂順序的數(shù)組,并不改變原來的數(shù)組。
25 #b=np.random.permutation(10) 返回的b是nadarry類型
26 
27 iris_x_train = iris_x[indices[:-10]]
28 iris_y_train = iris_y[indices[:-10]]
29 #選取140個(gè)數(shù)據(jù)和標(biāo)簽作為訓(xùn)練數(shù)據(jù)集和訓(xùn)練數(shù)據(jù)集的標(biāo)簽
30 
31 iris_x_test = iris_x[indices[-10:]]
32 iris_y_test = iris_y[indices[-10:]]
33 #最后十個(gè)作為測試數(shù)據(jù)集
34 
35 knn = KNeighborsClassifier()
36 #定義了一個(gè)分類器對象
37 knn.fit(iris_x_train,iris_y_train)
38 #調(diào)用knn的訓(xùn)練方法,主要接受兩個(gè)參數(shù):訓(xùn)練數(shù)據(jù)集和其樣本標(biāo)簽
39 
40 iris_y_predict = knn.predict(iris_x_test)
41 #調(diào)用該對象的測試方法,主要接受一個(gè)參數(shù):測試數(shù)據(jù)集
42 
43 probility = knn.predict_proba(iris_x_test)
44 #計(jì)算各測試樣本基于概率的預(yù)測
45 
46 #score = knn.score(iris_x_test,iris_y_test,sample_weight=None)
47 #調(diào)用該對象的打分方法,計(jì)算出準(zhǔn)確率
48 
49 print('iris_y_predict=')
50 print(iris_y_predict)
51 #測試結(jié)果
52 
53 print('iris_y_test=')
54 print(iris_y_test)
55 #真實(shí)的測試集的標(biāo)簽
56 
57 #print('accuracy:')
58 #print(score)
59 #正確率
60 
61 #print(neighborpoint)
62 #臨點(diǎn)
63 print(probility)
64 #概率預(yù)測

View Code

第一步:定義分類器對象

knn = KNeighborClassifier()

第二步:訓(xùn)練樣本

knn.fit(x_train,y_train)

第三步:測試數(shù)據(jù)集

y_predict = knn.predict(x_test)

第四步:顯示預(yù)測概率,顯示測試數(shù)據(jù)集標(biāo)簽,顯示預(yù)測數(shù)據(jù)集標(biāo)簽

probility = knn.predict_proba(x_test)

y_test

y_predict

方法解讀:

np.tile(A,B)

1 >>> import numpy
2 >>> numpy.tile([0,0],5) #在列方向上重復(fù)[0,0]5次,默認(rèn)行1次
3 array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
4 
5 >>> numpy.tile([0,0],(1,3)) #行方向上重復(fù)1次,列方向上重復(fù)3次
6 array([[0, 0, 0, 0, 0, 0]])

sum()函數(shù)

1 #0:壓縮為一行,每列的元素全都加起來
2       第一維的元素,相應(yīng)位置加起來
3 >>> np.sum([[0, 1], [0, 5]], axis=0) 
4 array([0, 6])
5 
6 #1:壓縮為一列,每一行的元素都加起來
7       第二維的元素加起來
8 >>> np.sum([[0, 1], [0, 5]], axis=1)
9 array([1, 5])

argsort函數(shù)

argsort函數(shù)是Numpy模塊中的函數(shù),返回的是數(shù)組值從小到大的索引值。

#One dimensional array:一維數(shù)組
>>> x = np.array([3, 1, 2])
>>> np.argsort(x)           #也可以 x.argsort()
array([1, 2, 0])

#Two-dimensional array:二維數(shù)組
>>> x = np.array([[0, 3], [2, 2]])
>>> x
array([[0, 3],
[2, 2]])

>>> np.argsort(x, axis=0) #按列排序
array([[0, 1],
[1, 0]])

>>> np.argsort(x, axis=1) #按行排序
array([[0, 1],
[0, 1]])

>>> x = np.array([3, 1, 2])
>>> np.argsort(x) #按升序排列
array([1, 2, 0])
>>> np.argsort(-x) #按降序排列
array([0, 2, 1])

字典的get()方法

dict.get(key, default=None)

>>>dict = {'A':1, 'B':2}
>>>print(dict.get('A'))
1
>>>print(dict.get('C'))
None
>>>print(dict.get('A', 0))  #A存在字典中時(shí),返回對應(yīng)值,不在時(shí)返回0
>>>1
>>>print(dict.get('C', 0))
>>>0

operator.itemgetter函數(shù)

operator模塊提供的itemgetter函數(shù)用于獲取對象的哪些維的數(shù)據(jù),參數(shù)為一些序號(hào)。要注意,operator.itemgetter函數(shù)獲取的不是值,而是定義了一個(gè)函數(shù),通過該函數(shù)作用到對象上才能獲取值。

1 a = [1,2,3] 
2 >>> b=operator.itemgetter(1)     //定義函數(shù)b,獲取對象的第1個(gè)域的值
3 >>> b(a) 
4 2 
5 >>> b=operator.itemgetter(1,0)   //定義函數(shù)b,獲取對象的第1個(gè)域和第0個(gè)的值
6 >>> b(a) 
7 (2, 1) 

sorted函數(shù)

Python內(nèi)置的排序函數(shù)sorted可以對list或者iterator進(jìn)行排序。

sorted(iterable[,cmp[,key[,reverse]]])

(1)iterable指定要排序的list或者iterable

(2)cmp為函數(shù),指定排序時(shí)進(jìn)行比較的函數(shù),可以指定一個(gè)函數(shù)或者lambda函數(shù),如:

students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
sorted(students, key=lambda student : student[2])
(3)key為函數(shù),指定取待排序元素的哪一項(xiàng)進(jìn)行排序,函數(shù)用上面的例子來說明,代碼如下:
sorted(students, key=lambda student : student[2])
例如要通過student的第三個(gè)域排序,可以這么寫:
  sorted(students, key=operator.itemgetter(2))
  sorted函數(shù)也可以進(jìn)行多級(jí)排序,例如要根據(jù)第二個(gè)域和第三個(gè)域進(jìn)行排序,可以這么寫:
  sorted(students, key=operator.itemgetter(1,2))
(4)reverse參數(shù)就不用多說了,是一個(gè)bool變量,默認(rèn)為false(升序排列),定義為True時(shí)將按降序排列。

sklearn方法

KNeighborsClassifier是一個(gè)類,它集成了其他的NeighborsBase,KNeighborsMixin,SupervisedIntegerMixin, ClassifierMixin。

__init__()

初始化函數(shù)(構(gòu)造函數(shù)) 它主要有一下幾個(gè)參數(shù):

n_neighbors=5 int 型參數(shù),knn算法中指定以最近的幾個(gè)最近鄰樣本具有投票權(quán),默認(rèn)參數(shù)為5

weights='uniform' str參數(shù),即每個(gè)擁有投票權(quán)的樣本是按什么比重投票,'uniform'表示等比重投票,'distance'表示按距離反比投票,[callable]表示自己定義的一個(gè)函數(shù), 這個(gè)函數(shù)接收一個(gè)距離數(shù)組,返回一個(gè)權(quán)值數(shù)組。默認(rèn)參數(shù)為‘uniform’

algrithm='auto' str參數(shù),即內(nèi)部采用什么算法實(shí)現(xiàn)。有以下幾種選擇參數(shù):'ball_tree':球樹、'kd_tree':kd樹、'brute':暴力搜索、'auto':自動(dòng)根據(jù)數(shù)據(jù)的類型和結(jié)構(gòu)選擇合適的算法。默認(rèn)情況下是‘a(chǎn)uto’。暴力搜索就不用說了大家都知道。具體前兩種樹型數(shù)據(jù)結(jié)構(gòu)哪種好視情況而定。KD樹是對依次對K維坐標(biāo)軸,以中值切分構(gòu)造的樹,每一個(gè)節(jié)點(diǎn)是一個(gè)超矩形,在維數(shù)小于20時(shí)效率最高--可以參看《統(tǒng)計(jì)學(xué)習(xí)方法》第二章。ball tree 是為了克服KD樹高維失效而發(fā)明的,其構(gòu)造過程是以質(zhì)心C和半徑r分割樣本空間,每一個(gè)節(jié)點(diǎn)是一個(gè)超球體。一般低維數(shù)據(jù)用kd_tree速度快,用ball_tree相對較慢。超過20維之后的高維數(shù)據(jù)用kd_tree效果反而不佳,而ball_tree效果要好,具體構(gòu)造過程及優(yōu)劣勢的理論大家有興趣可以去具體學(xué)習(xí)。

leaf_size=30 int參數(shù),基于以上介紹的算法,此參數(shù)給出了kd_tree或者ball_tree葉節(jié)點(diǎn)規(guī)模,葉節(jié)點(diǎn)的不同規(guī)模會(huì)影響數(shù)的構(gòu)造和搜索速度,同樣會(huì)影響儲(chǔ)樹的內(nèi)存的大小。具體最優(yōu)規(guī)模是多少視情況而定。

matric='minkowski' str或者距離度量對象,即怎樣度量距離。默認(rèn)是閔氏距離,閔氏距離不是一種具體的距離度量方法,它可以說包括了其他距離度量方式,是其他距離度量的推廣,具體各種距離度量只是參數(shù)p的取值不同或者是否去極限的不同情況,具體大家可以參考這里,講的非常詳細(xì)。                        

  p=2 int參數(shù) 就是以上閔氏距離各種不同的距離參數(shù),默認(rèn)為2,即歐氏距離。p=1代表曼哈頓距離等等

  metric_params=None 距離度量函數(shù)的額外關(guān)鍵字參數(shù),一般不用管,默認(rèn)為None

  n_jobs=1 int參數(shù) 指并行計(jì)算的線程數(shù)量,默認(rèn)為1表示一個(gè)線程,為-1的話表示為CPU的內(nèi)核數(shù),也可以指定為其他數(shù)量的線程,這里不是很追求速度的話不用管,需要用到的話去看看多線程。

.fit(traindata,trainlabels)

訓(xùn)練函數(shù),它是最主要的函數(shù)。參數(shù):訓(xùn)練數(shù)據(jù)集和標(biāo)簽集,其實(shí)該函數(shù)并不是KNeighborsClassifier這個(gè)類的方法,而是它的父類SupervisedIntegerMixin繼承下來的方法。

.predict(testdata)

預(yù)測函數(shù) 接收輸入的數(shù)組類型測試樣本,一般是二維數(shù)組,每一行是一個(gè)樣本,每一列是一個(gè)屬性返回?cái)?shù)組類型的預(yù)測結(jié)果,如果每個(gè)樣本只有一個(gè)輸出,則輸出為一個(gè)一維數(shù)組。如果每個(gè)樣本的輸出是多維的,則輸出二維數(shù)組,每一行是一個(gè)樣本,每一列是一維輸出。

predict_prob(testdata)

基于概率的軟判決,也是預(yù)測函數(shù),只是并不是給出某一個(gè)樣本的輸出是哪一個(gè)值,而是給出該輸出是各種可能值的概率各是多少接收參數(shù)和上面一樣返回參數(shù)和上面類似,只是上面該是值的地方全部替換成概率,比如說輸出結(jié)果又兩種選擇0或者1,上面的預(yù)測函數(shù)給出的是長為n的一維數(shù)組,代表各樣本一次的輸出是0還是1.而如果用概率預(yù)測函數(shù)的話,返回的是n*2的二維數(shù)組,每一行代表一個(gè)樣本,每一行有兩個(gè)數(shù),分別是該樣本輸出為0的概率為多少,輸出1的概率為多少。而各種可能的順序是按字典順序排列,比如先0后1,或者其他情況等等都是按字典順序排列。

score(testdata,reallabel,weigh)

計(jì)算準(zhǔn)確率的函數(shù),接受參數(shù)有3個(gè)。X:接收輸入的數(shù)組類型測試樣本,一般是二維數(shù)組,每一行是一個(gè)樣本,每一列是一個(gè)屬性。y:X這些預(yù)測樣本的真實(shí)標(biāo)簽,一維數(shù)組或者二維數(shù)組。sample_weight=None,是一個(gè)和X第一位一樣長的各樣本對準(zhǔn)確率影響的權(quán)重,一般默認(rèn)為None.輸出為一個(gè)float型數(shù),表示準(zhǔn)確率。內(nèi)部計(jì)算是按照predict()函數(shù)計(jì)算的結(jié)果記性計(jì)算的。其實(shí)該函數(shù)并不是KNeighborsClassifier這個(gè)類的方法,而是它的父類KNeighborsMixin繼承下來的方法。

kneighbors(目標(biāo)樣本,臨近樣本數(shù)量,是否返回距離值)

計(jì)算某些測試樣本的最近的幾個(gè)近鄰訓(xùn)練樣本。接收3個(gè)參數(shù)。X=None:需要尋找最近鄰的目標(biāo)樣本。n_neighbors=None,表示需要尋找目標(biāo)樣本最近的幾個(gè)最近鄰樣本,默認(rèn)為None,需要調(diào)用時(shí)給出。return_distance=True:是否需要同時(shí)返回具體的距離值。返回最近鄰的樣本在訓(xùn)練樣本中的序號(hào)。其實(shí)該函數(shù)并不是KNeighborsClassifier這個(gè)類的方法,而是它的父類KNeighborsMixin繼承下來的方法。

sklearn有數(shù)據(jù)集,需要引入: from sklearn import datasets

總結(jié)

以上是生活随笔為你收集整理的k近邻法(k-nearest neighbor, k-NN)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。