可编程逻辑
双线性插值顾名思义是线性插值Pro,为了说明白什么是双线性插值,首先得先从线性插值说起。那么什么又是线性呢?用数学课本上的话来说,两个变量之间存在一次方函数关系,就称它们之间存在线性关系。可能这么说有些太抽象,下面举个生活中的例子来形象地说明一下线性插值。
将单线性插值升维成双线性插值后,计算一个点的情况如下图所示。首先蓝色的点是水平方向单线性插值算出来的数,接着在垂直方向上2个蓝色的点线性插值出红色的点,经过两次单线性插值之后就完成了双线性插值的整个过程。
在计算机图像的过程中,图片放大有很多种不同的方法。速度最快的就是最邻近法(简单图像缩放),它的原理就是直接把源图像距离最近的像素点值填充到放大图像的像素点。缺点就是会在放大图片中出现很多的马赛克,图像放大非常不平滑。而双线性插值的方法则是每个点都通过前文介绍的线性插值的方法计算出来的,图片的缩放过程会比较平滑。下面的原理示意图对比了2种过程的不同。
实际上,无论是像素点的选择还是权重的计算都依赖源图片和目标图片长和宽像素点的比例关系。根据源图片和目标图片的比例关系可以先算出一个基础系数(Base_Parameter)。但这并不意味着一个2*2的图片扩大成4*4的图片,比例系数就由2/4直接得到,因为双线性插值的的点是指的每个像素点的中心点的值。
所以实际的比例关系计算应该是中心点距离的总和之间的比例关系,也就是像素点减一之后的比例关系。还是举例说明的话,2*2的图片扩大成4*4的图片应该就是(2-1)/(4-1)这样来得出比例关系。为了证明这个推导的正确性,下面是caffe里面interp层的c++代码,可以从图中看到的是选择像素点的代码,确实是需要进行减一操作的。
用3*3扩大成4*4的例子来举例说明。根据上面推导出的公式可以得到这个过程中的基础比例系数是(3-1)/(4-1)=0.67。如下图所示,目标图片的第二行第二列的点是由1,2,4,5四个点计算的。因为此时,选择像素点行的参数为0.67*1=0.67没有超过1且选择像素点水平方向和垂直方向的参数为0.67*1=0.67没有超过1。所以,参与计算的源图片像素点。
是最左最上的2*2矩阵。到计算目标图片的第二行第三列数时,水平方向的参数为0.67*2=1.34,这个值超过了1,所以源图片水平2*2的矩阵要向右移动一个像素的位置。而垂直方向的参数还是0.67,故而垂直方向无需移动。参与运算的数就从1、2、4、5变为了2、3、5、6。
还是用3*3扩大成4*4的例子来举例说明。现在需要计算0Base下(1,1)的数,也就是图中黄色的像素点。由于它的行坐标和列坐标都为1,所以这层的计算参数需要分别将行和列的基础系数乘1得到,也就是行为0.67,列为0.67。具体计算过程为1*(1-0.67)*(1-0.67) + 2*0.67(1-0.67) + 4*(1-0.67)*0.67 +5*0.67*0.67。其中红字的部分就是权重的计算过程。
基础系数的计算需要用到除法,然后每个像素点的计算参数计算需要用基础系数和像素的index相乘来得到。在FPGA上,乘法是一件非常消耗资源的事,虽然Xilinx和Altera这样的FPGA厂商会在每块FPGA板上设计dsp来专门应对乘法、除法等复杂运算。但dsp的数量是十分有限的,dsp的使用水平很大程度上决定了整个FPGA的计算速度。
一个dsp可以当作一个乘法器使用,而一个除法器则需要多个DSP级联组成。除此以外,除法器消耗的周期也是十分巨大的,这就意味着除了dsp之外,也需要增加很多寄存器来同步数据,这样又会降低很多计算性能,还使得FPGA的布线更加困难。
FPGA之所以能提高神经网络的运算速度,很重要的一个原因就是它是一个灵活可变的架构,无数不同的设计最终可以实现同样的效果。雪湖之所以能在相对低端的板子上跑运算量巨大的网络,本质的原因也是公司内部有着大量优秀的FPGA开发工程师。
通过对Interp代码的仔细研究,工程师们发现了其中的计算规律。只要输入和输出的分辨率固定,基础系数可以在FPGA外部提前算出,去掉除法器。同时,每个像素点的计算参数也会根据基础系数提前算出,到时候通过导入二进制文件的方式进入FPGA的计算单元,减少DSP的使用。
全部0条评论
快来发表一下你的评论吧 !