用Python实现多层感知器神经网络

做者|Vivek Patel
编译|Flin
来源|towardsdatasciencepython

除非你能学习到一些东西,不然不要重复造轮子。算法

强大的库已经存在了,如:TensorFlow,PyTorch,Keras等等。我将介绍在Python中建立多层感知器(MLP)神经网络的基本知识。数据库

感知器是神经网络的基本组成部分。感知器的输入函数是权重,误差和输入数据的线性组合。具体来讲:in_j = weight input + bias.(in_j =权重输入+误差)。在每一个感知器上,咱们均可以指定一个激活函数g。网络

激活函数是一种确保感知器“发射”或仅在达到必定输入水平后才激活的数学方法。常见的非线性激活函数为S型,softmax,整流线性单位(ReLU)或简单的tanH。机器学习

激活函数有不少选项,可是在本文中咱们仅涉及Sigmoid和softmax。函数

图1:感知器
性能

对于有监督的学习,咱们稍后将输入的数据经过一系列隐藏层转发到输出层。这称为前向传播。在输出层,咱们可以输出预测y。经过咱们的预测y,咱们能够计算偏差| y*-y | 并使偏差经过神经网络向后传播。这称为反向传播。经过随机梯度降低(SGD)过程,将更新隐藏层中每一个感知器的权重和误差。学习

图2:神经网络的基本结构
测试

如今咱们已经介绍了基础知识,让咱们实现一个神经网络。咱们的神经网络的目标是对MNIST数据库中的手写数字进行分类。我将使用NumPy库进行基本矩阵计算。优化

在咱们的问题中,MNIST数据由 [748,1] 矩阵中的8位颜色通道表示。从本质上讲,咱们有一个 [748,1] 的数字矩阵,其始于[0,1,.... 255],其中0表示白色,255表示黑色。

结果

MNIST手写数字数据库包含60,000个用于训练目的的手写示例和10,000个用于测试目的的示例。在对60,000个示例进行了30个epoch的训练以后,我在测试数据集上运行了通过训练的神经网络,并达到了93.2%的准确性。甚至能够经过调整超参数来进一步优化。

它是如何工做的?

本文分为5个部分。这些部分是:

(1)激活函数
(2)权重初始化
(3)误差初始化
(4)训练算法
(5)进行预测

1. 激活函数

Sigmoid是由等式1 /(1+ exp(-x))定义的激活函数,将在隐藏层感知器中使用。

Softmax是一个激活函数,当咱们要将输入分为几类时,它一般在输出层中使用。在咱们的例子中,咱们但愿将一个数字分红10个bucket[0,1,2,…,9]中的一个。它计算矩阵中每一个条目的几率;几率将总计为1。具备最大几率的条目将对应于其预测,即0,1,…,9。Softmax定义为exp(x)/ sum(exp(x))。

图3:激活函数的实现

2. 权重初始化

对于咱们的每一个隐藏层,咱们将须要初始化权重矩阵。有几种不一样的方法能够作到这一点,这里是4。

  1. 零初始化-初始化全部权重= 0。

  2. 随机初始化-使用随机数初始化权重,而不是彻底随机。咱们一般使用标准正态分布(均值0和方差1)中的随机数。

  3. Xavier初始化-使用具备设定方差的正态分布中的随机数初始化权重。咱们将基于上一层的大小设置方差。

如上所述,进入感知器的边缘乘以权重矩阵。关键的一点是,矩阵的大小取决于当前图层的大小以及它以前的图层。明确地,权重矩阵的大小为[currentLayerSize,previousLayerSize]。

如上所述,进入感知器的边缘乘以权重矩阵。关键的一点是,矩阵的大小取决于当前图层的大小以及它以前的图层。明确地,权重矩阵的大小为[currentLayerSize,previousLayerSize]。

假设咱们有一个包含100个节点的隐藏层。咱们的输入层的大小为[748,1],而咱们所需的输出层的大小为[10,1]。输入层和第一个隐藏层之间的权重矩阵的大小为[100,748]。隐藏层之间的每一个权重矩阵的大小为[100,100]。最后,最终隐藏层和输出层之间的权重矩阵的大小为[10,100]。

出于教育目的,咱们将坚持使用单个隐藏层;在最终模型中,咱们将使用多层。

