深度学习与自然语言处理(3)_斯坦福cs224d Lecture

来源:互联网 编辑:wan玩得好手游小编更新:2024-10-30 18:31:47 人气:

说明:本文为斯坦福大学CS224d课程的中文版内容笔记,已得到斯坦福大学课程@Richard Socher教授的授权翻译与发表

课堂笔记:第3课


关键词:神经网络,正向计算,反向传播,神经元,最大化间隔损失,梯度检验, 参数的哈维初始化, 学习速率, ADAGRAD(自适应梯度法)

这是斯坦福CS224d深度学习与自然语言处理的第3课,这节课先会介绍单层和多层神经网络和它们在机器学习分类任务中的应用, 接着介绍如何利用反向传播算法来训练这些神经网络模型(在这个方法中,我们将利用偏导数的链式法则来层层更新神经元参数)。在给出神经网络以及这些算法严谨的数学定义后,介绍了训练神经网络的一些实用的技巧和窍门,比如,神经元(非线性激励),梯度检验,参数的Xavier初始化方法,学习速率,ADAGRAD(自适应梯度法)等。最后,我们在神经网络模型的基础上来建立语言模型

我们发现notes最后语言模型这个部分被略去了,回头ppt里面扒出来补充给大家

1 神经网络:基础

我们在前面的课程中提到,由于大部分数据并非线性可分,线性分类模型在这些数据上的分类效果略显尴尬,而非线性的分类模型通常能取得更好的效果。 如下图1所示,神经网络模型就是这样一类具备非线性决策边界的分类器。 从图上我们可以看到神经网络生成了非线性判定边界,来对2类样本做分类,那咱们一起来看看,它是怎么做到的呢。

深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图 1 ︰ 在图上可以看到神经网络产生的非线性判定边界,更好地把2类样本点分隔开了。这就是神经网络的强大之处(不纠结原始样本的分布状况)。

一点小历史 ︰ 神经网络是受生物学启发的分类器,因此它也常被称为人工神经网络(ANN),以区别于生物学上的神经网络。事实上,人类的神经网络复杂性高很多,也比ANN具有更强大的能力,所以即使名字很接近,两者之间倒没有那么多的相似之处。

1.1 神经元

简单说来,神经元其实就是一个取n

n个输入,并产生单一输出的通用计算单元。每层神经元通过不同的参数(也称权重)产生不同的输出结果(通常情况下同一层神经元的输入值是相同的,只是权重不同)。比较常见的神经元(激励函数)是”Sigmoid函数”,也叫作”二项逻辑回归”单元。这种神经元,对于输入的 n

n维向量,通过与n

n维的权重向量 w

w和一个偏差标量b

b做组合运算,输出一个标量a

a(咱们也把它叫做标量激活结果),具体的运算过程如下公式所示:

a=1

1+exp(−(w

T

x+b))

a=11+exp(−(wTx+b))

其中w

w是权重,b

b是偏移量,x

x是输入

为了运算的一致性和精简性,我们也可以把权重向量和偏差变量写到一个n+1

n+1维的向量里,得到上式的一个等价形式:

a=1

1+exp(−[w

T

b]⋅[x 1])

a=11+exp(−[wT b]⋅[x 1])

你们看出来了,就是把偏移量放作权重的一部分

下图2是这种神经元的一个直观一点的解释:

深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图 2 ︰ 这就是所谓的”二元逻辑回归”神经元,输入向量 x

x 的各个元素被 w

w 中对应的权重缩放后求和,加上偏移量b

b(数学上可以看做对对输入x做线性的变换)之后放进”Sigmond函数”。

一点小总结:神经元呢,可以看做神经网络的基本组成功能单元,有多种多样功能(就是对输入做不同非线性变换)的神经元,它们共同去帮助整个神经网络形成非线性切分的能力。

1.2 单层神经元

