Press "Enter" to skip to content

数学、乐高积木、神经网络产生怎样的花火?超超超赞!

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

想必大家都玩过乐高吧?

 

好玩不?

 

好玩!

 

 

 

 

接下来

 

有更好玩的

 

↓ ↓ ↓

 

 

用乐高积木结合数学来解释神经网络

 

好玩不?

 

来,小哥哥,小姐姐

 

我们教你玩!

 

文档+代码文末获取

 

神经网络是线性和非线性模块的巧妙组合。当我们明智地选择并连接它们时,我们就有了一个强大的工具来近似任何数学函数。例如,用非线性决策边界分离类的方法。

 

让我们从头开始构建一个神经网络,看看神经网络的内部功能,使用乐高积木块作为模块类比,每次一块积木。

 

神经网络作为一个组成部分

 

上图描述了一些用于训练神经网络的数学。在本文中,我们将对此进行解释。读者可能会发现,神经网络是一堆具有不同用途的模块:

 

输入X: 向神经网络提供原始数据,原始数据存储在一个矩阵中,其中观察值为行,维度为列。

 

权值W1: 将输入X映射到第一个隐藏层h1。权值W1是线性核函数

 

Sigmoid函数: 通过将隐藏层中的数字缩放到0-1。结果是一系列神经激活h1 = Sigmoid(WX)

 

这些操作仅计算一般线性系统,该系统不具有模拟非线性交互的能力。当我们再叠加一层时,情况就不同了,这就给这个模块结构增加了深度。网络越深,我们可以学到更微妙的非线性相互作用,我们可以解决更复杂的问题,这可能部分解释了深层神经模型的兴起。

 

举例:学习XOR函数

 

让我们打开黑匣子。现在我们将从头构建一个学习XOR函数的神经网络。这个非线性函数的选择绝不是随机的。如果没有反向传播,就很难学会用直线分隔类。

 

为了说明这个重要的概念,请注意下面一条直线是如何不能将XOR函数的输出0和1分开的。现实生活中的问题也是非线性可分的。

 

 

网络拓扑结构很简单:

 

1、输入X是一个二维向量;

 

2、权值W1是一个具有随机初始化值的2×3矩阵;

 

3、隐藏层h1由三个神经元组成。每个神经元接受一个加权的观测值作为输入,这是下图中绿色高亮显示的内积:z1 = [x1, x2][w1, w2];

 

4、权值W2是一个具有随机初始化值和的3×2矩阵;

 

5、输出层h2由两个神经元组成,因为XOR函数返回0 (y1=[0,1])或1 (y2 =[1,0])

 

更直观的展示:

 

 

现在我们来训练模型。在我们的简单示例中,可训练的参数是权重,但请注意,目前的研究正在探索更多类型的参数进行优化。例如层之间的快捷方式、正则化分布、拓扑结构、残差、学习率等。

 

反向传播是一种向(梯度)方向更新权值的方法,它在给定一批标记的观测值的情况下最小化预定义的误差度量(称为损失函数)。这种算法已经被多次重新发现,它是一种更通用的技术的特例,这种技术称为逆向累加模式下的自动微分。

 

网络初始化

 

让我们用随机数初始化网络权重。

 

 

向前一步

 

这一步的目标是将输入X向前传播到网络的每一层,直到计算输出层h2中的向量为止。

 

事情是这样发生的:

 

以权值W1为核,线性映射输入数据X:

 

 

使用Sigmoid函数缩放该加权和z1,以获得第一个隐藏层h1的值。注意,原来的2D向量现在映射到3D空间。

 

 

第二层h2也发生了类似的过程。我们先计算第一个隐层的加权和z2,它现在是输入数据。

 

 

然后计算它们的Sigmoid活函数。该向量[0.37166596 0.45414264]表示由给定输入X的网络计算的对数概率或预测向量。

 

 

计算总损失

 

