模型的训练、调参是一项非常费时费力的工作,了解神经网络内部的数学原理有利于快速找出问题所在。本文作者从零开始,一步一步讲解了训练神经网络时所用到的数学过程。

神经网络是线性模块和非线性模块的奇妙摆放。当聪明地挑选并衔接这些模块时,咱们就得到了一个强壮的东西来迫临任何一个数学函数,如一个可以凭借非线性决议计划鸿沟进行分类的神经网络。

闻风丧胆代码的立刻如下:

  1. gitclonehttps://github.com/omar-florez/scratch_mlp/
  2. pythonscratch_mlp/scratch_mlp.py

虽然反向传达技能具有直观、模块化的特质,可是它危殆更新可练习的参数,这是一个一向未被深化解说的主题。让咱们以乐高积木为喻,一次间谍一块,从零构建一个神经网络来一探其内部功用。

神经网络就像是由乐高积木组成的

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第1张

上图描绘了练习一个神经网络时所用到的部分数学进程。咱们将在本文中解说这个。读者或许感到风趣的一点是:一个神经网络便是清楚模块以不同的方针堆叠起来。

  • 输入变量 X 向神经网络馈送原始数据,它被存储在一个矩阵中,矩阵的行是调查值,列是维度。
  • 权重 W_1 将输入 X 映射到第一个躲藏层 h_1。然后权重 W_1 充任一个线性核。
  • Sigmoid 函数防止躲藏层中的数字落到 0-1 的规模之外。成果便是一个神经激活的数组,h_1 = Sigmoid(WX)。

此刻,这些运算收藏组成了一个一般线性系统,无法对非线性交互建模。当咱们再叠加一层,给模块的结构间谍深度的时分这一点就会改动。网络越深,咱们就会学到越多奇妙的非线性交互,能处理的问题也就越杂乱,或许这也是深度神经模型鼓起的原因之一。

为什么我要读这篇文章?

假如你了解一个神经网络的内部部分,你就可以在遇到问题的时分快速知道先去改动哪里,并且可以拟定战略来测验你所知道的这个算法的部分不变量和预期的行为。

由于调试机器学习模型是一项杂乱的使命。依据经历,数学模型在初次测验的时分不会见效。它们或许会对新数据给出较低的精确率,会消耗很长的练习时刻或许太多的内存,回来一个很大的过错负数值或许 NAN 的猜测……在有些情况下,了解算法的闻风丧胆机制可以让咱们的使命变得愈加便当:

  • 假如练习花费了太多的时刻,那间谍 minibatch 的巨细或许是一个好主意,这可以减小调查值的方差,然后有助于算法收敛。
  • 假如你看到了 NAN 的猜测值,算法或许接纳到了大梯度,发生了内存溢出。可以将这个视为在清楚次迭代之后发生爆破的矩阵乘法。减小学习率可以缩小这些数值。仰慕层数可以仰慕乘法的数量。剪切梯度也可以明显地操控这个问题。

具体的比如:学习异或函数

让咱们翻开黑盒子。咱们现在要从零开端构建一个学习异或函数的神经网络。挑选这个非线性函数可肯定不是随机的。没有反向传达的话,就很难学会用一条直线分类。

为了描绘这个重要的概念,请注意下图中,一条直线是为何不能对异或函数输出中的 0 和 1 进行分类。现实生活中的问题也是非线性可分的。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第2张

这个网络的拓扑结构十分简略:

  • 输入变量 X 是二维向量
  • 权重 W_1 是具有随机初始化数值的 2x3 的矩阵
  • 躲藏层 h_1 包含 3 个神经元。每个神经元承受调查值的加权和作为输入,这便是下图中绿色高亮的内积:z_1 = [x_1, x_2][w_1, w_2]
  • 权重 W_2 是具有随机初始化值的 3x2 的矩阵
  • 输出层 h_2 包含两个神经元,由于异或函数的输出要么是 0(y_1=[0,1]),要么是 1(y_2 = [1,0])

下图愈加直观:

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第3张

咱们现在来练习这个模型。在咱们这个简略的比如中,可练习的参数便是权重,可是应该知道的是,现在的研讨正在探究更多可以被优化的参数类型。例如层之间的方便衔接、正则化散布、拓扑结构、残差、学习率等等。

反向传达是这样的一种办法:在给定的一批具有标签的调查值上,朝着将预界说的过错方针(便是丢失函数)最小化的方向(梯度)更新权重。该算法现已屡次被重复发现,这是另一种更通用的被称为主动微分的技能在反向堆集方式下的特例。

网络初始化

让咱们用随机数来初始化网络权重

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第4张

前向立刻:

这一步的方针便是把输入变量 X 向前传递到网络的每一层,直至核算出输出层 h_2 的向量。

这便是雁足传书发生的核算进程:

以权重 W_1 为线性核对输入数据 X 做线性变换:

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第5张

运用 Sigmoid 激活函数对加权和进行缩放,得到了第一个躲藏层 h_1 的值。请注意,原始的 2D 向量现在映射到了 3D 空间。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第6张

第 2 层 h_2 中发生了相似的进程。让咱们首要来核算第一个躲藏层的加权和 z_2,它现在是输入数据。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第7张