刚才看完1个神经元的情况了,也知道它在做的非线性变换(输入到输出的运算)是什么,现在咱们拓展一下,看看对于一组输入x

x,一层神经元(其实就是多个神经元)的变换和处理情况,基本的结构,就如下图3所示。

深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图 3 ︰ 传说中神经网络的一层(多个”二元逻辑回归”神经元),它们的输入是一致的,都是x。

我们分别用{w

(1)

,⋯,w

(m)

}

{w(1),⋯,w(m)},{b

1

⋯,b

m

}

{b1⋯,bm}和{a

1

⋯,a

m

}

{a1⋯,am} 来表示m

m个神经元的权重向量,偏移量以及激励输出,则有一下的结果:

a

1

=1

1+exp(w

(1)T

x+b

1

))

a1=11+exp(w(1)Tx+b1))

a

m

=1

1+exp(w

(m)T

x+b

m

))

am=11+exp(w(m)Tx+bm))

式子多了看着有点乱,咱们设定一下以下的数学标记,简化简化在神经网络中的公式:

σ(z)=⎡

1

1+exp(z

1

)

1

1+exp(z

m

)

σ(z)=[11+exp(z1)⋮11+exp(zm)]

b=⎡

b

1

b

m

∈R

m

b=[b1⋮bm]∈Rm

W=⎡

−w

(1)T

−w

(m)T

∈R

m×n

W=[−w(1)T−⋮−w(m)T−]∈Rm×n

其中,

z=Wx+b

z=Wx+b

这样咱们的二元逻辑回归的激励输出就可以写成:

a

1

a

m

=σ(z)=σ(Wx+b)

[a1⋮am]=σ(z)=σ(Wx+b)

那这些激励输出到底是干嘛的呢,有什么物理含义? 一种理解方式是, 每个神经元都是对输入向量一个不同角度的处理加工, 提取输入向量的某一部分信息(比如图像数据中的纹理、颜色、轮廓,或者文本信息中的词性、时态等等)。然后这些信息会被用到分类任务中去,为决策提供依据。

1.3 前向计算

上一节咱们讨论了如何将一个向量x∈R

n

x∈Rn输给神经网络中的一层(一组(m

m个)二元回归神经元)进而得到他们的激励输出 a∈R

m

a∈Rm。 也简单提了一下这么做的意义,为了加深理解,咱们还是用命名实体识别(NER)的例子来直观解释一下这个过程吧。看这样一个例子:

“Museums in Paris are amazing”

我们要来判断这里的中心词”Paris”是不是个命名实体。在这种情况下, 我们不止要知道这个词窗内哪些词向量出现过,可能也需要知道他们之间的相互作用。 比如说,可能只有在”Museums”出现在第1个位置,”in”出现在第二个位置的时候,Paris才是命名实体。如果你直接把词向量丢给Softmax函数, 这种非线性的决策是很难做到的。所以我们需要用1.2中讨论的方法对输入的变量进行非线性的处理加工(神经元产出非线性激励输出),再把这些中间层的产物输入到Softmax函数中去。 这样我们可以用另一个矩阵U∈R

m+1

U∈Rm+1,与激励输出结果运算生成得分(当然,这里是未归一化的),从而进一步用于分类任务:

s=U

T

a=U

T

f(Wx+b)

s=UTa=UTf(Wx+b)

公式中的f

f是前面提到的做非线性变化的激励函数(激活函数)。维度分析: 如果我们用4维词向量表示这些词,且用一个5

5词窗口作为输入(就像上面这个例子),那输入的变量就是x∈R

20

x∈R20. 如果在隐藏层中使用8个sigmoid神经元,并且由其激励输出生成1个得分,我们就有W∈R

20

,b∈R

8

,U∈R

8×1

,s∈R

W∈R20,b∈R8,U∈R8×1,s∈R。

整个运算的过程(逐级的)大概是如下这个样子:

z=Wx+b

z=Wx+b

a=σ(z)

a=σ(z)

s=U

T