损失函数的目标是量化预测向量h2与y提供的实际标号之间的距离,也称为“实际减去预测值”。

 

请注意,Loss函数包含一个正则化组件,该组件惩罚较大的权重值,就像在Ridge回归中一样。换句话说,较大的平方权重值将增加损失函数,这是我们确实想要最小化的误差度量。

 

 

向后一步

 

该步骤的目标是更新神经网络的权值,使其损失函数最小化。我们将看到,这是一个递归算法,它可以重用以前计算的梯度,并且严重依赖于可微函数。由于这些更新减少了损失函数,网络“学会”用已知类近似观察值的标签。称为泛化的属性。

 

这个步骤的顺序是向后的,而不是向前的。首先计算损失函数对输出层(dLoss / dW2)和隐藏层(dLoss / dW1)的权重的偏导数。让我们详细解释每一个。

 

dLoss/ DW2:

 

链式法则说我们可以把神经网络的梯度计算分解成可微的部分:

 

 

作为一个内存助手,这些是上面使用的函数定义及其一阶导数:

 

 

更直观地说,我们的目标是在下面的图中更新权重W2(蓝色)。为了达到这个目的,我们需要计算沿着这个链的三个偏导数。

 

 

将值代入这些偏导数中,我们就可以计算出关于权值W2的梯度,如下所示。

 

 

结果是一个3×2矩阵dLoss/dW2,它将按照最小化损失函数的方向更新原始的W2值。

 

 

dLoss / dW1:

 

计算用于更新第一个隐藏层W1的权重的链式规则显示了重用现有计算的可能性。

 

 

更直观地说,从输出层到权值W1的路径涉及到已经在后面几层计算过的偏导数。

 

 

例如,偏导数dLoss/dh2和dh2/dz2在上一节中已经被计算为输出层dLoss/dW2学习权值的依赖项。

 

 

将所有的导数放在一起,我们可以再次执行链式法则来更新隐藏层W1的权值:

 

 

最后,我们将新值赋给权值,并在网络上完成了一个训练步骤。

 

 

代码实现

 

让我们把上面的数学方程转换成只用Numpy作为线性代数引擎的代码。神经网络是在一个循环中训练的,在这个循环中,每次迭代都向网络提供已校准的输入数据。在这个示例中,我们只考虑每次迭代中的整个数据集。由于我们在每个循环中更新可训练参数(代码中的矩阵w1和w2)及其相应的梯度(矩阵dL_dw1和dL_dw2),因此对前向步、损失步和向后步的计算具有良好的泛化性。代码见文末:

 

 

运行代码

 

下面是一些经过训练的神经网络,它们经过多次迭代来逼近XOR函数。

 

首先,让我们看看隐藏层中有3个神经元的神经网络是如何具有小容量的。该模型学习用一个简单的决策边界将两个类分开,该边界开始是一条直线,但随后显示出非线性行为。随着训练的继续,右边图中的损失函数很好地降低了 。

 

 

左图:准确性,中间:学习决策边界,右图:损失函数

 

在隐层中有50个神经元可以显着提高模型学习更复杂决策边界的能力。这不仅能产生更精确的结果,而且还能产生梯度爆炸,这在训练神经网络时是一个值得注意的问题。这种情况发生在非常大的梯度,在反向传播过程中乘以权重,从而生成较大的更新权重时。这就是为什幺在训练的最后一步(> 90)损失值突然增加的原因。损失函数的正则化组件计算平方值的权重已经非常大(sum(W²)/ 2N)。

 

 

可以通过降低学习率来避免这个问题,如下所示。或者通过实施一项随着时间的推移而降低学习速度的策略。或者通过加强正则化,也许是L1而不是L2。梯度爆炸和梯度消失是有趣的现象,我们将在后面进行完整的分析。

 

 

来源:https://towardsai.net/

Be First to Comment

发表评论

邮箱地址不会被公开。 必填项已用*标注