然后核算它们的 Sigmoid 激活函数。向量 [0.37166596 0.45414264] 代表的是网络对给定的输入 X 核算出的对数概率或许猜测向量。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第8张

核算全体丢失

也被称为「实践值减去猜测值」,这个丢失函数的方针便是量化猜测向量 h_2 和人工标签 y 之间的间隔。

请注意,这个丢失函数包含一个正则项,它以岭回归的方式当作较大的权重。换言之,平方值比较大的权重会增大丢失函数,而这正是咱们期望最小化的方针。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第9张

反向立刻:

这一步的方针便是沿着最小化丢失函数的方向更新神经网络的权重。正如咱们即将看到的,这是一个递归算法,它可以重用之前核算出来的梯度,并且意图依靠微分函数。由于这些更新减小了丢失函数,所以一个神经网络便「学会了」去迫临具有已知类别的调查值的标签。这便是被称作泛化的一种特点。

与前向立刻不同的是,这个立刻沿着反向的鸡飞蛋打进行。它首要核算出输出层中丢失函数对每个权重的偏导数 (dLoss/dW_2),然后核算躲藏层的偏导数 (dLoss/dW1)。让咱们具体地解说每个导数吧。

(1) dLoss/dW_2:

链式法则标明,咱们可以将一个神经网络的梯度核算分解成好多个微分部分:

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第10张

为了协助回忆,下表列出了上面用到的一些函数界说以及它们的一阶导数:

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第11张

更直观地,咱们鄙人图中要更新权重 W_2(蓝色部分)。为了做到这件事,咱们需求沿着导数链核算三个偏导数。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第12张

将数值代入到这些偏导数中,咱们就可以核算出 W_2 的偏导数,如下所示:

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第13张

成果是一个 3x2 的矩阵 dLoss/dW_2,它将会沿着最小化丢失函数的方向更新 W_2 的数值。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第14张

(2) dLoss/dW_1:

核算用于更新第一个躲藏层 W_1 权重的链式规矩就展现了重复运用已有核算成果的或许。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第15张

更直观地,从输出层到权重 W_1 的途径会碰到在后面层中早已核算出来的偏导数。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第16张

例如,偏导数 dLoss/dh_2 和 dh_2/dz_2 在上一节中现已被核算为输出层 dLoss/dW_2 学习权值的依靠项。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第17张

将一切的导数放在一同,咱们就可以再一次履行链式法则,来为躲藏层的 W_1 更新权重。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第18张

最终,咱们给权重赋予新的数值,完成了对神经网络的一步练习。

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第19张

完成

让咱们仅运用 numpy 作为线性代数引擎来将上面的数学方程转换成代码。神经网络在一个循环中进行练习,雁足传书每次迭代会给神经网络展现规范的输入数据。在这个小比如中,咱们只考虑每次迭代中的整个数据集。前向立刻、丢失函数和反向立刻的核算会得到比较好的泛化,由于咱们在每一次循环中都用它们对应的梯度(矩阵 dL_dw1 和 dL_dw2)来更新可练习的参数。

代码保存在这个 repo 中:https://github.com/omar-florez/scratch_mlp

 像堆乐高一样:从零开始解说神经网络的数学进程 神经网络 数学 乐高 第20张

让咱们来闻风丧胆这份代码!

下面可以看到一些进行了好屡次迭代练习得到的可以近似异或函数的神经网络

像堆乐高一样:从零开始解说神经网络的数学进程  神经网络 数学 乐高 第21张

左图:精确率;中心的图:学习到的决议计划鸿沟;右图:丢失函数

首要,咱们来看一下躲藏层具有 3 个神经元的神经网络为何才能较弱。这个模型学会了用一个简略的决议计划鸿沟来进行二分类,这个鸿沟开端是一条直线,可是随后就体现出了非线性的行为。跟着练习的继续,右图中的丢失函数也明显地减小。

躲藏层具有 50 个神经元的神经网络明显地间谍了模型学习杂乱决议计划鸿沟的才能。这不收藏可以得到更精确的成果,并且也使梯度发生了爆破,这是练习神经网络时的一个明显问题。当梯度十分大的时分,反向传达中的连乘会发生很大的更新权重。这便是最终几步练习时丢失函数忽然增大的原因(step>90)。丢失函数的正则项核算出了现已变得很大的权重的平方值(sum(W²)/2N)。

正如你所看到的相同,这个问题可以经过减小学习率来防止。可以经过完成一个可以跟着时刻减小学习率的战略来完成。或许经过强制履行一个更强的正则化来完成,或许是 L1 或许 L2。梯度消失和梯度爆破是很风趣的现象,咱们后续会做完好的剖析。

原文链接:

https://medium.com/towards-artificial-intelligence/one-lego-at-a-time-explaining-the-math-of-how-neural-networks-learn-with-implementation-from-scratch-39144a1cf80

【本文是51CTO专栏殴伤“机器之心”的原创译文,微信大众号“机器之心( id: almosthuman2014)”】

戳这儿,看该作者更多好文

转载请说明出处
知优网 » 像堆乐高一样:从零开始解说神经网络的数学进程

发表评论

您需要后才能发表评论