论文发布时间:2012年
全文概括
这个方法,命名为CSK(Circulant Strructure … Kernels)。
作者发现,离散的分类器可以用于跟踪系统上,借鉴足够快速的线性分类器使用对偶空间的核机制的想法,使用循环结构的快速傅里叶变换可以加速跟踪的进行。【个人解读:用过滤器窗口在图片上遍历,找到最大相应的思想,和分类找到最大概率的类别是差不多的】
方法大概如下:以目标为中心从原图截图一个区域(一般为 target_size的两倍大),通过公式(4)(4)(4)找到其最大相应值,为其下一阵的目标中心点;通过公式(3)(3)(3)(α\alphaα 和 xxx)更新训练新的模型;
简介
之前的方法都有一个共同点:采用了稀疏采样的策略(在一定程度上减少overlap区域的冗余计算)。其使用一定数量的与目标边框一样大小的子图像区域(在目标附近的子区域),这很显然仍会带来相当一部分的重叠,这表明图像的结构一直被忽略。
作者证明了取图像子窗口的过程会产生循环结构,这就给傅里叶分析带来机会,可以使用快速傅里叶变换(FFT)来快速合并所有的子区域,而无需迭代它们。
作者也表示使用核技巧在非线性特征空间分类与在传统图像空间一样。
本文的贡献:
- 一个框架去学习通用分类器,使其可以用一张图片的所有子窗口训练(使其可以不用限制于稀疏样本的表达能力),作者称这种方法为dense sampling;
- 证明了在这种情况下的核矩阵具有循环结构,对于单一的核而言;
- 封闭形式,快速而精确的解决方案:
(a) 密集采样的内核正则化最小二乘
(b)使用通用核分类器检测所有的子窗口
©在所有子窗口计算多种核,包括流行的高斯核与多项式核 - 基于以上想法,提出了一个跟踪器。该跟踪器在达到当时最优效果的同时,实现更简单、跑的更快。
用密集样本学习
基于检测后的跟踪任务的核心是分类器。传统方法,在每一帧上,在目标周围采集一定数量的样本(一般就目标边框大小,或者x倍大),近的标位正样本,远的标为负样本,对分类器进行适应性训练。
与传统方法不同,本文使用所有样本训练分类器(dense sampling),这是因为内核矩阵变得高度结构化,因此可以充分利用其优势。
最小化正则风险
分类器f(x)f(x)f(x)有以下形式:f(x)=<w,x>+bf(x)=<w,x>+bf(x)=<w,x>+b其中<⋅,⋅>< \cdot, \cdot ><⋅,⋅>表示点乘,其最小化问题为minw,b∑i=1mL(yi,f(xi))+λ∥w∥2\mathop{min}\limits_{w,b}\sum\limits^m_{i=1}L(y_i,f(x_i))+\lambda\|w\|^2w,bmini=1∑mL(yi,f(xi))+λ∥w∥2
核技巧允许分类器在高维空间分类,其将输入映射,即将x→φ(x)x\rightarrow\varphi(x)x→φ(x),定义核为k(x,x′)=<φ(x),φ(x′)>\mathscr{k}(x, x')=<\varphi(x), \varphi(x')>k(x,x′)=<φ(x),φ(x′)>我们想要求得的参数可以通过输入映射后的表示的线性组合来表示:w=∑iαiφ(xi)w=\sum_i\alpha_i\varphi(x_i)w=i∑αiφ(xi)该解需要求出向量α\alphaα,而α\alphaα有闭式解:(1)α=(K+λI)−1y\alpha=(K+\lambda I)^{-1}y\tag{1}α=(K+λI)−1y(1)其中,K为核矩阵,其元素值Kij=k(xi,xj)K_{ij}=\mathcal{k}(x_i,x_j)Kij=k(xi,xj),III是单位矩阵,yyy是输入的yiy_iyi元素的向量。
循环矩阵
在合适的条件下,核矩阵是循环的,这将允许充分学习(密集样本)。n∗nn*nn∗n核矩阵(循环形式)C(u)C(u)C(u)可以由n∗1n*1n∗1个向量uuu通过循环偏移得到(第一行是uuu,第二行是uuu循环右移一位,以此类推)。
循环矩阵的动机是编码向量的卷积,这循环向量的表示接近于使用分类器在很多不同的子窗口上。因此,矩阵和向量的乘积C(u)vC(u)vC(u)v可以表示为向量u和vu和vu和v的卷积:C(u)v=F−1(F∗(u)⊙F(v))C(u)v=\mathcal{F}^{-1}(F^*(u)\odot \mathcal{F}(v))C(u)v=F−1(F∗(u)⊙F(v))其中,⊙\odot⊙是元素乘积,F\mathcal{F}F和F−1\mathcal{F}^{-1}F−1是傅里叶变换和逆傅里叶变换,∗*∗是共轭复数。
从循环矩阵的定义可以看出,我们可以不用定义和计算C(u)C(u)C(u),因为其可以由uuu来得到;C(u)C(u)C(u)的第iii行可以表示为PiuP^iuPiu,PPP是置换矩阵,可以将uuu循环循环移动一个元素,PiP^iPi表示置换了iii次。
假设一张图片xxx,表示为n∗1n*1n∗1向量,则样本集(子窗口)可以表示为xi=Pix,∀i=0,...,n−1x_i=P^ix, \forall i=0,...,n-1xi=Pix,∀i=0,...,n−1直观上来说,这些样本包含了xxx的所有变换版本。
有效的核最小平方解决方案
定义向量kkk每个元素为:(2)ki=k(x,Pix)k_i=\mathbb{k}(x,P^ix)\tag{2}ki=k(x,Pix)(2),则核矩阵K=C(k)K=C(k)K=C(k)注意:kkk是n∗1n*1n∗1向量,而KKK是n∗nn*nn∗n。
应用以上特性于公式(1)(1)(1)和(2)(2)(2),可以得该解决方案的解:(3)α=F−1(F(y)F(k)+λ)\alpha=\mathcal{F}^{-1}(\frac{\mathcal{F}(y)}{\mathcal{F}(k)+\lambda})\tag{3}α=F−1(F(k)+λF(y))(3)其中,除法是逐元素除法。
该解决方案,只是用了FFT和逐元素操作。
快速检测
一般来说,输入一堆训练集{xi,yi}\{x_i, y_i\}{xi,yi}。由一个输入zzz得到的分类器的响应为y′=∑iαik(xi,z)y'=\sum_i\alpha _i\mathbb{k}(x_i, z)y′=i∑αik(xi,z)该公式通过滑动窗口的方法计算所有窗口的响应,并得到其中的最大值。
由于循环结构允许我们同时计算所有位置的响应,因此这个向量在所有位置的响应为(4)y^=F−1(F(kˉ)⊙F(α))\hat{y}=\mathcal{F}^{-1}(\mathcal{F}(\bar{k})\odot\mathcal{F}(\alpha))\tag{4}y^=F−1(F(kˉ)⊙F(α))(4)其中,kˉ\bar{k}kˉ是一个向量,其元素为kiˉ=k(z,Pix)\bar{k_i}=\mathbb{k}(z, P^ix)kiˉ=k(z,Pix)。因此2D图片的处理时间复杂度从O(n4)→O(n2logn)O(n^4)\rightarrow O(n^2logn)O(n4)→O(n2logn)
非线性核的快速计算
Dot-product kernels
点积核的形式为k(x,x′)=g(<x,x′>)k(x,x')=g(<x,x'>)k(x,x′)=g(<x,x′>),对于一些函数 ggg。内核矩阵的紧凑表示 kkk 标记为 kdpk^{dp}kdp,kdpk^{dp}kdp 的每一个元素定义如下:kidp=k(x,pix′)=g(xTPix′)k^{dp}_i=\mathbb{k}(x,p^ix')=g(x^TP^ix')kidp=k(x,pix′)=g(xTPix′)ggg 函数作用于输入向量的每一个元素,所以 kdpk^{dp}kdp 可以写成kdp=g(C(x′)x)k^{dp} =g(C(x')x) kdp=g(C(x′)x)应用傅里叶变换,则变为:kdp=(F−1(F(x)⊙F∗(x′)))k^{dp}=(\mathcal{F^{-1}}(\mathcal{F}(x)\odot\mathcal{F^*}(x')))kdp=(F−1(F(x)⊙F∗(x′)))
实际上,多项式内核在此的傅里叶形式为:kpoly=(F−1(F⊙F∗(x′))+c)dk^{poly}=(\mathcal{F^{-1}}(\mathcal{F}\odot\mathcal{F^*}(x'))+c)^dkpoly=(F−1(F⊙F∗(x′))+c)d
Radial Basis Function kernels
径向基函数核的形式为k(x,x′)=h(∥x−x′∥2)k(x,x')=h(\|x-x'\|^2)k(x,x′)=h(∥x−x′∥2),对于一些函数 hhh。kirbf=k(x,Pix′)=h(∥x−Pix′∥2)=h(∥x∥2+∥x′∥2−2xTPix′)k^{rbf}_i=\mathbb{k}(x, P^ix')=h(\|x-P^ix'\|^2)=h(\|x\|^2+\|x'\|^2-2x^TP^ix')kirbf=k(x,Pix′)=h(∥x−Pix′∥2)=h(∥x∥2+∥x′∥2−2xTPix′)因为∥x∥2和∥x′∥2\|x\|^2和\|x'\|^2∥x∥2和∥x′∥2是常数,所以上式和点积核的形式相同:krbf=h(∥x∥2+∥x′∥2−2F−1(F(x)⊙F∗(x′)))k^{rbf}=h(\|x\|^2+\|x'\|^2-2\mathcal{F^{-1}}(\mathcal{F(x)\odot\mathcal{F^*}(x')}))krbf=h(∥x∥2+∥x′∥2−2F−1(F(x)⊙F∗(x′)))
实际上,高斯核的傅里叶应用形式为kgauss=exp(−1σ2∥x∥2+∥x′∥2−2F−1(F(x)⊙F∗(x′)))k^{gauss}=exp(-\frac{1}{\sigma^2}\|x\|^2+\|x'\|^2-2\mathcal{F^{-1}}(\mathcal{F}(x)\odot\mathcal{F^*}(x')))kgauss=exp(−σ21∥x∥2+∥x′∥2−2F−1(F(x)⊙F∗(x′)))
def dense_gauss_kernel(sigma, x, y=None):
xf = FFT3D(x)
xx = np.sum(x * x)
yf = FFT3D(y)
yy = np.sum(y * y)
xyf = xf * np.conj(yf)
xy = np.real(IFFT2(np.sum(xyf, axis=2)))
tmp1 = np.abs(xx + yy - 2 * xy)
k = np.exp(-1 / sigma ** 2 * (tmp1 / np.prod(x.shape)))
kf = FFT2D(k)
return kf
对于一个n∗nn*nn∗n图片,在n2n^2n2个位置直接进行内核运算将需要O(n4)O(n^4)O(n4)个操作,但是相应的在频率上的操作将只需要O(n2logn)O(n^2\mathop{log}n)O(n2logn)个操作。
Linear kernels
线性核可以显示地计算www,而不需要隐式地计算α\alphaα:w=F−1(F(x)⊙F∗(y)F(x)⊙F∗(x)+λ)w=\mathcal{F^{-1}}(\frac{\mathcal{F}(x)\odot\mathcal{F^*}(y)}{\mathcal{F}(x)\odot\mathcal{F^*}(x)+\lambda})w=F−1(F(x)⊙F∗(x)+λF(x)⊙F∗(y))
def dense_linear_kernel(x, y=None):
xf = FFT3D(x)
yf = FFT3D(y)
kf_real = np.sum(xf.real * yf.real + xf.imag * yf.imag, axis = 2) / np.prod(x.shape)
kf_imag = np.sum(xf.imag * yf.real - xf.real * yf.imag, axis = 2) / np.prod(x.shape)
kf = asarray(kf_real).astype(complex, copy=False)
kf.imag = kf_imag
return kf
实验
预处理
本文提出的方法是基于像素值的,而不是进行特征提取。但傅里叶变换是周期性的,原始图像两端的不连续将给傅里叶变换的进行带来噪声,所以我们需要对原始图像进行预处理。一个共识的解决方案是给原始图像(行方向)加一个正弦或者余弦的窗口。Xij=(xijraw−0.5)sin(πni)sin(πnj) ∀i,j=0,...,n−1X_{ij}=(x_{ij}^{raw}-0.5)sin(\frac{\pi}ni)sin(\frac{\pi}nj)\ \ \ \ \ \ \ \forall i,j=0,...,n-1Xij=(xijraw−0.5)sin(nπi)sin(nπj) ∀i,j=0,...,n−1这将导致图像越靠近边缘的像素值,越接近于0,以消除图像两端的不连续性。