近朱者赤近墨者黑的K近鄰算法

一. KNN算法原理

KNN算法在機器學習里面,屬于相對簡單的算法。KNN即K近鄰(K Nerest Neighbor)算法,KNN算法原理用一句話說肺缕,就是“近朱者赤近墨者黑”原理。舉個例子吨些,KNN算法是知道我朋友的是什么人搓谆,來判斷我是什么人的算法。根據(jù)我所有的朋友中豪墅,如果我多數(shù)朋友屬于待人誠懇的人,那我多半也是個待人誠懇的人(:))黔寇。

二. KNN算法的步驟

KNN算法可以用于分類和回歸偶器,所謂的分類,比如要把電影分為功夫片缝裤,喜劇片屏轰,愛情片等,得到的值是相當于一個枚舉值憋飞;回歸問題霎苗,結果是連續(xù)值中的一個,比如要求一個人的身高榛做,求一個而房屋的房價估值唁盏,這就算回歸。

KNN算法检眯,中的K是距離待分類物體的K個離它最近的鄰居厘擂,一般套路是:

  • 計算要待分類與其他物體之間的距離。
  • 得到與待分類物體的最近的K個物體锰瘸。
  • 判斷這K個物體屬于什么類別刽严,那么這個待分類的物體就屬于什么類別。
    K近鄰算法從上面看出避凝,其實不需要擬合什么模型舞萄,只是基于存儲的算法眨补。
    也可以看出兩個最為關鍵:
    1.K值如何選擇?
    2.距離如何計算倒脓。
    K值不能選的太小撑螺,太小,有可能是噪音節(jié)點和待分類節(jié)點靠近把还,那么就造成分類的錯誤实蓬;如果K值過大,不在一類的物體分到一類里面了吊履,容易造成欠擬和安皱,有可能沒有把物體的分類真正分出來。

舉個例子:


K近鄰算法

如上面的例子:
1)選擇K=3的時候艇炎,離綠色待分類點最近的三個點中酌伊,2個屬于紅色三角形,1個屬于藍色正方形這一類缀踪,我們把綠色節(jié)點歸于紅色三角類居砖。
2)選擇K=5的時候,離綠色待分類點最近的5個點中驴娃,3個屬于藍色正方形類奏候,2個屬于紅色三角類,所以綠色待分類的節(jié)點屬于藍色正方形類唇敞。
至于這些藍色正方形和紅色三角形確定好的分類蔗草,是以前標記過的。
好的疆柔,下面來看看KNN中的幾種計算距離的算法:
歐式距離
1.歐式距離咒精,就是空間中兩個點的直線距離。
空間兩個點的坐標分別為:(x1,y1)和(x2,y2)那么它們的歐式距離為:

公式

這個公式其實就是求出了如下圖中的AB之間的這個斜線的長度旷档。

歐式距離

N維空間中的AB兩點的歐式距離公式為:
A點的坐標為(x1,x2,x3...xn)
B點的坐標為(y1,y2,y3...yn)


N維空間中AB兩點中歐式距離

曼哈頓距離
2.曼哈頓距離是兩點的坐標的之差的絕對值之和模叙。點A坐標為(x1,y1),點B的坐標為(x2,y2)
公式為:

曼哈頓距離公式

曼哈頓距離

圖中的黃色的和灰色也就是最外面兩個折線就是曼哈頓距離鞋屈,紅色和藍色也是等價的曼哈頓距離范咨,綠色的為上面說的歐式距離。

N維的曼哈頓距離為:


N維曼哈頓距離

切比雪夫距離
3.切比雪夫距離在 二維空間 內(nèi)谐区,兩個點之間的切比雪夫距離為它們橫坐標之差的絕對值與縱坐標之差的絕對值的最大值湖蜕。比如A點坐標為(X1,Y1) B點坐標為(X2,Y2) .則 A,B 之間的切比雪夫距離用公式可以表示為:

切比雪夫距離

閔可夫斯基距離
這個閔可夫斯基距離 不是一個距離,是一組距離的定義宋列,公式如下:

閔可夫斯基距離

p表示維度昭抒,如果p為1,則為曼哈頓距離,如果p為2則為歐式距離灭返,p為無窮大盗迟,則為切比雪距離。

