python機(jī)器學(xué)習(xí)之KNN分類(lèi)算法
本文為大家分享了python機(jī)器學(xué)習(xí)之KNN分類(lèi)算法,供大家參考,具體內(nèi)容如下
1、KNN分類(lèi)算法
KNN分類(lèi)算法(K-Nearest-Neighbors Classification),又叫K近鄰算法,是一個(gè)概念極其簡(jiǎn)單,而分類(lèi)效果又很優(yōu)秀的分類(lèi)算法。
他的核心思想就是,要確定測(cè)試樣本屬于哪一類(lèi),就尋找所有訓(xùn)練樣本中與該測(cè)試樣本“距離”最近的前K個(gè)樣本,然后看這K個(gè)樣本大部分屬于哪一類(lèi),那么就認(rèn)為這個(gè)測(cè)試樣本也屬于哪一類(lèi)。簡(jiǎn)單的說(shuō)就是讓最相似的K個(gè)樣本來(lái)投票決定。
這里所說(shuō)的距離,一般最常用的就是多維空間的歐式距離。這里的維度指特征維度,即樣本有幾個(gè)特征就屬于幾維。
KNN示意圖如下所示。(圖片來(lái)源:百度百科)

上圖中要確定測(cè)試樣本綠色屬于藍(lán)色還是紅色。
顯然,當(dāng)K=3時(shí),將以1:2的投票結(jié)果分類(lèi)于紅色;而K=5時(shí),將以3:2的投票結(jié)果分類(lèi)于藍(lán)色。
KNN算法簡(jiǎn)單有效,但沒(méi)有優(yōu)化的暴力法效率容易達(dá)到瓶頸。如樣本個(gè)數(shù)為N,特征維度為D的時(shí)候,該算法時(shí)間復(fù)雜度呈O(DN)增長(zhǎng)。
所以通常KNN的實(shí)現(xiàn)會(huì)把訓(xùn)練數(shù)據(jù)構(gòu)建成K-D Tree(K-dimensional tree),構(gòu)建過(guò)程很快,甚至不用計(jì)算D維歐氏距離,而搜索速度高達(dá)O(D*log(N))。
不過(guò)當(dāng)D維度過(guò)高,會(huì)產(chǎn)生所謂的”維度災(zāi)難“,最終效率會(huì)降低到與暴力法一樣。
因此通常D>20以后,最好使用更高效率的Ball-Tree,其時(shí)間復(fù)雜度為O(D*log(N))。
人們經(jīng)過(guò)長(zhǎng)期的實(shí)踐發(fā)現(xiàn)KNN算法雖然簡(jiǎn)單,但能處理大規(guī)模的數(shù)據(jù)分類(lèi),尤其適用于樣本分類(lèi)邊界不規(guī)則的情況。最重要的是該算法是很多高級(jí)機(jī)器學(xué)習(xí)算法的基礎(chǔ)。
當(dāng)然,KNN算法也存在一切問(wèn)題。比如如果訓(xùn)練數(shù)據(jù)大部分都屬于某一類(lèi),投票算法就有很大問(wèn)題了。這時(shí)候就需要考慮設(shè)計(jì)每個(gè)投票者票的權(quán)重了。
2、測(cè)試數(shù)據(jù)
測(cè)試數(shù)據(jù)的格式仍然和前面使用的身高體重?cái)?shù)據(jù)一致。不過(guò)數(shù)據(jù)增加了一些:
1.5 40 thin
1.5 50 fat
1.5 60 fat
1.6 40 thin
1.6 50 thin
1.6 60 fat
1.6 70 fat
1.7 50 thin
1.7 60 thin
1.7 70 fat
1.7 80 fat
1.8 60 thin
1.8 70 thin
1.8 80 fat
1.8 90 fat
1.9 80 thin
1.9 90 fat
3、Python代碼
scikit-learn提供了優(yōu)秀的KNN算法支持。使用Python代碼如下:
# -*- coding: utf-8 -*-
import numpy as np
from sklearn import neighbors
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import classification_report
from sklearn.cross_validation import train_test_split
import matplotlib.pyplot as plt
''' 數(shù)據(jù)讀入 '''
data = []
labels = []
with open("data\\1.txt") as ifile:
for line in ifile:
tokens = line.strip().split(' ')
data.append([float(tk) for tk in tokens[:-1]])
labels.append(tokens[-1])
x = np.array(data)
labels = np.array(labels)
y = np.zeros(labels.shape)
''' 標(biāo)簽轉(zhuǎn)換為0/1 '''
y[labels=='fat']=1
''' 拆分訓(xùn)練數(shù)據(jù)與測(cè)試數(shù)據(jù) '''
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2)
''' 創(chuàng)建網(wǎng)格以方便繪制 '''
h = .01
x_min, x_max = x[:, 0].min() - 0.1, x[:, 0].max() + 0.1
y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
''' 訓(xùn)練KNN分類(lèi)器 '''
clf = neighbors.KNeighborsClassifier(algorithm='kd_tree')
clf.fit(x_train, y_train)
'''測(cè)試結(jié)果的打印'''
answer = clf.predict(x)
print(x)
print(answer)
print(y)
print(np.mean( answer == y))
'''準(zhǔn)確率與召回率'''
precision, recall, thresholds = precision_recall_curve(y_train, clf.predict(x_train))
answer = clf.predict_proba(x)[:,1]
print(classification_report(y, answer, target_names = ['thin', 'fat']))
''' 將整個(gè)測(cè)試空間的分類(lèi)結(jié)果用不同顏色區(qū)分開(kāi)'''
answer = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:,1]
z = answer.reshape(xx.shape)
plt.contourf(xx, yy, z, cmap=plt.cm.Paired, alpha=0.8)
''' 繪制訓(xùn)練樣本 '''
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap=plt.cm.Paired)
plt.xlabel(u'身高')
plt.ylabel(u'體重')
plt.show()
4、結(jié)果分析
其輸出結(jié)果如下:
[ 0. 0. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1.]
[ 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1.]
準(zhǔn)確率=0.94, score=0.94
precision recall f1-score support
thin 0.89 1.00 0.94 8
fat 1.00 0.89 0.94 9
avg / total 0.95 0.94 0.94 17

