[学习笔记] Tangent Distance
Tangent Distance
简介
切空间距离可以用在KNN方法中度量距离,其解决的是图像经过有限变换之后还能否被分类正确,例如。对一张数字为5的手写数字图片,将其膨胀后得到图像p1,此时KNN还应认为p1与原图接近,即距离较近,而不是距离其他类别较近。而Tangent Distance较好的解决了经过图像变换后距离度量的问题,其通过梯度下降算法在切空间中优化求得被分类向量和原始图像及其经过变换后图像的空间中最近的点。
Question

对于上面这张图,我们使用传统的欧式距离,极有可能将左边的图分类成4,而不是9。这暴露出一个问题,传统的欧式距离对旋转、缩放、平移等等变换是不鲁棒的,这就告诉我们我们需要一个新的对于常规变换鲁棒的距离评估标准。
Tangent Vector
切空间向量是如何定义的呢?简单的说,切空间向量的切是指在参数变化方向上的切,即输入图像/向量关于参数的微分。要理解这个,首先我们要先将图像变换数学化(为将问题简单化,我们认为只有一种变换,即旋转变换):
\]
上式表示输入图像x旋转a角度变为xt,我们怎么求旋转变换关于角度a的微分呢?很简单:
\]
这个定义,也就是图像关于a的微分,也就是切空间向量的定义。
那么这个切空间向量有什么用呢,很有用!
我们可以在切线方向也就是切空间里去搜索一种最合适的变换,也就是得到一个最合适的a,使得变换后的图像与原图的欧式距离最小。
一个简单的想法就是穷举出所有的经过变换后的图像,我们将图片每隔1度旋转增广一张,那么肯定能找到一张与所需要分类的图片距离最近的图像。
当然,切空间距离可不是这么简单,上面的想法是让a离散化的想法,实际上a是连续的,我们可以通过梯度下降法来求得一个最为合适的参数a,从而找到最合适的距离。
Tangent Distance
上面我们定义了切空间向量,下面是切空间距离的定义:
\]
这个定义可以这么理解,T由于是参数方向上的微分,乘以系数a然后加上x就是在参数方向上的变换,a取0度,就是不旋转,a取15度就是旋转15度。而a是参数,通过最小化与需要判别图像的欧式距离来得到参数a,继而得到切空间距离。
显然这里优化过程是需要用到梯度下降算法的。
将上式扩展为多种变换,就是对T的定义扩展为矩阵,比如有r种变换,图像像素维度d,则T矩阵就是r x d的。a就是d x 1维度。
Gradient Descent
简答推导一下这里梯度下降的公式:
\]
好了,上面推导完了梯度,可以开始写代码了。
Coding
import cv2 as cv
import numpy as np
import copy
class GradientDescent():
def __init__(self,T):
self.T = T #(2,784)
def __call__(self,x,y):
r,d = self.T.shape # (2,784)
a = np.ones(shape = (r,1)) # (2,1)
t = 0
while True:
b = copy.copy(a)
# (784,2).dot (2,1) -> (784,1) -> (2,1)
a = a - 0.0005 * self.T.dot(x + self.T.T.dot(a) - y)
t += 1
#print(a,b)
if np.sqrt(np.mean((b-a)**2)) < 0.0001 or t > 5000:
break
return a,self.T
class TanhDistance():
def __init__(self,frame,transforms = None):
self.vectors = []
h,w = frame.shape
self.hw = h*w
if transforms is not None:
for transform in transforms:
t = transform(frame) # (h,w)
self.vectors.append(np.reshape(t,(h*w,)) - np.reshape(frame,(h*w,)))
self.gradientDescent = GradientDescent(np.array(self.vectors)) # r,28*28
def __call__(self,x,y):
x = np.reshape(x,(self.hw,1))
y = np.reshape(y,(self.hw,1))
a,T = self.gradientDescent(x,y) # (28*28,1)
return np.sqrt(np.mean((x + T.T.dot(a) - y)**2))
def get_transforms(frame):
h,w = frame.shape
transformations = []
# rotate
delta_theta = 5
M = cv.getRotationMatrix2D(((w-1)/2.0,(h-1)/2.0),delta_theta,1)
transformations.append(lambda x:cv.warpAffine(x,M,(w,h)))
# shift
delta_x = 2
delta_y = 0
M = np.float32([[1,0,delta_x],[0,1,delta_y]])
transformations.append(lambda x:cv.warpAffine(x,M,(w,h)))
return transformations
if __name__ == "__main__":
img = cv.imread("/home/xueaoru/图片/0000.jpg")
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
gray = cv.resize(gray,(28,28))/255
transforms = get_transforms(gray)
metric = TanhDistance(gray,transforms)
img2 = cv.imread("/home/xueaoru/图片/000.jpg")
gray2 = cv.cvtColor(img2,cv.COLOR_BGR2GRAY)
gray2 = cv.resize(gray2,(28,28))/255
print("tan distance:{}".format(metric(gray,gray2)))
print("l2 distance:{}".format(np.sqrt(np.mean((gray - gray2)**2))))
#for transform in transforms:
# print(transform(gray))
所用图片:


