大脑可与神经网络相媲美。 这是通常用于帮助刚接触该主题的人理解机器学习和人工神经网络背后的思想的类比。
因为在幕后进行了几层数学和统计计算,将这些网络定义为数学函数是一种更高级的方法。
这是为那些真正对机器学习感兴趣并想了解 Python 神经网络代码是如何编写的人准备的。
在本文中,我们将演示如何从头开始构建完全连接的深度神经网络 (DNN) 蟒蛇 3.
我们的 Python 神经网络代码的文件结构概述
这里将创建三个文件。 第一个是简单的 nn.py 文件,将在“设置辅助函数”和“从头开始构建神经网络”中讨论。
我们还将有一个名为 mnist loader.py 的文件来加载测试数据,如“加载 MNIST 数据”中所述。
最后,我们将有一个名为 test.py 的文件,它将在终端中启动以测试我们的神经网络。
该文件在“运行测试”中有详细描述。
装置
必须下载 NumPy Python 库才能学习本教程。 您可以通过在终端上使用以下命令来完成此操作:
导入模块并设置 Helper 功能
我们需要的仅有的两个库是 random 和 NumPy,我们将立即导入它们。 对于我们神经网络的初始权重,我们将使用随机库对它们进行洗牌。
为了加快计算速度,我们将使用 NumPy 或 np(按照惯例,它通常作为 np 导入)。 我们的两个辅助函数将在我们的导入之后生成。 两个 sigmoid 函数:一个和 sigmoid prime。
逻辑回归将使用 sigmoid 函数对数据进行分类,而反向传播将使用 sigmoid 素数函数计算增量或梯度。
创建网络类
构建一个完全链接的神经网络是本节的唯一重点。 网络类将包含后面的所有功能。 函数 Object() { [native code] } 最初将在我们的网络类中创建。
函数 Object() { [native code] } 需要一个参数,sizes。 size 变量是一组数值,表示我们神经网络的每一层中存在的输入节点的数量。
我们在 __init__ 方法中初始化了四个属性。 输入变量sizes分别用于设置层大小列表和层数num层。
第一步是将我们网络的初始偏差随机分配给输入层之后的每一层。
最后,输入和输出层之间的每个链接都有随机生成的权重。 Np.Random.Randn() 给出从上下文的正态分布中抽取的随机样本。
前馈功能
在神经网络中,信息由前馈函数向前发送。 此函数将需要一个参数 a,表示当前激活向量。
该函数通过迭代网络中的所有偏差和权重来估计每一层的激活。 给出的答案是预测,即最后一层的激活。
小批量梯度下降
我们网络类的主力是梯度下降。 在这个版本中,我们使用小批量(随机)梯度下降,梯度下降的一种修改变体。
这表明将使用一小批数据点来更新我们的模型。 四个必需参数和一个可选参数传递给此方法。 四个必需的变量是训练数据集、时期数、小批量的大小和学习率 (eta)。
可根据要求提供测试数据。 当我们最终评估这个网络时,我们将提供测试数据。 一旦训练数据转换为列表类型,此函数中的样本数最初设置为列表的长度。
我们也将相同的过程应用于测试数据。这是因为它们不是作为列表返回给我们,而是实际上是列表的拉链。 当我们稍后加载 MNIST 数据样本时,我们将了解更多相关信息。
如果我们可以确保将两种类型的数据都作为列表提供,那么这种类型转换就不一定是必要的。
一旦我们有了数据,我们就会循环遍历训练周期。 一个训练周期只是一轮神经网络训练。 在制作小批量列表之前,我们首先对每个 epoch 中的数据进行洗牌以确保随机性。
将为每个小批量调用更新小批量函数,如下所述。 如果测试数据可用,也会返回测试准确度。
成本导数辅助函数
在我们真正创建反向传播代码之前,让我们先开发一个称为成本导数的辅助函数。 如果我们在输出层出错,成本导数函数会显示出来。
它需要两个输入:输出激活数组和预期输出值的 y 坐标。
反向传播函数
我们目前的激活向量,激活,以及任何其他激活向量,激活和 z 向量,zs,都必须牢记在心。 首先激活一个称为输入层的层。
在放置它们之后,我们将遍历每个偏差和权重。 每个循环都涉及将 z 向量计算为权重和激活的点积,将其添加到 zs 列表中,重新计算激活,并将更新的激活添加到激活列表中。
最后,数学。 delta 等于前一层的误差乘以 zs 向量的最后一个元素的 sigmoid 素数,是在我们开始反向传播之前计算的。
nabla b 的最后一层设置为 delta,nabla w 的最后一层设置为 delta 和倒数第二层激活的点积(转置以便我们可以实际进行数学运算) .
我们像以前一样继续,从第二层开始,到最后一层结束,并在完成最后一层之后重复该过程。 然后将 nablas 作为元组返回。
更新小批量梯度下降
我们之前的 SGD(随机梯度下降)方法结合了小批量更新。 由于它在 SGD 中使用,但也需要反向传播,所以我讨论了将这个函数放在哪里。
最后,我选择把它贴在这里。 它首先生成 0 个偏差和权重 nablas 的向量,就像我们的反向传播函数一样。
它需要 mini-batch 和 eta 学习率作为它的两个输入。 在 mini-batch 中,我们使用 backprop 函数来获得每个 nabla 数组对于每个输入 x 和输出 y 的增量。 然后使用这些增量更新 nabla 列表。
最后,我们使用学习率和 nablas 来更新网络的权重和偏差。 每个值都更新为最近的值,减去学习率,乘以 minibatch 大小,然后添加到 nabla 值。
评估功能
评估函数是我们需要编写的最后一个函数。 测试数据是此功能的唯一输入。 在此函数中,我们仅将网络的输出与预期结果 y 进行比较。 通过向前馈送输入 x,网络的输出被确定。
完整的代码
当我们组合所有代码时,它就是这样出现的。
测试神经网络
加载 MNIST 数据
MNIST 数据 是 .pkl.gz 格式,我们将使用 GZIP 打开并使用 pickle 加载。 让我们编写一个快速方法来将此数据加载为大小为 XNUMX 的元组,分为训练、验证和测试数据。
为了使我们的数据更易于管理,我们将编写另一个函数来将 y 编码为 10 项数组。 除了与图像的正确数字匹配的 0 之外,该数组将全为 1。
我们将使用基本加载数据和一种热编码方法将我们的数据加载为可读格式。 将编写另一个函数,它将我们的 x 值转换为大小为 784 的列表,与图像的 784 像素匹配,并将我们的 y 值转换为它们的单个热编码向量形式。
然后我们将组合 x 和 y 值,使一个索引与另一个索引匹配。 这适用于训练、验证和测试数据集。 然后我们返回更改后的数据。
运行测试
我们将创建一个名为“mnist loader”的新文件,该文件将在开始测试之前导入我们之前建立的神经网络(simple nn)和 MNIST 数据集加载器。
在这个文件中,我们需要做的就是导入数据,构建一个输入层大小为 784,输出层大小为 10 的网络,在训练数据上运行网络的 SGD 函数,然后使用测试数据对其进行测试。
请记住,对于我们的输入层列表,784 和 10 之间的任何数字都没有区别。我们可以随意更改其他层; 只是输入和输出大小是固定的。
不需要三层; 我们可能会使用四个、五个甚至两个。 尽情尝试吧。
结论
在这里,我们使用 Python 3 从头开始创建神经网络。 除了高级数学,我们还讨论了实现的细节。
我们从实现辅助函数开始。 对于神经元的工作,sigmoid 和 sigmoid 素数函数是至关重要的。 然后我们将前馈函数付诸实践,这是将数据输入神经网络的基本过程。
接下来,我们在 Python 中创建了梯度下降函数,这是驱动神经网络的引擎。 为了找到“局部最小值”并优化其权重和偏差,我们的神经网络使用梯度下降。 我们使用以下命令创建了反向传播函数 梯度下降.
通过在输出与正确标签不匹配时提供更新,此功能使神经网络能够“学习”。
最后,我们把我们全新的 Python 神经网络 使用 MNIST 数据集进行测试。 一切运行顺利。
编码愉快!
发表评论