本文風(fēng)格:以??簡(jiǎn)單易懂??的語(yǔ)言帶你徹底搞懂KNN,了解什么是有監(jiān)督學(xué)習(xí)算法。
認(rèn)真看完這篇文章,徹底了解KNN、了解監(jiān)督學(xué)習(xí)算法絕對(duì)是一樣很簡(jiǎn)單的事情。
注:本篇文章非常詳細(xì),同時(shí)我也附加了Python代碼,歡迎收藏后慢慢閱讀。
本文主要介紹的有監(jiān)督學(xué)習(xí)算法是KNN,后續(xù)會(huì)接著介紹決策樹、線性回歸等算法。
首先,第一個(gè)也是最主要的問(wèn)題——KNN是如何對(duì)樣本進(jìn)行分類的呢?
它的本質(zhì)是通過(guò)距離判斷兩個(gè)樣本是否相似,如果距離夠近就認(rèn)為他們足夠相似屬于同一類別。
當(dāng)然只對(duì)比一個(gè)樣本是不夠的,誤差會(huì)很大,我們需要找到離其最近的 k 個(gè)樣本,并將這些樣本稱之為「近鄰」(nearest neighbor)。對(duì)這 k 個(gè)近鄰,查看它們的都屬于何種類別(這些類別我們稱作「標(biāo)簽」 (labels))。
然后根據(jù)“少數(shù)服從多數(shù),一點(diǎn)算一票”原則進(jìn)行判斷,數(shù)量最多的的標(biāo)簽類別就是新樣本的標(biāo)簽類別。其中涉及到的原理是“越相近越相似”,這也是KNN的基本假設(shè)。
假設(shè) X_test 待標(biāo)記的數(shù)據(jù)樣本,X_train 為已標(biāo)記的數(shù)據(jù)集。
該算法的「距離」在二維坐標(biāo)軸就表示兩點(diǎn)之間的距離,計(jì)算距離的公式有很多。
我們常用歐拉公式,即“歐氏距離”?;貞浺幌拢粋€(gè)平面直角坐標(biāo)系上,如何計(jì)算兩點(diǎn)之間的距離?
應(yīng)該不難會(huì)想起來(lái)吧,公式應(yīng)該大致如下: d i s t a n c e ( A , B ) = ( x A ? x B ) 2 + ( y A ? y B ) 2 distance(A, B)=/sqrt[]{(x_A-x_B)^2+(y_A-y_B)^2} distance(A,B)=(xA??xB?)2+(yA??yB?)2?那如果不是在一個(gè)平面直角坐標(biāo)系,而是在立體直角坐標(biāo)系上,怎么計(jì)算呢? d i s t a n c e ( A , B ) = ( x A ? x B ) 2 + ( y A ? y B ) 2 + ( z A ? z B ) 2 distance(A, B)=/sqrt[]{(x_A-x_B)^2+(y_A-y_B)^2+(z_A-z_B)^2} distance(A,B)=(xA??xB?)2+(yA??yB?)2+(zA??zB?)2?那如果是n維空間呢? d i s t a n c e ( A , B ) = ( x 1 A ? x 1 B ) 2 + ( x 2 A ? x 2 B ) 2 + ( x 3 A ? x 3 B ) 2 + . . . . . . + ( x n A ? x n B ) 2 = ∑ i = 1 n ( x i A ? x i B ) 2 distance(A, B)=/sqrt[]{(x_{1A}-x_{1B})^2+(x_{2A}-x_{2B})^2+(x_{3A}-x_{3B})^2+......+(x_{nA}-x_{nB})^2}=/sqrt[]{/sum_{i=1}^{n} {(x_{iA}-x_{iB})^2}} distance(A,B)=(x1A??x1B?)2+(x2A??x2B?)2+(x3A??x3B?)2+......+(xnA??xnB?)2?=i=1∑n?(xiA??xiB?)2?而在我們的機(jī)器學(xué)習(xí)中,坐標(biāo)軸上的值 x 1 x_1 x1?, x 2 x_2 x2? , x 3 x_3 x3? ,…… x n x_n xn?正是我們樣本數(shù)據(jù)上的 n 個(gè)特征。
算法參數(shù)是 k,k 可以理解為標(biāo)記數(shù)據(jù)周圍幾個(gè)數(shù)作為參考對(duì)象,參數(shù)選擇需要根據(jù)數(shù)據(jù)來(lái)決定。
默認(rèn)情況下,在計(jì)算距離時(shí),權(quán)重都是相同的,但實(shí)際上我們可以針對(duì)不同的鄰居指定不同的距。離權(quán)重,比如距離越近權(quán)重越高。
使用一定半徑內(nèi)的點(diǎn)取代距離最近的 k 個(gè)點(diǎn)。
這里我還是先以上篇文章講到的紅酒分類為例子,待會(huì)還會(huì)有其他實(shí)例。
import numpy as npimport pandas as pdimport matplotlib.pyplot as plt# 解決坐標(biāo)軸刻度負(fù)號(hào)亂碼plt.rcParams["axes.unicode_minus"] = False# 解決中文亂碼問(wèn)題plt.rcParams["font.sans-serif"] = ["Simhei"]plt.style.use("ggplot")# plt.figure(figsize=(2,3),dpi=720)
首先隨機(jī)設(shè)置十個(gè)樣本點(diǎn)表示十杯酒,這里取了部分樣本點(diǎn)。
為了方便驗(yàn)證,這里使用 Python 的字典 dict 構(gòu)建數(shù)據(jù)集,然后再將其轉(zhuǎn)化成 DataFrame 格式。
rowdata = {"顏色深度": [14.23,13.2,13.16,14.37,13.24,12.07,12.43,11.79,12.37,12.04], "酒精濃度": [5.64,4.38,5.68,4.80,4.32,2.76,3.94,3.1,2.12,2.6], "品種": [0,0,0,0,0,1,1,1,1,1]} # 0 代表 “黑皮諾”,1 代表 “赤霞珠” wine_data = pd.DataFrame(rowdata)wine_data
X = np.array(wine_data.iloc[:,0:2]) #我們把特征(酒的屬性)放在X y = np.array(wine_data.iloc[:,-1]) #把標(biāo)簽(酒的類別)放在Y
我們先來(lái)畫一下圖。
#探索數(shù)據(jù),假如我們給出新數(shù)據(jù)[12.03,4.1] ,你能猜出這杯紅酒是什么類別么? new_data = np.array([12.03,4.1]) plt.scatter(X[y==1,0], X[y==1,1], color="red", label="赤霞珠") #畫出標(biāo)簽y為1 的、關(guān)于“赤霞珠”的散點(diǎn) plt.scatter(X[y==0,0], X[y==0,1], color="purple", label="黑皮諾") #畫出標(biāo)簽y為0 的、關(guān)于“黑皮諾”的散點(diǎn) plt.scatter(new_data[0],new_data[1], color="yellow") # 新數(shù)據(jù)點(diǎn) new_data plt.xlabel("酒精濃度") plt.ylabel("顏色深度") plt.legend(loc="lower right") plt.savefig("葡萄酒樣本.png")
講道理,你應(yīng)該一下就能看出來(lái)了。不過(guò),如果是計(jì)算機(jī),會(huì)這么分辨呢?
我們使用歐式距離公式,計(jì)算新數(shù)據(jù)點(diǎn) new_data 與現(xiàn)存的 X 數(shù)據(jù)集每一個(gè)點(diǎn)的距離:
from math import sqrt distance = [sqrt(np.sum((x-new_data)**2)) for x in X ] distance
那現(xiàn)在,我們就已經(jīng)得到黃點(diǎn)距離其它每個(gè)點(diǎn)的距離啦。
sort_dist = np.argsort(distance) # 這里是用到了argsort方法,可以返回?cái)?shù)據(jù)對(duì)應(yīng)的下標(biāo),如果直接用sort方法的話是返回打亂的數(shù)據(jù),我們也不好區(qū)分對(duì)應(yīng)是什么類別。sort_dist
array([6, 7, 1, 4, 5, 9, 2, 8, 3, 0], dtype=int64)
6、7、4為最近的3個(gè)“數(shù)據(jù)點(diǎn)”的索引值,那么這些索引值對(duì)應(yīng)的原數(shù)據(jù)的標(biāo)簽是什么?
k = 3 topK = [y[i] for i in sort_dist[:k]] topK
[1,1,0]
這個(gè)時(shí)候我們就得到了離黃點(diǎn)最近的三個(gè)點(diǎn)對(duì)應(yīng)的類別啦。
# 在numpy中有mean、median方法可以求平均數(shù)和中位數(shù),不過(guò)沒(méi)有方法直接求眾數(shù)。pd.Series(topK).value_counts().index[0]
1
所以當(dāng)我們的k取3時(shí),分類結(jié)果為1,也就是赤霞珠。大家看一下是不是跟我們?nèi)四X分辨的結(jié)果是一樣的呢?
那為了后續(xù)更好的操作,我們可以將上述過(guò)程封裝成一個(gè)函數(shù)。
def KNN(new_data,dataSet,k): """ 函數(shù)功能:KNN分類器 參數(shù)說(shuō)明: new_data: 需要預(yù)測(cè)分類的數(shù)據(jù)集 dataSet: 已知分類標(biāo)簽的數(shù)據(jù)集 k: k-近鄰算法參數(shù),選擇距離最小的k個(gè)點(diǎn) return: result: 分類結(jié)果 """ from math import sqrt from collections import Counter import numpy as np import pandas as pd result = [] distance = [sqrt(np.sum((x-new_data)**2)) for x in np.array(dataSet.iloc[:,0:2])] sort_dist = np.argsort(distance) topK = [dataSet.iloc[:,-1
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/119682.html
摘要:進(jìn)入當(dāng)前程序的學(xué)習(xí)系統(tǒng)的所有樣本稱作輸入,并組成輸入空間。結(jié)束語(yǔ)注意這篇文章僅僅是我接下來(lái)的機(jī)器學(xué)習(xí)系列的第一篇,后續(xù)還會(huì)有更多的內(nèi)容。 往期回顧:統(tǒng)計(jì)學(xué)習(xí)方法第...
摘要:小栗子對(duì)于可樂(lè)來(lái)講,只要是同一個(gè)品牌的可樂(lè),他們就有著同樣的成分,這被稱之為配方。小栗子對(duì)于可樂(lè)來(lái)說(shuō),按照配方把可樂(lè)生產(chǎn)出來(lái)的過(guò)程就是實(shí)例化的過(guò)程。小栗子類的屬性與正常的變量并無(wú)區(qū)別。 前言 我是栗子,帶大家從零開始學(xué)習(xí)Python,希望每篇文章都能讓你收獲滿滿! 今天我們要說(shuō)的是面向?qū)ο蟮?..
閱讀 3589·2021-09-22 10:52
閱讀 1600·2021-09-09 09:34
閱讀 2001·2021-09-09 09:33
閱讀 768·2019-08-30 15:54
閱讀 2687·2019-08-29 11:15
閱讀 726·2019-08-26 13:37
閱讀 1680·2019-08-26 12:11
閱讀 2987·2019-08-26 12:00