Do not insert newline/space between multibyte chars (e.g. Chinese)

https://emacs-china.org/t/ox-hugo-auto-fill-mode-markdown/9547/5
master
Kaushal Modi 7 years ago
parent a83cf75e59
commit ad9eb05203
  1. 20
      ox-hugo.el
  2. 4
      test/site/content-org/all-posts.org
  3. 2
      test/site/content/posts/filling-is-not-preserved.md
  4. 1
      test/site/content/posts/filling-is-preserved.md
  5. 191
      test/site/content/real-examples/nn-intro.md

@ -2384,18 +2384,32 @@ communication channel."
(format "<a id=\"%s\"></a>\n\n" lbl)
"")))
ret)
;; (message "[org-hugo-paragraph DBG] para 1: %s" contents)
;; Join consecutive Chinese lines into a single long line without
;; unwanted space inbetween.
;; https://emacs-china.org/t/ox-hugo-auto-fill-mode-markdown/9547/5
;; Example: 这是一个测试 -> 这是一个测试文本 ("This is a test text")
;; 文本
(setq contents (replace-regexp-in-string
"\\([[:multibyte:]]\\)[[:blank:]]*\n[[:blank:]]*\\([[:multibyte:]]\\)" "\\1\\2"
contents))
;; (message "[org-hugo-paragraph DBG] para 2: %s" contents)
(unless (org-hugo--plist-get-true-p info :hugo-preserve-filling)
(setq contents (concat (mapconcat 'identity (split-string contents) " ") "\n")))
;; Glue footnotes to the words before them using &nbsp; so that the
;; footnote reference does not end up on a new line by itself.
(setq contents (replace-regexp-in-string
;; Glue footnotes to the words before them using
;; &nbsp; so that the footnote reference does not
;; end up on a new line by itself.
;; "something FN" -> "something&nbsp;FN"
"[[:blank:]]+\\(\\[\\^[^]]+\\]\\)" "&nbsp;\\1"
(replace-regexp-in-string
;; "FN ." -> "FN."
"\\(\\[\\^[^]]+\\]\\)[[:blank:]]*\\([.]+\\)" "\\1\\2"
contents)))
;; (message "[org-hugo-paragraph DBG] para: %s" contents)
;; (message "[org-hugo-paragraph DBG] para 3: %s" contents)
(setq ret (concat label
(org-md-paragraph paragraph contents info)))

@ -4694,6 +4694,8 @@ current subtree.
abc
def
ghi
这是一个测试
文本
** Filling is not preserved
:PROPERTIES:
:EXPORT_FILE_NAME: filling-is-not-preserved
@ -4702,6 +4704,8 @@ ghi
abc
def
ghi
这是一个测试
文本
* Section Inheritance :section_inheritance:
** Section A
:PROPERTIES:

@ -4,4 +4,4 @@ tags = ["filling"]
draft = false
+++
abc def ghi
abc def ghi 这是一个测试文本

@ -7,3 +7,4 @@ draft = false
abc
def
ghi
这是一个测试文本

@ -22,12 +22,7 @@ Disclaimer
### 神经元模型 {#神经元模型}
神经网络从大脑的工作原理得到启发,可用于解决通用的学习问题。神经网络的
基本组成单元是 **神经元(neuron)** 。每个神经元具有一个轴突和多个树突。每
个连接到本神经元的树突都是一个输入,当所有输入树突的兴奋水平之和超过某
一阈值,神经元就会被激活。激活的神经元会沿着其轴突发射信号,轴突分出数
以万计的树突连接至其他神经元,并将本神经元的输出并作为其他神经元的输入。
数学上,神经元可以用 **感知机** 的模型表示。
神经网络从大脑的工作原理得到启发,可用于解决通用的学习问题。神经网络的基本组成单元是 **神经元(neuron)** 。每个神经元具有一个轴突和多个树突。每个连接到本神经元的树突都是一个输入,当所有输入树突的兴奋水平之和超过某一阈值,神经元就会被激活。激活的神经元会沿着其轴突发射信号,轴突分出数以万计的树突连接至其他神经元,并将本神经元的输出并作为其他神经元的输入。数学上,神经元可以用 **感知机** 的模型表示。
{{< figure src="/images/Vonng/neuron.png" >}}
@ -56,9 +51,7 @@ a
)
\\]
激活函数通常使用S型函数,又称为sigmoid或者logsig,因为该函数具有良好的
特性: **光滑可微** ,形状接近感知机所使用的硬极限传输函数,函数值与 **导
数值计算方便** 。
激活函数通常使用S型函数,又称为sigmoid或者logsig,因为该函数具有良好的特性: **光滑可微** ,形状接近感知机所使用的硬极限传输函数,函数值与 **导数值计算方便**
\\[
σ(z) = \frac 1 {1+e^{-z}}
@ -68,18 +61,15 @@ a
σ'(z) = σ(z)(1-σ(z))
\\]
也有一些其他的激活函数,例如:硬极限传输函数(hardlim),对称硬极限函数(hardlims),
线性函数(purelin), 对称饱和线性函数(satlins) ,对数-s形函数(logsig),正线性函数
(poslin),双曲正切S形函数(tansig),竞争函数(compet),有时候为了学习速度或者其他
原因也会使用,表过不提。
也有一些其他的激活函数,例如:硬极限传输函数(hardlim),对称硬极限函数(hardlims),线性函数(purelin), 对称饱和线性函数(satlins) ,对数-s形函数(logsig),正线性函数
(poslin),双曲正切S形函数(tansig),竞争函数(compet),有时候为了学习速度或者其他原因也会使用,表过不提。
### 单层神经网络模型 {#单层神经网络模型}
可以并行操作的神经元组成的集合,称为神经网络的一层。
现在考虑一个具有 \\(n\\) 个输入, \\(s\\) 个神经元(输出)的单层神经网络,则原来单个神经元的数
学模型可扩展如下:
现在考虑一个具有 \\(n\\) 个输入, \\(s\\) 个神经元(输出)的单层神经网络,则原来单个神经元的数学模型可扩展如下:
| 名称 | 符号 | 说明 |
|----|-------|---------------------------------------------------|
@ -105,20 +95,16 @@ a
)
\\]
单层神经网络能力有限,通常都会将多个单层神经网络的输出和输入相连,组成
多层神经网络。
单层神经网络能力有限,通常都会将多个单层神经网络的输出和输入相连,组成多层神经网络。
### 多层神经网络模型 {#多层神经网络模型}
- 多层神经网络的层数从1开始计数,第一层为 **输入层** ,第 \\(L\\) 层为 **输出
层** ,其它的层称为 **隐含层**
- 多层神经网络的层数从1开始计数,第一层为 **输入层** ,第 \\(L\\) 层为 **输出层** ,其它的层称为 **隐含层**
- 每一层神经网络都有自己的参数 \\(W,b,z,a,⋯\\) ,为了区别,使用上标区分:
\\(W^2,W^3,⋯\\) 。
- 整个多层网络的输入,即为输入层的激活值 \\(x=a^1\\) ,整个网络的输出,即
为输出层的激活值: \\(y'=a^L\\) 。
- 因为输入层没有神经元,所以该层所有参数中只有激活值 \\(a^1\\) 作为网络输入
值而存在,没有 \\(W^1,b^1,z^1\\) 等。
- 整个多层网络的输入,即为输入层的激活值 \\(x=a^1\\) ,整个网络的输出,即为输出层的激活值: \\(y'=a^L\\) 。
- 因为输入层没有神经元,所以该层所有参数中只有激活值 \\(a^1\\) 作为网络输入值而存在,没有 \\(W^1,b^1,z^1\\) 等。
现在考虑一个 \\(L\\) 层的神经网络,其各层神经元个数依次为:
\\(d\_1,d\_2,⋯,d\_L\\) 。则该网络的数学模型可扩展如下:
@ -151,28 +137,24 @@ a
多层神经网络的权值由一系列权值矩阵表示
- 第 \\(l\\) 层网络的权值矩阵可记作 \\(W^l\\) ,表示前一层( \\(l-1\\) )到本层
(\\(l\\))的连接权重
- 第 \\(l\\) 层网络的权值矩阵可记作 \\(W^l\\) ,表示前一层( \\(l-1\\) )到本层(\\(l\\))的连接权重
- \\(W^l\\) 的第 \\(j\\) 行可记作 \\(W^l\_{j\*}\\)
,表示从 \\(l-1\\) 层所有 \\(d\_{l-1}\\) 个神经元出发,到达 \\(l\\)
层 \\(j\\) 号神经元的连接权重
- \\(W^l\\) 的第 \\(k\\) 列可记作 \\(W^l\_{\*k}\\)
,表示从 \\(l-1\\) 层第 \\(k\\) 号神经元出发,到达 \\(l\\)
层所有 \\(d\_l\\) 个神经元的连接权重
- \\(W^l\\) 的 \\(j\\) 行 \\(k\\) 列可记作 \\(W^l\_{jk}\\) ,表示从 \\(l-1\\) 层 \\(k\\) 号神经元
出发,到达 \\(l\\) 层 \\(j\\) 神经元的连接权重
- \\(W^l\\) 的 \\(j\\) 行 \\(k\\) 列可记作 \\(W^l\_{jk}\\) ,表示从 \\(l-1\\) 层 \\(k\\) 号神经元出发,到达 \\(l\\) 层 \\(j\\) 神经元的连接权重
- 如图, \\(w^3\_{24}\\) 表示从2层4号神经元到3层2号神经元的连接权值:
{{< figure src="/images/Vonng/nn-weight.png" >}}
只要记住,权值矩阵 \\(W\\) 的 **行标表示本层神经元** 的标号, **列标表示上层
神 经元** 的标号即可。
只要记住,权值矩阵 \\(W\\) 的 **行标表示本层神经元** 的标号, **列标表示上层神 经元** 的标号即可。
## 神经网络推断 {#神经网络推断}
**前馈(feed forward)** 是指神经网络接受输入,产生输出的一次计算过程。又
称为一次 **推断(inference)**
**前馈(feed forward)** 是指神经网络接受输入,产生输出的一次计算过程。又称为一次 **推断(inference)**
计算过程如下:
@ -185,25 +167,19 @@ a^L &= σ(W^La^{L-1} + b^L) \\\\\\
y &= a^L \\\\\\
\end{align}
推断实际上就是一系列矩阵乘法与向量运算,一个训练好的神经网络可以高效地
使用各种语言实现。神经网络的功能是通过推断而体现的。推断实现起来很简单,
但如何 **训练神经网络** 才是真正的难点。
推断实际上就是一系列矩阵乘法与向量运算,一个训练好的神经网络可以高效地使用各种语言实现。神经网络的功能是通过推断而体现的。推断实现起来很简单,但如何 **训练神经网络** 才是真正的难点。
## 神经网络训练 {#神经网络训练}
神经网络的训练,是调整网络中的权值参数与偏置参数,从而提高网络工作效果
的过程。
神经网络的训练,是调整网络中的权值参数与偏置参数,从而提高网络工作效果的过程。
通常使用 **梯度下降(Gradient Descent)** 的方法来调整神经网络的参数,首先
要定义一个 **代价函数(cost function)** 用以衡量神经网络的误差,然后通过
梯度下降方法计算合适的参数修正量,从而 **最小化** 网络误差。
通常使用 **梯度下降(Gradient Descent)** 的方法来调整神经网络的参数,首先要定义一个 **代价函数(cost function)** 用以衡量神经网络的误差,然后通过梯度下降方法计算合适的参数修正量,从而 **最小化** 网络误差。
### 代价函数 {#代价函数}
代价函数是用于衡量神经网络工作效果的函数,是定义在一个或多个样本上的实
值函数,通常应满足以下条件:
代价函数是用于衡量神经网络工作效果的函数,是定义在一个或多个样本上的实值函数,通常应满足以下条件:
1. **误差是非负的,神经网络效果越好,误差越小**
2. **代价可以写成神经网络输出的函数**
@ -216,30 +192,23 @@ y &= a^L \\\\\\
C(w,b) = \frac{1}{2n} \sum\_x{{\\|y(x)-a\\|}^2}
\\]
前面的系数 \\(\frac 1 2\\) 是为了求导后简洁的形式而添加的, \\(n\\) 是使用样本
的数量,这里 \\(y\\) 和 \\(x\\) 都是已知的样本数据。
前面的系数 \\(\frac 1 2\\) 是为了求导后简洁的形式而添加的, \\(n\\) 是使用样本的数量,这里 \\(y\\) 和 \\(x\\) 都是已知的样本数据。
理论上任何可以反映网络工作效果的指标都可以作为代价函数。但之所以使用
MSE,而不是诸如"正确分类图像个数"的指标,是因为只有一个 **光滑可导**
代价函数才可以使用 **梯度下降** (Gradient Descent)调整参数。
MSE,而不是诸如"正确分类图像个数"的指标,是因为只有一个 **光滑可导** 的代价函数才可以使用 **梯度下降** (Gradient Descent)调整参数。
#### 样本的使用 {#样本的使用}
代价函数的计算需要一个或多个训练样本。当训练样本非常多时,如果每轮训练
都要重新计算网络整个训练集上所有样本的误差函数,开销非常大,速度难以接
受。若只使用总体的一小部分,计算就能快很多。不过这样做依赖一个假设:
代价函数的计算需要一个或多个训练样本。当训练样本非常多时,如果每轮训练都要重新计算网络整个训练集上所有样本的误差函数,开销非常大,速度难以接受。若只使用总体的一小部分,计算就能快很多。不过这样做依赖一个假设:
**随机样本的代价,近似等于总体的代价。**
按照使用样本的方式,梯度下降又分为:
- 批量梯度下降法(Batch GD):最原始的形式,更新每一参数都使用所有样本。可以得到全
局最优解,易于并行实现,但当样本数量很多时,训练速度极慢。
- 批量梯度下降法(Batch GD):最原始的形式,更新每一参数都使用所有样本。可以得到全局最优解,易于并行实现,但当样本数量很多时,训练速度极慢。
- 随机梯度下降法(Stochastic GD):解决BGD训练慢的问题,每次随机使用一个样本。训练
速度快,但准确度下降,且并不是全局最优,也不易于并行实现。
- 小批量梯度下降法(MiniBatch GD):在每次更新参数时使用b个样本(例如每次10个样本),
在BGD与SGD中取得折中。
- 随机梯度下降法(Stochastic GD):解决BGD训练慢的问题,每次随机使用一个样本。训练速度快,但准确度下降,且并不是全局最优,也不易于并行实现。
- 小批量梯度下降法(MiniBatch GD):在每次更新参数时使用b个样本(例如每次10个样本),在BGD与SGD中取得折中。
每次只使用一个样本时,又称为在线学习或递增学习。
@ -248,18 +217,12 @@ MSE,而不是诸如"正确分类图像个数"的指标,是因为只有一个
### 梯度下降算法 {#梯度下降算法}
若希望通过调整神经网络中的某个参数来减小整体代价,则可以考虑微分的方法。
因为每层的激活函数,以及最终的代价函数都是光滑可导的。所以最终的代价函
数 \\(C\\) 对于某个我们感兴趣的参数 \\(w,b\\) 也是光滑可导的。轻微拨动某个参数
的值,最终的误差值也会发生连续的轻微的变化。不断地沿着参数的梯度方向,
轻微调整每个参数的值,使得总误差值向下降的方向前进,最终达到极值点。就
是梯度下降法的核心思想。
若希望通过调整神经网络中的某个参数来减小整体代价,则可以考虑微分的方法。因为每层的激活函数,以及最终的代价函数都是光滑可导的。所以最终的代价函数 \\(C\\) 对于某个我们感兴趣的参数 \\(w,b\\) 也是光滑可导的。轻微拨动某个参数的值,最终的误差值也会发生连续的轻微的变化。不断地沿着参数的梯度方向,轻微调整每个参数的值,使得总误差值向下降的方向前进,最终达到极值点。就是梯度下降法的核心思想。
#### 梯度下降的逻辑 {#梯度下降的逻辑}
现在假设代价函数 \\(C\\) 为两个变量 \\(v\_1,v\_2\\) 的可微函数,梯度下降实际上就是
选择合适的 \\(Δv\\) ,使得 \\(ΔC\\) 为负。由微积分可知:
现在假设代价函数 \\(C\\) 为两个变量 \\(v\_1,v\_2\\) 的可微函数,梯度下降实际上就是选择合适的 \\(Δv\\) ,使得 \\(ΔC\\) 为负。由微积分可知:
\\[
ΔC ≈ \frac{∂C}{∂v\_1} Δv\_1 + \frac{∂C}{∂v\_2} Δv\_2
@ -267,20 +230,17 @@ MSE,而不是诸如"正确分类图像个数"的指标,是因为只有一个
这里 \\(Δv\\) 是向量: \\(Δv = \left[ \begin{array}{v} Δv\_1 \\ Δv\_2
\end{array}\right]\\) , \\(∇C\\) 是梯度向量 \\(\left[ \begin{array}{C}
\frac{∂C}{∂v\_1} \\ \frac{∂C}{∂v\_2} \end{array} \right]\\) ,于是上式可重
写为
\frac{∂C}{∂v\_1} \\ \frac{∂C}{∂v\_2} \end{array} \right]\\) ,于是上式可重写为
\\[
ΔC ≈ ∇C·Δv
\\]
怎样的 \\(Δv\\) 才能令代价函数的变化量为负呢?一种简单办法是令即 \\(Δv\\) 取一
个与梯度 \\(∇C\\) 共线反向的小向量,此时 \\(Δv = -η∇C\\) ,则损失函数变化量
怎样的 \\(Δv\\) 才能令代价函数的变化量为负呢?一种简单办法是令即 \\(Δv\\) 取一个与梯度 \\(∇C\\) 共线反向的小向量,此时 \\(Δv = -η∇C\\) ,则损失函数变化量
\\(ΔC ≈ -η{∇C}^2\\) ,可以确保为负值。按照这种方法,通过不断调整 \\(v\\) : \\(v
→ v' = v -η∇C\\) ,使得 \\(C\\) 最终达到极小值点。
这即梯度下降的涵义所在: **所有参数都会沿着自己的梯度(导数)方向不断进行
轻微下降, 使得总误差到达极值点。**
这即梯度下降的涵义所在: **所有参数都会沿着自己的梯度(导数)方向不断进行轻微下降, 使得总误差到达极值点。**
对于神经网络,学习的参数实际上是权重 \\(w\\) 与偏置量 \\(b\\) 。原理是一样的,不过这里的
\\(w,b\\) 数目非常巨大
@ -290,13 +250,9 @@ w →w' = w-η\frac{∂C}{∂w} \\\\\\
b → b' = b-η\frac{∂C}{∂b}
\\]
真正棘手的问题在于梯度 \\(∇C\_w,∇C\_b\\) 的计算方式。如果使用微分的方法,通
过 \\(\frac {C(p+ε)-C} {ε}\\) 来求参数的梯度,那么网络中的每一个参数都需要
进行一次前馈和一次 \\(C(p+ε)\\) 的计算,在神经网络汪洋大海般的参数面前,这
样的办法是行不通的。
真正棘手的问题在于梯度 \\(∇C\_w,∇C\_b\\) 的计算方式。如果使用微分的方法,通过 \\(\frac {C(p+ε)-C} {ε}\\) 来求参数的梯度,那么网络中的每一个参数都需要进行一次前馈和一次 \\(C(p+ε)\\) 的计算,在神经网络汪洋大海般的参数面前,这样的办法是行不通的。
**反向传播(Back propagation)算法** 可以解决这一问题。通过巧妙的简化,可
以在一次前馈与一次反传中,高效地计算整个网络中所有参数梯度。
**反向传播(Back propagation)算法** 可以解决这一问题。通过巧妙的简化,可以在一次前馈与一次反传中,高效地计算整个网络中所有参数梯度。
## 反向传播 {#反向传播}
@ -306,23 +262,18 @@ b → b' = b-η\frac{∂C}{∂b}
### 反向传播误差δ {#反向传播误差δ}
反向传播算法需要引入一个新的概念:误差 \\(δ\\) 。误差的定义源于这样一种朴素的思想:如
果轻微修改某个神经元的带权输入 \\(z\\) ,而最终代价 \\(C\\) 已不再变化,则可认为 \\(z\\) 已经到达
极值点,调整的很好了。于是损失函数 \\(C\\) 对某神经元带权输入 \\(z\\) 的偏导 \\(\frac {∂C}{∂z}\\)
反向传播算法需要引入一个新的概念:误差 \\(δ\\) 。误差的定义源于这样一种朴素的思想:如果轻微修改某个神经元的带权输入 \\(z\\) ,而最终代价 \\(C\\) 已不再变化,则可认为 \\(z\\) 已经到达极值点,调整的很好了。于是损失函数 \\(C\\) 对某神经元带权输入 \\(z\\) 的偏导 \\(\frac {∂C}{∂z}\\)
可以作为该神经元上误差 \\(δ\\) 的度量。故定义第 \\(l\\) 层的第 \\(j^{th}\\) 个神经元上的误差 \\(δ^l\_j\\) 为:
\\[
δ^l\_j ≡ \frac{∂C}{∂z^l\_j}
\\]
与激活值 \\(a\\) , 带权输入 \\(z\\) 一 样,误差也可以写作向量。第 \\(l\\) 层 的误差向量记作 \\(δ^l\\) 。 虽
然看上去差不多,但之所以使用带权输入 \\(z\\) 而 不是激活值输出 \\(a\\) 来 定义本层的误差,有着
形式上巧妙的设计。
与激活值 \\(a\\) , 带权输入 \\(z\\) 一 样,误差也可以写作向量。第 \\(l\\) 层 的误差向量记作 \\(δ^l\\) 。 虽然看上去差不多,但之所以使用带权输入 \\(z\\) 而 不是激活值输出 \\(a\\) 来 定义本层的误差,有着形式上巧妙的设计。
引入反向传播误差的概念,是为了通过误差向量来计算梯度 \\(∇C\_w,∇C\_b\\) 。
反向传播算法一言蔽之:计算出 **输出层误差** ,通过递推方程逐层回算出 **每
一层的误差** ,再由每一层的误差算出 **本层的权值梯度与偏置梯度**
反向传播算法一言蔽之:计算出 **输出层误差** ,通过递推方程逐层回算出 **每一层的误差** ,再由每一层的误差算出 **本层的权值梯度与偏置梯度**
这需要解决四个问题:
@ -376,16 +327,13 @@ b → b' = b-η\frac{∂C}{∂b}
\\]
而因为误差函数 \\(C = \frac 1 2 \\|\vec{y} -\vec{a}\\|^2= \frac 1 2
[(y\_1 - a\_1)^2 + ⋯ + (y\_{d\_L} - a\_{d\_L})^2]\\) ,方程两侧对某个 \\(a\_j\\) 取偏导则
有:
[(y\_1 - a\_1)^2 + ⋯ + (y\_{d\_L} - a\_{d\_L})^2]\\) ,方程两侧对某个 \\(a\_j\\) 取偏导则有:
\\[
\frac {∂C}{∂a^L\_j} = (a^L\_j-y\_j)
\\]
因为误差函数中,其他神经元的输出不会影响到误差函数对神经元 \\(j\\) 输出的
偏导,系数也正好平掉了。写作向量形式即为: \\((a^L - y)\\) 。另一方面,易
证 \\(σ'(z^L) = (1-a^L)⊙ a^L\\) 。
因为误差函数中,其他神经元的输出不会影响到误差函数对神经元 \\(j\\) 输出的偏导,系数也正好平掉了。写作向量形式即为: \\((a^L - y)\\) 。另一方面,易证 \\(σ'(z^L) = (1-a^L)⊙ a^L\\) 。
QED
@ -401,8 +349,7 @@ QED
##### 证明 {#证明}
本方程可以直接从反向传播误差的定义,以后一层所有神经元的带权输入 \\(z^{l+1}\\) 作 为中间变
量进行链式求导推导出:
本方程可以直接从反向传播误差的定义,以后一层所有神经元的带权输入 \\(z^{l+1}\\) 作 为中间变量进行链式求导推导出:
\\[
δ^l\_j = \frac {∂C}{∂z^l\_j}
@ -410,9 +357,7 @@ QED
= \sum\_{k=1}^{d\_{l+1}} (δ^{l+1}\_k \frac{∂z^{l+1}\_k}{∂z^{l}\_j})
\\]
通过链式求导,引入后一层带权输入作为中间变量,从而在方程右侧引入后一层
误差的表达形式。现在要解决的就是 \\(\frac{∂z^{l+1}\_k}{∂z^{l}\_j}\\) 是 什么的问
题。由带权输入的定义 \\(z = wx + b\\) 可知:
通过链式求导,引入后一层带权输入作为中间变量,从而在方程右侧引入后一层误差的表达形式。现在要解决的就是 \\(\frac{∂z^{l+1}\_k}{∂z^{l}\_j}\\) 是 什么的问题。由带权输入的定义 \\(z = wx + b\\) 可知:
\\[
z^{l+1}\_k = W^{l+1}\_{k,\*} ·a^l + b^{l+1}\_{k} = W^{l+1}\_{k,\*} · σ(z^{l}) + b^{l+1}\_{k}
@ -437,11 +382,9 @@ z^{l+1}\_k = W^{l+1}\_{k,\*} ·a^l + b^{l+1}\_{k} = W^{l+1}\_{k,\*} · σ(z^{
这里,对后一层所有神经元的误差权值之积求和,可以改写为两个向量的点积:
- 后一层 \\(k\\) 个 神经元的误差向量
- 后一层权值矩阵的第 \\(j\\) 列 ,即所有从本层 \\(j\\) 神 经元出发前往下一层所有 \\(k\\) 个 神经元的
权值。
- 后一层权值矩阵的第 \\(j\\) 列 ,即所有从本层 \\(j\\) 神 经元出发前往下一层所有 \\(k\\) 个 神经元的权值。
又因为向量点积可以改写为矩阵乘法:以行向量乘以列向量的方式进行,所以将权值矩阵转
置,原来拿的是列,现在则拿出了行向量。这时候再改写回向量形式为:
又因为向量点积可以改写为矩阵乘法:以行向量乘以列向量的方式进行,所以将权值矩阵转置,原来拿的是列,现在则拿出了行向量。这时候再改写回向量形式为:
\\[
δ^l = σ'(z^l) ⊙ (W^{l+1})^Tδ^{l+1}
@ -452,8 +395,7 @@ QED
#### BP3:权值梯度方程 {#bp3-权值梯度方程}
每一层的权值梯度 \\(∇C\_{W^l}\\) 可 以根据本层的误差向量(列向量),与上层的输出向量(行向
量)的外积得出。
每一层的权值梯度 \\(∇C\_{W^l}\\) 可 以根据本层的误差向量(列向量),与上层的输出向量(行向量)的外积得出。
\\[
∇C\_{W^l} = δ^l × {(a^{l-1})}^T
@ -599,15 +541,12 @@ Round {10}: {9526}/{10000}
一轮迭代后,网络在测试集上的分类准确率就达到90%,最终收敛至96%左右。
对于五十行代码,这个效果是值得惊叹的。然而96%的准确率在实际生产中恐怕仍然是无法
接受的。想要达到更好的效果,就需要对神经网络进行优化。
对于五十行代码,这个效果是值得惊叹的。然而96%的准确率在实际生产中恐怕仍然是无法接受的。想要达到更好的效果,就需要对神经网络进行优化。
## 神经网络优化 {#神经网络优化}
神经网络的基础知识也就这么多,但优化其表现却是一个无尽的挑战。每一种优化的手段都
可以当做一个进阶的课题深入研究。优化手段也是八仙过海各显神通:有数学,有科学,有
工程学,也有哲学,还有玄学...
神经网络的基础知识也就这么多,但优化其表现却是一个无尽的挑战。每一种优化的手段都可以当做一个进阶的课题深入研究。优化手段也是八仙过海各显神通:有数学,有科学,有工程学,也有哲学,还有玄学...
改进神经网络的学习效果有几种主要的方法:
@ -618,8 +557,7 @@ Round {10}: {9526}/{10000}
- 修改神经网络输入的组织方式:递归神经网络(Recurrent
NN),卷积神经网络(Convolutional NN)。
- 添加层数:深度神经网络(Deep NN)
- 通过尝试,选择合适的 **超参数(hyper-parameters)** ,按照迭代轮数或评
估效果动态调整超参数。
- 通过尝试,选择合适的 **超参数(hyper-parameters)** ,按照迭代轮数或评估效果动态调整超参数。
- 采用其他的梯度下降方法:基于动量的梯度下降
- 使用更好的 **初始化权重**
- 人为扩展已有训练数据集
@ -638,9 +576,7 @@ MSE输出层误差的计算公式为: \\[
δ^L = (a^L - y)σ'(z^L)
\\]
sigmoid又称为逻辑斯蒂曲线,其导数 \\(σ'\\) 是 一个钟形曲线。所以当带权输入 \\(z\\) 从 大到小或
从小到大时,梯度的变化会经历一个"小,大,小"的过程。学习的速度也会被导数项拖累,
存在一个"慢,快,慢"的过程。
sigmoid又称为逻辑斯蒂曲线,其导数 \\(σ'\\) 是 一个钟形曲线。所以当带权输入 \\(z\\) 从 大到小或从小到大时,梯度的变化会经历一个"小,大,小"的过程。学习的速度也会被导数项拖累,存在一个"慢,快,慢"的过程。
| MSE | Cross Entropy |
|----------------------------|--------------------------------------|
@ -660,8 +596,7 @@ C = - [ y ln(a) + (1-y)ln(1-a)]
虽然看起来很复杂,但输出层的误差公式变得异常简单,变为: \\(δ^L = a^L - y\\)
比起MSE少掉了导数因子,所以误差直接和(预测值-实际值)成正比,不会遇到学习速度被
激活函数的导数拖慢的问题,计算起来也更为简单。
比起MSE少掉了导数因子,所以误差直接和(预测值-实际值)成正比,不会遇到学习速度被激活函数的导数拖慢的问题,计算起来也更为简单。
#### 证明 {#证明}
@ -691,17 +626,11 @@ C = - [ y ln(a) + (1-y)ln(1-a)]
拥有大量的自由参数的模型能够描述特别神奇的现象。
费米说:"With four parameters I can fit an elephant, and with five I can make
him wiggle his trunk"。神经网络这种动辄百万的参数的模型能拟合出什么奇妙的东西是
难以想象的。
him wiggle his trunk"。神经网络这种动辄百万的参数的模型能拟合出什么奇妙的东西是难以想象的。
一个模型能够很好的拟合已有的数据,可能只是因为模型中足够的自由度,使得
它可以描述几乎所有给定大小的数据集,而不是真正洞察数据集背后的本质。发
生这种情形时, **模型对已有的数据表现的很好,但是对新的数据很难泛化**
这种情况称为 **过拟合(overfitting)**
一个模型能够很好的拟合已有的数据,可能只是因为模型中足够的自由度,使得它可以描述几乎所有给定大小的数据集,而不是真正洞察数据集背后的本质。发生这种情形时, **模型对已有的数据表现的很好,但是对新的数据很难泛化** 。这种情况称为 **过拟合(overfitting)**
例如用3阶多项式拟合一个带随机噪声的正弦函数,看上去就还不错;而10阶多项式,虽然
完美拟合了数据集中的所有点,但实际预测能力就很离谱了。它拟合的更多地是数据集中的
噪声,而非数据集背后的潜在规律。
例如用3阶多项式拟合一个带随机噪声的正弦函数,看上去就还不错;而10阶多项式,虽然完美拟合了数据集中的所有点,但实际预测能力就很离谱了。它拟合的更多地是数据集中的噪声,而非数据集背后的潜在规律。
```python
x, xs = np.linspace(0, 2 * np.pi, 10), np.arange(0, 2 * np.pi, 0.001)
@ -715,17 +644,13 @@ plt.plot(xs, np.polyval(p2, xs));plt.plot(x, y, 'ro');plt.plot(xs, np.sin(xs), '
|------------------------------|-------------------------------|
| ![](/images/Vonng/overfit-3.png) | ![](/images/Vonng/overfit-10.png) |
一个模型真正的测验标准,是它对没有见过的场景的预测能力,称为 **泛化能力
(generalize)** 。
一个模型真正的测验标准,是它对没有见过的场景的预测能力,称为 **泛化能力(generalize)**
如何避免过拟合?按照奥卡姆剃刀原理: **两个效果相同的解释,选择简单的那
一个。**
如何避免过拟合?按照奥卡姆剃刀原理: **两个效果相同的解释,选择简单的那一个。**
当然这个原理只是我们抱有的一种信念,并不是真正的定理铁律:这些数据点真的由拟合出
的十阶多项式产生,也不能否认这种可能...
当然这个原理只是我们抱有的一种信念,并不是真正的定理铁律:这些数据点真的由拟合出的十阶多项式产生,也不能否认这种可能...
总之,如果出现非常大的权重参数,通常就意味着过拟合。例如拟合所得十阶多项式系数就
非常畸形:
总之,如果出现非常大的权重参数,通常就意味着过拟合。例如拟合所得十阶多项式系数就非常畸形:
```text
-0.001278386964370502
@ -741,8 +666,7 @@ plt.plot(xs, np.polyval(p2, xs));plt.plot(x, y, 'ro');plt.plot(xs, np.sin(xs), '
0.4211227089756039
```
通过添加权重衰减项,可以有效遏制过拟合。例如 \\(L2\\) 规 范化为损失函数添
加了一个 \\(\frac λ 2 w^2\\) 的惩罚项:
通过添加权重衰减项,可以有效遏制过拟合。例如 \\(L2\\) 规 范化为损失函数添加了一个 \\(\frac λ 2 w^2\\) 的惩罚项:
\\[
C = -\frac{1}{n} \sum\_{xj} \left[ y\_j \ln a^L\_j+(1-y\_j) \ln
@ -763,8 +687,7 @@ C = C\_0 + \frac {λ}{2n} \sum\_w {w^2}
\frac{∂C}{∂w} = \frac{ ∂C\_0}{∂w}+\frac{λ}{n} w
\\]
因此,引入 \\(L2\\) 规 范化惩罚项在计算上的唯一变化,就是在处理权值梯度时首先要乘一个衰
减系数:
因此,引入 \\(L2\\) 规 范化惩罚项在计算上的唯一变化,就是在处理权值梯度时首先要乘一个衰减系数:
\\[
w → w' = w\left(1 - \frac{ηλ}{n} \right) - η\frac{∂C\_0}{∂ w}
@ -847,11 +770,9 @@ Round {30}: {9802}/{10000}
可见只是简单的变更,就使准确率有了显著提高,最终收敛至98%。
修改Size为 `[784,128,64,10]` 添加一层隐藏层,可以进一步提升测试集准确
率至98.33%,验证集至98.24%。
修改Size为 `[784,128,64,10]` 添加一层隐藏层,可以进一步提升测试集准确率至98.33%,验证集至98.24%。
对于MNIST数字分类任务,目前最好的准确率为99.79%,那些识别错误的case,恐怕人类想
要正确识别也很困难。神经网络的分类效果最新进展可以参看这里:
对于MNIST数字分类任务,目前最好的准确率为99.79%,那些识别错误的case,恐怕人类想要正确识别也很困难。神经网络的分类效果最新进展可以参看这里:
[classification\\\_datasets\\\_results](http://rodrigob.github.io/are%5Fwe%5Fthere%5Fyet/build/classification%5Fdatasets%5Fresults.html)。
本文是tensorflow官方推荐教程:[Neural Networks and Deep Learning](http://neuralnetworksanddeeplearning.com/)的笔记整理,原文

Loading…
Cancel
Save