KNN分類(lèi)器在眾多分類(lèi)算法中屬于最簡(jiǎn)單的之一,需要注意的地方不多。有這幾點(diǎn)要說(shuō)明:
1、KNeighborsClassifier可以設(shè)置3種算法:‘brute',‘kd_tree',‘ball_tree'。如果不知道用哪個(gè)好,設(shè)置‘a(chǎn)uto'讓KNeighborsClassifier自己根據(jù)輸入去決定。
2、注意統(tǒng)計(jì)準(zhǔn)確率時(shí),分類(lèi)器的score返回的是計(jì)算正確的比例,而不是R2。R2一般應(yīng)用于回歸問(wèn)題。
3、本例先根據(jù)樣本中身高體重的最大最小值,生成了一個(gè)密集網(wǎng)格(步長(zhǎng)h=0.01),然后將網(wǎng)格中的每一個(gè)點(diǎn)都當(dāng)成測(cè)試樣本去測(cè)試,最后使用contourf函數(shù),使用不同的顏色標(biāo)注出了胖、廋兩類(lèi)。
容易看到,本例的分類(lèi)邊界,屬于相對(duì)復(fù)雜,但卻又與距離呈現(xiàn)明顯規(guī)則的鋸齒形。
這種邊界線性函數(shù)是難以處理的。而KNN算法處理此類(lèi)邊界問(wèn)題具有天生的優(yōu)勢(shì)。我們?cè)诤罄m(xù)的系列中會(huì)看到,這個(gè)數(shù)據(jù)集達(dá)到準(zhǔn)確率=0.94算是很優(yōu)秀的結(jié)果了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解使用python3.7配置開(kāi)發(fā)釘釘群自定義機(jī)器人(2020年新版攻略)
這篇文章主要介紹了詳解使用python3.7配置開(kāi)發(fā)釘釘群自定義機(jī)器人(2020年新版攻略),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04
基于Python實(shí)現(xiàn)數(shù)據(jù)庫(kù)表結(jié)構(gòu)導(dǎo)出工具
這篇文章主要為大家詳細(xì)介紹了如何基于Python實(shí)現(xiàn)將數(shù)據(jù)庫(kù)表結(jié)構(gòu)導(dǎo)出到 Word 文檔的實(shí)用工具,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04
實(shí)例解析Python的Twisted框架中Deferred對(duì)象的用法
Deferred對(duì)象在Twsited框架中用于處理回調(diào),這對(duì)于依靠異步的Twisted來(lái)說(shuō)十分重要,接下來(lái)我們就以實(shí)例解析Python的Twisted框架中Deferred對(duì)象的用法2016-05-05
pytest?用例執(zhí)行失敗后其他不再執(zhí)行
本文主要介紹了pytest?用例執(zhí)行失敗后其他不再執(zhí)行,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
使用Python的urllib2模塊處理url和圖片的技巧兩則
這篇文章主要介紹了使用Python的urllib2模塊處理url和圖片的兩個(gè)小技巧,分別是獲取帶有中文參數(shù)的url內(nèi)容和獲取遠(yuǎn)程圖片的大小和尺寸,需要的朋友可以參考下2016-02-02
Python sqrt()函數(shù)用法說(shuō)明
這篇文章主要介紹了Python sqrt()函數(shù)用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
Tensorflow 定義變量,函數(shù),數(shù)值計(jì)算等名字的更新方式
今天小編就為大家分享一篇Tensorflow 定義變量,函數(shù),數(shù)值計(jì)算等名字的更新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
Python unittest裝飾器實(shí)現(xiàn)原理及代碼
這篇文章主要介紹了Python unittest裝飾器實(shí)現(xiàn)原理及代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09

