在本篇博文中,我们只使用numpy来搭建一个简单的包含输入层、隐藏层、输出层的神经网络,我们选择sigmoid作为激活函数,选择均方差损失函数,最后使用mnist数据集进行了训练和测试。
1、公式推导
均方差损失函数:
\[loss = J(W,b,x,y)=\frac{1}{2}||a^L-y||^2
\]
前向传播过程:
\[ z^l = W^la^{l-1}+b^l \\
a^l=\sigma(z^l)
\]
反向传播过程:
\[ \frac{\partial J}{\partial W^l}=\delta^l(a^{l-1})^T \\
\frac{\partial J}{\partial b^l}=\delta^l \\
\delta^l=[(W^{l+1})^T\delta^{l+1}]\odot\sigma'(z^l)\\
\delta^L=(a^L-y)\odot\sigma'(z^L)
\]
2、一些工具函数
包括sigmoid激活函数及其一阶导数,和将标签进行one-hot编码的函数,如下所示:
# 标签one-hot处理
def onehot(targets, num):
result = np.zeros((num, 10))
for i in range(num):
result[i][targets[i]] = 1
return result
# sigmoid
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# sigmoid的一阶导数
def Dsigmoid(x):
return sigmoid(x)*(1-sigmoid(x))
3、神经网络具体实现
代码中的self.d2和d1代表公式中的\(\delta\),其他变量均直接按照公式命名,代码如下:
class NN(object):
def __init__(self, l0, l1, l2):
self.lr = 0.1 # 学习率
self.W1 = np.random.randn(l0, l1) * 0.01 # 初始化
self.b1 = np.random.randn(l1) * 0.01
self.W2 = np.random.randn(l1, l2) * 0.01
self.b2 = np.random.randn(l2) * 0.01
# 前向传播
def forward(self, X, y):
self.X = X # m x 784
self.z1 = n