余弦距離
余弦距離以前的文章有介紹熙含,其實算是求兩個向量的夾角罚缕,可以用來計算物品的相似度,或搜索文本的相似度怎静,適合做搜索邮弹。

KNN的近鄰算法需要大量計算兩個物體的距離,所以性能比較低蚓聘,為了提升性能腌乡,就有了KD數(shù),這是對N維向量的二叉樹表示的數(shù)據(jù)結構夜牡,

三 實戰(zhàn)

sklearn里面也有knn算法与纽,里面的核心函數(shù)說明如下:

def KNeighborsClassifier(n_neighbors = 5,
                       weights='uniform',
                       algorithm = '',
                       leaf_size = '30',
                       p = 2,
                       metric = 'minkowski',
                       metric_params = None,
                       n_jobs = None
                       )
                                       

參數(shù)說明:

  1. n_neighbors: 這個值就是指 KNN 中的 “K”。
  2. weights:權重塘装,這個參數(shù)有三個可選參數(shù)的值急迂,決定了如何分配權重。參數(shù)選項如下:
    ? 'uniform':不管遠近權重都一樣蹦肴,就是最普通的 KNN 算法的形式僚碎。
    ? 'distance':權重和距離成反比,距離預測目標越近具有越高的權重阴幌。
    ? 自定義函數(shù):自定義函數(shù)听盖,根據(jù)輸入的坐標值返回對應的權重,達到自定義權重的目的裂七。
  3. algorithm: 在 sklearn 中,要構建 KNN 模型有三種構建方式:
  • 暴力法仓坞,就是直接計算距離存儲比較的背零,適合小數(shù)據(jù)集合。
  • 使用 kd 樹構建 KNN 模型
  • 使用球樹構建无埃。
    如果數(shù)據(jù)量比較大一般會選擇用 KD 樹構建 KNN 模型徙瓶,而當 KD 樹也比較慢的時候,則可以試試球樹來構建 KNN嫉称。參數(shù)選項如下:
    ? 'brute' :蠻力實現(xiàn)
    ? 'kd_tree':KD 樹實現(xiàn) KNN 適合數(shù)據(jù)量大的情況
    ? 'ball_tree':球樹實現(xiàn) KNN 適合的數(shù)據(jù)量很大的情況侦镇。
    ? 'auto': 默認參數(shù),自動選擇合適的方法構建模型织阅。
    不過當數(shù)據(jù)較小或比較稀疏時壳繁,無論選擇哪個最后都會使用 'brute'
  1. leaf_size:如果是選擇蠻力實現(xiàn),那么這個值是可以忽略的,當使用KD樹或球樹闹炉,它就是是停止建子樹的葉子節(jié)點數(shù)量的閾值蒿赢。默認30,但如果數(shù)據(jù)量增多這個參數(shù)需要增大渣触,否則速度過慢不說羡棵,還容易過擬合。

  2. p:和metric結合使用的嗅钻,當metric參數(shù)是"minkowski"的時候皂冰,p=1為曼哈頓距離, p=2為歐式距離养篓。默認為p=2秃流。

  • metric:指定距離度量方法,一般都是使用歐式距離觉至。
    ? 'euclidean' :歐式距離
    ? 'manhattan':曼哈頓距離
    ? 'chebyshev':切比雪夫距離
    ? 'minkowski': 閔可夫斯基距離剔应,默認參數(shù)
    6.n_jobs:指定多少個CPU進行運算,默認是-1语御,也就是全部都算峻贮。

利用sklearn里面的手寫數(shù)據(jù)集合做測試,手寫數(shù)據(jù)集合一共有1797個樣本应闯,每個樣本都是8*8 個像素點纤控,每個點的值為一個0-255的灰度值,可以先運行看看數(shù)據(jù)情況:

from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_digits
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt


# 加載數(shù)據(jù)
digits = load_digits()
data = digits.data
# 數(shù)據(jù)探索
print(data.shape)
# 查看第2幅圖像
print(digits.images[1])
# 第2幅圖像代表的數(shù)字含義
print(digits.target[1])
# 將第2幅圖像顯示出來
plt.gray()
plt.imshow(digits.images[1])
plt.show()
數(shù)據(jù)展示

