knn可视化、稠密dsift原理、手势识别
一、knn可视化:
1、knn算法简单介绍:
KNN是一种监督学习算法,通过计算新数据与训练数据特征值之间的距离,然后选取K(K>=1)个距离最近的邻居进行分类判(投票法)或者回归。若K=1,新数据被简单分配给其近邻的类。
2、算法描述:
从训练集中找到和新数据最接近的k条记录,然后根据多数类来决定新数据类别。
如下图:
(1) 已知两类“先验”数据,分别是蓝方块和红三角,他们分布在一个二维空间中;
(2) 有一个未知类别的数据(绿点),需要判断它是属于“蓝方块”还是“红三角”类;
(3) 考察离绿点最近的3个(或k个)数据点的类别,占多数的类别即为绿点判定类别。
3、knn算法实现过程:
(1)选择一种距离计算方式, 通过数据所有的特征计算新数据与已知类别数据集中的数据点的距离;
(2)按照距离递增次序进行排序,选取与当前距离最小的k个点;
(3)对于离散分类,返回k个点出现频率最多的类别作预测分类;对于回归则返回k个点的加权值作为预测值;
4、算法的关键:
(1)数据的所有特征都要做可比较的量化
若是数据特征中存在非数值的类型,必须采取手段将其量化为数值。例如样本特征中包含颜色,可通过将颜色转换为灰度值来实现距离计算。
(2)样本特征要做归一化处理
样本有多个参数,每一个参数都有自己的定义域和取值范围,他们对距离计算的影响不一样,如取值较大的影响力会盖过取值较小的参数。所以样本参数必须做一些scale处理,最简单的方式就是所有特征的数值都采取归一化处置。
(3)需要一个距离函数以计算两个样本之间的距离
距离的定义:欧氏距离、余弦距离、汉明距离、曼哈顿距离等,一般选欧氏距离作为距离度量,但是这是只适用于连续变量。在文本分类这种非连续变量情况下,汉明距离可以用来作为度量。通常情况下,如果运用一些特殊的算法来计算度量的话,K近邻分类精度可显著提高,如运用大边缘最近邻法或者近邻成分分析法。
(4)确定K的值
K值选的太大易引起欠拟合,太小容易过拟合。交叉验证确定K值。
5、knn可视化的实现:
在此次实验中运用的度量方式是欧式距离度量法。欧几里得度量是一个通常采用的距离定义,指在m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离),在二维和三维空间中的欧氏距离就是两点之间的实际距离,当然在此次实验中主要度量二维空间的距离,度量方式为:
from numpy import *
class KnnClassifier(object):def __init__(self,labels,samples):""" 使用训练数据初始化分类器"""self.labels = labelsself.samples = samplesdef classify(self,point,k=3):""" 在训练数据上采用K邻近分类,并返回标记""# 计算所有训练数据点的额距离dist = array([L2dist(point,s) for s in self.samples])# 对它们进行排序ndx = dist.argsort()# 用字典存储K近邻votes = {}for i in range(k):label = self.labels[ndx[i]]votes.setdefault(label,0)votes[label] += 1return max(votes, key=lambda x: votes.get(x))
def L2dist(p1,p2):return sqrt( sum( (p1-p2)**2) )
def L1dist(v1,v2):return sum(abs(v1-v2))
我们首先建立一个简单的二维实例数据集来说明并可视化分类器的工作原理,下面的脚本将创建两个不同的二维点集,每个集点有两类,并用pickle模块来保存创建的数据:
from numpy.random import randn
import pickle
from pylab import *# 创建二维样本数据
n = 200
# 两个正太分布数据集
class_1 = 0.6 * randn(n,2)
class_2 = 1.2 * 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.6 * randn(n,2)
r = 0.8 * 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!")
用不同的文件保存文件名运行该脚本两次,例如第一次用代码中的文件名进行保存,第二次将代码中的points_normal_t.pkl和points_ring_pkl分别改为points_normal_test.pkl和points_ring_test.pkl进行保存,将得到四个二维数据集文件,每个分布都有两个文件,我们可以将一个用来训练,另一个用来做测试。
用KNN分类器完成,先创建一个脚本:
with open(pklfile, '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)))
这里用Pickle模块来创建一个knn分类器模型。
#用Pickle模块载入测试数据with open(pklfile[:-4]+'_test.pkl', 'rb') as f:class_1 = pickle.load(f)class_2 = pickle.load(f)labels = pickle.load(f)#在测试数据集的第一个数据点上进行测试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()
用K邻近分类器分类二维数据,每个示例中,不同颜色代表类标记,正确分类的点用星号表示,分类错误的点用圆表示,曲线是分类器的决策边界:
def plot_2D_boundary(plot_range,points,decisionfcn,labels,values=[0]):clist = ['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]==dincorrect_ndx = labels[i]!=dplot(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')
上面代码中:
decisionfcn:评估函数;
lables:是函数decidionfcn关于每个类返回的标记列表;
points:是类数据点列表。
上面函数需要一个决策函数,并且用meshgird()函数在一个网格上进行预测。决策函数的等值线可以显示边界的位置,默认边界为零等值线,结果如下图所示:
5、knn算法的优缺点:
优点:
•1.简单、有效。
•2.重新训练的代价较低(类别体系的变化和训练集的变化,在Web环境和电子商务应用中是很常见的)。
•3.计算时间和空间线性于训练集的规模(在一些场合不算太大)。
•4.由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
•5.该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
缺点:
•1.KNN算法是懒散学习方法(lazy learning,基本上不学习),一些积极学习的算法要快很多。
•2.类别评分不是规格化的(不像概率评分)(???)。
•3.输出的可解释性不强,例如决策树的可解释性较强。
•4.该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。该算法只计算最近的邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法(和该样本距离小的邻居权值大)来改进。
•5.计算量较大。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。
二、稠密sift原理:
dense SIFT在目标分类和场景分类有重要的应用。接触较多文献的朋友可以发现,dense SIFT经常会用在bag of words 模型中[1]。在近年关于场景分类的论文中,我们可能会看到如下的细节。如以16×16 pixel大小的size和8 pixels的stepsize提取dense SIFT特征,然后做max pooling。在此,我们引出dense SIFT与做特征匹配所用到的SIFT的不同点。dense SIFT是提取我们感兴趣的patches中的每个位置的SIFT特征。而通常做特征匹配的SIFT算法只是得到感兴趣区域或者图像上若干个稳定的关键点的SIFT特征。如图所示,目前关于dense SIFT提取比较流行的做法是,拿一个size固定的掩模或者bounding box,以一定的步长(stepsize)在图像上自左向右、从上到下提取dense SIFT的patch块。
from PIL import Image
from numpy import *
import os
from PCV.localdescriptors import sift
def process_image_dsift(imagename,resultname,size=20,steps=10,force_orientation=False,resize=None):im = Image.open(imagename).convert('L')if resize!=None:im = im.resize(resize)m,n = im.sizeif imagename[-3:] != 'pgm':#创建一个pgm文件im.save('tmp.pgm')imagename = 'tmp.pgm'# 创建帧并保存到临时文件scale = size/3.0x,y = meshgrid(range(steps,m,steps),range(steps,n,steps))xx,yy = x.flatten(),y.flatten()frame = array([xx,yy,scale*ones(xx.shape[0]),zeros(xx.shape[0])])savetxt('tmp.frame',frame.T,fmt='%03.3f')path = os.path.abspath(os.path.join(os.path.dirname("__file__"),os.path.pardir))path = path + "\\python3-ch08\\win32vlfeat\\sift.exe "if force_orientation:cmmd = str(path+imagename+" --output="+resultname+" --read-frames=tmp.frame --orientations")else:cmmd = str(path+imagename+" --output="+resultname+" --read-frames=tmp.frame")os.system(cmmd)print ('processed', imagename, 'to', resultname)
用密集采样的sift描述字处理一幅图像,并将结果保存到一个文件中,可选的输入为:
size:特征的大小;
steps:位置之间的步长;
force_orientation:用于调整图像大小的元组(false表示所有的方位是朝上的)。
为了使用命令行处理,我们用savetxt()函数将帧数组存储在一个文本文件中,该函数的最后一个参数可以在提取描述子之前对图像的大小调整,最后,如果force_orientation为真。则提取出来的描述子会基于局部主梯度方向进行归一化,否则,所有的描述子的方向只是简单的朝上,下面的代码计算稠密sift描述子,并可视化它们的位置。
from PCV.localdescriptors import sift, dsift
from pylab import *
from PIL import Image
dsift.process_image_dsift('gesture/empire.jpg','empire.dsift',90,40,True)
l,d = sift.read_features_from_file('gesture/empire.dsift')
im = array(Image.open('gesture/empire.jpg'))
sift.plot_features(im,l,True)
title('dense SIFT')
show()
使用用于定位描述子的局部梯度方向,该代码可以在整个图像中计算出稠密SIFT特征,结果显示如下:
三、手势识别:
在这个应用中,我们会用稠密sift描述子来表示这些手势图像,并建立一个简单的手势识别系统,我们用静态手势数据库中的一些图像进行演示(参见地址:[(http://www.idiap.ch/resource/gestures/)),在该数据库主页上下载数据较小的测试集,将下载后的所有图像放在一个名为uniform的文件夹里,每一类均分两组,并分别放在train和test的两个文件夹中。用上面的稠密sift函数对图像进行处理,可以得到所有的额图像特征向量。这里在此假设列表imlist中包含了所有图像的文件名,可以通过下面的代码得到每幅图像的稠密sift特征:
for i, im in enumerate(imlist):print (im)dsift.process_image_dsift(im,im[:-3]+'dsift',90,40,True)l,d = sift.read_features_from_file(im[:-3]+'dsift')dirpath, filename=os.path.split(im)im = array(Image.open(im))
上面代码会对每一幅图像创建一个特征文件,文件名后缀为.dsift。
注意:
这里将图像分辨率调成了常见的固定大小,这里是非常重要的,否则这些图像会有不同数量的描述子,从而每幅的特征向量长度也不一样,这将导致在后面比较它们时出错。
利用数据库的手势得到的描述子图像如下:
用自己的图像得到描述子为:
由于图片分辨率改变了所以,找出来的描述子和前面数据库找出来的大小不一样,改变分辨率可以改变手势的明显程度和描述子大小。
定义一个辅助函数,用于从文件中读取稠密描述子:
def read_gesture_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 = [featfile.split('/')[-1][0] for featfile in featlist]return features,array(labels)
然后用下面的脚本读取训练集、测试集的特征和标记信息:
features,labels = read_gesture_features_labels('gesture/train/')
test_features,test_labels = read_gesture_features_labels('gesture/test/')
classnames = unique(labels)
在数据上使用前面的K近邻代码:
k = 1
knn_classifier = knn.KnnClassifier(labels,features)
res = array([knn_classifier.classify(test_features[i],k) for i in
range(len(test_labels))])
# accuracy
acc = sum(1.0*(res==test_labels)) / len(test_labels)
print ('Accuracy:', acc)
首先,用训练数据极其标记作为输入,创建分类器对象,然后在整个测试集上遍历并用classsify()方法对每幅图像进行分类。将布尔数组和1相乘并求和,可以计算出分类的正确率。由于该例中真值为1,所以很容易计算出正确分类数,打印出以下结果:
Accuracy:0.7426568425
这说明该例中有70%的图像是正确的。
虽然上面的正确率显示了一个对于给定的测试集有多少图像是正确分类的,但是它并没有告诉我们哪些手势难以分类,或会有哪些典型错误,混淆矩阵是一个可以显示每个类有多少样本被分在哪一类矩阵中,可以显示错误的分布情况。
def print_confusion(res,test_labels,classnames):n = len(classnames)class_ind=dict([(classnames[i],i)for i in range(n)])confuse = zeros((n,n))for i in range(len(test_labels)):confuse[class_ind[res[i]],class_ind[test_labels[i]]]+=1print('Confusion matrix for')print(classnames)print(confuse)
knn可视化、稠密dsift原理、手势识别相关推荐
- H5 可视化构建工具原理解析(一)
前言 总共进 8 万行代码实现H5可视化构建工具,自去年十月开始陆续做了大半年,现已投入到业务中使用,虽然算是个人项目,但组件和部署模块涉及大量公司业务代码,就不开源了,主要讲讲实现思路,算是该项目的 ...
- Atiitt 可视化 报表 图表之道 attilax著 Atiitt 可视化的艺术 attilax著 v2 s51.docx Atitit.可视化与报表原理与概论 1. 、什么是可视化(这一
Atiitt 可视化 报表 图表之道 attilax著 Atiitt 可视化的艺术 attilax著 v2 s51.docx Atitit.可视化与报表原理与概论 1. .什么是可视化(这一节有点 ...
- 用Python实现KNN算法(从原理到代码的实现)
用Python实现KNN算法(从原理到代码的实现) 环境 1.Pycharm 2.python3.6 声明:本栏的所有文章皆为本人学习时所做笔记而整理成篇,转载需授权且需注明文章来源,禁止商业用途,仅 ...
- GradCAM神经网络可视化解释(原理和实现)
GradCAM是经典的特征图可视化工具,在CV任务中,能用于分析CNN学到了什么东西.先看一张图: 这就是GradCAM做出的效果,它直观地表示出咱们模型认为图片是Dog的是依据哪些地方. GradC ...
- UnityEditor蒙皮动画SkinnedMeshRenderer 使用骨骼RootBones的Gizmos可视化工具和原理解析
Unity的蒙皮动画 在UnityEditor,使用SkinnedMeshRenderer承载蒙皮动画 帧动画和骨骼动画,蒙皮动画等等理论,还是得抽空学习一下的, 但要是在不懂原理的情况下(不懂比似懂 ...
- (GIS可视化)热点分析原理及实现
1 Z值和P值 1.1 零假设 零假设(null hypothesis),有时候又称原假设,官方的解释是:指进行统计检验时预先建立的假设. 也就是说,你在检验你的结果之前,先对这些结果假设一个数值区间 ...
- 计算机视觉——KNN算法以及手势识别应用
文章目录 概述 KNN算法原理 KNN二维分类器模型 DSIFT 手势识别应用 手势识别具体流程 概述 本文介绍了KNN算法的基本原理,以及配合dfift(稠密sift)进行一个手势识别方面的应用 K ...
- 【机器学习】最近邻算法KNN原理、流程框图、代码实现及优缺点
通过机器学习教学视频,初识KNN算法,对原理和算法流程通过小应用进行Python实现,有了自己的一些理解.因此在此整理一下,既是对自己学习的阶段性总结,也希望能和更多的朋友们共同交流学习相关算法,如有 ...
- KNN(一)--简单KNN原理及实现
原文: http://blog.csdn.net/damotiansheng/article/details/40628417 1. Knn算法介绍: 百度百科:http://baike.baidu. ...
最新文章
- 查询mysql数量_科研学习记录--MySQL
- SAP MM 移动类型101与103+105组合混用?
- php svn up,php中执行svn update问题
- C语言中float double等类型在内存中的存储
- 李彦宏:自动驾驶是起点,终局是智能交通;iPhone15将搭载苹果自研5G基带芯片;英特尔收购Linutronix|极客头条...
- python3_configparser模块详解
- 飞客蠕虫专杀工具_案例-飞客蠕虫攻击
- MEMZ病毒详细分析
- 微信指纹支付提示java6_苹果6微信指纹支付每次提示请验证已有的指纹用于支付,怎样才能支付?...
- JS特效三:LightBox(轮播图+图片弹窗)
- 服务器2008r2如何系统还原,windows如何创建系统还原点和还原点还原系统的使用方法...
- Layui 后台ajax 腾讯地图 多点标记mark
- 网易云音乐推出异乡人年度企划:不同圈层音乐人演绎他乡故事
- 微信公众号推送天气教程,自动定时推送【Java版】开发者和小白详细教程
- UVALive 7456 Least Crucial Node
- 软件缺陷报告模板(微信缺陷报告案例)
- 中搜网络与齐齐哈尔达成战略合作 携手共建智慧城市
- Python财务分析
- JS逆向|使用pyexecjs库替换加密字符串
- 再探Struts框架
热门文章
- twig模板引擎使用php,Twig模板引擎
- python matplotlib 论文画图代码总结
- 四川计算机专业的二本大学排名及分数线,2019-2020四川二本大学排名及分数线(理科+文科)...
- Git 常用命令练习
- 数据结构2(线性表)
- tableau做折线图_用Tableau制作10种漂亮的折线图
- 如何提高流量主广告收益,这些方法你可以用用
- 【往届EI已检索】2023年第三届应用数学、建模与智能计算国际研讨会(CAMMIC2023)
- linux音频文件格式转换,在Ubuntu @ Linux 中音频和音乐文件的格式转换
- word中设置奇偶页页眉页脚