機(jī)器學(xué)習(xí)實(shí)戰(zhàn) K-近鄰算法

K-近鄰算法概述

簡(jiǎn)單地說(shuō)垂谢,k-近鄰算法采用測(cè)量不同特征值之間的距離的方法進(jìn)行分類疮茄。他的優(yōu)點(diǎn)是精度高、對(duì)異常值不敏感徙邻、無(wú)數(shù)據(jù)輸入設(shè)定畸裳。缺點(diǎn)是計(jì)算復(fù)雜度高、空間復(fù)雜度高怖糊。使用數(shù)據(jù)范圍為:數(shù)值型和標(biāo)稱型伍伤。

k-近鄰算法(kNN)的工作原理是:存在一個(gè)樣本數(shù)據(jù)集合,也稱作訓(xùn)練樣本集扰魂,并且樣本集合中每個(gè)數(shù)據(jù)都存在標(biāo)簽,即我們知道樣本集中每一數(shù)據(jù)與所屬分類的對(duì)應(yīng)關(guān)系姐直。輸入沒(méi)有標(biāo)簽的新數(shù)據(jù)后蒋畜,將新數(shù)據(jù)的每個(gè)特征與樣本集中數(shù)據(jù)對(duì)應(yīng)的特征進(jìn)行比較,然后算法提取樣本集中特征最相似(最近鄰)的分類標(biāo)簽插龄。一般來(lái)說(shuō)佣渴,我們只選擇樣本數(shù)據(jù)集中前k個(gè)最相似數(shù)據(jù)的數(shù)據(jù),這就是k-近鄰算法中k的出處膨处,通常,k是不大于20的整數(shù)真椿。最后突硝,選擇k個(gè)最相似的數(shù)據(jù)中出現(xiàn)的次數(shù)最多的分類,作為新數(shù)據(jù)的分類解恰。

k-近鄰算法的一般流程

  1. 收集數(shù)據(jù): 可以使用任何方法

  2. 準(zhǔn)備數(shù)據(jù):距離計(jì)算所需要的數(shù)值,最好是結(jié)構(gòu)化的數(shù)據(jù)格式

  3. 分析數(shù)據(jù):可以使用任何方法

  4. 訓(xùn)練算法:此步驟不適合k-近鄰算法

  5. 測(cè)試算法:計(jì)算錯(cuò)誤率

  6. 使用算法:首先需要輸入樣本數(shù)據(jù)和結(jié)構(gòu)化的輸出結(jié)果挟纱。然后運(yùn)行k-近鄰算法判定輸入數(shù)據(jù)分別屬于哪個(gè)分類腐宋,最后應(yīng)用對(duì)計(jì)算出的分類執(zhí)行后續(xù)的處理。

k-近鄰算法的實(shí)施

對(duì)未知類別屬性的數(shù)據(jù)集中的每個(gè)點(diǎn)依次執(zhí)行以下操作:

  1. 計(jì)算已知類別數(shù)據(jù)集中的點(diǎn)中的每個(gè)點(diǎn)與當(dāng)前點(diǎn)之間的距離

  2. 按照距離遞增次序排序

  3. 選取與當(dāng)前距離最小的k個(gè)點(diǎn)

  4. 確定前k個(gè)點(diǎn)所在類別的出現(xiàn)頻率

  5. 返回前k個(gè)點(diǎn)出現(xiàn)頻率最高的類別作為當(dāng)前點(diǎn)的預(yù)測(cè)分類

點(diǎn)與點(diǎn)之間的距離的算法有很多欺嗤,這里使用了歐氏距離公式:
\sqrt{(xA_0 - xB_0)^2 + (xA_1 - xB_1)^2}
?

例如煎饼,點(diǎn)(0,0)與(1,2)之間的距離計(jì)算為:?\sqrt{(1 - 0)^2 + (2 - 0)^2}

數(shù)據(jù)的歸一化

對(duì)于某些數(shù)據(jù)剃盾,其特征值之間的數(shù)值差異比較大淤袜,而差值最大的屬性對(duì)結(jié)果影響也很大。這會(huì)大大提高分類模型的錯(cuò)誤率积蔚。因此將該類數(shù)據(jù)歸一化是一個(gè)重要的操作烦周。下面的公式可以將任取值范圍的特征值轉(zhuǎn)換為0到1之間的值:?。其中漱贱,min和max分別是數(shù)據(jù)集中的最小特征值和最大特征值夭委。

