[学习笔记] 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尚未成熟,现在数据编辑功能才简 ...
随机推荐
- 正则表达式 Regular expression为学习助跑
这是一个Regular expression的铁路图(至少我现在是这么称呼的)的图形化界面帮助检验和理解我们所写的Regular expression是否正确. 1.官网 :https://regex ...
- python的索引与切片和元祖
'''索引: 1.索引从0开始 2.末尾元素为 -1 3.能被for循环,有序的数据集合 切片: 1.顾头不顾尾 2.a = "123abcdfg" print(a[0::2]) ...
- okhttp框架源码分析从同步&异步请求使用开始
对于okhttp在如今项目中的普及程度已经不言而喻啦,基本上如今网络请求都会基于它去进行封装,而非前几年用Android的网络框架HttpURLConnection和Apache HttpClient ...
- 使用Mutex實現單一程式執行個體的注意事項(转)
相信大家都知道在.NET程式中若要實現單一程式執行個體,一般來說有幾種方法,像是去判斷是否已經有開啟的Process是相同的程式.用Mutex與Semaphore之類的技術來判斷是否程式正在開啟.但是 ...
- poj3691 DNA repair[DP+AC自动机]
$给定 n 个模式串,和一个长度为 m 的原串 s,求至少修改原串中的几个字符可以使得原串中不包含任一个模式串.模式串总长度 ≤ 1000,m ≤ 1000.$ 先建出模式串的AC自动机,然后考虑怎么 ...
- Struts2标签:s:password 修改时密码为空的问题
s:password 有个属性showPassword默认为false,想要密码显示,设置标签属性 showPassword="true" 即可.
- css 判断是iphone4s iphone5 加载不同样式
@media (device-height:480px) and (-webkit-min-device-pixel-ratio:2){/* 兼容iphone4/4s */ .class{}}@med ...
- Redis和Memcache区别
1. Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等. 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供li ...
- 设计一个Mypoint类,求两个点之间的距离
package Test; public class test6 { public static void main(String[] args) { // TODO Auto-generated m ...
- http 异步 接收 回传 数据文字和文件流
public void HttpListenerStar() { try { HttpListener httpListener = new HttpListener(); httpListener. ...