最后展示下課中代碼碉纺,注意這里面在做多項式樸素貝葉斯分類的時候采用的是采用Min-Max規(guī)范化船万,是因為算法不準許為負數(shù)。

from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_digits
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt


# 加載數(shù)據(jù)
digits = load_digits()
#這個data可以看成一個二維數(shù)組骨田,第一維度為1797個耿导,
#每一個是由一個8*8個像素點的灰度值組成
data = digits.data
# 數(shù)據(jù)探索
print(data.shape)
# 查看第2幅圖像
print(digits.images[1])
# 第2幅圖像代表的數(shù)字含義
print(digits.target[1])
# 將第2幅圖像顯示出來
plt.gray()
plt.imshow(digits.images[1])
plt.show()

# 分割數(shù)據(jù),將20%的數(shù)據(jù)作為測試集态贤,其余作為訓練集
train_x, test_x, train_y, test_y = train_test_split(data, digits.target, test_size=0.2, random_state=33)
# 采用Z-Score規(guī)范化
ss = preprocessing.StandardScaler()
train_ss_x = ss.fit_transform(train_x)
test_ss_x = ss.transform(test_x)


# 創(chuàng)建KNN分類器
knn = KNeighborsClassifier() 
knn.fit(train_ss_x, train_y) 
predict_y = knn.predict(test_ss_x) 
print("KNN準確率: %.4lf" % accuracy_score(test_y, predict_y))



# 創(chuàng)建SVM分類器
svm = SVC()
svm.fit(train_ss_x, train_y)
predict_y=svm.predict(test_ss_x)
print('SVM準確率: %0.4lf' % accuracy_score(test_y, predict_y))
# 采用Min-Max規(guī)范化
mm = preprocessing.MinMaxScaler()
train_mm_x = mm.fit_transform(train_x)
test_mm_x = mm.transform(test_x)
# 創(chuàng)建Naive Bayes分類器
mnb = MultinomialNB()
mnb.fit(train_mm_x, train_y) 
predict_y = mnb.predict(test_mm_x) 
print("多項式樸素貝葉斯準確率: %.4lf" % accuracy_score(test_y, predict_y))


# 創(chuàng)建CART決策樹分類器
dtc = DecisionTreeClassifier()
dtc.fit(train_mm_x, train_y) 
predict_y = dtc.predict(test_mm_x) 
print("CART決策樹準確率: %.4lf" % accuracy_score(test_y, predict_y))

看下結果:


計算結果
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舱呻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子悠汽,更是在濱河造成了極大的恐慌箱吕,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柿冲,死亡現(xiàn)場離奇詭異茬高,居然都是意外死亡,警方通過查閱死者的電腦和手機假抄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門怎栽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丽猬,“玉大人,你說我怎么就攤上這事婚瓜”模” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵巴刻,是天一觀的道長愚铡。 經(jīng)常有香客問我,道長胡陪,這世上最難降的妖魔是什么沥寥? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮柠座,結果婚禮上邑雅,老公的妹妹穿的比我還像新娘。我一直安慰自己妈经,他們只是感情好淮野,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著吹泡,像睡著了一般骤星。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上爆哑,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天洞难,我揣著相機與錄音,去河邊找鬼揭朝。 笑死队贱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的潭袱。 我是一名探鬼主播柱嫌,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼屯换!你這毒婦竟也來了慎式?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤趟径,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后癣防,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜗巧,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年蕾盯,在試婚紗的時候發(fā)現(xiàn)自己被綠了幕屹。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖望拖,靈堂內(nèi)的尸體忽然破棺而出渺尘,到底是詐尸還是另有隱情,我是刑警寧澤说敏,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布鸥跟,位于F島的核電站,受9級特大地震影響盔沫,放射性物質(zhì)發(fā)生泄漏医咨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一架诞、第九天 我趴在偏房一處隱蔽的房頂上張望拟淮。 院中可真熱鬧,春花似錦谴忧、人聲如沸很泊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽委造。三九已至,卻和暖如春搏屑,著一層夾襖步出監(jiān)牢的瞬間争涌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工辣恋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亮垫,地道東北人。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓伟骨,卻偏偏與公主長得像饮潦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子携狭,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349