工作背景
因为我们的工作是要实现神经网络在FPGA上的实现(使用Network On Chips的方法),所以我们的计算需要非常注意时间问题。除了卷积运算外,神经网络上面最占用时间的就是激活函数部分了。如果我们可以把激活函数拟合成与或门的逻辑电路,这无疑是非常节省时间的。
我的工作
现在讲一下我的工作,我主要是在matlab上面去仿真了一种高效的Sigmoid数字实现方式。论文翻译工作我就不做了,文章末尾会提供实现方法的链接。
我根据原文的参考文献了解了很多关于用与或门实现函数仿真的原理,发现还是有点难度的,不建议非微电子电子专业的人过多接触。现在简单介绍一下原论文的实现方式:
我们先来看一幅Sigmoid图像:
可以看到函数得梯度在x超过4以后已经很小了,那么我们是不是可以只在[-4,4]内,或者害怕精度不够在[-8,8]内去实现sigmiod的仿真呢,这样就不用考虑大于阈值的函数值了。p_2_3_6提供的就是这么一种方法(在[-4,4]内部拟合函数)。首先说一下p2_3_6里面的各个数字的意义。p代表positive,因为x大于和小于0的值是关于(0,0.5)这个点对称的,所以我们只需要考虑正向的部分(x>0)。
p_2_3_6里面的2,3分别代表输入的二进制数的整数部分位数和小数部分位数,可以看到输入的范围是00.000到11.111,也就是十进制的0到3.875。然后我们把二进制的每一位由高到低取出来分别令他们为x4x3x2x1x0,然后进行下面的逻辑运算即可,注意到的是后面的输出Output=y5y5y4y3y2y1y0这个地方是有错误的,应该是Output=y5y4y3y2y1y0。输出也是一个二进制数,它的整数部分为0,y5y4y3y2y1y0表示的是小数位从高到低,也就是说实际的输出应该是0.y5y4y3y2y1y0。方法规定y5=1,其实就是表示x>0时y>0.5。
下面是另一种x在[-8,8]内的方法:
输入变成了整数部分三位,x的实际范围变成[0,7.875]。然后输出的小数位变成了七位,精度更高的,当然可以看到他的逻辑电路是要复杂一些的。
编程思路
matlab不能直接生成二进制数,所以我的思路是构建一个步长为0.001(二进制)也就是十进制步长为0.125的数组,成为x=0:0.125:7.875(p_3_3_7)。 然后把十进制数转化为二进制数,取出其中的每一位,进行逻辑与或计算就可以了。
代码
function y=dectobin(innum,N)
%十进制小数转换为二进制数
%输入参数为innum和N
%innum为输入的十进制小数
%N为指定转换后二进制的位数
if (innum>1)||(N == 0)%判断输入的有效性
disp('error!');
return;
end
count=0;
tempnum=innum;
record=zeros(1,N);
while(N)
count=count+1;%长度小于N
if(count>N)
N=0;
return;
end
tempnum=tempnum*2;%小数转换为二进制,乘2取整
if tempnum>1
record(count)=1;
tempnum=tempnum-1;
elseif(tempnum==