如何測(cè)試分類器

分類器并不會(huì)得到百分百正確的結(jié)果,我們可以使用多種方法檢測(cè)分類器的正確率。此外分類器的性能也會(huì)受到多種因素的影響擎值,如分類器設(shè)置和數(shù)據(jù)集等逐抑。不同的算法在不同數(shù)據(jù)集上的表現(xiàn)可能完全不同。

為了測(cè)試分類器的效果进每,我們可以使用已知答案的數(shù)據(jù)命斧,檢驗(yàn)分類器給出的結(jié)果是否符合預(yù)期結(jié)果。通過(guò)大量的測(cè)試數(shù)據(jù)肉瓦,我們可以得到分類器的錯(cuò)誤率----分類器給出錯(cuò)誤結(jié)果的次數(shù)除以測(cè)試執(zhí)行的總數(shù)胃惜。錯(cuò)誤率是常用的評(píng)估方法,主要用于評(píng)估分類器在某個(gè)數(shù)據(jù)集上的執(zhí)行效果鲫趁。完美分類器的錯(cuò)誤率為0利虫,最差分類器的錯(cuò)誤率是1.0。

示例: 使用k-近鄰算法改進(jìn)約會(huì)網(wǎng)站的配對(duì)效果

數(shù)據(jù)集見(jiàn):datingTestSet.txt(提取碼:80ms)疫剃。數(shù)據(jù)一共分四列硼讽,前三列為三種特征,第四列為三種人物類型固阁。我們將通過(guò)前三種特征值备燃,生成一個(gè)kNN分類器,來(lái)預(yù)測(cè)不同人對(duì)于你的吸引力并齐。

飛行里程數(shù)/年 視頻游戲時(shí)間百分比 每周消費(fèi)冰激凌公升數(shù) 吸引力
40920 8.326976 0.953952 largeDoses
14488 7.153469 1.673904 smallDoses
26052 1.441871 0.805124 didntLike

約會(huì)網(wǎng)站K-近鄰分類器生成步驟:

  1. 收集數(shù)據(jù):提供文本文件

  2. 準(zhǔn)備數(shù)據(jù):使用python解析文本文件

  3. 測(cè)試算法:使用部分?jǐn)?shù)據(jù)作為測(cè)試樣本。計(jì)算分類器的錯(cuò)誤率

  4. 使用算法:產(chǎn)生簡(jiǎn)單的命令行程序唁奢,然后可以輸入一些特征數(shù)據(jù)以判斷對(duì)方是否為自己喜歡的類型麻掸。

python3代碼實(shí)現(xiàn)

#!/usr/bin/env python3
# coding: utf-8
# Author:Shen Yi
# Date :2020/2/13 21:19
?
"""機(jī)器學(xué)習(xí)實(shí)戰(zhàn) 第二章 k-近鄰算法
?
k-近鄰算法的完整實(shí)現(xiàn),包含了k-近鄰算法的距離計(jì)算脊奋,錯(cuò)誤率統(tǒng)計(jì)诚隙,數(shù)據(jù)集矩陣標(biāo)準(zhǔn)化以及一個(gè)戀愛(ài)網(wǎng)站的demo.
?
"""
?
from collections import Counter
from numpy import *
?
?
def knn_classify(in_x, data_set, labels, k_num):
    """ implementation of algorithm of knn
?
    calculation of distance between prediction and training, then sorted and extract the most common labels in top k_num closer data
?
     :param in_x: the vector to predict
     :param data_set: training data
     :param labels:  label of training data
     :param k_num:  number of k
     :return:  label of predict
 """
?
    # calculation of distance
    data_set_size = data_set.shape[0]
    diff_mat = tile(in_x, (data_set_size, 1)) - data_set
    distances = ((diff_mat ** 2).sum(axis=1)) ** 0.5
    sort_distances_index = distances.argsort()
