機器學習實戰2.1. 超詳細的k-近鄰演算法KNN(附Python程式碼)
機器學習實戰2.1. 超詳細的k-近鄰演算法KNN(附Python程式碼)
搜尋微信公眾號:‘AI-ming3526’或者’計算機視覺這件小事’ 獲取更多機器學習乾貨
csdn:https://blog.csdn.net/baidu_31657889/
github:https://github.com/aimi-cn/AILearners
本文參考地址:[apachecn/AiLearning]
本文出現的所有程式碼,均可在github上下載,不妨來個Star把謝謝~:Github程式碼地址
KNN 概述
k-近鄰(kNN, k-NearestNeighbor)演算法是一種基本分類與迴歸方法,我們這裡只討論分類問題中的 k-近鄰演算法。
一句話總結:近朱者赤近墨者黑!
工作原理:
存在一個樣本資料集合,也稱作為訓練樣本集,並且樣本集中每個資料都存在標籤,即我們知道樣本集中每一個資料與所屬分類的對應關係。輸入沒有標籤的新資料後,將新的資料的每個特徵與樣本集中資料對應的特徵進行比較,然後演算法提取樣本最相似資料(最近鄰)的分類標籤。一般來說,我們只選擇樣本資料集中前k個最相似的資料,這就是k-近鄰演算法中k的出處,通常k是不大於20的整數。最後,選擇k個最相似資料中出現次數最多的分類,作為新資料的分類。
k近鄰演算法的輸入為例項的特徵向量,對應於特徵空間的點;輸出為例項的類別,可以取多類。k 近鄰演算法假設給定一個訓練資料集,其中的例項類別已定。分類時,對新的例項,根據其 k 個最近鄰的訓練例項的類別,通過多數表決等方式進行預測。因此,k近鄰演算法不具有顯式的學習過程。
k近鄰演算法實際上利用訓練資料集對特徵向量空間進行劃分,並作為其分類的“模型”。 k值的選擇、距離度量以及分類決策規則是k近鄰演算法的三個基本要素。
KNN 場景
電影可以按照題材分類,那麼如何區分 動作片
和 愛情片
呢?
- 動作片:打鬥次數更多
- 愛情片:親吻次數更多
基於電影中的親吻、打鬥出現的次數,使用 k-近鄰演算法構造程式,就可以自動劃分電影的題材型別。
現在根據上面我們得到的樣本集中所有電影與未知電影的距離,按照距離遞增排序,可以找到 k 個距離最近的電影。
假定 k=3,則三個最靠近的電影依次是, He’s Not Really into Dudes 、 Beautiful Woman 和 California Man。
knn 演算法按照距離最近的三部電影的型別,決定未知電影的型別,而這三部電影全是愛情片,因此我們判定未知電影是愛情片。
對於K近鄰演算法概念還沒搞太清楚的同學 可以往下面看 直到看完整個demo你就可以理解KNN演算法是幹啥的了
KNN 原理
KNN 工作原理
- 假設有一個帶有標籤的樣本資料集(訓練樣本集),其中包含每條資料與所屬分類的對應關係。
- 輸入沒有標籤的新資料後,將新資料的每個特徵與樣本集中資料對應的特徵進行比較。
- 計算新資料與樣本資料集中每條資料的距離。
- 對求得的所有距離進行排序(從小到大,越小表示越相似)。
- 取前 k (k 一般小於等於 20 )個樣本資料對應的分類標籤。
- 求 k 個資料中出現次數最多的分類標籤作為新資料的分類。
KNN 通俗理解
給定一個訓練資料集,對新的輸入例項,在訓練資料集中找到與該例項最鄰近的 k 個例項,這 k 個例項的多數屬於某個類,就把該輸入例項分為這個類。
KNN 開發流程
收集資料:任何方法
準備資料:距離計算所需要的數值,最好是結構化的資料格式
分析資料:任何方法
訓練演算法:此步驟不適用於 k-近鄰演算法
測試演算法:計算錯誤率
使用演算法:輸入樣本資料和結構化的輸出結果,然後執行 k-近鄰演算法判斷輸入資料分類屬於哪個分類,最後對計算出的分類執行後續處理
KNN 演算法特點
優點:精度高、對異常值不敏感、無資料輸入假定
缺點:計算複雜度高、空間複雜度高
適用資料範圍:數值型和標稱型
話不多說直接上程式碼:
程式碼地址:https://github.com/aimi-cn/AILearners/tree/master/src/py2.x/ml/jqxxsz/2.KNN/KNN.py
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File : KNN.py
@Time : 2019/03/27 11:07:01
@Author : xiao ming
@Version : 1.0
@Contact : xiaoming3526@gmail.com
@Desc : KNN近鄰演算法
@github : https://github.com/aimi-cn/AILearners
@reference: https://github.com/apachecn/AiLearning
'''
# here put the import lib
from __future__ import print_function
from numpy import *
import numpy as np
import operator
# 匯入科學計算包numpy和運算子模組operator
from os import listdir
from collections import Counter
def createDataSet():
"""
建立資料集和標籤
呼叫方式
import kNN
group, labels = kNN.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 test1():
group, labels = createDataSet()
'''
[[1. 1.1] #標籤對應A
[1. 1. ] #標籤對應A
[0. 0. ] #標籤對應B
[0. 0.1]] #標籤對應B
['A', 'A', 'B', 'B']
'''
#print(str(group))
#print(str(labels))
#print(classify0([0.1, 0.1], group, labels, 3))
print(classify1([0.1, 0.1], group, labels, 3))
def classify0(inX, dataSet, labels, K):
'''
inX: 用於分類的輸入向量 輸入的測試資料
dataSet:輸入的訓練樣本
lables:標籤向量
k:選擇最近鄰居的數目 通常小於20
注意:labels元素數目和dataSet行數相同;程式使用歐式距離公式.
預測資料所在分類可在輸入下列命令
kNN.classify0([0,0], group, labels, 3)
'''
# -----------實現 classify0() 方法的第一種方式----------------------------------------------------------------------------------------------------------------------------
# 1. 距離計算
#計算資料大小
dataSetSize = dataSet.shape[0]
'''
tile使用: 列3表示複製的行數, 行1/2表示對inX的重複的次數
In [2]: inx = [1,2,3]
In [3]: tile(inx,(3,1)) #列3表示複製的行數 行1表示對inX的重複的次數
Out[3]:
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3]])
In [4]: tile(inx,(3,2)) #列3表示複製的行數 行2表示對inX的重複的次數
Out[4]:
array([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3]])
'''
# tile生成和訓練樣本對應的矩陣,並與訓練樣本求差
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
'''
歐氏距離: 點到點之間的距離
第一行: 同一個點 到 dataSet的第一個點的距離。
第二行: 同一個點 到 dataSet的第二個點的距離。
...
第N行: 同一個點 到 dataSet的第N個點的距離。
[[1,2,3],[1,2,3]]-[[1,2,3],[1,2,0]]
(A1-A2)^2+(B1-B2)^2+(c1-c2)^2
'''
# 取平方
sqDiffMat = diffMat ** 2
# 講矩陣的每一行相加
sqDistances = sqDiffMat.sum(axis=1)
# 開方
distances = sqDistances ** 0.5
#print ('distances=', distances)
#distances= [1.3453624 1.27279221 0.14142136 0.1]
# 根據距離排序從小到大的排序,返回對應的索引位置
sortedDistIndicies = distances.argsort()
#print ('distances.argsort()=', sortedDistIndicies)
#distances.argsort()= [3 2 1 0]
# 2. 選擇距離最小的K個點
classCount = {}
for i in range(K):
#找到該樣本的型別
voteIlabel = labels[sortedDistIndicies[i]]
# 在字典中將該型別加一
# 字典的get方法
# 如:list.get(k,d) 其中 get相當於一條if...else...語句,引數k在字典中,字典將返回list[k];如果引數k不在字典中則返回引數d,如果K在字典中則返回k對應的value值
# l = {5:2,3:4}
# print l.get(3,0)返回的值是4;
# Print l.get(1,0)返回值是0;
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
#print(classCount)
#{'A': 1, 'B': 2}
# 3. 排序並且返回出現最多的那個資料型別
# 字典的 items() 方法,以列表返回可遍歷的(鍵,值)元組陣列。
# 例如:dict = {'Name': 'Zara', 'Age': 7} print "Value : %s" % dict.items() Value : [('Age', 7), ('Name', 'Zara')]
# sorted 中的第2個引數 key=operator.itemgetter(1) 這個引數的意思是先比較第幾個元素
# 例如:a=[('b',2),('a',1),('c',0)] b=sorted(a,key=operator.itemgetter(1)) >>>b=[('c',0),('a',1),('b',2)] 可以看到排序是按照後邊的0,1,2進行排序的,而不是a,b,c
# b=sorted(a,key=operator.itemgetter(0)) >>>b=[('a',1),('b',2),('c',0)] 這次比較的是前邊的a,b,c而不是0,1,2
# b=sorted(a,key=opertator.itemgetter(1,0)) >>>b=[('c',0),('a',1),('b',2)] 這個是先比較第2個元素,然後對第一個元素進行排序,形成多級排序。
#我們現在需要出現次數最多的那個 所以使用reverse=True列表反向排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def classify1(inX, dataSet, labels, K):
'''
inX: 用於分類的輸入向量 輸入的測試資料
dataSet:輸入的訓練樣本
lables:標籤向量
k:選擇最近鄰居的數目 通常小於20
注意:labels元素數目和dataSet行數相同;程式使用歐式距離公式.
預測資料所在分類可在輸入下列命令
kNN.classify0([0,0], group, labels, 3)
'''
# -----------實現 classify0() 方法的第二種方式----------------------------------------------------------------------------------------------------------------------------
# 歐氏距離: 點到點之間的距離
# 第一行: 同一個點 到 dataSet的第一個點的距離。
# 第二行: 同一個點 到 dataSet的第二個點的距離。
# ...
# 第N行: 同一個點 到 dataSet的第N個點的距離。
# [[1,2,3],[1,2,3]]-[[1,2,3],[1,2,0]]
# (A1-A2)^2+(B1-B2)^2+(c1-c2)^2
# inx - dataset 使用了numpy broadcasting,見 https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html
# np.sum() 函式的使用見 https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.sum.html
# """
dist = np.sum((inX - dataSet)**2, axis=1)**0.5
# """
# 2. k個最近的標籤
# 對距離排序使用numpy中的argsort函式, 見 https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.sort.html#numpy.sort
# 函式返回的是索引,因此取前k個索引使用[0 : k]
# 將這k個標籤存在列表k_labels中
# """
k_labels = [labels[index] for index in dist.argsort()[0 : K]]
# """
# 3. 出現次數最多的標籤即為最終類別
# 使用collections.Counter可以統計各個標籤的出現次數,most_common返回出現次數最多的標籤tuple,例如[('lable1', 2)],因此[0][0]可以取出標籤值
# """
label = Counter(k_labels).most_common(1)[0][0]
return label
if __name__ == '__main__':
test1()
輸入:
dataSet:輸入的訓練樣本
[[1.0,1.1] #標籤對應A
[1.0,1.0] #標籤對應A
[0, 0] #標籤對應B
[0, 0.1]] #標籤對應B
lables:標籤向量
['A', 'A', 'B', 'B']
inX: 用於分類的輸入向量 輸入的測試資料
[0.1, 0.1]
輸出:
B
說明這個輸出的標籤更靠近B 輸入B類
###
詳細介紹看程式碼註釋哈
AIMI-CN AI學習交流群【1015286623】 獲取更多AI資料
掃碼加群:
分享技術,樂享生活:我們的公眾號每週推送“AI”系列資訊類文章,歡迎您的關注!
相關文章
- 機器學習演算法——kNN(k-近鄰演算法)機器學習演算法KNN
- 機器學習——KNN近鄰演算法機器學習KNN演算法
- 機器學習-K近鄰演算法-KNN機器學習演算法KNN
- 【機器學習】機器學習建立演算法第2篇:K-近鄰演算法【附程式碼文件】機器學習演算法
- 機器學習——KNN(K近鄰)機器學習KNN
- 機器學習_K近鄰Python程式碼詳解機器學習Python
- 機器學習經典分類演算法 —— k-近鄰演算法(附python實現程式碼及資料集)機器學習演算法Python
- 機器學習演算法-K近鄰(KNN)演算法(三):馬絞痛資料--kNN資料預處理+kNN分類pipeline(程式碼附詳細註釋)機器學習演算法KNN
- 機器學習實戰----k值近鄰演算法(Python語言)機器學習演算法Python
- 機器學習實戰筆記-k近鄰演算法機器學習筆記演算法
- K-近鄰演算法介紹與程式碼實現演算法
- k-近鄰演算法演算法
- K-鄰近均值演算法演算法
- 機器學習——K近鄰演算法機器學習演算法
- 什麼是機器學習的分類演算法?【K-近鄰演算法(KNN)、交叉驗證、樸素貝葉斯演算法、決策樹、隨機森林】機器學習演算法KNN隨機森林
- K-最近鄰法(KNN)簡介KNN
- 什麼是機器學習分類演算法?【K-近鄰演算法(KNN)、交叉驗證、樸素貝葉斯演算法、決策樹、隨機森林】機器學習演算法KNN隨機森林
- 機器學習-11-k近鄰演算法機器學習演算法
- python機器學習演算法——KNN演算法Python機器學習演算法KNN
- 機器學習演算法之K近鄰演算法機器學習演算法
- 機器學習經典聚類演算法 —— k-均值演算法(附python實現程式碼及資料集)機器學習聚類演算法Python
- K近鄰演算法:機器學習萌新必學演算法演算法機器學習
- k-鄰近演算法實現約會網站的配對效果演算法網站
- educoder 機器學習 --- kNN演算法機器學習KNN演算法
- 機器學習 第4篇:sklearn 最鄰近演算法概述機器學習演算法
- 用定租問題學透機器學習的K近鄰演算法機器學習演算法
- 機器學習分享——KNN演算法及numpy實現機器學習KNN演算法
- 機器學習演算法(三):K近鄰(k-nearest neighbors)初探機器學習演算法REST
- 機器學習筆記(KNN演算法)機器學習筆記KNN演算法
- 13 種機器學習演算法概述(附 Python、R 程式碼)機器學習演算法Python
- 機器學習實踐篇第二篇-KNN演算法學習機器學習KNN演算法
- 機器學習經典演算法之KNN機器學習演算法KNN
- 機器學習入門實戰——基於knn的airbnb房租預測機器學習KNNAI
- 基於Sklearn機器學習程式碼實戰機器學習
- 超詳細!如何準備機器學習競賽?機器學習
- python機器學習實戰(二)Python機器學習
- 用Python進行機器學習(附程式碼、學習資源)Python機器學習
- 【機器學習】機器學習建立演算法第1篇:機器學習演算法課程定位、目標【附程式碼文件】機器學習演算法