2

基于Caffe的Large Margin Softmax Loss的实现(中)

小喵的唠叨话:前一篇博客,我们做完了L-Softmax的准备工作。而这一章,我们开始进行前馈的研究。

四、前馈

还记得上一篇博客,小喵给出的三个公式吗?不记得也没关系。

这次,我们要一点一点的通过代码来实现这些公式。小喵主要是GPU上实现前后馈的代码,因为这个层只是用来训练,GPU速度应该会快一点。

我们首先要进行一般的FC层的前馈,因为LM_FC的前馈只是修改了一般的FC中的若干个值,而大部分的值都是没有修改过的。

这样就计算完了一个普通的FC的前馈。

之后是一些具体的实现。

1,\cos(\theta_j)=\frac{W_j^Tx_i}{\|W_j\|\|x_i\|}

这是要求出label为j的weight的权值和feature之间的余弦值。公式大家在高中应该就学过了。这样需要出三部分:W_j^Tx_i\|W_j\|\|x_i\|。这里i表示feature的序号,因为一个mini batch中有很多张图片。j表示正确的label值。

W_j^Tx_i的计算非常简单,因为FC层的前馈计算出来的就是这个值。因此我们可以直接从FC的前馈结果中直接复制对应位置的结果。

\|W_j\|\|x_i\|是比较简单的模值的计算,使用caffe_cpu_dot很容易就可以求得(为什么不使用caffe_gpu_dot呢?因为小喵在使用caffe_gpu_dot的时候,caffe会报一个奇怪的错误,不知道是不是因为GPU的显存不能随意访问的)。

最后的余弦值带入到上面的式子,就一下子搞定~

这里用到了几个变量:

M_: batch size

N_: class num

K_: feature length

其中copy_label_score是我们自己编写的用来复制结果的核函数(如何编写Cuda程序就是另一门学科了):

相信机智如你的喵粉,看到这几行代码,一定可以轻松理解。

这里,小喵想多介绍一点东西。
我们知道Caffe里面的数据都是通过Blob结构来存储的,比如这里的bottom_data,其实就是一个blob,默认形状是(n, c, h, w),n表示的就是batch size,c是channel数,h,w分贝表示高和宽。而且blob中的内存的存储顺序,也和一般的C语言中的数组一样。因此我们这里计算feature的模的时候,是直接每K_个数值计算一次点乘。
同理,weight是存储在this->blobs[0]中的,那么weight的形状又是什么样子的呢?这里非常碰巧的是,如果我们在prototxt中设置的transpose为false的话,weight的形状是N_*K_,也就是说,我们可以将weight看成一个矩阵,它的每一行都与feature直接点乘,得到输出,也就是说weight的每一行都是我们需要计算模值的W_j,所以我们计算weight的模的时候,用的计算方法和计算feature模时很相似。我们这里强制设置transpose为false,因为这样计算会比较简单。如果你设成了true,那就必须自己写个求模的函数了。

2,\cos(m\theta_i)=\sum_n(-1)^n{C_m^{2n}\cos^{m-2n}(\theta_i)\cdot(1-\cos(\theta_i)^2)^n}, (2n\leq m)

我们在(1)中求出了\cos(\theta),对于给定的margin,只需要代入公式就可以求出\cos(m\theta)的值了。

上面是用来计算\cos(m\theta)的cuda函数,调用也十分的简单:

3,f_{y_{i}}=(-1)^k\cdot\|W_{y_{i}}\|\|x_{i}\|\cos(m\theta_i)-2k\cdot\|W_{y_i}\|\|x_i\|

严格上来说,我们需要求的并不是这个式子,而是:

    \[ f_{y_i}=\frac{\lambda\|W_{y_i}\|\|x_i\|\cos(\theta_{y_i})+\|W_{y_i}\|\|x_i\|\varphi(\theta_{y_i})}{1+\lambda} \]

    \[ \varphi(\theta)=(-1)^k\cos(m\theta)-2k, \theta\in[\frac{k\pi}{m}, \frac{(k+1)\pi}{m}] \]

可以看出,当\lambda为0的时候,这两个式子就退化成前面的一个式子了。

k的求法十分简单,只需要将\cos(\theta)与各个区间进行比较就可以得到。

最后一步就是计算出真正的前馈值了!按照公式容易编写程序:

调用也十分简单:

最后附上,完整的前馈代码(省略头文件和caffe的名字空间):

那么,这样关于large margin softmax loss的前馈我们就轻松的实现了。下一篇,我们要讲最复杂的后馈的实现了。

 

如果您觉得本文对您有帮助,那请小喵喝杯茶吧~~O(∩_∩)O~~ 再次感慨 \LaTeX 大法好。

%e6%89%93%e8%b5%8f

转载请注明出处~

 

 

miao

miao

2 Comments

发表评论

电子邮件地址不会被公开。