距离结果:
tangent distance:0.3062723225969733
l2 distance:0.336102326896069Q
[学习笔记] Tangent Distance的更多相关文章
- ArcGIS JS 学习笔记1 用ArcGIS JS 实现仿百度地图的距离量测和面积量测
一.开篇 在博客注册了三年,今天才决定写第一篇博客,警告自己不要懒!!! 二.关于ArcGIS JS 版本选择 在写这篇博客时ArcGIS JS 4.0正式版已经发布.它和3.x版本的不同是,Map不 ...
- <老友记>学习笔记
这是六个人的故事,从不服输而又有强烈控制欲的monica,未经世事的千金大小姐rachel,正直又专情的ross,幽默风趣的chandle,古怪迷人的phoebe,花心天真的joey——六个好友之间的 ...
- 【Unity Shaders】学习笔记——SurfaceShader(十一)光照模型
[Unity Shaders]学习笔记——SurfaceShader(十一)光照模型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5664792.html ...
- 【Unity Shaders】学习笔记——SurfaceShader(九)Cubemap
[Unity Shaders]学习笔记——SurfaceShader(九)Cubemap 如果你想从零开始学习Unity Shader,那么你可以看看本系列的文章入门,你只需要稍微有点编程的概念就可以 ...
- 【Unity Shaders】学习笔记——SurfaceShader(七)法线贴图
[Unity Shaders]学习笔记——SurfaceShader(七)法线贴图 转载请注明出处:http://www.cnblogs.com/-867259206/p/5627565.html 写 ...
- DirectX 11游戏编程学习笔记之8: 第6章Drawing in Direct3D(在Direct3D中绘制)(习题解答)
本文由哈利_蜘蛛侠原创,转载请注明出处.有问题欢迎联系2024958085@qq.com 注:我给的电子版是700多页,而实体书是800多页,所以我在提到相关概念的时候 ...
- osgEarth学习笔记(转载)
osgEarth学习笔记1. 通过earth文件创建图层时,可以指定多个影像数据源和多个高程数据源,数据源的顺序决定渲染顺序,在earth文件中处于最前的在渲染时处于最底层渲染:所以如果 ...
- Unity3D 骨骼动画原理学习笔记
最近研究了一下游戏中模型的骨骼动画的原理,做一个学习笔记,便于大家共同学习探讨. ps:最近改bug改的要死要活,博客写的吭哧吭哧的~ 首先列出学习参考的前人的文章,本文较多的参考了其中的表述: 1. ...
- ArcGIS API for JavaScript 4.2学习笔记[21] 对3D场景上的3D要素进行点击查询【Query类学习】
有人问我怎么这个系列没有写自己做的东西呢? 大哥大姐,这是"学习笔记"啊!当然主要以解读和笔记为主咯. 也有人找我要实例代码(不是示例),我表示AJS尚未成熟,现在数据编辑功能才简 ...
随机推荐
- Nginx作为静态资源web服务之防盗链
Nginx作为静态资源web服务之防盗链 首先,为什么需要防盗链,因为有些资源存在竞争对手的关系,比如淘宝的商品图片,不会轻易的让工具来爬虫爬走收集.但是如果使用防盗链,需要知道上一个访问的资源,然后 ...
- innodb存储引擎之内存
1.innoDB存储引擎体系架构 如上图所示,innoDB存储是基于磁盘存储的,并且其中的记录以页的方式进行管理,但为什么要引入一个内存池呢? 其目的就是为了协调CUP速度与磁盘速度的鸿沟,基于磁盘的 ...
- SQL语句复习【专题二】
SQL语句复习[专题二] 单行函数(日期.数学.字符串.通用函数.转换函数)多行函数.分组函数.多行数据计算一个结果.一共5个.sum(),avg(),max(),min(),count()分组函数 ...
- shell脚本基础和grep文本处理工具企业应用3
文本处理工具: linux上文本处理三剑客 grep,egrep,fgrep:文本过滤工具(模式:pattern)工具 grep:默认支持的是基本正则表达式: ...
- oracle学习1 基于oracle数据库的PLSQL编程以及存储过程的创建和使用视频
https://www.bilibili.com/video/av46777605 plsql中选择testWindow中可以进行测试 1.编写函数在plsql的testwindow中 begin d ...
- 一键登录怎么在iOS端实现?这篇文章教会你!
在一键登录出现之前,市场上最常见的APP 注册登录方式主要有账号密码.短信验证及第三方登录.这几种方式看似常见且便捷,实则存在许多安全隐患,用户体验也相对较差.首先,短信验证码到达率低.用户操作繁琐且 ...
- Linux命令行——scp命令
原创声明:本文系博主原创文章,转载或引用请注明出处. scp 一般格式: scp [option] src dst 1. src和dst格式为: [user@]host:/path/to/file ...
- 王某的NLP之路前言
感谢基友jayjay和海英学姐的指路,其实我的方向一直比较迷茫. 因为自己是会计学出身的,前三年也没接触编程,第一次接触还是在2016年,尝试用聚宽的量化接口,当时顺便学了python 的一点知识. ...
- Python3-os模块详解
import os # 返回一个目录的名称 print(os.path.basename("d:/python")) # 返回一个目录的目录名 print(os.path.dirn ...
- Flyway详解以及Springboot集成Flyway(转)
Flayway是一款数据库版本控制管理工具,,支持数据库版本自动升级,Migrations可以写成sql脚本,也可以写在java代码里:不仅支持Command Line和java api ,也支持Bu ...