k-近鄰算法(kNN)

最近開始學習《機器學習實戰(zhàn)》這本書,以下是在學習過程中學到的一些python基礎(chǔ)知識以及算法思想袖外。
python版本:3.6

1奏甫、算法核心思想概述

算法思想:k-近鄰算法采用測量不同特征值之間的距離方法進行分類扶供。
優(yōu)點:精度高囤耳、對異常值不敏感、無數(shù)據(jù)輸入假定
缺點:計算復(fù)雜度高面褐、空間復(fù)雜度高
適用數(shù)據(jù)范圍:數(shù)值型拌禾、標稱型

一個樣本在特征空間里k個距離最短的樣本中,大多數(shù)樣本屬于A類展哭,則這個樣本也屬于A類湃窍。

1.1 k-近鄰算法的一般流程

(1)收集數(shù)據(jù):可以使用任何方法
(2)準備數(shù)據(jù):距離計算所需的數(shù)值,最好是結(jié)構(gòu)化的數(shù)據(jù)格式
(3)分析數(shù)據(jù):可以使用任何方法
(4)測試數(shù)據(jù):計算錯誤率
(5)使用算法:首先需要輸入樣本數(shù)據(jù)和結(jié)構(gòu)化的輸出結(jié)果匪傍,然后運行kNN算法判定輸入數(shù)據(jù)屬于哪個分類您市,最后應(yīng)用對計算出的分類執(zhí)行后續(xù)的處理。

1.2 分類函數(shù)

本函數(shù)的功能為:使用kNN算法將每組數(shù)據(jù)劃分到某個類別中役衡。首先計算出特征向量間的距離茵休,然后選取與當前距離最小的k個點,并通過這k個點類別出現(xiàn)的頻率來確定當前點的預(yù)測分類。
在最初的學習中遇到以下幾個python相關(guān)的基礎(chǔ)知識:
(1)shape函數(shù)
a.shape[0]計算行數(shù)
a.shape[1]計算列數(shù)
(2)title函數(shù)

>>>a = array([1,2])
>>>title(a, (3,2))
array([[1, 2, 1, 2],
       [1, 2, 1, 2],
       [1, 2, 1, 2]])

(3)axis=0 矩陣每一列相加榕莺, axis=1矩陣每一行相加
(4)argsort函數(shù):返回數(shù)組的索引值
(5)dict.get(key, default=None)
key:要查找的鍵俐芯;default:指定鍵的值不存在則返回默認值。
以下是算法詳細代碼:

from numpy import *
import operator


def createDataSet():
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels


