神经网络的理论与python实现

符号说明

  1. $S(z)$:sigmoid函数,$S(z)=1/(1+\exp(-z))$,其导数为$S’(z)=S(z)(1-S(z))$
  2. $a_{l,ij}$:第$l$层神经元的第$j$个神经元对于第$i$组输入数据的数值。
  3. $w_{l,ij}$:从第$l$层的第$i$个神经元计算第$l+1$层的第$j$个神经元的权重,所以有递推公式$a_{l,ij}=S(\sum_k a_{l-1,ik}w_{l-1,kj})=S(b_{l,ij})$,其中$b_{l,ij}=\sum_k a_{l-1,ik}w_{l-1,kj}$,写出矩阵形式,$a_l=S(b_l)=S(a_{l-1}w_{l-1})$
  4. $y_{ij}$:输入第$i$组数据时输出神经元的第$j$个神经元的真实值

两层神经网络

输出的总误差为
$$\begin{aligned}
C&=\frac{1}{2}\sum_{ij}(a_{2,ij}-y_{ij})2\\
&=\frac{1}{2}\sum_{ij}\left(S(\sum_k a_{1,ik}w_{1,kj})-y_{ij}\right)^2
\end{aligned}$$
次误差为权重的函数,要想是的误差最小,我们使用梯度下降算法,使误差沿着梯度的负方向变化。
$$\begin{aligned}
\frac{\partial C}{\partial w_{1,kj}}&=\sum_{i}\left(S(\sum_k a_{1,ik}w_{1,kj})-y_{ij}\right)S’(\sum_k a_{1,ik}w_{1,kj})a_{1,ik}\\
&=\sum_i a^T_{1,ki}(S(b_{2,ij})-y_{ij})S’(b_{2,ij})
\end{aligned}$$
写出矩阵形式
$$\nabla_1 C=\frac{\partial C}{\partial w_1}=a_1^T\delta_2$$
其中$\delta_{2,ij}=(S(b_{2,ij})-y_{ij})S’(b_{2,ij})$,写出矩阵形式为,$\delta_2=(S(b_2)-y).S’(b_2)$。所以权重的更新规则为
$$\begin{aligned}
w_1&:=w_1-\eta \nabla_1 C\\
&:=w_1-\eta a_1^T \delta_2\\
&:=w_1-\eta a_1^T ((S(a_1 w_1)-y).
S’(a_1 w_1))
\end{aligned}$$

示例

a b c out1 out2
0 1 0 0 1
1 1 0 1 1
1 0 0 1 0
0 0 1 0 1

三个输入神经元,两个输出神经元,我们这里规则是,$out1=a,out2=b+c$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import numpy as np
def sigmoid(x,deriv=False):
if(deriv==True):
# return sigmoid(x)*(1-sigmoid(x))
return np.exp(-x)/(1+np.exp(-x))**2
return 1/(1+np.exp(-x))
def nn2(a1,y):
eta=1
step=30000
w1=2*np.random.random((a1.shape[1],y.shape[1]))-1
for i in range(step):
b2=a1.dot(w1)
w1=w1-eta*a1.T.dot((sigmoid(b2)-y)*sigmoid(b2,True))
return w1
a1=np.array([[0,1,0],[1,1,0],[1,0,0],[0,0,1]])
y=np.array([[0,1],[1,1],[1,0],[0,1]])
testa=np.array([[1,0.4,0.2]])
testy=np.array([[1,1]])
print 'for train data'
w1=nn2(a1,y)
out=sigmoid(a1.dot(w1))
print y
print out
print 'for test data'
out=sigmoid(testa.dot(w1))
print testy
print out

多层神经网络

如果在神经网络中还存在隐藏层,也即中间层,其功效将会大大增加,理论推导类似。