?
    # extract the most common label
    vote_labels = [labels[index] for index in sort_distances_index[0: k_num]]
    most_label = Counter(vote_labels).most_common(1)[0][0]
    return most_label
?
?
def auto_norm(data_set):
    """data normalization"""
?
    min_vals = data_set.min(0)
    max_vals = data_set.max(0)
    ranges = max_vals - min_vals
    m = data_set.shape[0]
    norm_data_set = data_set - tile(min_vals, (m, 1))
    norm_data_set = norm_data_set / tile(ranges, (m, 1))
    return norm_data_set, ranges, min_vals
?
?
def dating_class_test(data_mat, labels, ho_ratio, k_num):
    """calculate the accuracy of the model"""
?
    m = data_mat.shape[0]
    error_count = 0
    number_test_vecs = int(m * ho_ratio)
    for i in range(number_test_vecs):
        classifier_rslt = knn_classify(data_mat[i, :], data_mat[number_test_vecs: m, :], labels[number_test_vecs: m], k_num)
        if classifier_rslt != labels[i]:
            error_count += 1
     print(f"the total error rate is: {error_count / number_test_vecs}")
     return error_count / number_test_vecs
?
?
def demo_date():
     """demo: used knn algorithm model to predict the matching effect of dating websites"""
?
     file_name = "data\\Ch02\\datingTestSet.txt"
     lines = open(file_name).readlines()
     lines_number = len(lines)
     data_mat = zeros((lines_number, 3))
     labels = []
     index = 0
     for line in lines:
         line = line.strip().split('\t')
         data_mat[index, :] = line[0: 3]
         labels.append(line[-1])
         index += 1
?
     norm_data_set, ranges, min_vals = auto_norm(data_mat)
     dating_class_test(norm_data_set, labels, 0.1, 3)
?
     percent_tas = float(input("percentage of time spent playing video games: "))
     ffmiles = float(input("frequent flier miles earned per year: "))
     ice_cream = float(input("liters of ice cream consumed per year:"))
     in_array = (array([ffmiles, percent_tas, ice_cream]) - min_vals) / ranges
     classifier_result = knn_classify(in_array, norm_data_set, labels, 3)
     print(f"you will probably like this person: {classifier_result}")
?
?
if __name__ == '__main__':
    demo_date()

運(yùn)行結(jié)果:

the total error rate is: 0.05
percentage of time spent playing video games: 10
frequent flier miles earned per year: 10000
liters of ice cream consumed per year:0.5
you will probably like this person: smallDoses</pre>

從結(jié)果可以看出巫延,該分類器的錯(cuò)誤率為5%地消,在輸出一組特征值后,得到了預(yù)期的分類標(biāo)簽脉执。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末半夷,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子淘邻,更是在濱河造成了極大的恐慌嗦随,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異署恍,居然都是意外死亡蜻直,警方通過(guò)查閱死者的電腦和手機(jī)袁串,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門呼巷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人破镰,你說(shuō)我怎么就攤上這事压储。” “怎么了孕似?”我有些...
    開(kāi)封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵刮刑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我臂拓,道長(zhǎng)习寸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任孵滞,我火速辦了婚禮鸯匹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘殴蓬。我一直安慰自己,他們只是感情好痘绎,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布孤页。 她就那樣靜靜地躺著涩馆,像睡著了一般允坚。 火紅的嫁衣襯著肌膚如雪蛾号。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天展运,我揣著相機(jī)與錄音轻腺,去河邊找鬼。 笑死贬养,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仰美。 我是一名探鬼主播儿礼,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼诉字!你這毒婦竟也來(lái)了知纷?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤伍绳,失蹤者是張志新(化名)和其女友劉穎乍桂,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體权谁,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忍疾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年卤妒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片则披。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡士复,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出便贵,到底是詐尸還是另有隱情冗荸,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布盔粹,位于F島的核電站程癌,受9級(jí)特大地震影響舷嗡,放射性物質(zhì)發(fā)生泄漏嵌莉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望只祠。 院中可真熱鬧,春花似錦熊杨、人聲如沸盗舰。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蛮位。三九已至较沪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間们何,已是汗流浹背控轿。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鹦蠕,地道東北人在抛。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像档悠,于是被迫代替她去往敵國(guó)和親望浩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355