def classify0(inK, dataSet, labels, k):
    # 計算訓(xùn)練樣本的行數(shù)钉鸯,也就是有幾組訓(xùn)練樣本
    dataSetSize = dataSet.shape[0]
    # 將新樣本與每一個訓(xùn)練樣本相減
    diffMat = tile(inK, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat ** 2
    # 將結(jié)果每一行相加泼各,平方和
    sqDistances = sqDiffMat.sum(axis=1)
    # 求距離
    distances = sqDistances ** 0.5
    # 將距離按照從小到大順序排列
    sortedDistIndicies = distances.argsort()  # argsort返回的是索引值
    classCount = {}
    # 選取與當前點距離最小的K個點,確定前K個點所在類別的出現(xiàn)頻率
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    # 將前K個值按照出現(xiàn)頻率最高的類別進行逆序排序
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

執(zhí)行代碼如下

import kNN

input = [3, 0]
group, labels = kNN.createDataSet()
output = kNN.classify0(input, group, labels, 3)
print("分類結(jié)果為:", output)

源碼下載

2亏拉、改進約會網(wǎng)站配對效果

示例內(nèi)容:產(chǎn)生簡單的命令行程序,用戶可以輸入一些特征數(shù)據(jù)來判斷對方是否為自己喜歡的類型逆巍。

2.1準備數(shù)據(jù):從文本文件中解析數(shù)據(jù)

此時數(shù)據(jù)已經(jīng)存放在文本文件中及塘,在將數(shù)據(jù)輸入到分類器之前,需要將待處理的數(shù)據(jù)變成分類器可以接受的格式锐极。(數(shù)據(jù)為看數(shù)據(jù)所占時間數(shù)笙僚、每年的飛行里程數(shù)、每周消耗的冰淇淋公升數(shù))
創(chuàng)建一個file2matrix的函數(shù)灵再,用來解析數(shù)據(jù)肋层。函數(shù)的輸入為文件名稱字符,輸出為訓(xùn)練樣本矩陣和類標簽向量翎迁。
以下是學到的一些小知識:
(1)readlines()函數(shù)
使用方法:fileObject.readlines( );
返回值:返回列表栋猖,包含所有的行
(2)numpy高維數(shù)組操作
本部分主要是想提一下以slice的方式來獲取數(shù)據(jù)
下圖來自博客園

555058-20160922145821965-2072195840.png

以下是算法詳細代碼:

def file2matrix(filename):
    # 得到文件的行數(shù)
    fr = open(filename)
    arrayOLines = fr.readlines()
    numberOfLines = len(arrayOLines)
    # 創(chuàng)建返回的numpy矩陣,矩陣使用0填充,numberOfLines行汪榔,3列
    returnMat = zeros((numberOfLines, 3))
    classLabelVector = []
    index = 0
    # 解析文件數(shù)據(jù)到列表蒲拉,循環(huán)處理文件中的每行數(shù)據(jù)
    for line in arrayOLines:
        # 去掉每行回車字符
        line = line.strip()
        # 將上一步得到的整行數(shù)據(jù)分割成一個元素列表    
        listFromLine = line.split('\t')
        # 選取列表的前3個元素并存儲到特征向量中
        returnMat[index, :] = listFromLine[0:3]
        # 將列表的最后一列存儲到向量中
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector

在測試結(jié)果時,需要重載kNN模塊痴腌,需要導(dǎo)入模塊importlib
然后輸入如下命令:

importlib.reload(kNN)
datingDataMat, datingLabels = kNN.file2matrix('datingTestSet2.txt')

2.2分析數(shù)據(jù):使用Matplotlib創(chuàng)建散點圖

本部分主要采用直觀的圖表來分析數(shù)據(jù)結(jié)構(gòu)雌团。
以下是算法詳細代碼:

import kNN
import numpy
import matplotlib
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,0], datingDataMat[:,1], 15.0*numpy.array(datingLabels), 15.0*numpy.array(datingLabels))
plt.show()

2.3準備數(shù)據(jù):歸一化數(shù)值

由于kNN算法就是在求方差,數(shù)值偏大的屬性值的影響遠遠大于數(shù)值偏小的屬性值士聪。故需要將數(shù)據(jù)進行歸一化處理锦援,通常將取值范圍處理為0到1或-1到1之間。
以下是算法詳細代碼

def autoNorm(dataSet):
    # 參數(shù)0指取列的最值
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m, 1))
    normDataSet = normDataSet / tile(ranges, (m, 1))
    return normDataSet, ranges, minVals

2.4測試算法:作為完整程序驗證分類器

機器學習一個非常重要的工作就是評估算法的正確率剥悟,通常使用已有數(shù)據(jù)的90%作為訓(xùn)練樣本來訓(xùn)練分類器灵寺,剩余10%的數(shù)據(jù)用于測試分類器∨嘲可以使用錯誤率來檢測分類器的性能替久。對于分類器而言,錯誤率就是分類器給出錯誤結(jié)果的次數(shù)除以測試數(shù)據(jù)的總數(shù)躏尉。
算法過程
此算法首先使用file2matrixautoNorm函數(shù)從文件讀取數(shù)據(jù)并將數(shù)據(jù)歸一化處理蚯根。接著確定哪些數(shù)據(jù)用于測試,哪些數(shù)據(jù)用做訓(xùn)練樣本,然后將這兩部分數(shù)據(jù)輸入到分類器函數(shù)classify0颅拦,最后輸出錯誤率蒂誉。
以下是算法詳細代碼