a

s=UTa

深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图4: 这张图描述了一个前向计算网络如何运算得到输出值

1.4 最大化间隔目标函数

跟大多数机器学习模型一样,神经网络也需要一个优化目标,一个用来衡量模型好坏的度量。优化算法在做的事情呢,通常说来就是找到一组权重,来最优化目标或者最小化误差。这里我们讨论一个比较流行的度量,叫做最大化间隔目标函数。直观的理解就是我们要保证被正确分类的样本分数要高于错误分类的样本得分。

继续用之前的例子,如果我们把一个正确标记的词窗 “Museums in Paris are amazing”(这里Paris是命名实体)的得分记做 s

s, 而错误标记的词窗“Not all Museums in Paris”(这里Paris不是命名实体)的得分记作s

c

sc (c表示这个词窗”corrupt”了)

于是,我们的目标函数就是要最大化 (s−s

c

)

(s−sc) 或者最小化(s

c

−s)

(sc−s)。 但是,我们要对这个目标函数稍作修改,让他只有在 s

c

>s=>(s

c

−s)>0

sc>s=>(sc−s)>0 的时候才计算这个函数的值。因为当正确标记的词窗得分比错误标记的词窗得分高的时候,我们认为是满足要求的,并没有误差,我们只关心错误标记的词窗比正确标记的词窗得分高了多少,它代表了误差的程度。 于是,我们的目标函数在s

c

>s

sc>s的时候取值(s

c

−s)

(sc−s),其余时候取值为0

0现在,优化目标变成:

minimizeJ=max(s

c

−s,0)

minimizeJ=max(sc−s,0)

但是这个优化函数还不稳妥,因为它缺乏一个用来保证安全划分的间隔。我们希望那些被正确标记的词窗得分不仅要比错误标记的词窗得分高,还希望至少高出一个取值为正的间隔Δ

Δ。 换句话说, 我们希望在

