两层全连接网络的构建及求参数梯度的代码实现
上一篇文章写了使用softmax进行多类别分类时使用的交叉熵损失函数对softmax输入单元求导的公式推导。最后求出来的导数非常简单,我不禁感叹设计者的睿智。这篇文章我将利用上次的推导结果实现一个简单的两层全连接神经网络用于多类别分类。代码将给出网络的前向传播过程、求loss损失、以及对网络中参数的求梯度。代码的实现用到了numpy,并没有使用更高级的深度学习框架。
代码将模型写在一个类当中,类中包含了很多方法,包括:求loss损失和参数梯度,train方法给定一些训练参数对使用随机梯度下降(SGD)优化器对模型进行训练,以及predict预测方法给定测试样本输出每个样本最有可能的分类。
- 模型首先初始化参数值,W服从的是随机的带有生态分布的初始值并限制在一个很小的值范围,b初始化为0。
- 网络中隐藏层使用Rlue作为激活函数,对输出使用softmax归一化并使用交叉熵损失函数。
- 损失函数中添加了L2正则化。
- 求参数梯度部分是难点。根据上篇文章的推导可以求出softmax输入单元S2的梯度ds2,通过反向传播算法根据ds2可以很容易求出w2、b2、w1、b1的参数。
代码如下:
class TwoLayerNet(object):
def __init__(self, input_size, hidden_size, output_size, std=1e-4):
self.params = {
}
self.params["w1"] = std * np.random.randn(input_size, hidden_size)
self.params["b1"] = np.zeros(hidden_size)
self.params["w2"] = std * np.random.randn(hidden_size, output_size)
self.params["b2"] = std * np.random.randn(output_size)
def loss(self, X, y=None, reg=0.0):
w1, b1 = self.params["w1"], self.params["b1&#