def datingClassTest() -> object:
    # 選取多少數(shù)據(jù)測試分類器
    hoRatio = 0.10
    # 得到數(shù)據(jù)矩陣和標簽向量
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    # 歸一化處理矩陣
    normMat, ranges, minVals = autoNorm(datingDataMat)
    # 獲取矩陣的行數(shù)
    m = normMat.shape[0]
    # 設(shè)置測試個數(shù)(10%)
    numTestVecs = int(m * hoRatio)
    errorCount = 0.0
    for i in range(numTestVecs):
        #第一個參數(shù):前10%的數(shù)據(jù)用于inX;第二個參數(shù):后90%用戶dataSet;第三個參數(shù):后90%的數(shù)據(jù)的標簽;k=3
        classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
        print("分類后的結(jié)果為:,", classifierResult, "原結(jié)果為:", datingLabels[i])
        if (classifierResult != datingLabels[i]):
            errorCount += 1.0
    print("錯誤率是:", (errorCount / float(numTestVecs)))

2.5使用算法:構(gòu)建完整可用系統(tǒng)

現(xiàn)在通過輸入看數(shù)據(jù)所占時間數(shù)距帅、每年的飛行里程數(shù)右锨、每周消耗的冰淇淋公升數(shù)這些數(shù)據(jù)來給出喜歡對方程度的預(yù)測值。
以下是算法詳細代碼

def classifyPerson():
    resultList = ['一點也不喜歡', '有一點喜歡', '非常喜歡']
    percentTats = float(input("看視頻所占的時間比:"))
    miles = float(input("每年的飛行里程數(shù):"))
    iceCream = float(input("每周消耗的冰淇淋公升數(shù):"))
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
    normMat, ranges, minVals = autoNorm(datingDataMat)
    inArr = array([miles, percentTats, iceCream])
    classifierResult = classify0((inArr - minVals) / ranges, normMat, datingLabels, 3)
    print("你對這個人的喜歡程度:", resultList[classifierResult - 1])

源碼下載
個人主頁
未完碌秸。绍移。。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末讥电,一起剝皮案震驚了整個濱河市蹂窖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恩敌,老刑警劉巖瞬测,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纠炮,居然都是意外死亡月趟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門恢口,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孝宗,“玉大人,你說我怎么就攤上這事弧蝇√及” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵看疗,是天一觀的道長沙峻。 經(jīng)常有香客問我,道長两芳,這世上最難降的妖魔是什么摔寨? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮怖辆,結(jié)果婚禮上是复,老公的妹妹穿的比我還像新娘。我一直安慰自己竖螃,他們只是感情好淑廊,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著特咆,像睡著了一般季惩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天画拾,我揣著相機與錄音啥繁,去河邊找鬼。 笑死青抛,一個胖子當著我的面吹牛旗闽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蜜另,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼适室,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了举瑰?” 一聲冷哼從身側(cè)響起亭病,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘶居,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體促煮,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡邮屁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了菠齿。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佑吝。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绳匀,靈堂內(nèi)的尸體忽然破棺而出芋忿,到底是詐尸還是另有隱情,我是刑警寧澤疾棵,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布戈钢,位于F島的核電站,受9級特大地震影響是尔,放射性物質(zhì)發(fā)生泄漏殉了。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一拟枚、第九天 我趴在偏房一處隱蔽的房頂上張望薪铜。 院中可真熱鬧,春花似錦恩溅、人聲如沸隔箍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜒滩。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帮掉,已是汗流浹背弦悉。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蟆炊,地道東北人稽莉。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像涩搓,于是被迫代替她去往敵國和親污秆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容