sigmoid函数的特性及硬件实现方法--含matlab代码实现及讲解
1. 简介
sigmoid是神经网络中常用的一种激活函数,在机械学习和很多降噪滤波算法中也常常会用到这个函数。sigmoid函数的表达式如下:
y
=
s
i
g
m
o
i
d
(
x
)
=
1
1
+
e
x
p
(
−
x
)
y=sigmoid(x)=\frac {1} {1+exp(-x)}
y = s i g m o i d ( x ) = 1 + e x p ( − x ) 1 本文主要会介绍一些sigmoid函数常用的特性。并且基于sigmoid函数特有的性质,我会给出一种硬件实现sigmoid函数的方法(不是多项式拟合法),为了方便读者理解,我还用matlab模拟了sigmoid函数的实现。有兴趣的小伙伴可以直接到我下面的链接中下载代码。 https://download.csdn.net/download/qq_35721810/10885213
2. sigmoid函数的特性介绍
2.1 sigmoid(x)与sigmoid(-x)的关系
sigmoid(x)与sigmoid(-x)的具有下面的关系:
s
i
g
m
o
i
d
(
−
x
)
=
1
−
s
i
g
m
o
i
d
(
x
)
sigmoid(-x) = 1 - sigmoid(x)
s i g m o i d ( − x ) = 1 − s i g m o i d ( x ) 推导过程如下:
1
−
s
i
g
m
o
i
d
(
x
)
=
1
−
1
1
+
e
x
p
(
−
x
)
=
e
x
p
(
−
x
)
1
+
e
x
p
(
−
x
)
=
1
1
+
e
x
p
(
x
)
=
s
i
g
m
o
i
d
(
−
x
)
1-sigmoid(x) = 1-\frac {1} {1+exp(-x)}=\frac {exp(-x)} {1+exp(-x)}=\frac {1} {1+exp(x)}= sigmoid(-x)
1 − s i g m o i d ( x ) = 1 − 1 + e x p ( − x ) 1 = 1 + e x p ( − x ) e x p ( − x ) = 1 + e x p ( x ) 1 = s i g m o i d ( − x )
2.2 sigmoid函数与tanh函数的关系
tanh(x)为双曲余弦函数,其表达式如下
t
a
n
h
(
x
)
=
e
x
p
(
x
)
−
e
x
p
(
−
x
)
e
x
p
(
x
)
+
e
x
p
(
−
x
)
tanh(x)=\frac {exp(x)-exp(-x)} {exp(x)+exp(-x)}
t a n h ( x ) = e x p ( x ) + e x p ( − x ) e x p ( x ) − e x p ( − x ) sigmoid(x)与tanh(x)函数的关系如下:
s
i
g
m
o
i
d
(
x
)
=
t
a
n
h
(
x
2
)
+
1
2
sigmoid(x) =\frac {tanh(\frac {x} {2})+1} {2}
s i g m o i d ( x ) = 2 t a n h ( 2 x ) + 1 推导过程如下:
t
a
n
h
(
x
2
)
+
1
2
=
e
x
p
(
x
/
2
)
−
e
x
p
(
−
x
/
2
)
e
x
p
(
x
/
2
)
+
e
x
p
(
−
x
/
2
)
+
1
2
=
e
x
p
(
x
/
2
)
(
e
x
p
(
x
/
2
)
+
e
x
p
(
−
x
/
2
)
)
=
1
1
+
e
x
p
(
−
x
)
=
s
i
g
m
o
i
d
(
x
)
\frac {tanh(\frac {x} {2})+1} {2}=\frac{\frac {exp(x/2)-exp(-x/2)} {exp(x/2)+exp(-x/2)}+1}{2}=\frac {exp(x/2)} {(exp(x/2)+exp(-x/2))}=\frac {1} {1+exp(-x)}=sigmoid(x)
2 t a n h ( 2 x ) + 1 = 2 e x p ( x / 2 ) + e x p ( − x / 2 ) e x p ( x / 2 ) − e x p ( − x / 2 ) + 1 = ( e x p ( x / 2 ) + e x p ( − x / 2 ) ) e x p ( x / 2 ) = 1 + e x p ( − x ) 1 = s i g m o i d ( x )
2.3 sigmoid函数的n阶导数
sigmoid函数求导有一个非常好的特殊性质,即导数的结果是可以完全表达成y的函数,与x无关。 假设
y
=
s
i
g
m
o
i
d
(
x
)
=
1
1
+
e
x
p
(
−
x
)
y=sigmoid(x)=\frac {1} {1+exp(-x)}
y = s i g m o i d ( x ) = 1 + e x p ( − x ) 1
d
y
d
x
=
e
x
p
(
−
x
)
[
1
+
e
x
p
(
−
x
)
]
2
=
(
1
−
1
1
+
e
x
p
(
−
x
)
)
1
1
+
e
x
p
(
−
x
)
=
y
(
1
−
y
)
\frac{dy}{dx}=\frac {exp(-x)} {[1+exp(-x)]^2}=\left( 1-\frac {1} {1+exp(-x)}\right)\frac {1} {1+exp(-x)}=y(1-y)
d x d y = [ 1 + e x p ( − x ) ] 2 e x p ( − x ) = ( 1 − 1 + e x p ( − x ) 1 ) 1 + e x p ( − x ) 1 = y ( 1 − y ) 即
d
y
d
x
\frac{dy}{dx}
d x d y 只是y的函数。如果要求二阶导数可以直接对
d
y
d
x
\frac{dy}{dx}
d x d y 再次求导
d
2
y
d
x
2
=
d
d
x
(
d
y
d
x
)
=
(
1
−
2
y
)
d
y
d
x
=
y
(
1
−
y
)
(
1
−
2
y
)
\frac{d^2y}{dx^2}=\frac{d}{dx}\left(\frac{dy}{dx}\right)=(1-2y)\frac{dy}{dx}=y(1-y)(1-2y)
d x 2 d 2 y = d x d ( d x d y ) = ( 1 − 2 y ) d x d y = y ( 1 − y ) ( 1 − 2 y ) 根据上述方法,sigmoid函数的前n-1阶导数一定一个只含有y的函数,对y求导再乘以y(1-y)就是sigmoid函数的n阶导数。这里我没有推导出sigmoid函数的n阶导数的紧凑表达式。有兴趣的同学可以自己推导试一下,也欢迎大神留言给出正解。 另一种求解sigmoid函数n阶导数的方法,就是利用它与tanh(x)的关系。由于
s
i
g
m
o
i
d
(
x
)
=
t
a
n
h
(
x
2
)
+
1
2
sigmoid(x) =\frac {tanh(\frac {x} {2})+1} {2}
s i g m o i d ( x ) = 2 t a n h ( 2 x ) + 1 ,因此sigmoid(x)的n阶导数其实就是
1
2
t
a
n
h
(
x
2
)
\frac{1}{2}tanh(\frac{x}{2})
2 1 t a n h ( 2 x ) 的n阶导。tanh(x)的n阶导数有一些复杂,国内的高等数学教材中并没有提到,最后我还是在一篇NASA的技术笔记 [1]中找到的,这里我直接给出tanh(x)函数的n阶导数结果:
d
2
n
t
a
n
h
(
x
)
d
x
2
n
=
t
a
n
h
(
x
)
∑
k
=
1
n
−
1
(
−
1
)
n
−
k
W
2
(
n
−
k
)
,
k
[
2
(
n
−
k
)
]
!
s
e
c
h
(
x
)
2
(
n
−
k
)
\frac{d^{2n}tanh(x)}{dx^{2n}}=tanh(x)\sum_{k=1}^{n-1} {(-1)^{n-k}W_{2(n-k),k}[2(n-k)]!sech(x)^{2(n-k)}}
d x 2 n d 2 n t a n h ( x ) = t a n h ( x ) k = 1 ∑ n − 1 ( − 1 ) n − k W 2 ( n − k ) , k [ 2 ( n − k ) ] ! s e c h ( x ) 2 ( n − k )
d
2
n
+
1
t
a
n
h
(
x
)
d
x
2
n
+
1
=
t
a
n
h
(
x
)
∑
k
=
0
n
(
−
1
)
n
−
k
W
2
(
n
−
k
+
1
)
,
k
[
2
(
n
−
k
)
+
1
]
!
s
e
c
h
(
x
)
2
(
n
−
k
+
1
)
\frac{d^{2n+1}tanh(x)}{dx^{2n+1}}=tanh(x)\sum_{k=0}^{n} {(-1)^{n-k}W_{2(n-k+1),k}[2(n-k)+1]!sech(x)^{2(n-k+1)}}
d x 2 n + 1 d 2 n + 1 t a n h ( x ) = t a n h ( x ) k = 0 ∑ n ( − 1 ) n − k W 2 ( n − k + 1 ) , k [ 2 ( n − k ) + 1 ] ! s e c h ( x ) 2 ( n − k + 1 ) 上式中的
W
2
n
,
k
W_{2n,k}
W 2 n , k 可以通过下面的递推公式得到
W
2
,
k
=
2
2
k
W_{2,k}=2^{2k}
W 2 , k = 2 2 k
W
4
,
k
=
∑
m
=
0
k
2
2
(
k
+
m
)
W_{4,k}=\sum_{m=0}^{k}{2^{2(k+m)}}
W 4 , k = m = 0 ∑ k 2 2 ( k + m )
W
2
n
,
k
=
(
2
n
)
2
W
2
n
,
k
−
1
+
W
2
(
n
−
1
)
,
k
W_{2n,k}=(2n)^{2}W_{2n,k-1}+W_{2(n-1),k}
W 2 n , k = ( 2 n ) 2 W 2 n , k − 1 + W 2 ( n − 1 ) , k 因此根据tanh(x)的n阶导数可以得到sigmoid(x)的n阶导数,具体形式如下
d
2
n
s
i
g
m
o
i
d
(
x
)
d
x
2
n
=
1
2
2
n
+
1
t
a
n
h
(
x
2
)
∑
k
=
1
n
−
1
(
−
1
)
n
−
k
W
2
(
n
−
k
)
,
k
[
2
(
n
−
k
)
]
!
s
e
c
h
(
x
2
)
2
(
n
−
k
)
\frac{d^{2n}sigmoid(x)}{dx^{2n}}=\frac{1}{2^{2n+1}}tanh(\frac{x}{2})\sum_{k=1}^{n-1} {(-1)^{n-k}W_{2(n-k),k}[2(n-k)]!sech(\frac{x}{2})^{2(n-k)}}
d x 2 n d 2 n s i g m o i d ( x ) = 2 2 n + 1 1 t a n h ( 2 x ) k = 1 ∑ n − 1 ( − 1 ) n − k W 2 ( n − k ) , k [ 2 ( n − k ) ] ! s e c h ( 2 x ) 2 ( n − k )
d
2
n
+
1
s
i
g
m
o
i
d
(
x
)
d
x
2
n
+
1
=
1
2
2
n
+
2
t
a
n
h
(
x
2
)
∑
k
=
0
n
(
−
1
)
n
−
k
W
2
(
n
−
k
+
1
)
,
k
[
2
(
n
−
k
)
+
1
]
!
s
e
c
h
(
x
2
)
2
(
n
−
k
+
1
)
\frac{d^{2n+1}sigmoid(x)}{dx^{2n+1}}=\frac{1}{2^{2n+2}}tanh(\frac{x}{2})\sum_{k=0}^{n} {(-1)^{n-k}W_{2(n-k+1),k}[2(n-k)+1]!sech(\frac{x}{2})^{2(n-k+1)}}
d x 2 n + 1 d 2 n + 1 s i g m o i d ( x ) = 2 2 n + 2 1 t a n h ( 2 x ) k = 0 ∑ n ( − 1 ) n − k W 2 ( n − k + 1 ) , k [ 2 ( n − k ) + 1 ] ! s e c h ( 2 x ) 2 ( n − k + 1 )
2.4 当x=n*ln2时的数值
这个特性其实非常有趣,当
x
=
n
∗
l
n
2
x=n*ln2
x = n ∗ l n 2 (n可以为任意非0的整数,可正可负)时,sigmoid函数可以变成
s
i
g
m
o
i
d
(
n
∗
l
n
2
)
=
1
1
+
2
−
n
sigmoid(n*ln2)=\frac{1}{1+2^{-n}}
s i g m o i d ( n ∗ l n 2 ) = 1 + 2 − n 1
1
1
+
2
−
n
\frac{1}{1+2^{-n}}
1 + 2 − n 1 的机械数是非常有规律的. 下面给一个几个例子 当
n
=
1
n=1
n = 1 时,
1
1
+
2
−
1
=
(
0.10101010...
)
2
\frac{1}{1+2^{-1}}=(0.10101010...)_2
1 + 2 − 1 1 = ( 0 . 1 0 1 0 1 0 1 0 . . . ) 2 上式中
(
)
2
()_2
( ) 2 代表2进制表示。 当
n
=
2
n=2
n = 2 时,
1
1
+
2
−
2
=
(
0.1100110011001100...
)
2
\frac{1}{1+2^{-2}}=(0.1100110011001100...)_2
1 + 2 − 2 1 = ( 0 . 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0 . . . ) 2 当
n
=
3
n=3
n = 3 时,
1
1
+
2
−
3
=
(
0.111000111000111000111000...
)
2
\frac{1}{1+2^{-3}}=(0.111000111000111000111000...)_2
1 + 2 − 3 1 = ( 0 . 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 . . . ) 2 以此类推,当n大于0时,sigmoid函数的结果的机器数为n个1和0交替。 当
n
=
−
1
n=-1
n = − 1 时,
1
1
+
2
1
=
(
0.01010101...
)
2
\frac{1}{1+2^{1}}=(0.01010101...)_2
1 + 2 1 1 = ( 0 . 0 1 0 1 0 1 0 1 . . . ) 2 当
n
=
−
2
n=-2
n = − 2 时,
1
1
+
2
2
=
(
0.0011001100110011...
)
2
\frac{1}{1+2^{2}}=(0.0011001100110011...)_2
1 + 2 2 1 = ( 0 . 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 . . . ) 2 当
n
=
−
3
n=-3
n = − 3 时,
1
1
+
2
3
=
(
0.000111000111000111000111...
)
2
\frac{1}{1+2^{3}}=(0.000111000111000111000111...)_2
1 + 2 3 1 = ( 0 . 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 . . . ) 2 当n小于0时,sigmoid函数的结果的机器数为n个0和1交替。 根据上述性质,我们可以很容易通过硬件实现
x
=
n
∗
l
n
2
x=n*ln2
x = n ∗ l n 2 时的sigmoid函数值。
2.5 其他关系式
sigmoid函数有一个非常类似柯西中值定理的关系式:
s
i
g
m
o
i
d
(
x
1
)
−
s
i
g
m
o
i
d
(
x
2
)
=
1
1
+
e
x
p
(
−
x
1
)
−
1
1
+
e
x
p
(
−
x
2
)
=
e
x
p
(
x
2
)
−
e
x
p
(
x
1
)
[
1
+
e
x
p
(
−
x
1
)
]
[
1
+
e
x
p
(
x
2
)
]
sigmoid(x_1)-sigmoid(x_2)=\frac {1} {1+exp(-x_1)}-\frac {1} {1+exp(-x_2)}=\frac {exp(x_2)-exp(x_1)} {[1+exp(-x_1)][1+exp(x_2)]}
s i g m o i d ( x 1 ) − s i g m o i d ( x 2 ) = 1 + e x p ( − x 1 ) 1 − 1 + e x p ( − x 2 ) 1 = [ 1 + e x p ( − x 1 ) ] [ 1 + e x p ( x 2 ) ] e x p ( x 2 ) − e x p ( x 1 )
s
i
g
m
o
i
d
(
x
1
)
−
s
i
g
m
o
i
d
(
x
2
)
e
x
p
(
−
x
1
)
−
e
x
p
(
−
x
2
)
=
−
s
i
g
m
o
i
d
(
x
1
)
s
i
g
m
o
i
d
(
x
2
)
\frac {sigmoid(x_1)-sigmoid(x_2)} {exp(-x_1)-exp(-x_2)}=-sigmoid(x_1)sigmoid(x_2)
e x p ( − x 1 ) − e x p ( − x 2 ) s i g m o i d ( x 1 ) − s i g m o i d ( x 2 ) = − s i g m o i d ( x 1 ) s i g m o i d ( x 2 ) 公式的左边与柯西中值定理很像
f
(
x
1
)
−
f
(
x
2
)
g
(
x
1
)
−
g
(
x
2
)
=
f
′
(
ξ
)
g
′
(
ξ
)
\frac {f(x_1)-f(x_2)} {g(x_1)-g(x_2)}=\frac{f'(\xi)}{g'(\xi)}
g ( x 1 ) − g ( x 2 ) f ( x 1 ) − f ( x 2 ) = g ′ ( ξ ) f ′ ( ξ )
3. 硬件实现方案
sigmoid函数的硬件实现很多是通过分区多项式拟合法得到的。这里我给大家介绍一种基于泰勒级数展开的硬件实现方法。并且在下文中我会给出matlab版本的实现 。 首先泰勒级数展开的方法如下:
f
(
x
0
+
Δ
x
)
=
f
(
x
0
)
+
d
f
(
x
0
)
d
x
Δ
x
+
1
2
!
d
2
f
(
x
0
)
d
x
2
(
Δ
x
)
2
+
.
.
.
+
1
n
!
d
n
f
(
x
0
)
d
x
n
(
Δ
x
)
n
f(x_0+\Delta x)=f(x_0)+\frac{df(x_0)}{dx}\Delta x+\frac{1}{2!}\frac{d^2f(x_0)}{dx^2}(\Delta x)^2+...+\frac{1}{n!}\frac{d^nf(x_0)}{dx^n}(\Delta x)^n
f ( x 0 + Δ x ) = f ( x 0 ) + d x d f ( x 0 ) Δ x + 2 ! 1 d x 2 d 2 f ( x 0 ) ( Δ x ) 2 + . . . + n ! 1 d x n d n f ( x 0 ) ( Δ x ) n 需要指出的是泰勒级数展开其实只能适用于一个
Δ
x
\Delta x
Δ x 很小的区域范围。对于从负无穷到正无穷范围取值的sigmoid函数,我们很难仅通过零点展开对其进行近似。 如果可以找到在任意
x
x
x 附近的一个
x
0
x_0
x 0 ,并且我们可以得到
f
(
x
0
)
f(x_0)
f ( x 0 ) ,
d
f
(
x
0
)
d
x
\frac{df(x_0)}{dx}
d x d f ( x 0 ) ,…,
d
n
f
(
x
0
)
d
x
n
\frac{d^nf(x_0)}{dx^n}
d x n d n f ( x 0 ) ,那么就可以计算泰勒级数的展开结果。对于硬件实现其实
1
n
!
\frac{1}{n!}
n ! 1 可以认为是一个预先算好的系数。 回忆第2节中我们提到两个sigmoid的性质。当
x
=
n
∗
l
n
2
x=n*ln2
x = n ∗ l n 2 时,sigmoid函数的机械数是很容易计算的,其次如果sigmoid函数的任意n阶导数只是sigmoid函数值的函数,即我们可以很容易得到
x
=
n
∗
l
n
2
x=n*ln2
x = n ∗ l n 2 时,sigmoid函数的任意n阶导数。根据上述方法我们可以得到一种基于泰勒级数展开的硬件实现方案。其基本思想如下: 1. 输入任意x,找到距离x最近的
x
0
=
n
∗
l
n
2
x_0=n*ln2
x 0 = n ∗ l n 2 。 2. 计算
x
0
=
n
∗
l
n
2
x_0=n*ln2
x 0 = n ∗ l n 2 时的函数值,以及n阶导数,
1
n
!
\frac{1}{n!}
n ! 1 可以预先计算好输入。 3. 利用泰勒级数展开公式对sigmoid函数进行计算。
4. matlab代码实现及讲解
下面我会给出泰勒级数展开法实现sigmoid函数的matlab代码。可以点击下面的链接下载我的代码: https://download.csdn.net/download/qq_35721810/10885213 图 1 matlab代码 解压sigmoid_function.rar里面有四个.m文件。test.m是一个测试案例。sigmoid_hw.m是主要的实现函数。buildRefVal.m是用来计算
x
0
=
n
l
n
2
x0=nln2
x 0 = n l n 2 时的结果。sigmoidTaylor.m是sigmoid的泰勒展系数的计算方法。下面我会依次介绍这几个文件。
1. test.m 其代码如下:
clear
% 计算x0 = nln2时,f(x0)的机械数的最大长度
byteNum = 64;
% 泰勒级数展开的阶数
taylorNum = 2;
% 生成x
dx = 0.01;
x = 0:dx:5;
% 计算golden数值
golden = 1 ./ (1 + exp(-x));
% 遍历每一个x 用泰勒级数展开法计算sigmoid函数
for i = 1:length(x)
[result_hw(i),~] = sigmoid_hw(x(i),byteNum,taylorNum);
end
% 显示结果
disp('the max error is ')
disp(max(abs(result_hw-golden)))
plot(x,golden)
hold on
plot(x,result_hw,'--r')
byteNum是当
x
0
=
n
l
n
2
x_0=nln2
x 0 = n l n 2 的最大机械数的长度,taylorNum是泰勒级数展开的阶数。计算中的golden直接通过matlab的函数直接实现。byteNum是当
x
0
=
n
l
n
2
x_0=nln2
x 0 = n l n 2 的最大机械数的长度,taylorNum是泰勒级数展开的阶数。计算中的golden直接通过matlab的函数直接实现。sigmoid_hw是实现泰勒级数展开发的核心函数。
2. sigmoid_hw.m 代码如下:
% 这个函数采用泰勒级数展开法计算函数sigmoid
% 输入:
% x 需要计算的sigmoid(x)的结果
% byteNum 为计算x0 = nln2时,f(x0)的机械数的最大长度
% taylorNum 为泰勒级数展开阶数
% 输出:
% val为最后结果
% taylorSeries 是一个n阶向量,它代表x0 = nln2时的n阶泰勒级数计算结果
function [val,taylorSeries] = sigmoid_hw(x,byteNum,taylorNum)
% 计算ln2
ln2 = log(2);
% 得到距离x最近的x0,refX就是x0
n = round(-x/ln2);
refX = -n * ln2;
% 计算x0 = nln2时的机器数,并且转化为10进制数
refVal = buildRefVal(n,byteNum);
% 计算dx
dx = x - refX;
% 计算x0 = nln2时的n阶泰勒级数计算结果
taylorSeries = sigmoidTaylor(refVal,taylorNum);
% 计算dx^n
for i = 1:length(taylorSeries)
if i == 1
dxn(i) = dx;
else
dxn(i) = dxn(i-1)*dx;
end
end
% 泰勒级数n阶求和
val = dot(taylorSeries,dxn) + refVal;
end
函数sigmoid_hw输入的是刚才提到的byteNum,taylorNum还有需要计算的点x。输出的结果是最后泰勒级数展开法计算得到的结果val以及泰勒级数的系数taylorSeries 。首先先找到里x最近的
x
0
=
n
l
n
2
x_0=nln2
x 0 = n l n 2 。这里
n
=
r
o
u
n
d
(
x
/
l
n
2
)
n=round(x/ln2)
n = r o u n d ( x / l n 2 ) 。buildRefVal函数是根据得到的n计算
s
i
g
m
o
i
d
(
x
0
)
sigmoid(x_0)
s i g m o i d ( x 0 ) ,也就是上文提到的一串循环重复的0,1序列。得到
s
i
g
m
o
i
d
(
x
0
)
sigmoid(x_0)
s i g m o i d ( x 0 ) 之后,根据sigmoidTaylor函数计算n阶泰勒级数展开的系数。buildRefVal和sigmoidTaylor会在下面讲解。
3. buildRefVal.m 代码如下:
% 本函数用于产生 1 / (1 + 2^n)的结果
% 当 n = 1, 1 / (1 + 2^n) = 01010101...
% 当 n = 2, 1 / (1 + 2^n) = 001100110011...
% 当 n = -1, 1 / (1 + 2^n) = 101010101...
% 当 n = -2, 1 / (1 + 2^n) = 110011001100...
% 输入
% n 是1 / (1 + 2^n)中的n
% threshold 最大的二进制长度
% 输出
% val 为1/(1 + 2^n)的十进制结果
function val = buildRefVal(n,threshold)
if n == 0
val = 0.5;
return
end
val = 0;
counter = 1;
if n > 0
while(counter <= threshold)
binary = mod(fix((counter-1)/n),2);
val = val + binary*1/2^counter;
counter = counter + 1;
end
else
while(counter <= threshold)
binary = 1-mod(fix((counter-1)/-n),2);
val = val + binary*1/2^counter;
counter = counter + 1;
end
end
end
当
x
0
=
n
l
n
2
x_0=nln2
x 0 = n l n 2 时,sigmoid函数等于
s
i
g
m
o
i
d
(
−
n
l
n
2
)
=
1
1
+
2
n
sigmoid(-nln2)=\frac{1}{1+2^{n}}
s i g m o i d ( − n l n 2 ) = 1 + 2 n 1 buildRefVal函数则是计算
1
1
+
2
n
\frac{1}{1+2^{n}}
1 + 2 n 1 的结果。如上文提到的
1
1
+
2
n
\frac{1}{1+2^{n}}
1 + 2 n 1 是一串n个连续循环的01序列,当n>0时,先0后1;当n<0时先1后0。buildRefVal函数中输出的结果是以十进制形式表示的,其基本实现是设置一个counter,当counter-1整除n为奇数时输出0(或者1),反之则输出1(或者0)。同事counter数有可以表示2进制数小数点后的位数,因此当结果为1时,在结果val中加上1/2^counter。
4. sigmoidTaylor 代码如下:
% 计算sigmoid的n阶泰勒级数展开项
% 输入
% valY 是f(x0)
% n 代表泰勒级数展开项
% 输出
% z 是一个n维向量, 代表[df/dx, d2f/dx2, ...,dnf/dxn]
function [z] = sigmoidTaylor(valY,n)
% 这里通过matlab的符号运算直接求导计算,在硬件实现过程中,可以实现知道函数的形式
syms t
for i = 1:n
if i == 1
% y0 代表df/dx
y0 = t*(1-t);
y = y0;
% 将y值带入方程
z(i) = double(subs(y,t,valY));
else
%对上一次的结果求导
y = diff(y,t)*y0;
z(i) = double(subs(y,t,valY));
%除以n的阶乘
z(i) = z(i)/factorial(n);
end
end
end
sigmoidTaylor函数用于求解n阶导数系数。这里为了提升函数的通用性我直接用符号运算中的求导来计算。事实上在硬件实现过程中这些函数,包括1/n!可以预先算好。求导的方法根据上文2.3节中提到的sigmoid函数n阶导数的求解方法即可。
最后给读者一张2阶精度拟合下的结果图。可以看到泰勒级数展开法的拟合结果与matlab里直接计算的golden结果还是比较贴近的,最大的误差为8.0948e-04。
[1] formulas for nth order derivatives of hyperbolic and trigonometric functions, Edwin G. Wintucky, 1971.