KNN算法检测手势动作
KNN算法原理:
KNN(k-nearest neighbor)是一個簡單而經典的機器學習分類算法,通過度量”待分類數據”和”類別已知的樣本”的距離(通常是歐氏距離)對樣本進行分類。?
這話說得有些繞口,且來分解一番:?
(1)分類問題都是監督(supervised)問題,也就是說一定數量的樣本類別是已知的。?
(2)既然我們已經有了一批分好類的樣本,那么接下來的工作自然應該是通過已知樣本訓練分類器(通過調節分類器的參數,使分類器能夠正確對訓練樣本分類),把分類器訓練好以后用于對未知樣本的分類(或類別預測)。?
看上去就是這么回事,問題的關鍵在于分類器的訓練。?
但對于KNN分類器來說,事情并不是這個樣子的。其實KNN并沒有這么復雜。因為KNN并沒有什么參數要調,換句話說,KNN其實并不需要訓練!?
作為最簡單也最好理解的分類器,KNN只是假設數據都分布在歐式的特征空間內(以特征值為坐標區分不同樣本的空間),然后我們恰好又知道全部數據在這個空間中的位置以及其中一部分數據的類別。那么現在我們怎么判斷剩余那些數據的類別呢??
為了讓分類進行下去,這里其實我們假設:空間中距離越近的點屬于一類的可能性越大。?
有了這條“公理”,那事情就好辦多了。我們只需要計算每個待分類數據到全部已知類別數據的距離就好了。如圖:?
有正方形和三角形兩個已知類,假如中間的圓形我們不知道它到底是三角形還是正方形。按照上面說的,我們可以正兒八經計算一下它到其他所有點的距離。在這里為了簡便,我們目測一下發現它離旁邊的三角形最近,好嘞,那么我們就把它歸為三角形一類的。?
注意這里我們把未知點和離它最近的那一個點歸為一類。這樣的分類器,準確來說叫最近鄰分類器(nearest-neighbor,NN)。這是KNN的特殊情況,是K=1的情況。?
那么K近鄰,顧名思義,就是要一個未知點參考離它最近的前k個一直類別的點,看在這k個點里面,屬于哪個類別的點最多,就認為未知點屬于哪一類。還是上面的圖,以圓形未知點為圓心,在實線畫出的圓中,相當于k=3,也就是選了前三個離得最近的點,其中三角形2個,方形1個,所以未知點歸到三角形一類。但是當考慮虛線范圍內時,也就是k=5時,我們發現方形3個,三角形2個,所以這個時候未知點歸到方形一類了。?
所以我們可以發現,不同的最近鄰個數往往會導致不同的分類結果,一般來說,我們在實際應用中要根據實際情況和經驗確定k的取值。
原理部分參考自博文:https://blog.csdn.net/weixin_41988628/article/details/80369850
使用KNN分類器實現分類一個簡單的二維例子
創建二維點集的代碼部分如下:
通過隨機生成的方式,創建兩個不同的二維點集class1和class2,每個點集有兩類,分別是正態分布和繞環狀分布,正態分布的范圍主要通過代碼中參數的調節實現,該參數越大,數據點范圍越大,就更分散.
?? 繞環分布的范圍,半徑r決定了外圈數據集的集中程度,當r越大時,數據范圍越大,就越分散
下載PCV庫并安裝 git clone https://github.com/jesolem/PCV.git cd PCV python setup.py install? ?打開? Python2.7 測試 能否導入
import PCV?
通過訓練的數據識別出手勢的代碼如下:
運行完后結果會用顯示正確率對于給定的測試集有多少圖像是正確分類的,但是它并沒有告訴我們哪些手勢難以分類,或者犯哪些錯誤。這時,我們可以通過混淆矩陣來顯示錯誤分類的情況。混淆矩陣是一個可以顯示每類有多少個樣本被分在每一類中的矩陣,它可以顯示錯誤的分布情況,以及哪些類是經常相互“混淆”的
import os from PIL import Image from numpy import * from pylab import * import pickle from scipy.cluster.vq import * import pca import dsift import sift import knn from svmutil import *import sys reload(sys) sys.setdefaultencoding('utf-8')def read_features_labels(path):# create list of all files ending in .dsiftfeatlist = [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.dsift')]# read the featuresfeatures = []for featfile in featlist:l,d = sift.read_features_from_file(featfile)features.append(d.flatten())features = array(features)# create labelslabels = [int(featfile.split('\\')[-1][0:3])/50 for featfile in featlist]return features,array(labels)imlist = [] path = 'C:\\Users\\RubyLyu\\PycharmProjects\\PictureDB\\data' imlist=[os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')] print imlistfor filename in imlist:featfile = filename[:-3]+'dsift'dsift.process_image_dsift(filename,featfile,10,5,resize=(150,200))imlist = [] path = 'C:\\Users\\RubyLyu\\PycharmProjects\\PictureDB\\src\\data' imlist=[os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]for filename in imlist:featfile = filename[:-3]+'dsift'dsift.process_image_dsift(filename,featfile,10,5,resize=(150,200))features,labels = read_features_labels('C:\\Users\\RubyLyu\\PycharmProjects\\PictureDB\\data')#print features test_features,test_labels = read_features_labels('C:\\Users\\RubyLyu\\PycharmProjects\\PictureDB\\src\\data')features = map(list,features) test_features = map(list,test_features) prob = svm_problem(labels,features) param = svm_parameter('-t 2') m = svm_train(prob,param) svm_save_model("C:\\Users\\RubyLyu\\PycharmProjects\\untitled1\\svmDsift200.model",m) res = svm_predict(labels,features,m) res = svm_predict(test_labels,test_features,m) #how does it perform on the test set? # m = svm_load_model("C:\\Users\\RubyLyu\\PycharmProjects\\untitled1\\svmDsift.model") # # res = svm_predict(test_labels[:5],test_features[:5],m)運行的結果如下:
結果顯示分類的正確率達到81.3%
混淆矩陣豎著看,比如A列,分類正確的有26,將A分錯成V有三個
A、B、C、F、V的分類結果都比較好,錯誤率較低
而P類錯分成V的概率很高
?
?
總結
以上是生活随笔為你收集整理的KNN算法检测手势动作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 恢复Linux系统权限
- 下一篇: std::call_once写单列模式