基于Python的K邻近分类法(KNN)+稠密SIFT+⼿势识别⼀、KNN原理分析
在分类⽅法中,最简单也⽤的最多的就是KNN(K邻近分类法)算法。这种算法把要分类的对象与训练集中,已知类标记的所有对象进⾏对⽐,并由k近邻对指派到哪⼀类进⾏投票。
这种⽅法通常分类效果很好,但也有很多弊端,例如:与K-menas聚类算法类似,需要预先设定k值,k值的选择会影响分类的性能。⽽且,这种⽅法要求整个训练集存储起来,如果训练集⾮常⼤时,就会出现搜索速度慢的现象。
⼆、⽤K邻近分类器分类⼆维数据
1、创建⼆维点集
通过随机⽣成的⽅式,创建两个不同的⼆维点集,每个点集有两类,分别是正态分布和绕环状分布,然后⽤Pickle模块保存数据集。⼆维点集的⼤⼩主要通过代码中参数的调节实现,该参数越⼤,数据点范围越⼤,就会⽐较分散。
数据在绕环状分布时,半径r决定了外圈数据集的集中程度,当r越⼤时,数据范围越⼤,也就越分散。
# -*- coding: utf-8 -*-
from numpy.random import randn
import pickle
from pylab import *
#创建⼆维样本数据
n = 200
# 两个正态分布数据集
class_1 = 1 * randn(n,2)
class_2 = 1.5 * randn(n,2) + array([5,1])
labels = hstack((ones(n),-ones(n)))
# ⽤Pickle模块保存
#with open('points_normal.pkl', 'w') as f:
with open('points_normal_test.pkl', 'wb') as f:
pickle.dump(class_1,f)
pickle.dump(class_2,f)
pickle.dump(labels,f)
# 正太分布,并使数据成环绕状分布
print ("save OK!")
class_1 = 0.3 * randn(n,2)
r = 0.5 * randn(n,1) + 5
angle = 2*pi * randn(n,1)
class_2 = hstack((r*cos(angle),r*sin(angle)))
labels = hstack((ones(n),-ones(n)))
# ⽤Pickle保存
#with open('points_ring.pkl', 'w') as f:
with open('points_ring_test.pkl', 'wb') as f:
pickle.dump(class_1,f)
pickle.dump(class_2,f)
pickle.dump(labels,f)
print ("save OK!")
保存成功后,在控制台输出如下:
2、创建KNN分类器
⽤Pickle模块载⼊之前创建的数据集,从⽽来创建⼀个KNN分类器模型。为可视化所有测试数据点的分类,并展⽰分类器如何将两个不同的类分开,就需要创建⼀个辅助函数classify(x,y,model=model),以获取x和y⼆维坐标数组和分类器,并且返回⼀个预测的类标记数组array。然后把函数classify作为参数传递给实际的绘图函数plot_2D_boundary。
这个绘图函数需要⼀个决策函数(分类器),并且⽤meshgrid()函数在⼀个⽹格上进⾏预测,⽹格的精度为0.1,每隔0.1采集⼀个点。决策函数的等值线可以显⽰边界的位置,默认边界为零等值线。对于每⼀个类,⽤*画出分类正确的类,⽤O画出分类不正确的点。
# -*- coding: utf-8 -*-
import pickle
from pylab import *
from PCV.classifiers import knn
ls import imtools
pklist=['points_normal.pkl','points_ring.pkl']
figure()
# ⽤Pickle载⼊⼆维数据点
for i, pklfile in enumerate(pklist):
with open(pklfile, 'rb') as f:
class_1 = pickle.load(f)
class_2 = pickle.load(f)
labels = pickle.load(f)
# ⽤Pickle模块载⼊测试数据
with open(pklfile[:-4]+'_test.pkl', 'rb') as f:
class_1 = pickle.load(f)
class_2 = pickle.load(f)
labels = pickle.load(f)
model = knn.KnnClassifier(labels,vstack((class_1,class_2)))
# 在测试数据集的第⼀个数据点上进⾏测试
print (model.classify(class_1[0]))
# 定义绘图函数
def classify(x,y,model=model):
return array([model.classify([xx,yy]) for (xx,yy) in zip(x,y)])
# 绘制分类边界
subplot(1,2,i+1)
imtools.plot_2D_boundary([-6,6,-6,6],[class_1,class_2],classify,[1,-1])
titlename=pklfile[:-4]
title(titlename)
show()
imtools函数:
def plot_2D_boundary(plot_range,points,decisionfcn,labels,values=[0]):
"""    Plot_range为(xmin,xmax,ymin,ymax), points是类数据点列表, decisionfcn is a funtion to evaluate, 是评估函数,labels是函数 decisionfcn 关于每⼀个类返回值的标记列表. """
import pickleclist = ['b','r','g','k','m','y'] # 不同的类⽤不同的颜⾊标识
# 在⼀个⽹格上进⾏评估,并画出决策函数的边界
x = arange(plot_range[0],plot_range[1],.1)
y = arange(plot_range[2],plot_range[3],.1)
xx,yy = meshgrid(x,y)
xxx,yyy = xx.flatten(),yy.flatten() # ⽹格中的x,y坐标点列表
zz = array(decisionfcn(xxx,yyy))
zz = zz.reshape(xx.shape)
# 以values画出边界
contour(xx,yy,zz,values)
# 对于每类,⽤ '*' 画出分类正确的点,⽤ 'o'画出分类不正确的点
for i in range(len(points)):
d = decisionfcn(points[i][:,0],points[i][:,1])
correct_ndx = labels[i]==d
incorrect_ndx = labels[i]!=d
plot(points[i][correct_ndx,0],points[i][correct_ndx,1],'*',color=clist[i])
plot(points[i][incorrect_ndx,0],points[i][incorrect_ndx,1],'o',color=clist[i])
axis('equal')
3、结果分析
(1)改变正态分布数据集的参数
修改参数前的数据集进⾏分类
结果如下:
调节参数后
分类结果如下:
分析:通过⽐较左侧的图看出,修改参数之前的数据集下,由于两个数据集的范围都⽐较⼤,就有可能出现了相同的数据点,给分类造成了⼲扰,⽆法进⾏分类,从⽽⽤原点标记出这⼏个错误的点。⽽在修改参数后的数据集下,两个数据集的范围相差较⼤,从⽽产⽣的数据点相差的⽐较⼤, 从⽽分类器能够较好的进⾏分类。
(2)改变环绕状数据集的参数
修改参数前的数据集进⾏分类
结果如下:
修改参数后的数据集进⾏分类
结果如下:
分析:由于半径变⼤,从⽽使外圈的数据集更加分散,从⽽更加靠近中间的内圈的数据集
⼆、Dense SIFT
1、原理分析
Dense-SIFT是sift的密集采样板,由于SIFT的实时性差,⽬前特征提取多采⽤密集采样。传统的SIFT算法即Sparse SIFT,不能很好地表征不同类之间的特征差异,达不到所需的分类要求。⽽Dense SIFT算法,是⼀种对输⼊图像进⾏分块处理,再进⾏SIFT运算的特征提取过程。Dense SIFT根据可调
的参数⼤⼩,来适当满⾜不同分类任务下对图像的特征表征能⼒。通常来讲Dense SIFT更适⽤于图像分类识别的任务,⽽Sparse SIFT更适⽤于图像检索分割的任务。
2、可视化
# -*- coding: utf-8 -*-
from PCV.localdescriptors import sift, dsift
from pylab import  *
from PIL import Image
dsift.process_image_dsift('gesture/b1.jpg','b1.dsift',90,60,True)
l,d = ad_features_from_file('b1.dsift')
im = array(Image.open('gesture/b1.jpg'))
sift.plot_features(im,l,True)
title('dense SIFT')
show()
dsift函数:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。