(s−s

c

(s−sc

c

(s−sc

minimizeJ=max(Δ+s

c

−s,0)

minimizeJ=max(Δ+sc−s,0)

我们可以把这个Δ

Δ的取值定为1,在学习的过程中,模型其他的权重参数自动会进行相应的缩放,而并不会影响最终分类模型的精度。如果你想了解更多细节的话,可以去读一下支持向量机中关于函数间隔和几何间隔(functional and geometric margins)的内容。所以最后我们定义了以下形式的目标函数,作为在训练集中所有词窗上求最优化的目标:

minimizeJ=max(1+s

c

−s,0)

minimizeJ=max(1+sc−s,0)

1.5 反向传播训练法(未向量化的逐元素形式)

在这一节中我们来讨论一下,当1.4节中的目标函数J

J取值为正的时候, 怎么来训练模型中的各个参数。 如果这个目标函数的取值是0, 那我们已经不再需要更新参数的取值了。 一般来讲,我们通过可以通过梯度下降法来更新参数(或者一些变种,像随机梯度下降/SGD)。这样就需要每个参数的梯度的信息来实现下面的更新过程:

θ

(t+1)

(t)

−αΔ

θ

(t)

J

θ(t+1)=θ(t)−αΔθ(t)J

反向传播这种方法利用导数的链式法则来计算损失函数(正向计算求得)在每个模型参数上的梯度。为了进一步理解上述内容, 我们来看下图5所示的这样一个简单的网络:

深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图5:这是一个 4-2-1的神经网络,第k

k层神经网络上的第j

j个神经元上的输入值是z

(k)

j

zj(k),输出的激励输出值为a

(k)

j

aj(k)

这里我们讨论的是一个只有1个隐藏层,1个单独的输出单元的神经网络。 我们先来统一以下标记:

  • x
  • i
  • xi 是神经网络的输入。
  • s
  • s是神经网络的输出。
  • 神经网络的每一层(包括输入层和输出层)都有神经元来进行输入和输出。 第k
  • k层神经网络上的第j
  • j个神经元上的输入值是z
  • (k)
  • j
  • zj(k),输出的激励输出值为a
  • (k)
  • j
  • aj(k)。
  • 我们把反向传播到z
  • (k)
  • j
  • zj(k)上的误差记为δ
  • (k)
  • j
  • δj(k)。
  • 第1层指的是输入层而不是第一个隐藏层。对于输入层,我们有x
  • j
  • =z
  • (1)
  • j
  • =a
  • (1)
  • j
  • xj=zj(1)=aj(1)。
  • W
  • (k)
  • W(k) 是把k
  • k层的激活子输出值映射到k+1
  • k+1层输入值的转换矩阵。于是,把这个一般化的标记用在1.3节例子中就有了 W
  • (1)
  • =W
  • W(1)=W 以及 W
  • (1)
  • =U
  • W(1)=U 。

一起来看看反向传播吧: 假设目标函数 J=(1+s

c

−s)

J=(1+sc−s) 取正值,我们希望更新权重参数W

(1)

14

W14(1)(如图5及图6所示),我们注意到这里W

(1)

14

W14(1)只在计算z

(2)

1

z1(2) 和 a

(2)

1

a1(2)时出现。这一点对于理解反向传播很重要-参数的反向传播梯度只被那些在正向计算中用到过这个参数的值所影响。 a

(2)

1

a1(2)在之后的正向计算中和 W

(2)

1

W1(2)相乘进而参与到分类得分的计算中。我们从最大化边界损失的形式看到:

∂J

∂s

=−∂J

∂s

c

=−1

∂J∂s=−∂J∂sc=−1

于是,为了简化计算, 我们这里可以只考虑∂J

∂W

(1)

ij

∂J∂Wij(1)。于是

∂J

∂s

=−∂J

∂s

c

=−1

∂J∂s=−∂J∂sc=−1

这样, 我们可以对∂s

∂W

(1)

ij

∂s∂Wij(1)化简如下:

∂s

∂W

(1)

ij

=∂W

(2)

a

(2)

∂W

(1)

ij

=∂W

(2)

i

a

(2)

i

∂W

(1)

ij

=W

(2)

i

∂a

(2)

i

∂W

(1)

ij

∂s∂Wij(1)=∂W(2)a(2)∂Wij(1)=∂Wi(2)ai(2)∂Wij(1)=Wi(2)∂ai(2)∂Wij(1)

⟹W

(2)

i

∂a

(2)

i

∂W

(1)

ij

=W

(2)

i

∂a

(2)

i

∂z

(2)

i

∂z

(2)

i

∂W

(1)

ij

⟹Wi(2)∂ai(2)∂Wij(1)=Wi(2)∂ai(2)∂zi(2)∂zi(2)∂Wij(1)

=W

(2)

i

f(z

(2)

i

)

∂z

(2)

i

∂z

(2)

i

∂W

(1)

ij

=Wi(2)f(zi(2))∂zi(2)∂zi(2)∂Wij(1)

=W

(2)

i

f′(z

(2)

i

)∂z

(2)

i

∂W

(1)

ij

=Wi(2)f′(zi(2))∂zi(2)∂Wij(1)

=W

(2)

i

f′(z

(2)

i

)∂

∂W

(1)

ij

(b

(1)

i

+a

(1)

1

W

(1)

i1

+a

(1)

2

W

(1)

i2

+a

(1)

3

W

(1)

i3

+a

(1)

4

W

(1)

i4

)

=Wi(2)f′(zi(2))∂∂Wij(1)(bi(1)+a1(1)Wi1(1)+a2(1)Wi2(1)+a3(1)Wi3(1)+a4(1)Wi4(1))

=W

(2)

i

f′(z

(2)

i

)∂

∂W

(1)

ij

(b

(1)

i

+∑

k

a

(1)

k

W

(1)

ik

)

=Wi(2)f′(zi(2))∂∂Wij(1)(bi(1)+∑kak(1)Wik(1))

=W

(2)

i

f′(z

(2)

i

)a

(1)

j

=Wi(2)f′(zi(2))aj(1)

(2)

i

⋅a

(1)

j

=δi(2)⋅aj(1)我们可以看到这个梯度最终可以简化为δ

(2)

i

⋅a

(1)

j

δi(2)⋅aj(1) 这样一个形式。 这里δ

(2)

i

δi(2) 就是反向逆推到第2

2层上第i

i个神经元的误差。 a

(1)

j

aj(1)则与W

ij

Wij相乘后输入到第2

2层上第i

i个神经元的计算中。

译者注:这里所谓的反向传播误差δ(k)iδi(k)其实就是最终的目标函数对于第kk层上第ii个激励输出值z(k)izi(k)的导数。当我们要求目标函数关于Wk−1ijWijk−1的导数时, 因为第kk层上只有z(k)izi(k)的计算涉及到Wk−1ijWijk−1, 所以可以把z(k)izi(k)写成关于Wk−1ijWijk−1的函数,接着利用导数的链式法则,得到目标函数关于Wk−1ijWijk−1的导数。误差δ(k)δ(k)从kk层传播到k−1k−1层的过程就等价于求目标函数高11阶的导数,这一步同样可以由偏导数的链式法则得到。
深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图6:这个子网络描述的是当我们更新 W

(1)

ij

Wij(1)时所用到的神经网络的有关部分

我们以图6为例子,从”误差分配/分散”的角度来诠释一下反向传播。比如说我们如果要更新 W

(1)

14

W14(1):

  1. 我们从a
  2. (3)
  3. 1
  4. a1(3)上的误差信息1
  5. 1开始进行逆向传播。
  6. 我们把这个误差乘以把z
  7. (3)
  8. 1
  9. z1(3)映射到a
  10. (3)
  11. 1
  12. a1(3)的神经元的局部梯度上。在这里这个梯度恰好也等于1 (有兴趣可以自己去算一下)。所以我们得到δ
  13. (3)
  14. 1
  15. =1
  16. δ1(3)=1。
  17. 于是,这个误差信息1
  18. 1已经传到了z
  19. (3)
  20. 1
  21. z1(3)上。 我们需要把这个误差分配到上一层a
  22. (2)
  23. 1
  24. a1(2)上去。(这里我们不关心2
  25. 2层上的其他激励输出,因为他们的计算不涉及到W
  26. (1)
  27. 14
  28. W14(1))
  29. 分配到a
  30. (2)
  31. 1
  32. a1(2)上的误差为(z
  33. (3)
  34. 1
  35. (z1(3) 上的误差 =δ
  36. (3)
  37. 1
  38. )×W
  39. (2)
  40. 1
  41. =δ1(3))×W1(2)。 于是传播到a
  42. (2)
  43. 1
  44. a1(2)上的误差为W
  45. (2)
  46. 1
  47. W1(2)。这里记作W
  48. (2)
  49. 11
  50. W11(2)比较合适
  51. 像第2步一样,我们通过把a
  52. (2)
  53. 1
  54. a1(2)上的误差乘以把z
  55. (2)
  56. 1
  57. z1(2)映射到a
  58. (2)
  59. i
  60. ai(2)的神经元的局部梯度上,来把误差传播到z
  61. (2)
  62. 1
  63. z1(2)上。这里这个梯度是f
  64. (z
  65. (2)
  66. 1
  67. )
  68. f′(z1(2))。
  69. 于是z
  70. (2)
  71. 1
  72. z1(2)上的误差就等于f
  73. (z
  74. (2)
  75. 1
  76. )W
  77. (2)
  78. 1
  79. f′(z1(2))W1(2)。记作δ
  80. (2)
  81. 1
  82. δ1(2)。
  83. 最后,我们要把这个误差乘以参与前向计算的a
  84. (4)
  85. 1
  86. a1(4) 从而把误差信息分配到 W
  87. (1)
  88. 14
  89. W14(1)上。
  90. 于是,目标函数关于W
  91. k−1
  92. ij
  93. Wijk−1的导数就有了a
  94. (4)
  95. 1
  96. f
  97. (z
  98. (2)
  99. 1
  100. )W
  101. (2)
  102. 1
  103. a1(4)f′(z1(2))W1(2)这样的形式。

我们可以看到,我们从哪个角度出发,最后得到的结果都是一样的。所以对于反向传播我们既可以从链式法则的角度来理解,也可以从误差分配/分散的角度来理解。

偏移量的更新 偏移量(如b

(1)

1

b1(1))在计算下一层神经元输入值z

(2)

1

z1(2)时,与其他权重参数在数学形式上是等价的,只不过更他相乘的是常量1。所以,对于第k

k层上第i

i个神经元偏移量的梯度就是δ

(k)

i

δi(k)。比方说,如果我们在上面的例子中,要更新的是b

(1)

1

b1(1)而不是W

(1)

14

W14(1), 那它的梯度就是f

(z

(2)

1

)W

(2)

1

f′(z1(2))W1(2)。

从 δ

(k)

δ(k)到δ

(k−1)

δ(k−1)反向传播的一般化步骤:

  1. 我们从z
  2. (k)
  3. i
  4. zi(k)上的误差信息δ
  5. (k)
  6. i
  7. δi(k)(即第k
  8. k层的第i
  9. i个神经元)开始,见图7。
  10. 我们通过把δ
  11. (k)
  12. i
  13. δi(k)乘以路径上的权重W
  14. (k−1)
  15. ij
  16. Wij(k−1)来把这个误差反向传播到上一层的激励输出a
  17. (k−1)
  18. j
  19. aj(k−1)上。
  20. 于是,激励输出a
  21. (k−1)
  22. j
  23. aj(k−1)收到了误差信息δ
  24. (k)
  25. i
  26. W
  27. (k−1)
  28. ij
  29. δi(k)Wij(k−1)。
  30. 不过a
  31. (k−1)
  32. j
  33. aj(k−1)在前向计算中,参与到下一层中多个神经元的计算中。比如k
  34. k层上第m
  35. m个神经元上的误差信息也将通过类似第3步中的方式传递到a
  36. (k−1)
  37. j
  38. aj(k−1)上。
  39. 这样,a
  40. (k−1)
  41. j
  42. aj(k−1)收到的误差信息就会变成δ
  43. (k)
  44. i
  45. W
  46. (k−1)
  47. ij
  48. (k)
  49. m
  50. W
  51. (k−1)
  52. mj
  53. δi(k)Wij(k−1)+δm(k)Wmj(k−1)。
  54. 因为第k
  55. k层上有很多个神经元,a
  56. (k−1)
  57. j
  58. aj(k−1)收到的误差信息可以写成一般化的形式∑
  59. i
  60. δ
  61. (k)
  62. i
  63. W
  64. (k−1)
  65. ij
  66. ∑iδi(k)Wij(k−1)
  67. 这样 a
  68. (k−1)
  69. j
  70. aj(k−1)就收到关于它的所有误差信息了,于是我们通过乘以这个神经元上的局部梯度f
  71. (z
  72. (k−1)
  73. j
  74. )
  75. f′(zj(k−1))来把误差信息传播 到 z
  76. (k−1)
  77. j
  78. zj(k−1)上。
  79. 最终,到达 z
  80. (k−1)
  81. j
  82. zj(k−1)上的误差信息就是 z
  83. (k−1)
  84. j
  85. i
  86. δ
  87. (k)
  88. i
  89. W
  90. (k−1)
  91. ij
  92. zj(k−1)∑iδi(k)Wij(k−1),记作δ
  93. (k−1)
  94. j
  95. δj(k−1)。
深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图7:从 δ

(k)

δ(k)到δ

(k−1)

δ(k−1)反向传播

1.6 反向传播训练(向量化的形式)

我们前面介绍了如何计算模型中每个参数的梯度。这里我们要讨论如何把这些计算向量化及矩阵化(高效很多)。

对于权重参数 W

(k)

ij

Wij(k),我们知道它的误差梯度为δ

(k+1)

i

a

(k)

j

δi(k+1)aj(k),这里W

(k)

W(k)即为把a

(k)

a(k)映射到z

(k+1)

z(k+1)上的矩阵。 于是我们可以把误差信息对于整个矩阵W

(k)

W(k)的梯度表示成以下形式:

Δ

W

(k)

=⎡

δ

(k+1)

1

a

(k)

1

δ

(k+1)

2

a

(k)

1

δ

(k+1)

1

a

(k)

2

δ

(k+1)

2

a

(k)

2

(k+1)

a

(k)T

ΔW(k)=[δ1(k+1)a1(k)δ1(k+1)a2(k)⋯δ2(k+1)a1(k)δ2(k+1)a2(k)⋯⋮⋮⋱]=δ(k+1)a(k)T

于是,我们可以把这个矩阵形式的梯度写成(从下一层)反向传播过来的误差和(从这一层)参与到前向计算中的激励输出的外积。

深度学习与自然语言处理(3)_斯坦福cs224d Lecture 3

图 8︰从 δ

(k)

δ(k)到δ

(k−1)

δ(k−1)的误差传播

咱们接着看如何向量化的计算 δ

(k)

δ(k)。参考上面的图8,δ

(k)

j

=f

(z

(k)

j

)∑

i

δ

(k+1)

i

W

(k)

ij

δj(k)=f′(zj(k))∑iδi(k+1)Wij(k)。

这可以很容易推广到矩阵形式

δ

(k)

=f

(z

(k)

)∘(W

(k)T

δ

(k+1)

)

δ(k)=f′(z(k))∘(W(k)Tδ(k+1))

在上式中∘

∘ 表示元素对应位相乘(即Hadamard积 ∘:R

N

×R

N

→R

N

∘:RN×RN→RN )

计算效率: 我们知道,在很多科学计算软件中,像Matlab,Python(用NumPy/SciPy 包),向量化计算的效率远高于对每个元素逐个进行计算。所以,才实际操作中,我们尽可能的采用向量化的方式来训练参数。同时,我们在反向传播中应该尽量避免不必要的重复计算。比如说 δ

(k)

δ(k)的计算直接和 δ

(k+1)

δ(k+1)相关。 于是我们要保证在我们用 δ

(k+1)

δ(k+1)更新 W

(k)

W(k)的时候, 我们存下δ

(k+1)

δ(k+1)的值用来下一步计算 δ

(k)

δ(k)。以此类推,我们在(k−1),…,(1)

(k−1),…,(1) 上 我们重复这样的步骤,这种递归过程将使整个反向传播更加有效。

2 神经网络:技巧和窍门

前面的部分讨论了神经网络的技术原理,理论和实践结合起来才能发挥大作用,现在咱们介绍一些神经网络在实际应用中常见的技巧和窍门。

2.1 梯度检验

我们已经介绍了如何用微积分计算神经网络模型中参数的误差梯度。现在我们介绍另一种不使用误差反向传播,而近似估计梯度的方法:

f

(θ)≈J(θ

(i+)

)−J(θ

(i−)

)

f′(θ)≈J(θ(i+))−J(θ(i−))2ϵ

其中,θ

(i+)

=θ+ϵ×e

i

θ(i+)=θ+ϵ×ei

从微分的定义来看,上述公式显然是正确的,但是怎么将其应用到求解误差梯度呢?对于一个给定的数据集,当我们正向扰动参数θ

θ的第i个元素时(可以简单理解成θ

θ加上一个极小的正数),咱们基于前向传导可以计算出误差项J(θ

(i+)

)

J(θ(i+))。同理,当我们负向扰动参数θ

θ的第i个元素时,咱们基于前向传导可以计算出新的误差项J(θ

(i-)

)

J(θ(i-))。因此,其实通过做两次前向运算,我们就可以根据上面的公式估计出任何给定参数的梯度。当然了,其实只做一次前向传导所需要的运算量也不小了,所以在估计梯度时,这种方法比较耗时,但是,在用于验证反向传播的实现时,这种方法很赞,也用得很多。

梯度检验的简单实现可以参照下述方式:

def eval_numerical_gradient(f, x):
"""
a naive implementation of numerical gradient of f at x
- f should be a function that takes a single argument
- x is the point (numpy array) to evaluate the gradient
at
"""
fx = f(x) # evaluate function value at original point
grad = np.zeros(x.shape)
h = 0.00001
# iterate over all indexes in x
it = np.nditer(x, flags=[’multi_index’],
op_flags=[’readwrite’])
while not it.finished:
# evaluate function at x+h
ix = it.multi_index
old_value = x[ix]
x[ix] = old_value + h # increment by h
fxh = f(x) # evaluate f(x + h)
x[ix] = old_value # restore to previous value (very important!)
# compute the partial derivative
grad[ix] = (fxh - fx) / h # the slope
it.iternext() # step to next dimension
return grad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
以下为页边注

梯度检验:其实一般情况下,解析梯度是一个更快的梯度求解方法,不过容易出错,而梯度检验是个很好的比较解析梯度和数值型梯度的方法。数值型梯度可以用下述公式去计算:

f

(θ)≈J(θ

(i+)

)−J(θ

(i−)

)

f′(θ)≈J(θ(i+))−J(θ(i−))2ϵ

其中,J(θ

(i+)

)

J(θ(i+))和J(θ

(i−)

)

J(θ(i−))可以通过正向和负向微调θ

θ后两次前向传导来计算得到,这种方法的代码实现可以参阅Snippet 2.1。

以上为页边注

2.2 正则化

像大多数分类器一样,神经网络也容易产生过拟合,这会导致其在验证集和测试集上的结果并不一定那么理想。为了解决这个问题,简单一点咱们可以应用L2正则化,加上正则化项的损失函数J

R

JR可以通过下述公式来计算:

J

R

=J+λ∑

i=1

L

∥W

(i)

F

JR=J+λ∑i=1L‖W(i)‖F

在上述公式中,∥W

(i)

F

‖W(i)‖F是矩阵W

(i)

W(i)的F范数(frobenius norm),λ

λ是用于在加权和目标函数中进行正则化的相对权重。加上这个正则化项,意在通过作用到损失的平方来惩罚那些在数值上特别大的权重(译者注:也就是让权重的分配更均匀一些)。这样一来,目标函数(也就是分类器)的随意度(译者注:也就是可用于拟合的复杂度)就被降低了,约束了拟合函数的假设空间,因此减少了发生过拟合的可能性。施加这样一种约束条件可以用先验贝叶斯思想来理解,即最优的权重分配是所有权重都接近0。你想知道有多接近?对啦,这正是λ

λ所控制的——大的λ

λ会倾向于使所有权重都趋于0。值得注意的是,偏移量b

b不会被正则化,也不会被计算入上述的损失项(试着想想为什么?)。

2.3 神经单元

前面的内容里,我们已经讨论过了包含sigmoid神经元(sigmoidal neurons)来实现非线性分类的神经网络算法,然而在许多应用中,使用其他激励(激活)函数(activation functions)可以设计出

欢迎玩家到【wan玩得好手游】查看最新变态版手游攻略,只需要在百度输入【wan玩得好手游】就可以浏览最新上线送满vip的变态手游攻略了,更多有关BT手游的攻略和资讯,敬请关注玩得好手游!

更多...

热门推荐

更多...

相关文章