图4:权重初始化实现

3. 误差初始化

像权重初始化同样,偏置矩阵的大小取决于图层大小,尤为是当前图层大小。偏置初始化的一种方法是将偏置设置为零。

对于咱们的实现,咱们将须要为每一个隐藏层和输出层提供一个误差。偏置矩阵的大小为[100,1],基于每一个隐藏层100个节点,而输出层的大小为[10,1]。

图5:偏置初始化实现

4. 训练算法

前面已经说过,训练是基于随机梯度降低(SGD)的概念。在SGD中,咱们一次只考虑一个训练点。

在咱们的示例中,咱们将在输出层使用softmax激活。将使用“交叉熵损失”公式来计算损失。对于SGD,咱们将须要使用softmax来计算交叉熵损失的导数。也就是说,此导数减小为y* -y,即预测y*减去指望值y。

图6:关于softmax激活的交叉熵损失及其导数

咱们还须要编写S型激活函数的导数。在图7中,我定义了S型函数及其衍生函数

图7:Sigmoid函数(上)及其导数(下)

一般,神经网络将容许用户指定几个“超参数”。在咱们的实施中,咱们将着重于容许用户指定epoch,批处理大小,学习率和动量。还有其余优化技术!

  1. 学习率(LR):学习率是一个参数,用户能够经过它指定网络容许咱们学习和更新其参数的速度。选择一个好的学习率是一门艺术。若是LR过高,咱们可能永远不会收敛于良好的可接受的训练错误。若是LR过低,咱们可能会浪费大量的计算时间。

  2. epoch:epoch是整个训练集中的一个迭代。为了确保咱们不会过分拟合早期样本中的数据,咱们会在每一个时期以后对数据进行随机排序。

  3. 批次大小:经过Epoc2h的每次迭代,咱们将分批训练数据。对于批次中的每一个训练点,咱们将收集梯度,并在批次完成后更新权重/误差。

  4. 动量:这是一个参数,咱们将经过收集过去的梯度的移动平均值并容许在该方向上的运动来加速学习。在大多数状况下,这将致使更快的收敛。典型值范围从0.5到0.9。

下面,我编写了一些通用的伪代码来模拟反向传播学习算法的概况。为了便于阅读,已将诸如计算输出和将训练数据分红批次之类的任务做为注释编写。

如今,咱们将展现伪代码的实现.

5. 作出预测

如今,咱们仅缺乏此实现的一个关键方面。预测算法。在编写反向传播算法的过程当中,咱们已经完成了大部分工做。咱们只须要使用相同的前向传播代码便可进行预测。输出层的softmax激活函数将计算大小为[10,1]的矩阵中每一个条目的几率。

咱们的目标是将数字分类为0到9。所以,aj2矩阵的索引将与预测相对应。几率最大的索引将由np.argmax()选择,并将做为咱们的预测。

结论

这就对了!咱们结束了。咱们已经用Python编写了神经网络的实现。

可是,咱们如何选择最佳参数?咱们可使用算法的通常知识来选择有意义的超参数。咱们须要选择能归纳但不能过分拟合数据的超参数。咱们能够调整动量,学习率,时期数,批处理大小和隐藏节点的数量,以实现咱们的目标。向前迈出一步,咱们能够编写更多算法来为咱们作这件事!

遗传算法是一种AI算法,可用于选择最佳参数。遗传算法的思想是建立一组具备不一样参数的子代,并让他们产生与参数相关的测试错误。咱们能够对具备最佳超参数的神经网络进行繁殖和变异,以找到性能更好的参数。花费大量时间后,咱们将可以学习有关超参数状况的大量知识,并找到新的最佳超参数值。

咱们还能够采起其余措施来减小测试错误吗?是的,咱们能够缩放输入数据。像许多算法同样,数量更多会对算法的结果产生重大影响。在咱们的示例中,数字范围为[0到255]。若是咱们按比例缩放数字,使它们的范围从[0到1],则能够减小该误差。

感谢你的阅读!

原文连接:https://towardsdatascience.com/implementing-a-multi-layer-perceptron-neural-network-in-python-b22b5a3bdfa3

欢迎关注磐创AI博客站:
http://panchuang.net/

sklearn机器学习中文官方文档:
http://sklearn123.com/

欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/

相关文章
相关标签/搜索