使用Python从头搭建神经网络:深入理解深度学习的内部工作原理
动机是为了更深入地理解深度学习,所以我们要使用 Python 语言从头搭建一个神经网络,而不是像 Tensorfl 那样去做。

从零开始用Python构建神经网络
动机是为了更深入地理解深度学习,所以我们会用 Python 语言从开始就搭建一个神经网络,而不会使用像 Tensorflow 那样封装好的框架。我觉得理解神经网络的内部工作原理对数据科学家而言是极为重要的。
这篇文章的内容是我的所学,希望也能对你有所帮助。
神经网络是什么?
介绍神经网络的文章大多会把它和大脑作类比。若你未曾深入研究大脑与神经网络的类比,那么把神经网络解释为一种能将给定输入映射为期望输出的数学关系,就会更易于理解。
神经网络包括以下组成部分
? 一个输入层,x
? 任意数量的隐藏层
? 每层之间有一组权值和偏置,W and b
选择一种激活函数用于隐藏层,即 σ。在教程里我们选用的是 Sigmoid 激活函数。
下图展示了一种结构,这种结构是 2 层神经网络的结构(需要注意的是,在计算网络层数的时候,通常会把输入层排除在外)
2 层神经网络的结构
用 Python 可以很容易的构建神经网络类
训练神经网络
这个网络的输出 ? 为:
你或许会留意到,在上述等式里,输出? 属于 W 和 b 的函数。
W 和 b 的值会影响预测的准确率。因此,依据输入数据对 W 和 b 进行调整和优化的这个过程,被称作训练神经网络。
每步训练迭代包含以下两个部分:
? 计算预测结果 ?,这一步称为前向传播
? 更新 W 和 b,,这一步成为反向传播
下面的顺序图展示了这个过程:
前向传播
我们从上图中可以看到,前向传播的计算较为简单。对于一个基础的 2 层网络而言,它的输出情况如下:
我们在 NeuralNetwork 类里增添一个用于计算前向传播的函数。为了让事情简单些,我们假定偏置 b 是 0 。
但是我们还需要一个办法来评判预测结果的优劣,也就是要评判预测值与真实值之间的误差。而要做到这一点,就需要用到损失函数。
损失函数
常用的损失函数有多种,需根据模型的需求进行选择。在本教程里,我们将误差平方和当作损失函数。
误差平方和是将每个预测值与真实值之间的误差进行求和。这个误差是它们的差值求平方,这样做是为了便于我们观察误差的绝对值。
训练的目标是找到一组 W 和 b,这样能让损失函数达到最小,也就是让预测值与真实值之间的距离最小。
反向传播
我们已经把预测的误差(损失)给度量出来了。现在的任务是找到一种办法去传播这个误差,并且通过这种传播来更新权值和偏置。
为了知晓怎样恰当调整权值和偏置,我们得知道损失函数对于权值 W 以及偏置 b 的导数。
回想微积分中的概念,函数的导数就是函数的斜率。
梯度下降法
如果我们已经求出了导数,那么就能够通过对导数值进行增加或减少的操作来更新权值 W 和偏置 b(参考上图)。这种更新权值和偏置的方式被称作梯度下降法。
但是我们无法直接对损失函数关于权值和偏置进行求导。因为在损失函数的等式里,并没有明确地包含权值和偏置。所以,我们需要借助链式求导法则来协助计算导数。
链式法则可用来计算损失函数对 W 和 b 的导数。需注意,为了简洁明了,我们仅展示了假定网络只有 1 层时的偏导数。
这虽然较为简陋,然而我们依旧能够获得想要的结果,即损失函数对权值 W 的导数(斜率)。所以,我们可以依据此来相应地调整权值。
现在我们将反向传播算法的函数添加到 Python 代码中
为了更深入地理解微积分原理以及反向传播中的链式求导法则,我强烈推荐 3Blue1Brown 的以下这些教程:
Youtube:
整合并完成一个实例
我们已经拥有了包含前向传播和反向传播的完整 Python 代码,接下来就把它应用到一个例子当中,看看它是怎样工作的吧。
神经网络能够通过学习来获取函数的权重。然而,仅仅依靠观察的话,是很难获取到函数的权重的。
我们训练神经网络进行 1500 次迭代,来看看会有什么情况发生。要注意观察下面每次迭代时的损失函数。通过观察,我们能够清楚地看到损失函数在单调递减,最终达到最小值。这与之前介绍的梯度下降法是相符合的。
让我们看看神经网络经过 1500 次迭代后的最终预测结果。
经过 1500 次迭代训练后的预测结果
我们成功了!我们应用了前向传播算法和方向传播算法,成功地训练了神经网络,并且预测结果收敛到了真实值。
注意允许存在细微的误差,即预测值和真实值之间有差异。这样能防止模型过拟合,还能让神经网络对未知数据有更强的泛化能力。
下一步是什么?
幸运的是我们的学习之旅尚未结束,依然有诸多关于神经网络和深度学习的内容有待学习。比如:
? 除了 Sigmoid 以外,还可以用哪些激活函数
? 在训练网络的时候应用学习率
? 在面对图像分类任务的时候使用卷积神经网络
我很快会写更多关于这个主题的内容,敬请期待!
最后的想法
我自己也从零开始写了很多神经网络的代码
可以使用 Tensorflow 和 Keras 等深度学习框架来方便地搭建深层网络,且无需完全理解其内部工作原理。然而,我认为对于有追求的数据科学家而言,理解内部原理是很有好处的。
这种练习对我而言已成为重要的时间投入,希望能对你有所助益。