Showing preview only (1,050K chars total). Download the full file or copy to clipboard to get everything.
Repository: DiHiera/Algorithm_Interview_Notes-Chinese-master
Branch: master
Commit: 0ec8522e3b7f
Files: 111
Total size: 689.2 KB
Directory structure:
gitextract_37cdkksy/
├── .gitignore
├── A-机器学习/
│ ├── A-机器学习基础.md
│ ├── A-机器学习实践.md
│ ├── A-机器学习算法.md
│ └── C-专题-集成学习.md
├── A-深度学习/
│ ├── A-深度学习基础.md
│ ├── A-深度学习实践.md
│ ├── B-专题-CNN.md
│ ├── B-专题-RNN.md
│ ├── C-专题-优化算法.md
│ ├── D-专题-序列建模.md
│ ├── 《深度学习》整理.md
│ └── 备忘-术语表.md
├── B-自然语言处理/
│ ├── A-NLP发展趋势.md
│ ├── A-自然语言处理基础.md
│ ├── B-专题-句嵌入.md
│ ├── B-专题-词向量.md
│ ├── C-专题-多模态.md
│ ├── D-视觉问答-1_综述.md
│ └── 深度查询理解/
│ └── A-综述.md
├── B-计算机视觉/
│ └── B-专题-基本模型.md
├── C-数学/
│ ├── A-概率论.md
│ ├── B-微积分的本质.md
│ ├── B-深度学习的核心.md
│ └── README.md
├── C-算法/
│ ├── README.md
│ ├── 专题-A-字符串.md
│ ├── 专题-A-数据结构.md
│ ├── 专题-A-数据结构_Advanced.md
│ ├── 专题-B-动态规划.md
│ ├── 专题-B-双指针.md
│ ├── 专题-C-区间问题.md
│ ├── 专题-C-排列组合.md
│ ├── 专题-C-数学问题.md
│ ├── 专题-C-洗牌、采样、随机数.md
│ ├── 专题-D-大数运算.md
│ ├── 专题-D-海量数据处理.md
│ ├── 备忘-IO模板.md
│ ├── 备忘-必备算法.md
│ ├── 题解-LeetCode.md
│ ├── 题解-剑指Offer.md
│ └── 题解-面试真题.md
├── C-编程语言/
│ ├── Cpp-A-基础.md
│ ├── Cpp-A-面向对象.md
│ ├── Cpp-C-左值与右值.md
│ ├── Python-A-基础.md
│ └── README.md
├── D-笔试面经/
│ ├── README.md
│ ├── 笔试-360-180827.md
│ ├── 笔试-iHandy-180927.md
│ ├── 笔试-作业帮-180925.md
│ ├── 笔试-字节跳动-180812.md
│ ├── 笔试-小米-180920.md
│ ├── 笔试-度小满-180913.md
│ ├── 笔试-快手-180910.md
│ ├── 笔试-招行-180830.md
│ ├── 笔试-搜狐畅游-180915.md
│ ├── 笔试-滴滴-180918.md
│ ├── 笔试-爱奇艺-180915.md
│ ├── 笔试-百度-180911.md
│ ├── 笔试-百度-180914.md
│ ├── 笔试-百词斩-180920.md
│ ├── 笔试-腾讯-180916.md
│ ├── 笔试-迅雷-180912.md
│ └── 笔试-顺丰-180917.md
├── Jobs.md
├── README.md
├── ToDo.md
├── _codes/
│ ├── README.md
│ ├── cpp/
│ │ └── 面向对象-不通过继承实现多态-动态序列.cpp
│ ├── machine_learning/
│ │ └── KMeans/
│ │ ├── data.txt
│ │ └── kmeans.py
│ ├── model/
│ │ └── 倒排索引/
│ │ ├── data/
│ │ │ ├── a.txt
│ │ │ ├── b.txt
│ │ │ └── c.txt
│ │ └── inverse_index.py
│ ├── my_nlp/
│ │ ├── data/
│ │ │ ├── sentences.txt
│ │ │ ├── vocab.txt
│ │ │ └── wv.txt
│ │ └── src/
│ │ ├── __init__.py
│ │ ├── sentence2vec/
│ │ │ ├── __init__.py
│ │ │ └── sif.py
│ │ └── utils/
│ │ ├── __init__.py
│ │ └── vocab.py
│ ├── my_tensorflow/
│ │ ├── README.md
│ │ ├── src/
│ │ │ ├── __init__.py
│ │ │ ├── activations/
│ │ │ │ ├── __init__.py
│ │ │ │ └── relu.py
│ │ │ ├── initializers/
│ │ │ │ └── __init__.py
│ │ │ ├── layers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── attention.py
│ │ │ │ ├── cnn.py
│ │ │ │ ├── dense.py
│ │ │ │ ├── embedding/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── char_cnn.py
│ │ │ │ ├── highway.py
│ │ │ │ └── match/
│ │ │ │ ├── __init__.py
│ │ │ │ └── attention_flow.py
│ │ │ ├── regularizers/
│ │ │ │ ├── L1L2.py
│ │ │ │ └── __init__.py
│ │ │ └── utils/
│ │ │ ├── __init__.py
│ │ │ ├── array_op.py
│ │ │ └── math_op.py
│ │ └── test_layer.ipynb
│ └── 工具库/
│ └── gensim/
│ └── FastText.py
└── _notes/
├── 专题-Bash命令.md
├── 图示.pptx
├── 备忘-Markdown小技巧.md
├── 备忘-Python相关工具.md
├── 备忘-工具库.md
└── 备忘-常用子函数.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# IDE
.idea/
.vscode/
# folder
__*/
.ipynb_checkpoints/
out/
# file
-*
*.zip
*.tgz
Untitled.ipynb
MyCV.pdf
MyCV.md
GSD_*.pdf
# root
/demo.py
/test.py
# prevent being filtered
!__init__.py
# Python
.py[cod]
*.egg
*.egg-info
/dist/
__pycache__/
================================================
FILE: A-机器学习/A-机器学习基础.md
================================================
ML-机器学习基础
===
Index
---
<!-- TOC -->
- [偏差与方差](#偏差与方差)
- [导致偏差和方差的原因](#导致偏差和方差的原因)
- [深度学习中的偏差与方差](#深度学习中的偏差与方差)
- [偏差/方差 与 Boosting/Bagging](#偏差方差-与-boostingbagging)
- [偏差与方差的计算公式](#偏差与方差的计算公式)
- [偏差与方差的权衡(过拟合与模型复杂度的权衡)](#偏差与方差的权衡过拟合与模型复杂度的权衡)
- [生成模型与判别模型](#生成模型与判别模型)
- [先验概率与后验概率](#先验概率与后验概率)
<!-- /TOC -->
## 偏差与方差
> 《机器学习》 2.5 偏差与方差 - 周志华
- **偏差**与**方差**分别是用于衡量一个模型**泛化误差**的两个方面;
- 模型的**偏差**,指的是模型预测的**期望值**与**真实值**之间的差;
- 模型的**方差**,指的是模型预测的**期望值**与**预测值**之间的差平方和;
- 在**监督学习**中,模型的**泛化误差**可**分解**为偏差、方差与噪声之和。
<div align="center"><img src="../_assets/TIM截图20180817204652.png" height="" /></div>
- **偏差**用于描述模型的**拟合能力**;<br/>
**方差**用于描述模型的**稳定性**。
<div align="center"><img src="../_assets/TIM截图20180817192259.png" height="" /></div>
### 导致偏差和方差的原因
- **偏差**通常是由于我们对学习算法做了**错误的假设**,或者模型的复杂度不够;
- 比如真实模型是一个二次函数,而我们假设模型为一次函数,这就会导致偏差的增大(欠拟合);
- **由偏差引起的误差**通常在**训练误差**上就能体现,或者说训练误差主要是由偏差造成的
- **方差**通常是由于**模型的复杂度相对于训练集过高**导致的;
- 比如真实模型是一个简单的二次函数,而我们假设模型是一个高次函数,这就会导致方差的增大(过拟合);
- **由方差引起的误差**通常体现在测试误差相对训练误差的**增量**上。
### 深度学习中的偏差与方差
- 神经网络的拟合能力非常强,因此它的**训练误差**(偏差)通常较小;
- 但是过强的拟合能力会导致较大的方差,使模型的测试误差(**泛化误差**)增大;
- 因此深度学习的核心工作之一就是研究如何降低模型的泛化误差,这类方法统称为**正则化方法**。
> ../深度学习/[正则化](../A-深度学习/C-专题-正则化)
### 偏差/方差 与 Boosting/Bagging
> ./集成学习专题/[Boosting/Bagging 与 偏差/方差 的关系](./C-专题-集成学习#boostingbagging-与-偏差方差-的关系)
### 偏差与方差的计算公式
- 记在**训练集 D** 上学得的模型为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f(\boldsymbol{x};D)"><img src="../_assets/公式_20180817211749.png" height="" /></a></div>
模型的**期望预测**为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;\hat{f}(\boldsymbol{x})=\mathbb{E}_D[f(\boldsymbol{x};D)]"><img src="../_assets/公式_20180817210758.png" height="" /></a></div>
- **偏差**(Bias)
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;bias^2(\boldsymbol{x})=(\hat{f}(\boldsymbol{x})-y)^2"><img src="../_assets/公式_20180817210106.png" height="" /></a></div>
> **偏差**度量了学习算法的期望预测与真实结果的偏离程度,即刻画了学习算法本身的拟合能力;
- **方差**(Variance)
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;var(\boldsymbol{x})=\mathbb{E}_D\left&space;[&space;\left&space;(&space;f(\boldsymbol{x};D)-\hat{f}(\boldsymbol{x})&space;\right&space;)^2&space;\right&space;]"><img src="../_assets/公式_20180817211903.png" height="" /></a></div>
> **方差**度量了同样大小的**训练集的变动**所导致的学习性能的变化,即刻画了数据扰动所造成的影响(模型的稳定性);
<!-- - **噪声**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;var(\boldsymbol{x})=\mathbb{E}_D\left&space;[&space;\left&space;(&space;f(\boldsymbol{x};D)-\hat{f}(\boldsymbol{x})&space;\right&space;)^2&space;\right&space;]"><img src="../_assets/公式_20180817212111.png" height="" /></a></div> -->
- **噪声**则表达了在当前任务上任何学习算法所能达到的期望泛化误差的下界,即刻画了学习问题本身的难度。
- “**偏差-方差分解**”表明模型的泛化能力是由算法的能力、数据的充分性、任务本身的难度共同决定的。
### 偏差与方差的权衡(过拟合与模型复杂度的权衡)
- 给定学习任务,
- 当训练不足时,模型的**拟合能力不够**(数据的扰动不足以使模型产生显著的变化),此时**偏差**主导模型的泛化误差;
- 随着训练的进行,模型的**拟合能力增强**(模型能够学习数据发生的扰动),此时**方差**逐渐主导模型的泛化误差;
- 当训练充足后,模型的**拟合能力过强**(数据的轻微扰动都会导致模型产生显著的变化),此时即发生**过拟合**(训练数据自身的、非全局的特征也被模型学习了)
- 偏差和方差的关系和**模型容量**(模型复杂度)、**欠拟合**和**过拟合**的概念紧密相联
<div align="center"><img src="../_assets/TIM截图20180817214034.png" height="" /></div>
- 当模型的容量增大(x 轴)时, 偏差(用点表示)随之减小,而方差(虚线)随之增大
- 沿着 x 轴存在**最佳容量**,**小于最佳容量会呈现欠拟合**,**大于最佳容量会导致过拟合**。
> 《深度学习》 5.4.4 权衡偏差和方差以最小化均方误差
**Reference**
- [Understanding the Bias-Variance Tradeoff](http://scott.fortmann-roe.com/docs/BiasVariance.html)
- [机器学习中的Bias(偏差),Error(误差),和Variance(方差)有什么区别和联系?](https://www.zhihu.com/question/27068705) - 知乎
## 生成模型与判别模型
> 《统计学习方法》 1.7 生成模型与判别模型
- 监督学习的任务是学习一个模型,对给定的输入预测相应的输出
- 这个模型的一般形式为一个**决策函数**或一个**条件概率分布**(后验概率):
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_phv&space;\large&space;Y=f(X)\quad&space;\text{or}\quad&space;P(Y|X)"><img src="../_assets/公式_20180817220004.png" height="" /></a></div>
- **决策函数**:输入 X 返回 Y;其中 Y 与一个**阈值**比较,然后根据比较结果判定 X 的类别
- **条件概率分布**:输入 X 返回 **X 属于每个类别的概率**;将其中概率最大的作为 X 所属的类别
- 监督学习模型可分为**生成模型**与**判别模型**
- **判别模型**直接学习决策函数或者条件概率分布
- 直观来说,**判别模型**学习的是类别之间的最优分隔面,反映的是不同类数据之间的差异
- **生成模型**学习的是联合概率分布`P(X,Y)`,然后根据条件概率公式计算 `P(Y|X)`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_phv&space;\large&space;P(Y|X)=\frac{P(X,Y)}{P(X)}"><img src="../_assets/公式_20180817223923.png" height="" /></a></div>
**两者之间的联系**
- 由生成模型可以得到判别模型,但由判别模型得不到生成模型。
- 当存在“**隐变量**”时,只能使用**生成模型**
> 隐变量:当我们找不到引起某一现象的原因时,就把这个在起作用,但无法确定的因素,叫“隐变量”
**优缺点**
- **判别模型**
- 优点
- 直接面对预测,往往学习的准确率更高
- 由于直接学习 `P(Y|X)` 或 `f(X)`,可以对数据进行各种程度的抽象,定义特征并使用特征,以简化学习过程
- 缺点
- 不能反映训练数据本身的特性
- ...
- **生成模型**
- 优点
- 可以还原出联合概率分布 `P(X,Y)`,判别方法不能
- 学习收敛速度更快——即当样本容量增加时,学到的模型可以更快地收敛到真实模型
- 当存在“隐变量”时,只能使用生成模型
- 缺点
- 学习和计算过程比较复杂
**常见模型**
- 判别模型
- K 近邻、感知机(神经网络)、决策树、逻辑斯蒂回归、**最大熵模型**、SVM、提升方法、**条件随机场**
- 生成模型
- 朴素贝叶斯、隐马尔可夫模型、混合高斯模型、贝叶斯网络、马尔可夫随机场
**Reference**
- [机器学习---生成模型与判别模型](https://blog.csdn.net/u012101561/article/details/52814571) - CSDN博客
-
## 先验概率与后验概率
> [先验概率,后验概率,似然概率,条件概率,贝叶斯,最大似然](https://blog.csdn.net/suranxu007/article/details/50326873) - CSDN博客
**条件概率**(似然概率)
- 一个事件发生后另一个事件发生的概率。
- 一般的形式为 `P(X|Y)`,表示 y 发生的条件下 x 发生的概率。
- 有时为了区分一般意义上的**条件概率**,也称**似然概率**
**先验概率**
- 事件发生前的预判概率
- 可以是基于历史数据的统计,可以由背景常识得出,也可以是人的主观观点给出。
- 一般都是**单独事件**发生的概率,如 `P(A)`、`P(B)`。
**后验概率**
- 基于先验概率求得的**反向条件概率**,形式上与条件概率相同(若 `P(X|Y)` 为正向,则 `P(Y|X)` 为反向)
**贝叶斯公式**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_phv&space;\large&space;P(Y|X)=\frac{P(X|Y)*P(Y)}{P(X)}"><img src="../_assets/公式_20180817230314.png" height="" /></a></div>
================================================
FILE: A-机器学习/A-机器学习实践.md
================================================
专题-机器学习实践
===
Reference
---
- [CS229 课程讲义(中文)](https://github.com/Kivy-CN/Stanford-CS-229-CN) - Kivy-CN - GitHub
Index
---
<!-- TOC -->
- [超参数选择](#超参数选择)
- [Grid Search](#grid-search)
- [Random Search](#random-search)
- [相关库(未使用)](#相关库未使用)
- [几种参数估计的区别于联系: MLE、MAP、贝叶斯 TODO](#几种参数估计的区别于联系-mlemap贝叶斯-todo)
- [余弦相似度(Cos距离)与欧氏距离的区别和联系](#余弦相似度cos距离与欧氏距离的区别和联系)
- [监督学习和无监督学习](#监督学习和无监督学习)
- [熵,求投掷均匀正六面体骰子的熵](#熵求投掷均匀正六面体骰子的熵)
- [混淆矩阵、模型度量指标:准确率、精确率、召回率、F1 值等](#混淆矩阵模型度量指标准确率精确率召回率f1-值等)
- [如何处理数据中的缺失值](#如何处理数据中的缺失值)
- [介绍一个完整的机器学习项目流程](#介绍一个完整的机器学习项目流程)
- [数据清洗与特征处理](#数据清洗与特征处理)
- [关联规则挖掘的 3 个度量指标:支持度、置信度、提升度](#关联规则挖掘的-3-个度量指标支持度置信度提升度)
<!-- /TOC -->
## 超参数选择
### Grid Search
- 网格搜索
- 在高维空间中对一定区域进行遍历
### Random Search
- 在高维空间中随机选择若干超参数
### 相关库(未使用)
- [Hyperopt](http://hyperopt.github.io/hyperopt/)
- 用于超参数优化的 Python 库,其内部使用 Parzen 估计器的树来预测哪组超参数可能会得到好的结果。
- GitHub - https://github.com/hyperopt/hyperopt
- [Hyperas](http://maxpumperla.com/hyperas/)
- 将 Hyperopt 与 Keras 模型集成在一起的库
- GitHub - https://github.com/maxpumperla/hyperas
## 几种参数估计的区别于联系: MLE、MAP、贝叶斯 TODO
## 余弦相似度(Cos距离)与欧氏距离的区别和联系
> geekcircle/machine-learning-interview-qa/[4.md](https://github.com/geekcircle/machine-learning-interview-qa/blob/master/questions/4.md)
- 欧式距离和余弦相似度都能度量 2 个向量之间的相似度
- 放到向量空间中看,欧式距离衡量两点之间的**直线距离**,而余弦相似度计算的是两个向量之间的**夹角**
- **没有归一化时**,欧式距离的范围是 (0, +∞],而余弦相似度的范围是 (0, 1];余弦距离是计算**相似程度**,而欧氏距离计算的是**相同程度**(对应值的相同程度)
- **归一化的情况下**,可以将空间想象成一个超球面(三维),欧氏距离就是球面上两点的直线距离,而向量余弦值等价于两点的球面距离,本质是一样。
> [欧氏距离和余弦相似度的区别是什么?](https://www.zhihu.com/question/19640394) - 知乎
## 监督学习和无监督学习
> geekcircle/machine-learning-interview-qa/[6.md](https://github.com/geekcircle/machine-learning-interview-qa/blob/master/questions/6.md)
## 熵,求投掷均匀正六面体骰子的熵
> geekcircle/machine-learning-interview-qa/[7.md](https://github.com/geekcircle/machine-learning-interview-qa/blob/master/questions/7.md)
什么是熵?
> 深度学习/理论知识/[信息熵、KL 散度(相对熵)与交叉熵**](../A-深度学习/《深度学习》整理#信息熵kl-散度相对熵与交叉熵)
**求投掷均匀正六面体骰子的熵**
- 问题描述:向空中投掷硬币,落地后有两种可能的状态,一个是正面朝上,另一个是反面朝上,每个状态出现的概率为1/2。如投掷均匀的正六面体的骰子,则可能会出现的状态有6个,每一个状态出现的概率均为1/6。试通过计算来比较状态的不确定性与硬币状态的不确定性的大小。
- 答:
硬币:<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=-\sum^{n}_{i=1}P(X_i)\log&space;P(X_i)&space;=&space;-2*\frac{1}{2}*\log&space;P(\frac{1}{2})\approx&space;1&space;\text{bit}"><img src="../_assets/公式_20180620160408.png" height="" /></a></div>
六面体:<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=-\sum^{n}_{i=1}P(X_i)\log&space;P(X_i)&space;=&space;-6*\frac{1}{6}*\log&space;P(\frac{1}{6})\approx&space;2.6&space;\text{bit}"><img src="../_assets/公式_20180620160538.png" height="" /></a></div>
## 混淆矩阵、模型度量指标:准确率、精确率、召回率、F1 值等
**混淆矩阵**
- True Positive(TP):将正类预测为正类的数量.
- True Negative(TN):将负类预测为负类的数量.
- False Positive(FP):将负类预测为正类数 → 误报 (Type I error).
- False Negative(FN):将正类预测为负类数 → 漏报 (Type II error).
<div align="center"><img src="../_assets/confusion_matrix.png" height="" /></div>
**准确率**(accuracy)
<div align="center"><img src="../_assets/TIM截图20180620171915.png" height="" /></div>
**精确率**(precision)
<div align="center"><img src="../_assets/TIM截图20180620171300.png" height="" /></div>
> 准确率与精确率的区别:
>> 在正负样本不平衡的情况下,**准确率**这个评价指标有很大的缺陷。比如在互联网广告里面,点击的数量是很少的,一般只有千分之几,如果用acc,即使全部预测成负类(不点击)acc 也有 99% 以上,没有意义。
**召回率**(recall, sensitivity, true positive rate)
<div align="center"><img src="../_assets/TIM截图20180620190555.png" height="" /></div>
**F1值**——精确率和召回率的调和均值
<div align="center"><img src="../_assets/TIM截图20180620191137.png" height="" /></div>
> 只有当精确率和召回率都很高时,F1值才会高
## 如何处理数据中的缺失值
> geekcircle/machine-learning-interview-qa/[1.md](https://github.com/geekcircle/machine-learning-interview-qa/blob/master/questions/1.md)
可以分为以下 2 种情况:
1. **缺失值较多**
- 直接舍弃该列特征,否则可能会带来较大的噪声,从而对结果造成不良影响。
1. **缺失值较少**
- 当缺失值较少(<10%)时,可以考虑对缺失值进行填充,以下是几种常用的填充策略:
1. 用一个**异常值**填充(比如 0),将缺失值作为一个特征处理
` data.fillna(0) `
1. 用**均值**|**条件均值**填充
> 如果数据是不平衡的,那么应该使用条件均值填充
>
> 所谓**条件均值**,指的是与缺失值所属标签相同的所有数据的均值
`data.fillna(data.mean())`
1. 用相邻数据填充
```
# 用前一个数据填充
data.fillna(method='pad')
# 用后一个数据填充
data.fillna(method='bfill')
```
1. 插值
`data.interpolate()`
1. 拟合
> 简单来说,就是将缺失值也作为一个预测问题来处理:将数据分为正常数据和缺失数据,对有值的数据采用随机森林等方法拟合,然后对有缺失值的数据进行预测,用预测的值来填充。
## 介绍一个完整的机器学习项目流程
> geekcircle/machine-learning-interview-qa/[2.md](https://github.com/geekcircle/machine-learning-interview-qa/blob/master/questions/2.md)
1. 数学抽象
明确问题是进行机器学习的第一步。机器学习的训练过程通常都是一件非常耗时的事情,胡乱尝试时间成本是非常高的。
这里的抽象成数学问题,指的是根据数据明确任务目标,是分类、还是回归,或者是聚类。
1. 数据获取
数据决定了机器学习结果的上限,而算法只是尽可能逼近这个上限。
数据要有代表性,否则必然会过拟合。
对于分类问题,数据偏斜不能过于严重(平衡),不同类别的数据数量不要有数个数量级的差距。
对数据的量级要有一个评估,多少个样本,多少个特征,据此估算出内存需求。如果放不下就得考虑改进算法或者使用一些降维技巧,或者采用分布式计算。
1. 预处理与特征选择
良好的数据要能够提取出良好的特征才能真正发挥效力。
预处理/数据清洗是很关键的步骤,往往能够使得算法的效果和性能得到显著提高。归一化、离散化、因子化、缺失值处理、去除共线性等,数据挖掘过程中很多时间就花在它们上面。这些工作简单可复制,收益稳定可预期,是机器学习的基础必备步骤。
筛选出显著特征、摒弃非显著特征,需要机器学习工程师反复理解业务。这对很多结果有决定性的影响。特征选择好了,非常简单的算法也能得出良好、稳定的结果。这需要运用特征有效性分析的相关技术,如相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。
1. 模型训练与调优
直到这一步才用到我们上面说的算法进行训练。
现在很多算法都能够封装成黑盒使用。但是真正考验水平的是调整这些算法的(超)参数,使得结果变得更加优良。这需要我们对算法的原理有深入的理解。理解越深入,就越能发现问题的症结,提出良好的调优方案。
1. 模型诊断
如何确定模型调优的方向与思路呢?这就需要对模型进行诊断的技术。
过拟合、欠拟合 判断是模型诊断中至关重要的一步。常见的方法如交叉验证,绘制学习曲线等。过拟合的基本调优思路是增加数据量,降低模型复杂度。欠拟合的基本调优思路是提高特征数量和质量,增加模型复杂度。
误差分析也是机器学习至关重要的步骤。通过观察误差样本,全面分析误差产生误差的原因:是参数的问题还是算法选择的问题,是特征的问题还是数据本身的问题......
诊断后的模型需要进行调优,调优后的新模型需要重新进行诊断,这是一个反复迭代不断逼近的过程,需要不断地尝试, 进而达到最优状态。
1. 模型融合/集成
一般来说,模型融合后都能使得效果有一定提升。而且效果很好。
工程上,主要提升算法准确度的方法是分别在模型的前端(特征清洗和预处理,不同的采样模式)与后端(模型融合)上下功夫。因为他们比较标准可复制,效果比较稳定。而直接调参的工作不会很多,毕竟大量数据训练起来太慢了,而且效果难以保证。
1. 上线运行
这一部分内容主要跟工程实现的相关性更大。工程上是结果导向,模型在线上运行的效果直接决定模型的成败。不单纯包括其准确程度、误差等情况,还包括其运行的速度(时间复杂度)、资源消耗程度(空间复杂度)、稳定性是否可接受。
这些工作流程主要是工程实践上总结出的一些经验。并不是每个项目都包含完整的一个流程。这里的部分只是一个指导性的说明,只有多实践,多积累项目经验,才会有自己更深刻的认识。
## 数据清洗与特征处理
> geekcircle/machine-learning-interview-qa/[8.md](https://github.com/geekcircle/machine-learning-interview-qa/blob/master/questions/8.md)
<!-- <div align="center"><img src="../_assets/数据清洗与特征处理.jpg" height="" /></div> -->
> [机器学习中的数据清洗与特征处理综述](https://tech.meituan.com/machinelearning-data-feature-process.html) - 美团点评技术
## 关联规则挖掘的 3 个度量指标:支持度、置信度、提升度
**支持度**(Support)
- X → Y 的支持度表示项集 {X,Y} 在总项集中出现的概率
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=Support(X\rightarrow&space;Y)=\frac{P(X\cup&space;Y)}{P(I)}=\frac{\text{num}(X\cup&space;Y)}{\text{num}(I)}"><img src="../_assets/公式_20180620204006.png" height="" /></a></div>
- 其中,I 表示总事务集,`num()`表示事务集中特定项集出现的次数,`P(X)=num(X)/num(I)`
**置信度**(Confidence)
- X → Y 的置信度表示在先决条件 X 发生的情况下,由规则 X → Y 推出 Y 的概率。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=Confidence(X\rightarrow&space;Y)=P(Y|X)=\frac{P(X\cup&space;Y)}{P(X)}=\frac{\text{num}(X\cup&space;Y)}{\text{num}(X)}"><img src="../_assets/公式_20180620205055.png" height="" /></a></div>
**提升度**(Lift)
- X → Y 的提升度表示含有X的条件下,同时含有Y的概率,与Y总体发生的概率之比。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex={\displaystyle&space;{\begin{aligned}&space;Lift(X\rightarrow&space;Y)&=\frac{P(Y|X)}{P(Y)}=\frac{Confidence(X\rightarrow&space;Y)}{\text{num}(Y)/\text{num}(I)}\\&space;&=\frac{P(X\cup&space;Y)}{P(X)P(Y)}=\frac{\text{num}(X\cup&space;Y)\text{num}(I)}{\text{num}(X)\text{num}(Y)}&space;\end{aligned}}}"><img src="../_assets/公式_20180620213601.png" height="" /></a></div>
规则的有效性:
---
- 满足最小支持度和最小置信度的规则,叫做“强关联规则”
> 最小支持度和最小置信度是人工设置的阈值
- `Lift(X→Y) > 1` 的 X→Y 是有效的强关联规则
- `Lift(X→Y) <=1` 的 X→Y 是有效的强关联规则
- 特别地,`Lift(X→Y) = 1` 时,X 与 Y 相互独立。
**判断规则的有效性**
---
问题:已知有1000名顾客买年货,分为甲乙两组,每组各500人,其中甲组有500人买了茶叶,同时又有450人买了咖啡;乙组有450人买了咖啡,如表所示,请问“茶叶→咖啡”是一条有效的关联规则吗?
组次 | 买茶叶的人数 | 买咖啡的人数
--- | ---------- | ---------
甲组(500人) | 500 | 450
乙组(500人) | 0 | 450
答:
- “茶叶→咖啡”的支持度:Support(X→Y) = 450 / 1000 = 45%
- “茶叶→咖啡”的置信度:Confidence(X→Y) = 450 / 500 = 90%
- “茶叶→咖啡”的提升度:Lift(X→Y) = 90% / 90% = 1
由于提升度 `Lift(X→Y) = 1`,表示 X 与 Y 相互独立。也就是说,是否购买咖啡,与是否购买茶叶无关联。规则“茶叶→咖啡”不成立,或者说几乎没有关联,虽然它的置信度高达90%,但它不是一条有效的关联规则。
================================================
FILE: A-机器学习/A-机器学习算法.md
================================================
**RoadMap**
---
- [逻辑斯蒂回归](#逻辑斯蒂回归)
- [支持向量机](#支持向量机)
- [决策树](#决策树)
- [AdaBoost 算法](#adaboost-算法)
- [梯度提升决策树 GBDT](#梯度提升决策树-gbdt)
- [机器学习实践](#机器学习实践)
**Index**
---
<!-- TOC -->
- [符号说明](#符号说明)
- [信息论](#信息论)
- [逻辑斯蒂回归](#逻辑斯蒂回归)
- [逻辑斯蒂回归模型定义](#逻辑斯蒂回归模型定义)
- [逻辑斯蒂回归推导](#逻辑斯蒂回归推导)
- [多分类逻辑斯蒂回归模型 TODO](#多分类逻辑斯蒂回归模型-todo)
- [支持向量机](#支持向量机)
- [支持向量机简述](#支持向量机简述)
- [什么是支持向量](#什么是支持向量)
- [支持向量机的分类](#支持向量机的分类)
- [核函数与核技巧](#核函数与核技巧)
- [最大间隔超平面背后的原理](#最大间隔超平面背后的原理)
- [支持向量机推导](#支持向量机推导)
- [线性可分支持向量机推导](#线性可分支持向量机推导)
- [决策树](#决策树)
- [信息增益与信息增益比 TODO](#信息增益与信息增益比-todo)
- [分类树 - ID3 决策树与 C4.5 决策树 TODO](#分类树---id3-决策树与-c45-决策树-todo)
- [决策树如何避免过拟合 TODO](#决策树如何避免过拟合-todo)
- [回归树 - CART 决策树](#回归树---cart-决策树)
- [CART 回归树算法推导](#cart-回归树算法推导)
- [示例: 选择切分变量与切分点](#示例-选择切分变量与切分点)
- [集成学习](#集成学习)
- [集成学习的基本策略(3)](#集成学习的基本策略3)
- [1. Boosting](#1-boosting)
- [Boosting 策略要解决的两个基本问题](#boosting-策略要解决的两个基本问题)
- [2. Bagging](#2-bagging)
- [3. Stacking](#3-stacking)
- [AdaBoost 算法](#adaboost-算法)
- [AdaBoost 算法描述](#adaboost-算法描述)
- [AdaBoost 算法要点说明](#adaboost-算法要点说明)
- [前向分步算法](#前向分步算法)
- [加法模型](#加法模型)
- [前向分步算法描述](#前向分步算法描述)
- [前向分步算法与 AdaBoost](#前向分步算法与-adaboost)
- [梯度提升决策树 GBDT](#梯度提升决策树-gbdt)
- [提升树 Boosting Tree](#提升树-boosting-tree)
- [提升树算法描述](#提升树算法描述)
- [梯度提升(GB)算法](#梯度提升gb算法)
- [GBDT 算法描述](#gbdt-算法描述)
- [XGBoost 算法](#xgboost-算法)
- [XGBoost 与 GB 的主要区别](#xgboost-与-gb-的主要区别)
- [XGBoost 的一些内部优化](#xgboost-的一些内部优化)
- [随机森林](#随机森林)
- [机器学习实践](#机器学习实践)
- [Box–Muller 变换](#boxmuller-变换)
- [降维](#降维)
- [SVD](#svd)
- [PCA](#pca)
- [t-SNE](#t-sne)
- [Reference](#reference)
<!-- /TOC -->
<!-- # 什么是推导
- 给出一个问题或模型的定义,然后求其最优解的过程 -->
# 符号说明
- 基本遵从《统计学习方法》一书中的符号表示。
- 除特别说明,默认`w`为行向量,`x`为列向量,以避免在`wx`中使用转置符号;但有些公式为了更清晰区分向量与标量,依然会使用`^T`的上标,注意区分。
输入实例`x`的特征向量记为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=x=(x^{(1)},x^{(2)},\cdots,x^{(n)})^T"><img src="../_assets/公式_20180713114026.png" height="" /></a></div>
注意:`x_i` 和 `x^(i)` 含义不同,前者表示训练集中第 i 个实例,后者表示特征向量中的第 i 个分量;因此,通常记训练集为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=T=\left&space;\{&space;(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)&space;\right&space;\}"><img src="../_assets/公式_20180713132400.png" height="" /></a></div>
> 特征向量用小`n`表示维数,训练集用大`N`表示个数
- **公式说明**
所有公式都可以**点击**跳转至编辑页面,但是部分公式符号会与超链接中的转义冲突;如果编辑页面的公式与本页面中的不同,可以打开源文件,通过原链接打开。
# 信息论
> 《深度学习》 3.13 信息论
- 信息论的基本想法是:一件不太可能的事发生,要比一件非常可能的事发生,提供更多的信息。
- 该想法可描述为以下性质:
1. 非常可能发生的事件信息量要比较少,并且极端情况下,一定能够发生的事件应该没有信息量。
2. 比较不可能发生的事件具有更大的信息量。
3. 独立事件应具有增量的信息。例如,投掷的硬币两次正面朝上传递的信息量,应该是投掷一次硬币正面朝上的信息量的两倍。
<h3>信息熵 与 自信息</h3>
- **自信息**(self-information)是一种量化以上性质的函数,定义一个事件`x`的自信息为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=I(x)=-\log&space;P(x)"><img src="../_assets/公式_20180610215339.png" height="" /></a></div>
> 当该对数的底数为自然对数 e 时,单位为奈特(nats);当以 2 为底数时,单位为比特(bit)或香农(shannons)
- 自信息只处理单个的输出。
- **信息熵**(Information-entropy)用于对整个概率分布中的**不确定性总量**进行量化:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=H(\mathrm{X})=\mathbb{E}_{\mathrm{X}&space;\sim&space;P}[I(x)]=-\sum_{x&space;\in&space;\mathrm{X}}P(x)\log&space;P(x)"><img src="../_assets/公式_20180610215417.png" height="" /></a></div>
> 信息论中,记 `0log0 = 0`
<h3>交叉熵 与 相对熵/KL散度</h3>
- 定义 **P 对 Q** 的 **KL 散度**(Kullback-Leibler divergence):
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=D_P(Q)=\mathbb{E}_{\mathrm{X}\sim&space;P}\left&space;[&space;\log&space;\frac{P(x)}{Q(x)}&space;\right&space;]=\sum_{x&space;\in&space;\mathrm{X}}P(x)\left&space;[&space;\log&space;P(x)-\log&space;Q(x)&space;\right&space;]"><img src="../_assets/公式_20180610215445.png" height="" /></a></div>
**KL 散度在信息论中度量的是哪个直观量?**
- 在离散型变量的情况下, KL 散度衡量的是:当我们使用一种被设计成能够使得概率分布 Q 产生的消息的长度最小的编码,发送包含由概率分布 P 产生的符号的消息时,所需要的额外信息量。
**KL散度的性质**:
- 非负;KL 散度为 0 当且仅当P 和 Q 在离散型变量的情况下是相同的分布,或者在连续型变量的情况下是“几乎处处”相同的
- 不对称;D_p(q) != D_q(p)
**交叉熵**(cross-entropy):
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=H_P(Q)=-\mathbb{E}_{\mathrm{X}\sim&space;P}\log&space;Q(x)=-\sum_{x&space;\in&space;\mathrm{X}}P(x)\log&space;Q(x)"><img src="../_assets/公式_20180610215522.png" height="" /></a></div>
> [信息量,信息熵,交叉熵,KL散度和互信息(信息增益)](https://blog.csdn.net/haolexiao/article/details/70142571) - CSDN博客
**交叉熵 与 KL 散度的关系**
- **针对 Q 最小化交叉熵等价于最小化 P 对 Q 的 KL 散度**,因为 Q 并不参与被省略的那一项。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=H_P(Q)=H(P)+D_P(Q)"><img src="../_assets/公式_20180610215554.png" height="" /></a></div>
- 最大似然估计中,最小化 KL 散度其实就是在最小化分布之间的交叉熵。
> 《深度学习》 ch5.5 - 最大似然估计
# 逻辑斯蒂回归
## 逻辑斯蒂回归模型定义
<!-- TODO: 符号修改,匹配神经网络中的符号表示 -->
- **二项**逻辑斯蒂回归模型即如下的**条件概率分布**
<!-- [](http://www.codecogs.com/eqnedit.php?latex=P(Y=1|x)=\frac{\exp(z)}{1+\exp(z)}=\frac{1}{1+\exp(-z)}) -->
[](http://www.codecogs.com/eqnedit.php?latex=P(Y=1|x)=\frac{\exp(wx)}{1+\exp(wx)}=\frac{1}{1+\exp(-wx)})
[](http://www.codecogs.com/eqnedit.php?latex=P(Y=0|x)=1-P(Y=1|x))
> 简洁起见,省略了偏置 `b`;也可以看做将偏置扩充到了权重中
**其中**
<!-- [](http://www.codecogs.com/eqnedit.php?latex=P(Y=0|x)=1-P(Y=1|x)) -->
[](http://www.codecogs.com/eqnedit.php?latex=x\in&space;\mathbf{R}^n,Y\in&space;\left&space;\{&space;0,1&space;\right&space;\})
- 通常会将以上两个分布记作:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&P(Y=1|x)={\color{Blue}&space;\sigma(x)}\\&space;&P(Y=0|x)={\color{Blue}&space;1-\sigma(x)}&space;\end{aligned})
> 《统计学习方法》 6.1 逻辑斯蒂回归模型
>> 原书中记作 `π(x)` 和 `1-π(x)`,这里为了跟神经网络中统一,使用 `σ`
## 逻辑斯蒂回归推导
> [逻辑回归推导](https://www.cnblogs.com/daguankele/p/6549891.html) - 罐装可乐 - 博客园
- 推导的关键点 (3)
1. 逻辑斯蒂回归的定义
1. 损失函数(极大似然)
1. 参数优化(梯度下降)
- 给定训练集 `T={(x1,y1),..,(xN,yN)}`,其中 `x ∈ R^n, y ∈ {0, 1}`
1. **逻辑斯蒂回归**的定义:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&P(Y=1|x)={\color{Blue}&space;\sigma(x)}\\&space;&P(Y=0|x)={\color{Blue}&space;1-\sigma(x)}&space;\end{aligned})
2. **负对数函数**作为损失函数:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;L(w)&=-\log\left&space;(&space;\prod_{i=1}^N&space;[{\color{Red}&space;\sigma(x_i)}]^{{\color{Blue}&space;y_i}}&space;[{\color{Red}&space;1-&space;\sigma(x_i)}]^{{\color{Blue}&space;1-y_i}}&space;\right&space;)\\&space;&=-\sum_{i=1}^N&space;\left&space;[&space;y_i\log\sigma(x_i)+(1-y_i)\log(1-\sigma(x_i))&space;\right&space;]\\&space;&=-\sum_{i=1}^N&space;\left&space;[&space;y_i\log\frac{\sigma(x_i)}{1-\sigma(x_i)}+\log(1-\sigma(x_i))&space;\right&space;]&space;\end{aligned})
进一步代入 `σ(x)` 有:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;L(w)&=-\sum_{i=1}^N&space;\left&space;[&space;{\color{Blue}&space;y_i}(w{\color{Red}&space;x_i})-\log(1+\exp(w{\color{Red}&space;x_i}))&space;\right&space;]&space;\end{aligned})
3. **求梯度**
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\frac{\partial&space;L(w)}{\partial&space;w}&=-\sum_{i=1}^N&space;\left&space;[&space;y_ix_i-\frac{\exp(wx_i)}{1+\exp(wx_i)}x_i&space;\right&space;]\\&space;&=\sum_{i=1}^N&space;[\sigma&space;(x_i)-y_i]x_i&space;\end{aligned})
4. 使用**梯度下降法**求解参数
> 深度学习/[梯度下降法](../深度学习/README.md#梯度下降法)
## 多分类逻辑斯蒂回归模型 TODO
- 设 `Y ∈ {1,2,..K}`,则多项式逻辑斯蒂回归模型为:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;P(Y=k|x)&=\frac{\exp(w_kx)}{1+\sum_{k=1}^{K-1}&space;\exp(w_kx)}&space;\quad&space;k=1,2,..,K-1&space;\\&space;P(Y=K|x)&=\frac{1}{1+\sum_{k=1}^{K-1}\exp(w_kx)}&space;\end{aligned})
- 类似 `Softmax`
# 支持向量机
## 支持向量机简述
- 支持向量机(Support Vector Machines, SVM)是一种二分类模型。它的**基本模型**是定义在特征空间上的**间隔最大**的线性分类器,间隔最大使它有别于感知机;支持向量机还包括**核技巧**,这使其成为实质上的非线性分类器。
- **SVM 的学习策略就是间隔最大化**,可形式化为一个求解**凸二次规划**的问题,也等价于正则化的**合页损失函数**的最小化问题。
- SVM 的最优化算法是求解凸二次规划的最优化算法。
### 什么是支持向量
- 训练数据集中与分离超平面距离最近的样本点的实例称为支持向量
- 更通俗的解释:
- 数据集种的某些点,位置比较特殊。比如 `x+y-2=0` 这条直线,假设出现在直线上方的样本记为 A 类,下方的记为 B 类。
- 在寻找找这条直线的时候,一般只需看两类数据,它们各自最靠近划分直线的那些点,而其他的点起不了决定作用。
- 这些点就是所谓的“支持点”,在数学中,这些点称为**向量**,所以更正式的名称为“**支持向量**”。
> [SVM中支持向量的通俗解释](https://blog.csdn.net/AerisIceBear/article/details/79588583) - CSDN博客
### 支持向量机的分类
- 线性可分支持向量机
- 当训练数据**线性可分**时,通过**硬间隔最大化**,学习一个线性分类器,即线性可分支持向量机,又称**硬间隔支持向量机**。
- 线性支持向量机
- 当训练数据**接近线性可分**时,通过**软间隔最大化**,学习一个线性分类器,即线性支持向量机,又称**软间隔支持向量机**。
- 非线性支持向量机
- 当训练数据**线性不可分**时,通过使用**核技巧**及软间隔最大化,学习非线性支持向量机。
### 核函数与核技巧
- **核函数**表示将输入从输入空间映射到特征空间后得到的特征向量之间的内积
### 最大间隔超平面背后的原理
> 机器学习技法 (1-5) - 林轩田
- 相当于在**最小化权重**时对训练误差进行了约束——对比 L2 范数正则化,则是在最小化训练误差时,对权重进行约束

> 与 L2 正则化的区别
- 相当于**限制了模型复杂度**——在一定程度上防止过拟合,具有更强的泛化能力
## 支持向量机推导
- SVM 由简至繁包括:**线性可分支持向量机**、**线性支持向量机**以及**非线性支持向量机**
### 线性可分支持向量机推导
> 《统计学习方法》 & [支持向量机SVM推导及求解过程](https://blog.csdn.net/american199062/article/details/51322852#commentBox) - CSDN博客
- 当训练数据**线性可分**时,通过**硬间隔最大化**,学习一个线性分类器,即线性可分支持向量机,又称**硬间隔支持向量机**。
- 线性 SVM 的推导分为两部分
1. 如何根据**间隔最大化**的目标导出 SVM 的**标准问题**;
1. 拉格朗日乘子法对偶问题的求解过程.
**符号定义**:
---
- 训练集 `T`
[](http://www.codecogs.com/eqnedit.php?latex=T=\left&space;\{&space;(x_1,y_1),(x_2,y_2),\cdots,(x_N,y_N)&space;\right&space;\})
- **分离超平面** `(w,b)`
[](http://www.codecogs.com/eqnedit.php?latex=w^*\cdot&space;x+b^*=0)
如果使用映射函数,那么分离超平面为
[](http://www.codecogs.com/eqnedit.php?latex=w^*\cdot&space;\Phi&space;(x)+b^*=0)
> 映射函数 `Φ(x)` 定义了从输入空间到特征空间的变换,特征空间通常是更高维的,甚至无穷维;方便起见,这里假设 `Φ(x)` 做的是恒等变换。
- 分类决策函数 `f(x)`
[](http://www.codecogs.com/eqnedit.php?latex=f(x)=\mathrm{sign}(w^*\cdot&space;x+b^*))
**SVM 标准问题的推导**(2)
---
1. **从“函数间隔”到“几何间隔”**
给定训练集`T`和超平面`(w,b)`,定义**函数间隔`γ^`**:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\hat{\gamma}&=\underset{i=1,\cdots,N}{\min}\,y_i(wx_i+b)&space;\\&space;&=\underset{i=1,\cdots,N}{\min}\,\hat{\gamma}_i\end{aligned})
对 `w` 作规范化,使函数间隔成为**几何间隔`γ`**
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\gamma&=\underset{i=1,\cdots,N}{\min}\,y_i(\frac{w}{{\color{Red}&space;\left&space;\|&space;w&space;\right&space;\|}}x_i+\frac{b}{{\color{Red}&space;\left&space;\|&space;w&space;\right&space;\|}})\\&space;&=\underset{i=1,\cdots,N}{\min}\,\frac{\gamma_i}{{\color{Red}&space;\left&space;\|&space;w&space;\right&space;\|}}&space;\end{aligned})
1. **最大化几何间隔**
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&{\color{Red}&space;\underset{w,b}{\max}}&space;\quad\gamma&space;\\&space;&\&space;\mathrm{s.t.}\quad\,&space;y_i(\frac{w}{{\color{Red}&space;\left&space;\|&space;w&space;\right&space;\|}}x_i+\frac{b}{{\color{Red}&space;\left&space;\|&space;w&space;\right&space;\|}})&space;\geq&space;\gamma,\quad&space;i=1,2,\cdots,N&space;\end{aligned})
由函数间隔与几何间隔的关系,等价于
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&\underset{w,b}{\max}&space;\quad{\color{Red}&space;\frac{\hat{\gamma}}{\left&space;|&space;w&space;\right&space;|}}&space;\&space;&&space;\mathrm{s.t.}\quad,&space;y_i(wx_i+b)&space;\geq&space;{\color{Red}&space;\hat{\gamma}},\quad&space;i=1,2,\cdots,N&space;\end{aligned})
函数间隔`γ^`的取值不会影响最终的超平面`(w,b)`:取`γ^=1`;又最大化 `1/||w||` 等价于最小化`1/2*||w||^2`,于是有
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&{\color{Red}&space;\underset{w,b}{\max}&space;}&space;\quad\frac{\hat{\gamma}}{{\color{Red}&space;\left&space;\|&space;w&space;\right&space;\|}}&space;\\&space;&\&space;\mathrm{s.t.}\quad\,&space;y_i(wx_i+b)&space;\geq&space;\hat{\gamma}_i,\quad&space;i=1,2,\cdots,N&space;\end{aligned})
> 为什么令`γ^=1`?——比例改变`(ω,b)`,超平面不会改变,但函数间隔`γ^`会成比例改变,因此可以通过等比例改变`(ω,b)`使函数间隔`γ^=1`
- 该约束最优化问题即为**线性支持向量机**的标准问题——这是一个**凸二次优化**问题,可以使用商业 QP 代码完成。
理论上,线性 SVM 的问题已经解决了;但在高等数学中,**带约束的最优化问题**还可以用另一种方法求解——**拉格朗日乘子法**。该方法的优点一是更容易求解,而是自然引入**核函数**,进而推广到非线性的情况。
**SVM 对偶算法的推导**(5)
---
1. 构建**拉格朗日函数**
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;L(w,b,{\color{Red}&space;\alpha})=&\frac{1}{2}w^Tw-\sum_{i=1}^N{\color{Red}&space;\alpha_i}[y_i(w^Tx_i+b)-1]\\&space;&{\color{Red}&space;\alpha_i&space;\geq&space;0},\quad&space;i=1,2,\cdots,N&space;\end{aligned})
1. 标准问题是求极小极大问题:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;{\color{Red}&space;\underset{w,b}{\min}}\&space;{\color{Blue}&space;\underset{\alpha}{\max}}\&space;L(w,b,\alpha)&space;\end{aligned})
其对偶问题为:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;{\color{Blue}&space;\underset{\alpha}{\max}}\&space;{\color{Red}&space;\underset{w,b}{\min}}\&space;L(w,b,\alpha)&space;\end{aligned})
1. 求 `L` 对 `(w,b)` 的极小
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\mathrm{set}\quad&space;\frac{\partial&space;L}{\partial&space;w}=0&space;\;\;&\Rightarrow\;&space;w-\sum_{i=1}^N&space;{\color{Red}&space;\alpha_i&space;y_i&space;x_i}=0\\&space;&\Rightarrow\;&space;w=\sum_{i=1}^N&space;{\color{Red}&space;\alpha_i&space;y_i&space;x_i}&space;\end{aligned})
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\mathrm{set}\quad&space;\frac{\partial&space;L}{\partial&space;b}=0&space;\;\;&\Rightarrow\;&space;\sum_{i=1}^N&space;{\color{Red}&space;\alpha_i&space;y_i}=0&space;\end{aligned})
结果代入`L`,有:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;L(w,b,{\color{Red}&space;\alpha})&space;&=\frac{1}{2}w^Tw-\sum_{i=1}^N{\color{Red}&space;\alpha_i}[y_i(w^Tx_i+b)-1]\\&space;&=\frac{1}{2}w^Tw-w^T\sum_{i=1}^N&space;\alpha_iy_ix_i-b\sum_{i=1}^N&space;\alpha_iy_i+\sum_{i=1}^N&space;\alpha_i\\&space;&=\frac{1}{2}w^Tw-w^Tw+\sum_{i=1}^N&space;\alpha_i\\&space;&=-\frac{1}{2}w^Tw+\sum_{i=1}^N&space;\alpha_i\\&space;&=-\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N&space;\alpha_i\alpha_j\cdot&space;y_iy_j\cdot&space;{\color{Red}&space;x_i^Tx_j}+\sum_{i=1}^N&space;\alpha_i&space;\end{aligned})
即
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;L(w,b,{\color{Red}&space;\alpha})&space;&=\frac{1}{2}w^Tw-\sum_{i=1}^N{\color{Red}&space;\alpha_i}[y_i(w^Tx_i+b)-1]\\&space;&=\frac{1}{2}w^Tw-w^T\sum_{i=1}^N&space;\alpha_iy_ix_i-b\sum_{i=1}^N&space;\alpha_iy_i+\sum_{i=1}^N&space;\alpha_i\\&space;&=\frac{1}{2}w^Tw-w^Tw+\sum_{i=1}^N&space;\alpha_i\\&space;&=-\frac{1}{2}w^Tw+\sum_{i=1}^N&space;\alpha_i\\&space;&=-\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N&space;\alpha_i\alpha_j\cdot&space;y_iy_j\cdot&space;{\color{Red}&space;x_i^Tx_j}+\sum_{i=1}^N&space;\alpha_i&space;\end{aligned})
1. 求 `L` 对 `α` 的极大,即
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&\underset{\alpha}{\max}&space;\quad&space;-\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N&space;\alpha_i\alpha_j\cdot&space;y_iy_j\cdot&space;x_i^Tx_j+\sum_{i=1}^N&space;\alpha_i\\&space;&\&space;\mathrm{s.t.}\quad\;&space;\sum_{i=1}^N&space;\alpha_i&space;y_i=0,\&space;\&space;{\color{Red}&space;\alpha_i&space;\geq&space;0},\quad&space;i=1,2,\cdots,N&space;\end{aligned})
该问题的对偶问题为:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&{\color{Red}&space;\underset{\alpha}{\min}&space;}&space;\quad\&space;\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N&space;\alpha_i\alpha_j\cdot&space;y_iy_j\cdot&space;x_i^Tx_j-\sum_{i=1}^N&space;\alpha_i\\&space;&\&space;\mathrm{s.t.}\quad\;&space;\sum_{i=1}^N&space;\alpha_i&space;y_i=0,\&space;\&space;{\color{Red}&space;\alpha_i&space;\geq&space;0},\quad&space;i=1,2,\cdots,N&space;\end{aligned})
于是,标准问题最后等价于求解该**对偶问题**
> 继续求解该优化问题,有 [SMO 方法](https://blog.csdn.net/ajianyingxiaoqinghan/article/details/73087304#t11);因为《统计学习方法》也只讨论到这里,故推导也止于此
1. 设 `α` 的解为 `α*`,则存在下标`j`使`α_j > 0`,可得标准问题的解为:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;w^*&=\sum_{i=1}^N&space;\alpha_i^*y_ix_i\\&space;b^*&={\color{Red}&space;y_j}-\sum_{i=1}^N&space;\alpha_i^*y_i(x_i^T{\color{Red}&space;x_j})&space;\end{aligned})
可得分离超平面及分类决策函数为:
[](http://www.codecogs.com/eqnedit.php?latex=w^*\cdot&space;x+b^*=0)
[](http://www.codecogs.com/eqnedit.php?latex=f(x)=\mathrm{sign}(w^*\cdot&space;x+b^*))
# 决策树
- 决策树的训练通常由三部分组成:**特征选择**、**树的生成**、**剪枝**。
## 信息增益与信息增益比 TODO
## 分类树 - ID3 决策树与 C4.5 决策树 TODO
- ID3 决策树和 C4.5 决策树的**区别**在于:前者使用**信息增益**来进行特征选择,而后者使用**信息增益比**。
## 决策树如何避免过拟合 TODO
## 回归树 - CART 决策树
> 《统计学习方法》 5.5 CART 算法
- CART 算法是在给定输入随机变量 _`X`_ 条件下输出随机变量 _`Y`_ 的**条件概率分布**的学习方法。
- CART 算法假设决策树是**二叉树**,内部节点特征的取值为“**是**”和“**否**”。
这样的决策树等价于递归地二分每个特征,**将输入空间/特征空间划分为有限个单元**,然后在这些单元上确定在输入给定的条件下输出的**条件概率分布**。
- CART 决策树**既可以用于分类,也可以用于回归**;
对回归树 CART 算法用**平方误差最小化**准则来选择特征,对分类树用**基尼指数最小化**准则选择特征
### CART 回归树算法推导
- 一个回归树对应着输入空间/**特征空间**的一个**划分**以及在划分单元上的**输出值**;
- 假设已将输入空间划分为 `M` 个单元:`{R_1,..,R_m,..,R_M}`,并在每个单元上对应有输出值 `c_m`,则该回归树可表示为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_M(x)=\sum_{i=1}^M\sum_{j=1}^Jc_{m,j}{\color{Blue}&space;I(x\in&space;R_{m,j})}"><img src="../_assets/公式_20180717212747.png" /></a></div>
> `I(x)` 为指示函数
- **如果已经划分好了输入空间**,通常使用**平方误差**作为损失函数来表示回归树对于训练数据的预测误差,通过最小化损失函数来求解每个划分单元的**最优输出值**。
- 如果使用**平方误差**,易知**最优输出值**即每个划分单元上所有实例的均值
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\hat{c}_m={\color{Red}&space;\mathrm{avg}}(y_i|x_i\in&space;R_m)"><img src="../_assets/公式_20180717214302.png" /></a></div>
> 选用**平方误差**作为损失的原因
<h3>如何划分输入空间</h3>
- 一个启发式方法是:**以特征向量中的某一个特征为标准进行切分**。
假设选择**特征向量中第 `j` 个变量**作为**切分变量**,然后选择**某个实例中第 `j` 个值 `s`** 作为**切分点**,则定义如下两个划分单元
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\hat{c}_m={\color{Red}&space;\mathrm{avg}}(y_i|x_i\in&space;R_m)"><img src="../_assets/公式_20180717223137.png" /></a></div>
> 原书中这里表述不够清楚,需要结合 8.4.2 节中的示例一起看。
- 遍历**每个实例**的第`j`个值`s`,选择满足以下条件的作为**最优切分变量`j`和切分点`s`**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\hat{c}_m={\color{Red}&space;\mathrm{avg}}(y_i|x_i\in&space;R_m)"><img src="../_assets/公式_2018071891909.png" /></a></div>
其中输出值 `c1` 和 `c2` 分别为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\hat{c}_1={\color{Red}&space;\mathrm{avg}}(y_i|x_i\in&space;R_1(j,s)),\quad\&space;\hat{c}_2={\color{Red}&space;\mathrm{avg}}(y_i|x_i\in&space;R_2(j,s))"><img src="../_assets/公式_2018071893503.png" /></a></div>
> 示例: [选择切分变量与切分点](#示例-选择切分变量与切分点)
- 接着,继续对两个子空间重复以上步骤,直到满足条件为止;得到将输入空间划分为`M`个区域的决策树
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f(x)=\sum_{m=1}^M&space;\hat{c}_m{\color{Red}&space;I(x\in&space;R_m)}"><img src="../_assets/公式_2018071895945.png" /></a></div>
### 示例: 选择切分变量与切分点
> 《统计学习方法》 8.4.2
- 训练集
x_i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
-----|---|---|---|---|---|---|---|---|---|---
y_i |5.56|5.70|5.91|6.40|6.80|7.05|8.90|8.70|9.00|9.05
- 这里只有一个特征,即`j=1`;然后遍历每个实例的值作为**切分点**
`s = {1, 2, 3, 4, 5, 6, 7, 8, 9}`
> 原书使用的切分点为 `{1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5}`,即相邻两个点的均值;因为切分点并没有参与运算,所以我觉得两者没有区别;
>
> 最后一个点无法将数据划分为两个空间,所以不需要
- 以 `s=1` 为例
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&R_1(1,1)=\{x|x\le&space;1\}=\{1\}\\&space;&R_2(1,1)=\{x|x>1\}=\{2,3,4,5,6,7,8,9,10\}\\&space;&\&space;c_1=\frac{1}{|R_1|}=\frac{1}{1}\sum_{x_i\in&space;R_1}y_i=5.56\\&space;&\&space;c_2=\frac{1}{|R_2|}=\frac{1}{9}\sum_{x_i\in&space;R_2}y_i=7.50\\&space;&\&space;m(s)=\underset{c_1}{\min}\sum_{x_i\in&space;R_1}(y_i-c_1)^2+\underset{c_2}{\min}\sum_{x_i\in&space;R_2}(y_i-c_2)^2=0+15.72=15.72&space;\end{aligned}"><img src="../_assets/公式_20180718103749.png" /></a></div>
所有 `m(s)` 的计算结果如下
s | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
----|---|---|---|---|---|---|---|---|---
m(s)|15.72|12.07|8.36|5.78|3.91|1.93|8.01|11.73|15.74
- 当 `s=6` 时 `m(s)` 达到最小值,此时
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&R_1(1,6)=\{x|x\le&space;6\}=\{1,2,3,4,5,6\}\\&space;&R_2(1,6)=\{x|x>6\}=\{7,8,9,10\}\\&space;&\&space;c_1=\frac{1}{|R_1|}=\frac{1}{6}\sum_{x_i\in&space;R_1}y_i=6.24\\&space;&\&space;c_2=\frac{1}{|R_2|}=\frac{1}{4}\sum_{x_i\in&space;R_2}y_i=8.91\\&space;\end{aligned}"><img src="../_assets/公式_20180718104559.png" /></a></div>
- 所以第一棵决策树为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;T_1(x)&=\left\{\begin{matrix}&space;6.24,&space;&x<6&space;\\&space;8.91,&space;&x\ge6&space;\end{matrix}\right.\\&space;f_1(x)&=T_1(x)&space;\end{aligned}"><img src="../_assets/公式_20180718105727.png" /></a></div>
# 集成学习
- 基本思想:由多个学习器组合成一个性能更好的学习器
- **集成学习为什么有效?**——不同的模型通常会在测试集上产生不同的误差。平均上,集成模型能至少与其任一成员表现一致;并且**如果成员的误差是独立的**,集成模型将显著地比其成员表现更好。
> 《深度学习》 7.11 Bagging 和其他集成方法
## 集成学习的基本策略(3)
### 1. Boosting
- **Boosting**(提升)方法从某个**基学习器**出发,反复学习,得到一系列基学习器,然后组合它们构成一个强学习器。
- Boosting 基于**串行策略**:基学习器之间存在依赖关系,新的学习器需要依据旧的学习器生成。
- **代表算法/模型**:
- [提升方法 AdaBoost](#提升方法-adaboost)
- 提升树
- 梯度提升树 GBDT
#### Boosting 策略要解决的两个基本问题
1. 每一轮如何改变数据的权值或概率分布?
1. 如何将弱分类器组合成一个强分类器?
### 2. Bagging
- Bagging 基于**并行策略**:基学习器之间不存在依赖关系,可同时生成。
- **代表算法/模型**:
- [随机森林](#随机森林)
- 神经网络的 **Dropout** 策略
### 3. Stacking
- 介绍不多,有时间再整理
## AdaBoost 算法
- AdaBoost 是 Boosting 策略的一种具体算法
**AdaBoost 算法解决 [Boosting 两个基本问题](#boosting-策略要解决的两个基本问题)的方法**
1. 每一轮如何改变数据的权值或概率分布?——开始时,每个样本的权值是一样的,AdaBoost 的做法是提高上一轮弱分类器错误分类样本的权值,同时降低那些被正确分类样本的权值。
1. 如何将弱分类器组合成一个强分类器?—— AdaBoost 采取加权表决的方法([加法模型](#加法模型))。具体的,AdaBoost 会加大分类误差率小的基学习器的权值,使其在表决中起到更大的作用,同时减小分类误差率大的基学习器的权值。
### AdaBoost 算法描述
- 输入:训练集 `T={(x1,y1),..,(xN,yN)}, xi ∈ R^n, yi ∈ {-1,+1}`,基学习器 `G1(x)`
- 输出:最终学习器 `G(x)`
1. 初始化训练数据的全职分布
[](http://www.codecogs.com/eqnedit.php?latex=D_1=(w_{1,1},\cdots,w_{1,i},\cdots,w_{1,N}),\quad&space;w_{1,i}=\frac{1}{N},\quad&space;i=1,2,\cdots,N)
1. 对 `m=1,2,..,M`
1. 使用权值分布为`D_m`的训练集,得到基分类器:
[](http://www.codecogs.com/eqnedit.php?latex=G_m(x):\chi&space;\rightarrow&space;\{-1,+1\})
1. 计算 `G_m(x)` 在训练集上的分类误差率
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;e_m&=P(G_m(x_i)\neq&space;y_i)\\&=\sum_{i=1}^Nw_{m,i}\cdot&space;{\color{Red}&space;I(G_m(x_i)\neq&space;y_i)}&space;\end{aligned})
> `I(x)` 为指示函数:若`G(x)!=y`为真,则`I(G(x)!=y)=1`,反之为 `0`
>
> 实际上分类误差率就等于所有**分类错误的数据的权值之和**
1. 计算 `G_m(x)` 的系数
[](http://www.codecogs.com/eqnedit.php?latex=\alpha_m=\frac{1}{2}\ln\frac{1-e_m}{e_m})
1. 更新训练集的权值分布
<!-- [](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;D_{{\color{Red}m+1}}&=(w_{m+1,1},\cdots,w_{m+1,i},\cdots,w_{m+1,N})\\&space;w_{{\color{Red}m+1},i}&=\frac{w_{{\color{Red}m},i}\cdot\exp(-\alpha_{\color{Red}m}\cdot{\color{Blue}y_iG_m(x_i)&space;})}{\sum_{i=1}^Nw_{{\color{Red}m},i}\cdot\exp(-\alpha_{\color{Red}m}\cdot{\color{Blue}y_iG_m(x_i)&space;})}&space;\end{aligned}) -->
<!-- [](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;D_{{\color{Red}m+1}}&=(w_{m+1,1},\cdots,w_{m+1,i},\cdots,w_{m+1,N})\\&space;w_{{\color{Red}m+1},i}&=\frac{w_{{\color{Red}m},i}\cdot\exp(-\alpha_{\color{Red}m}\cdot{\color{Blue}y_iG_m(x_i)&space;})}{Z_{\color{Red}m}}&space;\end{aligned}) -->
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;D_{{\color{Red}m+1}}&=(w_{m+1,1},\cdots,w_{m+1,i},\cdots,w_{m+1,N})\\&space;w_{{\color{Red}m+1},i}&=\frac{w_{{\color{Red}m},i}\cdot\exp(-\alpha_{\color{Red}m}\cdot{\color{Blue}y_iG_m(x_i)&space;})}{Z_{\color{Red}m}}&space;\end{aligned})
其中 `Z_m` 为**规范化因子**,使 `D_m+1` 成为一个**概率分布**,类似 `Softmax` 函数
<!-- [](http://www.codecogs.com/eqnedit.php?latex=Z_{\color{Red}m}=\sum_{i=1}^Nw_{{\color{Red}m},i}\cdot\exp(-\alpha_{\color{Red}m}\cdot{\color{Blue}y_iG_m(x_i)&space;})) -->
因为 `y, G(x) ∈ {-1, 1}`,所以实际上
[](http://www.codecogs.com/eqnedit.php?latex={\color{Blue}y_iG_m(x_i)&space;}=\left\{\begin{matrix}&space;1,&&space;G_m(x_i)=y_i&space;\\&space;-1,&&space;G_m(x_i)\neq&space;y_i&space;\end{matrix}\right.)
因此 `w_{m+1,i}` 也可以写作
[](http://www.codecogs.com/eqnedit.php?latex=\dpi{120}&space;w_{m+1,i}=\left\{\begin{matrix}&space;\frac{w_{m,i}}{Z_m}e^{\color{Red}&space;{-\alpha_m}},&space;&&space;G_m(x_i)=y_i&space;\\&space;\frac{w_{m,i}}{Z_m}e^{\color{Red}&space;{\alpha_m}},&&space;G_m(x_i)\neq&space;y_i&space;\end{matrix}\right.)
1. 构建基学习器的**线性组合**
[](http://www.codecogs.com/eqnedit.php?latex=G(x)=\mathrm{sign}(\sum_{m=1}^M\alpha_mG_m(x)))
### AdaBoost 算法要点说明
- 开始时,训练集中所有数据具有均匀的权值分布
- 计算分类误差率,实际上就是计算所有分类错误的数据的权值之和
- `G_m(x)` 的系数 `α_m` 表示该学习器在最终学习器中的重要性;公式
[](http://www.codecogs.com/eqnedit.php?latex=\alpha_m=\frac{1}{2}\ln\frac{1-e_m}{e_m}) 表明当分类错误率 `e_m <= 1/2` 时,`α_m >= 0`,并且 `α_m` 随 `e_m` 的减小而增大
- 被基分类器分类错误的样本权值会扩大,而分类正确的权值会缩小——**不改变训练数据,而不断改变训练数据权值的分布,使训练数据在基学习器的学习中起到不同的作用**,这是 AdaBoost 的一个特点。
## 前向分步算法
### 加法模型
- 定义加法模型:
[](http://www.codecogs.com/eqnedit.php?latex=f(x)=\sum_{m=1}^M\beta_m\,b(x;\gamma_m))
其中`b(x;γ)`为基函数,`γ`为基函数的参数;`β`为基函数的系数
- 在给定训练数据和损失函数`L(y,f(x))`的情况下,学习加法模型相当于损失函数的最小化问题
[](http://www.codecogs.com/eqnedit.php?latex={\color{Red}&space;\underset{\beta_m,\gamma_m}{\min}}\sum_{i=1}^N&space;L\left&space;(&space;y_i,{\color{Blue}&space;\sum_{m=1}^M\beta_m\,b(x;\gamma_m)}&space;\right&space;))
### 前向分步算法描述
前向分步算法求解加法模型的想法是:如果能够从前向后,每一步只学习一个基函数及其系数,逐步优化目标函数
- 输入:训练集 `T={(x1,y1),..,(xN,yN)}`,损失函数 `L(y,f(x))`,基函数集 `{b(x;γ)}`
- 输出:加法模型 `f(x)`
1. 初始化 `f_0(x)=0`
1. 对 `m=1,2,..,M`
1. 极小化损失函数,得到 `(β_m,γ_m)`
[](http://www.codecogs.com/eqnedit.php?latex=(\beta_m,\gamma_m)=\arg\underset{\beta,\gamma}{\min}\sum_{i=1}^NL\left&space;(&space;y_i,{\color{Red}&space;f_{m-1}(x_i)+\beta&space;b(x_i;\gamma)}&space;\right&space;))
1. 更新模型 `f_m(x)`
[](http://www.codecogs.com/eqnedit.php?latex=f_m(x)={\color{Red}&space;f_{m-1}(x)+\beta&space;b(x;\gamma)})
1. 得到加法模型
[](http://www.codecogs.com/eqnedit.php?latex=f(x)=f_M(x)={\color{Red}&space;\sum_{m=1}^M}{\color{Blue}&space;\beta_m}b(x;\gamma_m))
- 前向分步算法将**同时**求解`m=1,2,..,M`所有参数`(β_m,γ_m)`的问题**简化**为**逐次**求解各`(β_m,γ_m)`的优化问题——思想上有点像**梯度下降**
### 前向分步算法与 AdaBoost
- AdaBoost 算法是前向分步算法的特例。
- 此时,基函数为基分类器,损失函数为指数函数`L(y,f(x)) = exp(-y*f(x))`
# 梯度提升决策树 GBDT
- GBDT 是以**决策树**为基学习器、采用 Boosting 策略的一种集成学习模型
- **与提升树的区别**:残差的计算不同,提升树使用的是真正的残差,梯度提升树用当前模型的负梯度来拟合残差。
## 提升树 Boosting Tree
- 以**决策树**为基学习器,对分类问题使用二叉分类树,回归问题使用二叉回归树。
- 解决回归问题时,通过不断拟合残差得到新的树。
- 提升树模型可表示为**决策树的加法模型**:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_M(x)=\sum_{m=1}^MT(x;\Theta_m)"><img src="../_assets/公式_20180717101425.png" /></a></div>
- 首先初始化提升树 `f_0(x)=0`,则第 m 步的模型为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_m(x)=f_{m-1}(x)+T(x;\Theta_m)" target="_blank"><img src="../_assets/公式_20180717110557.png" /></a></div>
- 然后通过最小化损失函数决定下一个决策树的参数
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\hat{\Theta}_m=\arg\underset{\Theta_m}{\min}\sum_{i=1}^NL(y_i,{\color{Red}&space;f_{m-1}(x_i)+T(x_i;\Theta_m)})"><img src="../_assets/公式_20180717112341.png" /></a></div>
- 对于二分类问题,提升树算法只需要将[AdaBoost 算法](#adaboost-算法描述)中的基学习器限制为二叉分类树即可
### 提升树算法描述
在回归问题中,新的树是通过不断拟合**残差**(residual)得到的。
- 输入:训练集 `T={(x1,y1),..,(xN,yN)}, xi ∈ R^n, yi ∈ R`
- 输出:回归提升树 `f_M(x)`
1. 初始化 `f_0(x)=0`
1. 对 `m=1,2,..,M`
1. 计算**残差**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex={\color{Red}&space;r_{m,i}}=y_i-f_{m-1}(x_i),\quad&space;i=1,2,..,N"><img src="../_assets/公式_20180717114628.png" /></a></div>
1. **拟合残差**学习下一个回归树的参数
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\hat{\Theta}_m=\arg\underset{\Theta_m}{\min}\sum_{i=1}^N&space;L({\color{Red}&space;r_{m,i}},{\color{Blue}&space;T(x_i;\Theta_m)})"><img src="../_assets/公式_20180717115402.png" /></a></div>
> [回归树算法推导](#回归树算法推导) TODO
1. 更新 `f_m(x)`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_m(x)=f_{m-1}(x)+T(x;\Theta_m)"><img src="../_assets/公式_20180717115616.png" /></a></div>
1. 得到回归提升树
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_M(x)=\sum_{m=1}^MT(x;\Theta_m)"><img src="../_assets/公式_20180717101425.png" /></a></div>
- 以平凡损失为例 TODO
## 梯度提升(GB)算法
- 当损失函数为平方损失或指数损失时,每一步的优化是很直观的;但对于一般的损失函数而言,不太容易——梯度提升正是针对这一问题提出的算法;
- 梯度提升是梯度下降的近似方法,其关键是利用损失函数的**负梯度作为残差的近似值**,来拟合下一个决策树。
## GBDT 算法描述
- 输入:训练集 `T={(x1,y1),..,(xN,yN)}, xi ∈ R^n, yi ∈ R`;损失函数 `L(y,f(x))`;
- 输出:回归树 `f_M(x)`
1. 初始化回归树
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_0(x)={\color{Red}&space;\arg\underset{c}{\min}}\sum_{i=1}^NL(y_i,c)"><img src="../_assets/公式_20180717144338.png" /></a></div>
1. 对 `m=1,2,..,M`
1. 对 `i=1,2,..,N`,计算残差/负梯度
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=r_{m,i}=-\frac{\partial&space;L(y_i,{\color{Red}&space;f_{m-1}(x_i)}))}{\partial&space;{\color{Red}&space;f_{m-1}(x_i)}}"><img src="../_assets/公式_20180717144904.png" /></a></div>
1. 对 `r_mi` 拟合一个回归树,得到第 `m` 棵树的叶节点区域
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=R_{m,j},\quad&space;j=1,2,..,J"><img src="../_assets/公式_20180717145223.png" /></a></div>
> [CART 回归树算法推导](#cart-回归树算法推导)
1. 对 `j=1,2,..,J`,计算
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=c_{m,j}={\color{Red}&space;\arg\underset{c}{\min}}\sum_{x_i\in&space;R_{m,j}}L(y_i,{\color{Blue}&space;f_{m-1}(x_i)+c})"><img src="../_assets/公式_20180717145448.png" /></a></div>
1. 更新回归树
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_m(x)=f_{m-1}+\sum_{j=1}^J&space;c_{m,j}{\color{Blue}&space;I(x\in&space;R_{m,j})}"><img src="../_assets/公式_20180717145625.png" /></a></div>
1. 得到回归树
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_M(x)=\sum_{i=1}^M\sum_{j=1}^Jc_{m,j}{\color{Blue}&space;I(x\in&space;R_{m,j})}"><img src="../_assets/公式_20180717145841.png" /></a></div>
- 说明:
- 算法第 1 步初始化,估计使损失函数最小的常数值,得到一棵只有一个根节点的树
- 第 2(i) 步计算损失函数的负梯度,将其作为残差的估计
- 对平方损失而言,负梯度就是残差;对于一般的损失函数,它是残差的近似
- 第 2(ii) 步估计回归树的节点区域,以拟合残差的近似值
- 第 2(iii) 步利用线性搜索估计叶节点区域的值,使损失函数最小化
## XGBoost 算法
> [一步一步理解GB、GBDT、xgboost](https://www.cnblogs.com/wxquare/p/5541414.html) - wxquare - 博客园
- XGBoost 是改进的[梯度提升(GB)算法](#梯度提升GB算法);
- [XGBoost 库](https://github.com/dmlc/xgboost)是 XGBoost 算法的高效实现
### XGBoost 与 GB 的主要区别
> [Introduction to Boosted Trees](http://xgboost.readthedocs.io/en/latest/model.html) — xgboost 0.72 documentation
- 首先,定义一棵树 `f(x)` 为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=f_t(x)&space;=&space;w_{q(x)},&space;w&space;\in&space;R^T,\quad&space;q:R^d\rightarrow&space;\{1,2,\cdots,T\}&space;."><img src="../_assets/公式_201807191434562.png" /></a></div>
> Here `w` is the vector of scores on leaves, `q` is a function assigning each data point to the corresponding leaf, and `T` is the number of leaves.
- 对损失函数加入**正则项**,包括 L2 权重衰减和对叶子数的限制
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;&L(\theta)&space;=&space;\sum_{i=1}^n&space;l(y_i,&space;\hat{y}_i^{(t)})&space;+&space;\sum_{i=1}^t\Omega(f_i)&space;\\&space;\text{where}\quad&space;&\Omega(f)&space;=&space;\gamma&space;T&space;+&space;\frac{1}{2}\lambda&space;\sum_{j=1}^T&space;w_j^2&space;\end{aligned}"><img src="../_assets/公式_20180719142639.png" /></a></div>
- 使用**牛顿法**代替**梯度下降法**寻找最优解
前者使用一阶+二阶导数作为残差,后者只使用了一阶导数
- 传统 CART树寻找最优切分点的标准是**最小化均方差**;
XGBoost 通过最大化**得分公式**来寻找最优切分点:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=Gain&space;=&space;\frac{1}{2}&space;\left[\frac{G_L^2}{H_L+\lambda}+\frac{G_R^2}{H_R+\lambda}-\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}\right]&space;-&space;\gamma"><img src="../_assets/公式_20180719144515.png" /></a></div>
> This formula can be decomposed as 1). the score on the new left leaf 2). the score on the new right leaf 3). The score on the original leaf 4). regularization on the additional leaf.
这同时也起到了“**剪枝**”的作用——如果分数小于`γ`,则不会增加分支;
### XGBoost 的一些内部优化
- 在寻找最佳分割点时,传统的方法会枚举每个特征的所有可能切分点。XGBoost 实现了一种近似的算法,大致的思想是根据百分位法列举几个可能成为分割点的候选者,然后从候选者中根据上面求分割点的公式计算找出最佳的分割点。
- XGBoost 考虑了训练数据为稀疏值的情况,可以为缺失值或者指定的值指定分支的默认方向,这能大大提升算法的效率,paper 提到能提高 50 倍。
- **特征列**排序后以块的形式存储在内存中,在迭代中可以重复使用;虽然 Boosting 算法迭代必须串行,但是在处理每个特征列时可以做到并行。
- 按照**特征列**方式存储能优化寻找最佳的分割点,但是当**以行计算梯度数据**时会导致内存的不连续访问,严重时会导致 **cache miss**,降低算法效率。Paper 中提到,可先将数据收集到线程内部的 buffer,然后再计算,提高算法的效率。
- XGBoost 还考虑了数据量比较大的情况,当内存不够时怎么有效的使用磁盘,主要是结合多线程、数据压缩、分片的方法,尽可能的提高算法的效率。
# 随机森林
TODO
# 机器学习实践
## Box–Muller 变换
> [Box-Muller变换原理详解](http://shishuai.org/index.php/2018/06/28/1-2/) – 史帅个人网站
- Box–Muller 变换是一个从**均匀分布**中得到**正态分布**采样的算法
- Box–Muller 变换定理:
假设随机变量`U1`和`U2`是 IID(独立同分布) 的,且 `U1,U2 ∽ U(0,1)`,令`Z1,Z2`满足
<div align="center"><img src="../_assets/公式_20180723153506.png" /></div>
<!-- \begin{aligned}Z_0&=\cos(2\pi U_1)\sqrt{-2\ln U_2}\\Z_1&=\sin(2\pi U_1)\sqrt{-2\ln U_2}\end{aligned} -->
则 `Z1,Z2 ∽ N(0, 1)`,即 `Z1,Z2` 服从标准正态分布。
# 降维
TODO
## SVD
## PCA
-
## t-SNE
- 在高维中接近,在低维中也接近
- 目标函数:KL 散度(非对称)
## Reference
- [Visualizing MNIST: An Exploration of Dimensionality Reduction](http://colah.github.io/posts/2014-10-Visualizing-MNIST/) - colah's blog
================================================
FILE: A-机器学习/C-专题-集成学习.md
================================================
ML-专题-集成学习
===
Index
---
<!-- TOC -->
- [集成学习基本问题](#集成学习基本问题)
- [集成学习的基本思想](#集成学习的基本思想)
- [集成学习为什么有效?](#集成学习为什么有效)
- [集成学习的基本策略](#集成学习的基本策略)
- [Boosting 方法](#boosting-方法)
- [Bagging 方法(Booststrap AGGregatING)](#bagging-方法booststrap-aggregating)
- [Stacking 方法](#stacking-方法)
- [为什么使用决策树作为基学习器?](#为什么使用决策树作为基学习器)
- [为什么不稳定的学习器更适合作为基学习器?](#为什么不稳定的学习器更适合作为基学习器)
- [还有哪些模型也适合作为基学习器?](#还有哪些模型也适合作为基学习器)
- [Bagging 方法中能使用线性分类器作为基学习器吗? Boosting 呢?](#bagging-方法中能使用线性分类器作为基学习器吗-boosting-呢)
- [Boosting/Bagging 与 偏差/方差 的关系](#boostingbagging-与-偏差方差-的关系)
- [AdaBoost 算法](#adaboost-算法)
- [GBDT 算法](#gbdt-算法)
<!-- /TOC -->
## 集成学习基本问题
- 集成学习的核心是将多个
### 集成学习的基本思想
- 结合多个学习器组合成一个性能更好的学习器
### 集成学习为什么有效?
- 不同的模型通常会在**测试集**上产生不同的误差;如果成员的误差是独立的,集成模型将显著地比其成员表现更好。
### 集成学习的基本策略
#### Boosting 方法
- 基于**串行策略**:基学习器之间存在依赖关系,新的学习器需要根据上一个学习器生成。
- **基本思路**:
- 先从**初始训练集**训练一个基学习器;初始训练集中各样本的权重是相同的;
- 根据上一个基学习器的表现,**调整样本权重**,使分类错误的样本得到更多的关注;
- 基于调整后的样本分布,训练下一个基学习器;
- 测试时,对各基学习器**加权**得到最终结果
- **特点**:
- 每次学习都会使用全部训练样本
- **代表算法**:
- [AdaBoost 算法](#adaboost-算法)
- [GBDT 算法](#gbdt-算法)
#### Bagging 方法(Booststrap AGGregatING)
- 基于**并行策略**:基学习器之间不存在依赖关系,可同时生成。
- **基本思路**:
- 利用**自助采样法**对训练集随机采样,重复进行 `T` 次;
- 基于每个采样集训练一个基学习器,并得到 `T` 个基学习器;
- 预测时,集体**投票决策****。
> **自助采样法**:对 m 个样本的训练集,有放回的采样 m 次;此时,样本在 m 次采样中始终没被采样的概率约为 `0.368`,即每次自助采样只能采样到全部样本的 `63%` 左右。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\lim_{m\to\infty}\left&space;(&space;1-\frac{1}{m}&space;\right&space;)^m\rightarrow&space;\frac{1}{e}\approx&space;0.368"><img src="../_assets/公式_20180902220459.png" height="" /></a></div>
- **特点**:
- 训练每个基学习器时只使用一部分样本;
- 偏好**不稳定**的学习器作为基学习器;
> 所谓不稳定的学习器,指的是对**样本分布**较为敏感的学习器。
#### Stacking 方法
- 基于**串行策略**:初级学习器与次级学习器之间存在依赖关系,初学习器的输出作为次级学习器的输入。
- **基本思路**:
- 先从初始训练集训练 `T` 个**不同的初级学习器**;
- 利用每个初级学习器的**输出**构建一个**次级数据集**,该数据集依然使用初始数据集的标签;
- 根据新的数据集训练**次级学习器**;
- **多级学习器**的构建过程类似。
> 周志华-《机器学习》中没有将 Stacking 方法当作一种集成策略,而是作为一种**结合策略**,比如**加权平均**和**投票**都属于结合策略。
- 为了降低过拟合的风险,一般会利用**交叉验证**的方法使不同的初级学习器在**不完全相同的子集**上训练
```tex
以 k-折交叉验证为例:
- 初始训练集 D={(x_i, y_i)} 被划分成 D1, D2, .., Dk;
- 记 h_t 表示第 t 个学习器,并在除 Dj 外的数据上训练;
- 当 h_t 训练完毕后,有 z_it = h_t(x_i);
- T 个初级学习器在 x_i 上共产生 T 个输出;
- 这 T 个输出共同构成第 i 个次级训练数据 z_i = (z_i1, z_i2, ..., z_iT),标签依然为 y_i;
- 在 T 个初级学习器都训练完毕后,得到次级训练集 D'={(z_i, y_i)}
```
### 为什么使用决策树作为基学习器?
- **类似问题**
- 基学习器有什么特点?
- 基学习器有什么要求?
- 使用决策树作为基学习器的原因:
```tex
(1). 决策树的表达能力和泛化能力,可以通过剪枝快速调整;
(2). 决策树可以方便地将**样本的权重**整合到训练过程中;
(3). 决策树是一种**不稳定**的学习器;
所谓不稳定,指的是数据样本的扰动会对决策树的结果产生较大的影响;
```
- 后两点分别适合 Boosting 策略和 Bagging 策略;所以它们一般都使用决策树作为基学习器。
#### 为什么不稳定的学习器更适合作为基学习器?
- 不稳定的学习器容易受到**样本分布**的影响(方差大),很好的引入了**随机性**;这有助于在集成学习(特别是采用 **Bagging** 策略)中提升模型的**泛化能力**。
- 为了更好的引入随机性,有时会随机选择一个**属性子集**中的最优分裂属性,而不是全局最优(**随机森林**)
#### 还有哪些模型也适合作为基学习器?
- **神经网络**
- 神经网络也属于**不稳定**的学习器;
- 此外,通过调整神经元的数量、网络层数,连接方式初始权重也能很好的引入随机性和改变模型的表达能力和泛化能力。
#### Bagging 方法中能使用线性分类器作为基学习器吗? Boosting 呢?
- Bagging 方法中**不推荐**
- 线性分类器都属于稳定的学习器(方差小),对数据不敏感;
- 甚至可能因为 Bagging 的采样,导致在训练中难以收敛,增大集成分类器的**偏差**
- Boosting 方法中可以使用
- Boosting 方法主要通过降低**偏差**的方式来提升模型的性能,而线性分类器本身具有方差小的特点,所以两者有一定相性
- XGBoost 中就支持以线性分类器作为基学习器。
### Boosting/Bagging 与 偏差/方差 的关系
> ./机器学习基础/[偏差与方差](./ML-A-机器学习基础.md#偏差与方差)
- 简单来说,**Boosting** 能提升弱分类器性能的原因是降低了**偏差**;**Bagging** 则是降低了**方差**;
- **Boosting** 方法:
- Boosting 的**基本思路**就是在不断减小模型的**训练误差**(拟合残差或者加大错类的权重),加强模型的学习能力,从而减小偏差;
- 但 Boosting 不会显著降低方差,因为其训练过程中各基学习器是强相关的,缺少独立性。
- **Bagging** 方法:
- 对 `n` 个**独立不相关的模型**预测结果取平均,方差是原来的 `1/n`;
- 假设所有基分类器出错的概率是独立的,**超过半数**基分类器出错的概率会随着基分类器的数量增加而下降。
- 泛化误差、偏差、方差、过拟合、欠拟合、模型复杂度(模型容量)的关系图:
<div align="center"><img src="../_assets/TIM截图20180817214034.png" height="" /></div>
## AdaBoost 算法
## GBDT 算法
================================================
FILE: A-深度学习/A-深度学习基础.md
================================================
深度学习基础
===
相关专题
---
- [《深度学习》整理](./《深度学习》整理)
- [CNN 专题](./B-专题-CNN)
- [RNN 专题](./B-专题-RNN)
- [优化算法专题](./C-专题-优化算法)
- **随机梯度下降**
- **动量**算法
- **自适应学习率**算法
- 基于**二阶梯度**的优化算法
Index
---
<!-- TOC -->
- [过拟合与欠拟合](#过拟合与欠拟合)
- [降低过拟合风险的方法](#降低过拟合风险的方法)
- [降低欠拟合风险的方法](#降低欠拟合风险的方法)
- [反向传播算法](#反向传播算法)
- [反向传播的作用/目的/本质](#反向传播的作用目的本质)
- [反向传播的公式推导](#反向传播的公式推导)
- [激活函数](#激活函数)
- [激活函数的作用——为什么要使用非线性激活函数?](#激活函数的作用为什么要使用非线性激活函数)
- [常见的激活函数](#常见的激活函数)
- [整流线性单元 `ReLU`](#整流线性单元-relu)
- [`ReLU` 的拓展](#relu-的拓展)
- [`sigmoid` 与 `tanh`](#sigmoid-与-tanh)
- [其他激活函数](#其他激活函数)
- [`ReLU` 相比 `sigmoid` 的优势 (3)](#relu-相比-sigmoid-的优势-3)
- [正则化](#正则化)
- [Batch Normalization(批标准化)](#batch-normalization批标准化)
- [动机](#动机)
- [基本原理](#基本原理)
- [BN 在训练和测试时分别是怎么做的?](#bn-在训练和测试时分别是怎么做的)
- [为什么训练时不采用移动平均?](#为什么训练时不采用移动平均)
- [相关阅读](#相关阅读)
- [L1/L2 范数正则化](#l1l2-范数正则化)
- [L1/L2 范数的作用、异同](#l1l2-范数的作用异同)
- [为什么 L1 和 L2 正则化可以防止过拟合?](#为什么-l1-和-l2-正则化可以防止过拟合)
- [为什么 L1 正则化可以产生稀疏权值,而 L2 不会?](#为什么-l1-正则化可以产生稀疏权值而-l2-不会)
- [Dropout](#dropout)
- [Bagging 集成方法](#bagging-集成方法)
- [Dropout 策略](#dropout-策略)
- [Dropout 与 Bagging 的不同](#dropout-与-bagging-的不同)
- [深度学习实践](#深度学习实践)
- [参数初始化](#参数初始化)
<!-- /TOC -->
# 过拟合与欠拟合
> 《深度学习》 5.2 容量、过拟合和欠拟合
- **欠拟合**指模型不能在**训练集**上获得足够低的**训练误差**;
- **过拟合**指模型的**训练误差**与**测试误差**(泛化误差)之间差距过大;
- 反映在**评价指标**上,就是模型在训练集上表现良好,但是在测试集和新数据上表现一般(**泛化能力差**);
## 降低过拟合风险的方法
> 所有为了**减少测试误差**的策略统称为**正则化方法**,这些方法可能会以增大训练误差为代价。
- **数据增强**
- 图像:平移、旋转、缩放
- 利用**生成对抗网络**(GAN)生成新数据
- NLP:利用机器翻译生成新数据
- **降低模型复杂度**
- 神经网络:减少网络层、神经元个数
- 决策树:降低树的深度、剪枝
- ...
- **权值约束**(添加正则化项)
- L1 正则化
- L2 正则化
- **集成学习**
- 神经网络:Dropout
- 决策树:随机森林、GBDT
- **提前终止**
## 降低欠拟合风险的方法
- 加入新的特征
- 交叉特征、多项式特征、...
- 深度学习:因子分解机、Deep-Crossing、自编码器
- 增加模型复杂度
- 线性模型:添加高次项
- 神经网络:增加网络层数、神经元个数
- 减小正则化项的系数
- 添加正则化项是为了限制模型的学习能力,减小正则化项的系数则可以放宽这个限制
- 模型通常更倾向于更大的权重,更大的权重可以使模型更好的拟合数据
# 反向传播算法
## 反向传播的作用/目的/本质
- **反向传播概述**:
**梯度下降法**中需要利用损失函数对所有参数的梯度来寻找局部最小值点;
而**反向传播算法**就是用于计算该梯度的具体方法,其本质是利用**链式法则**对每个参数求偏导。
## 反向传播的公式推导
> 数学/深度学习的核心/[反向传播的 4 个基本公式](../C-数学/B-深度学习的核心#反向传播的-4-个基本公式)
- 可以用 4 个公式总结反向传播的过程
**标量形式**:
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\frac{\partial&space;C}{\partial&space;{\color{Red}&space;a_j^{(L)}}}=\frac{\partial&space;C({\color{Red}&space;a_j^{(L)}},y_j)}{\partial&space;{\color{Red}&space;a_j^{(L)}}}&space;\end{aligned})
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\frac{\partial&space;C}{{\color{Red}&space;\partial&space;a_j^{(l)}}}={\color{Teal}\sum_{k=0}^{n_l-1}}&space;\frac{\partial&space;z_k^{(l+1)}}{{\color{Red}&space;\partial&space;a_j^{(l)}}}&space;\frac{{\color{Blue}&space;\partial&space;a_k^{(l+1)}}}{\partial&space;z_k^{(l+1)}}&space;\frac{\partial&space;C}{{\color{Blue}&space;\partial&space;a_k^{(l+1)}}}&space;\end{aligned})
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\frac{\partial&space;C}{{\color{Magenta}&space;\partial&space;w_{j,k}^{(l)}}}=\frac{\partial&space;z_j^{(l)}}{{\color{Magenta}&space;\partial&space;w_{j,k}^{(l)}}}\frac{{\color{Red}\partial&space;a_j^{(l)}}}{\partial&space;z_j^{(l)}}\frac{\partial&space;C}{{\color{Red}\partial&space;a_j^{(l)}}}&space;\end{aligned})
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\frac{\partial&space;C}{{\color{Magenta}&space;\partial&space;b_{j}^{(l)}}}=\frac{\partial&space;z_j^{(l)}}{{\color{Magenta}&space;\partial&space;b_{j}^{(l)}}}\frac{{\color{Red}\partial&space;a_j^{(l)}}}{\partial&space;z_j^{(l)}}\frac{\partial&space;C}{{\color{Red}\partial&space;a_j^{(l)}}}&space;\end{aligned})
> 上标 `(l)` 表示网络的层,`(L)` 表示输出层(最后一层);下标 `j` 和 `k` 指示神经元的位置;`w_jk` 表示 `l` 层的第 `j` 个神经元与`(l-1)`层第 `k` 个神经元连线上的权重
- **符号说明**,其中:
- `(w,b)` 为网络参数:权值和偏置
- `z` 表示上一层激活值的线性组合
- `a` 即 "activation",表示每一层的激活值,上标`(l)`表示所在隐藏层,`(L)`表示输出层
- `C` 表示激活函数,其参数为神经网络输出层的激活值`a^(L)`,与样本的标签`y`

- 以 **均方误差(MSE)** 损失函数为例,有
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;\frac{\partial&space;C}{\partial&space;{\color{Red}&space;a_j^{(L)}}}&=\frac{\partial&space;C({\color{Red}&space;a_j^{(L)}},y_j)}{\partial&space;{\color{Red}&space;a_j^{(L)}}}&space;\\&space;&=\frac{\partial&space;\left&space;(&space;\frac{1}{2}({\color{Red}a_j^{(L)}}-y_j)^2&space;\right&space;)&space;}{\partial&space;{\color{Red}a_j^{(L)}}}={\color{Red}a_j^{(L)}}-y&space;\end{aligned})
- Nielsen 的课程中提供了另一种更利于计算的表述,本质上是一样的。

> [The four fundamental equations behind backpropagation](http://neuralnetworksanddeeplearning.com/chap2.html#the_four_fundamental_equations_behind_backpropagation)
# 激活函数
## 激活函数的作用——为什么要使用非线性激活函数?
- 使用**激活函数**的目的是为了向网络中加入**非线性因素**;加强网络的表示能力,解决**线性模型**无法解决的问题
> [神经网络激励函数的作用是什么?有没有形象的解释?](https://www.zhihu.com/question/22334626) - 知乎
**为什么加入非线性因素能够加强网络的表示能力?——神经网络的万能近似定理**
- 神经网络的万能近似定理认为主要神经网络具有至少一个非线性隐藏层,那么只要给予网络足够数量的隐藏单元,它就可以以任意的精度来近似任何**从一个有限维空间到另一个有限维空间**的函数。
- 如果不使用非线性激活函数,那么每一层输出都是上层输入的**线性组合**;
此时无论网络有多少层,其整体也将是线性的,这会导致失去万能近似的性质
> 《深度学习》 6.4.1 万能近似性质和深度;
- 但仅**部分层是纯线性**是可以接受的,这有助于**减少网络中的参数**。
> 《深度学习》 6.3.3 其他隐藏单元
## 常见的激活函数
> 《深度学习》 6.3 隐藏单元
### 整流线性单元 `ReLU`
- ReLU 通常是激活函数较好的默认选择
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=g(z)=\max(0,z)"><img src="../_assets/公式_20180610213451.png" height="" /></a></div>
<div align="center"><img src="../_assets/TIM截图20180608212808.png" height="" /></div>
#### `ReLU` 的拓展
- `ReLU` 及其扩展都基于以下公式:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=g(z;\alpha)&space;=\max(0,z)+\alpha\min(0,z)"><img src="../_assets/公式_20180610214123.png" height="" /></a></div>
当 `α=0` 时,即标准的线性整流单元
- **绝对值整流**(absolute value rectification)
固定 `α = -1`,此时整流函数即**绝对值函数** `g(z)=|z|`
- **渗漏整流线性单元**(Leaky ReLU, Maas et al., 2013)
固定 `α` 为一个小值,比如 0.01
- **参数化整流线性单元**(parametric ReLU, PReLU, He et al., 2015)
将 `α` 作为一个可学习的参数
- **`maxout` 单元** (Goodfellow et al., 2013a)
`maxout` 单元 进一步扩展了 `ReLU`,它是一个可学习的 `k` 段函数
**Keras 简单实现**
```
# input shape: [n, input_dim]
# output shape: [n, output_dim]
W = init(shape=[k, input_dim, output_dim])
b = zeros(shape=[k, output_dim])
output = K.max(K.dot(x, W) + b, axis=1)
```
> 参数数量是普通全连接层的 k 倍
>> [深度学习(二十三)Maxout网络学习](https://blog.csdn.net/hjimce/article/details/50414467) - CSDN博客
### `sigmoid` 与 `tanh`
- `sigmoid(z)`,常记作 `σ(z)`;
- `tanh(z)` 的图像与 `sigmoid(z)` 大致相同,区别是**值域**为 `(-1, 1)`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\sigma(z)=\frac{1}{1+\exp(-z)}"><img src="../_assets/公式_20180610214846.png" height="" /></a></div>
<div align="center"><img src="../_assets/TIM截图20180608195851.png" height="" /></div>
### 其他激活函数
> 很多未发布的非线性激活函数也能表现的很好,但没有比流行的激活函数表现的更好。比如使用 `cos` 也能在 MNIST 任务上得到小于 1% 的误差。通常新的隐藏单元类型只有在被明确证明能够提供显著改进时才会被发布。
- **线性激活函数**:
如果神经网络的每一层都由线性变换组成,那么网络作为一个整体也将是线性的,这会导致失去万能近似的性质。但是,仅**部分层是纯线性**是可以接受的,这可以帮助**减少网络中的参数**。
- **softmax**:
softmax 单元常作为网络的输出层,它很自然地表示了具有 k 个可能值的离散型随机变量的概率分布。
- **径向基函数(radial basis function, RBF)**:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=h_i=\exp(-\frac{1}{\sigma_i^2}\left&space;\|&space;W_{:,i}-x&space;\right&space;\|^2)"><img src="../_assets/公式_20180610215150.png" height="" /></a></div>
在神经网络中很少使用 RBF 作为激活函数,因为它对大部分 x 都饱和到 0,所以很难优化。
- **softplus**:
`softplus` 是 `ReLU` 的平滑版本。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=g(z)=\zeta(z)=\log(1+\exp(z))"><img src="../_assets/公式_20180610215222.png" height="" /></a></div>
<div align="center"><img src="../_assets/TIM截图20180608204913.png" height="" /></div>
通常不鼓励使用 softplus 函数,大家可能希望它具有优于整流线性单元的性质,但根据经验来看,它并没有。
> (Glorot et al., 2011a) 比较了这两者,发现 ReLU 的结果更好。
- **硬双曲正切函数(hard tanh)**:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=g(a)=\max(-1,\min(1,a))"><img src="../_assets/公式_20180610215308.png" height="" /></a></div>
它的形状和 tanh 以及整流线性单元类似,但是不同于后者,它是有界的。
## `ReLU` 相比 `sigmoid` 的优势 (3)
1. **避免梯度消失*****
- `sigmoid`函数在输入取绝对值非常大的正值或负值时会出现**饱和**现象——在图像上表现为变得很平,此时函数会对输入的微小变化不敏感——从而造成梯度消失;
- `ReLU` 的导数始终是一个常数——负半区为 0,正半区为 1——所以不会发生梯度消失现象
2. **减缓过拟合****
- `ReLU` 在负半区的输出为 0。一旦神经元的激活值进入负半区,那么该激活值就不会产生梯度/不会被训练,造成了网络的稀疏性——**稀疏激活**
- 这有助于减少参数的相互依赖,缓解过拟合问题的发生
3. **加速计算***
- `ReLU` 的求导不涉及浮点运算,所以速度更快
> 总结自知乎两个答案 [Ans1](https://www.zhihu.com/question/52020211/answer/152378276) & [Ans2](https://www.zhihu.com/question/29021768/answer/43488153)
**为什么 ReLU 不是全程可微/可导也能用于基于梯度的学习?**
- 虽然从数学的角度看 ReLU 在 0 点不可导,因为它的左导数和右导数不相等;
- 但是在实现时通常会返回左导数或右导数的其中一个,而不是报告一个导数不存在的错误。从而避免了这个问题
# 正则化
## Batch Normalization(批标准化)
- BN 是一种**正则化**方法(减少泛化误差),主要作用有:
- **加速网络的训练**(缓解梯度消失,支持更大的学习率)
- **防止过拟合**
- 降低了**参数初始化**的要求。
### 动机
- **训练的本质是学习数据分布**。如果训练数据与测试数据的分布不同会**降低**模型的**泛化能力**。因此,应该在开始训练前对所有输入数据做归一化处理。
- 而在神经网络中,因为**每个隐层**的参数不同,会使下一层的输入发生变化,从而导致每一批数据的分布也发生改变;**致使**网络在每次迭代中都需要拟合不同的数据分布,增大了网络的训练难度与**过拟合**的风险。
### 基本原理
- BN 方法会针对**每一批数据**,在**网络的每一层输入**之前增加**归一化**处理,使输入的均值为 `0`,标准差为 `1`。**目的**是将数据限制在统一的分布下。
- 具体来说,针对每层的第 `k` 个神经元,计算**这一批数据**在第 `k` 个神经元的均值与标准差,然后将归一化后的值作为该神经元的激活值。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;\hat{x}_k\leftarrow&space;\frac{x_k-\mathrm{E}[x_k]&space;}{\sqrt{\mathrm{Var}[x_k]}}"><img src="../_assets/公式_20180831165546.png" height="" /></a></div>
- BN 可以看作在各层之间加入了一个新的计算层,**对数据分布进行额外的约束**,从而增强模型的泛化能力;
- 但同时 BN 也降低了模型的拟合能力,破坏了之前学到的**特征分布**;
- 为了**恢复数据的原始分布**,BN 引入了一个**重构变换**来还原最优的输入数据分布
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;y_k\leftarrow&space;\gamma&space;\hat{x}_k+\beta"><img src="../_assets/公式_20180831165516.png" height="" /></a></div>
其中 `γ` 和 `β` 为可训练参数。
**小结**
- 以上过程可归纳为一个 **`BN(x)` 函数**:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;\boldsymbol{y_i}=\mathrm{BN}(\boldsymbol{x_i})"><img src="../_assets/公式_20180903223427.png" height="" /></a></div>
其中
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;\begin{aligned}&space;\mathrm{BN}(\boldsymbol{x_i})&=\gamma\boldsymbol{\hat{x}_i}+\beta\\&space;&=\gamma\frac{\boldsymbol{x_i}-\boldsymbol{\mathrm{E}[x_i]}}{\sqrt{\boldsymbol{\mathrm{Var}[x_i]}+\epsilon}}+\beta&space;\end{aligned}"><img src="../_assets/公式_20180903224323.png" height="" /></a></div>
- **完整算法**:
<div align="center"><img src="../_assets/TIM截图20180903222433.png" height="" /></div>
### BN 在训练和测试时分别是怎么做的?
- **训练时**每次会传入一批数据,做法如前述;
- 当**测试**或**预测时**,每次可能只会传入**单个数据**,此时模型会使用**全局统计量**代替批统计量;
- 训练每个 batch 时,都会得到一组`(均值,方差)`;
- 所谓全局统计量,就是对这些均值和方差求其对应的数学期望;
- 具体计算公式为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;y_k\leftarrow&space;\gamma&space;\hat{x}_k+\beta"><img src="../_assets/公式_20180903220828.png" height="" /></a></div>
> 其中 `μ_i` 和 `σ_i` 分别表示第 i 轮 batch 保存的均值和标准差;`m` 为 batch_size,系数 `m/(m-1)` 用于计算**无偏方差估计**
>> 原文称该方法为**移动平均**(moving averages)
- 此时,`BN(x)` 调整为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\large&space;\begin{aligned}&space;\mathrm{BN}(\boldsymbol{x_i})&=\gamma\frac{\boldsymbol{x_i}-\boldsymbol{\mathrm{E}[x_i]}}{\sqrt{\boldsymbol{\mathrm{Var}[x_i]}+\epsilon}}+\beta\\&space;&=\frac{\gamma}{\sqrt{\boldsymbol{\mathrm{Var}[x_i]}+\epsilon}}\boldsymbol{x_i}+\left&space;(&space;\beta-\frac{\gamma\boldsymbol{\mathrm{E}[x_i]}}{\sqrt{\boldsymbol{\mathrm{Var}[x_i]}+\epsilon}}&space;\right&space;)&space;\end{aligned}"><img src="../_assets/公式_20180903224557.png" height="" /></a></div>
- **完整算法**:
<div align="center"><img src="../_assets/TIM截图20180903224842.png" height="" /></div>
#### 为什么训练时不采用移动平均?
> 群里一位同学的面试题
- 使用 BN 的目的就是为了保证每批数据的分布稳定,使用全局统计量反而违背了这个初衷;
- BN 的作者认为在训练时采用移动平均可能会与梯度优化存在冲突;
> 【**原文**】"It is natural to ask whether we could simply **use the moving averages** µ, σ to perform the normalization **during training**, since this would remove the dependence of the normalized activations on the other example in the minibatch. This, however, has been observed to lead to the model blowing up. As argued in [6], such use of moving averages would cause the gradient optimization and the normalization to counteract each other. For example, the gradient step may increase a bias or scale the convolutional weights, in spite of the fact that the normalization would cancel the effect of these changes on the loss. This would result in unbounded growth of model parameters without actually improving the loss. It is thus crucial to use the minibatch moments, and to backpropagate through them."
>> [1702.03275] [Batch Renormalization](https://arxiv.org/abs/1702.03275)
### 相关阅读
- [深入理解Batch Normalization批标准化 - 郭耀华](https://www.cnblogs.com/guoyaohua/p/8724433.html) - 博客园
- [深度学习中批归一化的陷阱](http://ai.51cto.com/art/201705/540230.htm) - 51CTO
## L1/L2 范数正则化
> 《深度学习》 7.1.1 L2 参数正则化 & 7.1.2 - L1 参数正则化
>
> [机器学习中正则化项L1和L2的直观理解](https://blog.csdn.net/jinping_shi/article/details/52433975) - CSDN博客
### L1/L2 范数的作用、异同
**相同点**
- 限制模型的学习能力——通过限制参数的规模,使模型偏好于**权值较小**的目标函数,防止过拟合。
**不同点**
- **L1 正则化**可以产生更**稀疏**的权值矩阵,可以用于特征选择,同时一定程度上防止过拟合;**L2 正则化**主要用于防止模型过拟合
- **L1 正则化**适用于特征之间有关联的情况;**L2 正则化**适用于特征之间没有关联的情况。
### 为什么 L1 和 L2 正则化可以防止过拟合?
- L1 & L2 正则化会使模型偏好于更小的权值。
- 更小的权值意味着**更低的模型复杂度**;添加 L1 & L2 正则化相当于为模型添加了某种**先验**,限制了参数的分布,从而降低了模型的复杂度。
- 模型的复杂度降低,意味着模型对于噪声与异常点的抗干扰性的能力增强,从而提高模型的泛化能力。——直观来说,就是对训练数据的拟合刚刚好,不会过分拟合训练数据(比如异常点,噪声)——**奥卡姆剃刀原理**
### 为什么 L1 正则化可以产生稀疏权值,而 L2 不会?
- 对目标函数添加范数正则化,训练时相当于在范数的约束下求目标函数 `J` 的最小值
- 带有**L1 范数**(左)和**L2 范数**(右)约束的二维图示


- 图中 `J` 与 `L1` 首次相交的点即是最优解。`L1` 在和每个坐标轴相交的地方都会有“**顶点**”出现,多维的情况下,这些顶点会更多;在顶点的位置就会产生稀疏的解。而 `J` 与这些“顶点”相交的机会远大于其他点,因此 `L1` 正则化会产生稀疏的解。
- `L2` 不会产生“**顶点**”,因此 `J` 与 `L2` 相交的点具有稀疏性的概率就会变得非常小。
## Dropout
> 《深度学习》 7.12 Dropout
### Bagging 集成方法
- **集成方法**的主要想法是分别训练不同的模型,然后让所有模型**表决**最终的输出。
集成方法奏效的原因是不同的模型**通常不会**在测试集上产生相同的误差。
集成模型能至少与它的任一成员表现得一样好。**如果成员的误差是独立的**,集成将显著提升模型的性能。
- **Bagging** 是一种集成策略——具体来说,Bagging 涉及构造 k 个**不同的数据集**。
每个数据集从原始数据集中**重复采样**构成,和原始数据集具有**相同数量**的样例——这意味着,每个数据集以高概率缺少一些来自原始数据集的例子,还包含若干重复的例子
> 更具体的,如果采样所得的训练集与原始数据集大小相同,那所得数据集中大概有原始数据集 `2/3` 的实例
**集成方法与神经网络**:
- 神经网络能找到足够多的不同的解,意味着他们可以从模型平均中受益——即使所有模型都在同一数据集上训练。
神经网络中**随机初始化**的差异、**批训练数据**的随机选择、**超参数**的差异等**非确定性**实现往往足以使得集成中的不同成员具有**部分独立的误差**。
### Dropout 策略
- 简单来说,Dropout 通过**参数共享**提供了一种廉价的 Bagging 集成近似—— Dropout 策略相当于集成了包括所有从基础网络除去部分单元后形成的子网络。
- 通常,**隐藏层**的采样概率为 `0.5`,**输入**的采样概率为 `0.8`;超参数也可以采样,但其采样概率一般为 `1`
<div align="center"><img src="../_assets/TIM截图20180611152559.png" height="" /></div>
**权重比例推断规则**
- 权重比例推断规则的目的是确保在测试时一个单元的期望总输入与在训练时该单元的期望总输入大致相同。
- 实践时,如果使用 `0.5` 的采样概率,**权重比例规则**相当于在训练结束后**将权重乘 `0.5`**,然后像平常一样使用模型;等价的,另一种方法是**在训练时**将单元的状态乘 2。
#### Dropout 与 Bagging 的不同
- 在 Bagging 的情况下,所有模型都是独立的;而在 Dropout 的情况下,所有模型**共享参数**,其中每个模型继承父神经网络参数的不同子集。
- 在 Bagging 的情况下,每一个模型都会在其相应训练集上训练到收敛。而在 Dropout 的情况下,通常大部分模型都没有显式地被训练;取而代之的是,在单个步骤中我们训练一小部分的子网络,参数共享会使得剩余的子网络也能有好的参数设定。
# 深度学习实践
## 参数初始化
- 一般使用服从的**高斯分布**(`mean=0, stddev=1`)或**均匀分布**的随机值作为**权重**的初始化参数;使用 `0` 作为**偏置**的初始化参数
- 一些**启发式**方法会根据**输入与输出的单元数**来决定初始值的范围
比如 `glorot_uniform` 方法 (Glorot and Bengio, 2010)
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=W_{i,j}\sim&space;U\left&space;(&space;-\sqrt&space;\frac{6}{n_{in}+n_{out}},&space;\sqrt&space;\frac{6}{n_{in}+n_{out}}&space;\right&space;)"><img src="../_assets/公式_20180706115540.png" height="" /></a></div>
> Keras 全连接层默认的**权重**初始化方法
- **其他初始化方法**
- 随机正交矩阵(Orthogonal)
- 截断高斯分布(Truncated normal distribution)
- Keras 提供的参数初始化方法:Keras/[Initializers](https://keras.io/initializers/)
================================================
FILE: A-深度学习/A-深度学习实践.md
================================================
深度学习实践
===
Index
---
<!-- TOC -->
- [加速训练的方法](#加速训练的方法)
- [内部方法](#内部方法)
- [外部方法](#外部方法)
<!-- /TOC -->
## 加速训练的方法
### 内部方法
- 网络结构
- 比如 CNN 与 RNN,前者更适合并行架构
- 优化算法的改进:动量、自适应学习率
> [./专题-优化算法](./C-专题-优化算法)
- 减少参数规模
- 比如使用 GRU 代替 LSTM
- 参数初始化
- Batch Normalization
### 外部方法
> [深度学习训练加速方法](https://blog.csdn.net/xuqiaobo/article/details/60769330) - CSDN博客
- GPU 加速
- 数据并行
- 模型并行
- 混合数据并行与模型并行
- CPU 集群
- GPU 集群
================================================
FILE: A-深度学习/B-专题-CNN.md
================================================
DL-专题-CNN
===
Index
---
<!-- TOC -->
- [CNN 的基本特征](#cnn-的基本特征)
- [动机](#动机)
- [意义](#意义)
- [卷积的内部实现](#卷积的内部实现)
- [Theano 中的实现](#theano-中的实现)
- [Caffe 中的实现](#caffe-中的实现)
- [卷积的反向传播](#卷积的反向传播)
- [卷积的结构](#卷积的结构)
- [卷积核的结构及其数量](#卷积核的结构及其数量)
- [基本卷积](#基本卷积)
- [转置卷积](#转置卷积)
- [空洞卷积](#空洞卷积)
- [可分离卷积](#可分离卷积)
- [Keras 实现](#keras-实现)
- [门卷积](#门卷积)
- [门卷积的作用](#门卷积的作用)
- [门卷积是如何防止梯度消失的](#门卷积是如何防止梯度消失的)
- [其他](#其他)
- [为什么使用 CNN 代替 RNN?](#为什么使用-cnn-代替-rnn)
- [Reference](#reference)
<!-- /TOC -->
## CNN 的基本特征
- **稀疏交互**和**参数共享**
### 动机
- **局部特征**——卷积的核心思想
- 平移等变性
### 意义
- **提高统计效率**
- 当处理一张图像时,输入的图像可能包含成千上万个像素点,但是我们可以通过只占用几十到上百个像素点的核来检测一些局部但有意义的特征,例如图像的边缘。
- **减少参数数量**
- 减少存储需求
- 加速计算
## 卷积的内部实现
### Theano 中的实现
> [Convolution as a matrix operation](http://deeplearning.net/software/theano/tutorial/conv_arithmetic.html#convolution-as-a-matrix-operation)
- 先把二维 `input` 展开成一维向量(`[in_h, in_w] -> [in_h * in_w]`);如果是一批 `inputs`,则依次堆叠为一个矩阵 `[N, in_h * in_w]`;
- 然后将 `kernel` 按 stride **循环**展开成一个**稀疏矩阵**;
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cm&space;C=\begin{pmatrix}&space;w_{0,0}&space;&&space;w_{0,1}&space;&&space;w_{0,2}&space;&&space;0&space;&&space;w_{1,0}&space;&&space;w_{1,1}&space;&&space;w_{1,2}&space;&&space;0&space;&&space;w_{2,0}&space;&&space;w_{2,1}&space;&&space;w_{2,2}&space;&&space;0&space;&&space;0&space;&&space;0&space;&&space;0&space;&&space;0\\&space;0&space;&&space;w_{0,0}&space;&&space;w_{0,1}&space;&&space;w_{0,2}&space;&&space;0&space;&&space;w_{1,0}&space;&&space;w_{1,1}&space;&&space;w_{1,2}&space;&&space;0&space;&&space;w_{2,0}&space;&&space;w_{2,1}&space;&&space;w_{2,2}&space;&&space;0&space;&&space;0&space;&&space;0&space;&&space;0\\&space;0&space;&&space;0&space;&&space;0&space;&&space;0&space;&&space;w_{0,0}&space;&&space;w_{0,1}&space;&&space;w_{0,2}&space;&&space;0&space;&&space;w_{1,0}&space;&&space;w_{1,1}&space;&&space;w_{1,2}&space;&&space;0&space;&&space;w_{2,0}&space;&&space;w_{2,1}&space;&&space;w_{2,2}&space;&&space;0\\&space;0&space;&&space;0&space;&&space;0&space;&&space;0&space;&&space;0&space;&&space;w_{0,0}&space;&&space;w_{0,1}&space;&&space;w_{0,2}&space;&&space;0&space;&&space;w_{1,0}&space;&&space;w_{1,1}&space;&&space;w_{1,2}&space;&&space;0&space;&&space;w_{2,0}&space;&&space;w_{2,1}&space;&&space;w_{2,2}&space;\end{pmatrix}"><img src="../_assets/公式_20180824140303.png" height="" /></a></div>
- 然后将卷积的计算转化为**矩阵相乘**。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cm&space;\large&space;y=C\cdot&space;x^\mathsf{T}"><img src="../_assets/公式_20180824141327.png" height="" /></a></div>
### Caffe 中的实现
> [High Performance Convolutional Neural Networks for Document Processing](https://hal.inria.fr/inria-00112631/document) (2006)
- 先对 `inputs` 做 **im2col** 操作得到**输入矩阵**,再将 `kernel` 转化为**权值矩阵**,然后将两个矩阵相乘得到输出矩阵:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;y=x\cdot&space;W"><img src="../_assets/公式_2018082492318.png" height="" /></a></div>
其中
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{aligned}&space;y\&space;\&space;\text{shape:}\&space;&&space;[{\color{Red}o_{height}*o_{width}},\&space;{\color{Blue}o_{channels}}]\\&space;x\&space;\&space;\text{shape:}\&space;&&space;[{\color{Red}o_{height}*o_{width}},\&space;i_{channels}*k_{height}*k_{width}]\\&space;W\&space;\&space;\text{shape:}\&space;&&space;[i_{channels}*k_{height}*k_{width},\&space;{\color{Blue}o_{channels}}]\\&space;\end{aligned}"><img src="../_assets/公式_20180824130328.png" height="" /></a></div>
- 其中 `o` 表示 out;`i` 表示 in;`k` 表示 kernel;
- 不包括 `batch_size` 的维度;
- `[o_height, o_width]` 的大小由 `[i_height, i_width]` 及 stride、padding 等参数共同决定。
- **im2col** 操作
> 先将一个输入矩阵(图像),重叠地划分为多个**子矩阵**(子区域),对每个子矩阵序列化成向量,然后将所有子向量**纵向**拼接成另一个矩阵;如果存在多个输入矩阵,则进一步将新生成矩阵横向拼接,最终构成一个大矩阵
<div align="center"><img src="../_assets/TIM截图20180823220850.png" height="" /></div>
> 这里可以看作是三张**单通道**图像,也可以看作是一张**三通道**的图像
>> 更直观的图示 > [caffe im2col 详解](https://blog.csdn.net/mrhiuser/article/details/52672824) - CSDN博客
>>
>> 具体的代码实现更复杂一些,因为这个图示中的操作并不能直接循环,具体请参考这篇 > [caffe源码深入学习6:超级详细的im2col绘图解析,分析caffe卷积操作的底层实现](https://blog.csdn.net/jiongnima/article/details/69736844) - CSDN博客
- 完整的计算过程
<div align="center"><img src="../_assets/TIM截图20180823213211.png" height="" /></div>
- 上半部分是卷积的直观操作,下半部分转换为矩阵乘法的操作
- 原文:“**输入为 `N=3` 个 `3*3` 的特征矩阵;输出为 `M=2` 个 `2*2` 的特征矩阵;kernel 的形状为 `2*2`,数量为 `N*M = 6` 个**”;
> **个人认为原文的表述不正确**:如果把 `N` 看作 batch_size 的话,输出 `M` 也应该是 3 才对。
>
> 更正确的说法应该是“**输入为 1 个 `3*3*3` 的三通道特征矩阵;输出为 1 个 `2*2*2` 的双通道特征矩阵;kernel 的形状为 `2*2*3`,数量为 `2` 个**”
>> [卷积核的结构及其数量](#卷积核的结构及其数量)
- **注意**:因为是按照 stride 来切“子矩阵”,所以可能存在重复。
## 卷积的反向传播
- 卷积的内部实现实际上是**矩阵相乘**,
- 因此,卷积的**反向传播**过程实际上跟普通的全连接是类似的
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{array}{ll}&space;\text{Forward-prop:}&space;&&space;y=x\cdot&space;W\\&space;\text{Backward-prop:}&space;&&space;\nabla{x}=\nabla{y}\cdot&space;W^\mathsf{T}\\&space;\text{Weight-Gradient:}&space;&&space;\nabla{W}=x^\mathsf{T}\cdot&space;\nabla{y}\\&space;\text{Weight-Update:}&space;&&space;W_{new}=W_{old}-\eta\nabla{W}&space;\end{array}"><img src="../_assets/公式_20180823231624.png" height="" /></a></div>
> [High Performance Convolutional Neural Networks for Document Processing](https://hal.inria.fr/inria-00112631/document)
**相关阅读**
- [CNN的反向传播](http://jermmy.xyz/2017/12/16/2017-12-16-cnn-back-propagation/) | Jermmy's Lazy Blog
- https://www.zhihu.com/question/56865789/answer/150785351
## 卷积的结构
> [一文了解各种卷积结构原理及优劣](https://zhuanlan.zhihu.com/p/28186857) - 知乎
>
> vdumoulin/[conv_arithmetic](https://github.com/vdumoulin/conv_arithmetic) - GitHUub
### 卷积核的结构及其数量
**以 Conv2D 为例**
- Tensorflow 中构造 conv2d 层的参数形状为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{array}{ll}&space;\text{kernel-shape:}&space;&[k_{height},&space;k_{width},&space;n_{in},&space;n_{out}]&space;\\&space;\text{bias-shape:}&space;&&space;[n_{out}]\\&space;\end{array}"><img src="../_assets/公式_20180824102139.png" height="" /></a></div>
> `[k_height, k_width]` 表示卷积核的大小;`n_in` 表示“输入的通道数”,`n_out` 表示“输出的通道数”
- 通常在描述卷积核的大小时,只会说 `[k_height, k_width]` 这一部分;比如 “这一层使用的是 `3*3` 的卷积核”。
- 但卷积核应该还包括**输入的通道数** `n_in`,即 `[k_height, k_width, n_in]` 这部分;从几何的角度来看,卷积核应该是一个“长方体”,而不是“长方形/矩形”
- 因此,卷积核的数量应该是 `n_out`,而不是 `n_in * n_out`
### 基本卷积
<table style="width:100%; table-layout:fixed;">
<tr>
<td>No padding, no strides</td>
<td>Arbitrary padding, no strides</td>
<td>Half padding, no strides</td>
<td>Full padding, no strides</td>
</tr>
<tr>
<td><img width="150px" src="../_assets/no_padding_no_strides.gif"></td>
<td><img width="150px" src="../_assets/arbitrary_padding_no_strides.gif"></td>
<td><img width="150px" src="../_assets/same_padding_no_strides.gif"></td>
<td><img width="150px" src="../_assets/full_padding_no_strides.gif"></td>
</tr>
<tr>
<td>No padding, strides</td>
<td>Padding, strides</td>
<td>Padding, strides (odd)</td>
</tr>
<tr>
<td><img width="150px" src="../_assets/no_padding_strides.gif"></td>
<td><img width="150px" src="../_assets/padding_strides.gif"></td>
<td><img width="150px" src="../_assets/padding_strides_odd.gif"></td>
</tr>
</table>
<!-- TODO: 更细的分类 -->
### 转置卷积
- 转置卷积(Transposed Convolution),又称反卷积(Deconvolution)、Fractionally Strided Convolution
> 反卷积的说法不够准确,数学上有定义真正的反卷积,两者的操作是不同的
- 转置卷积是卷积的**逆过程**,如果把基本的卷积(+池化)看做“缩小分辨率”的过程,那么转置卷积就是“**扩充分辨率**”的过程。
- 为了实现扩充的目的,需要对输入以某种方式进行**填充**。
- 转置卷积与数学上定义的反卷积不同——在数值上,它不能实现卷积操作的逆过程。其内部实际上执行的是常规的卷积操作。
- 转置卷积只是为了**重建**先前的空间分辨率,执行了卷积操作。
- 虽然转置卷积并不能还原数值,但是用于**编码器-解码器结构**中,效果仍然很好。——这样,转置卷积可以同时实现图像的**粗粒化**和卷积操作,而不是通过两个单独过程来完成。
<table style="width:100%; table-layout:fixed;">
<tr>
<td>No padding, no strides, transposed</td>
<td>Arbitrary padding, no strides, transposed</td>
<td>Half padding, no strides, transposed</td>
<td>Full padding, no strides, transposed</td>
</tr>
<tr>
<td><img width="150px" src="../_assets/no_padding_no_strides_transposed.gif"></td>
<td><img width="150px" src="../_assets/arbitrary_padding_no_strides_transposed.gif"></td>
<td><img width="150px" src="../_assets/same_padding_no_strides_transposed.gif"></td>
<td><img width="150px" src="../_assets/full_padding_no_strides_transposed.gif"></td>
</tr>
<tr>
<td>No padding, strides, transposed</td>
<td>Padding, strides, transposed</td>
<td>Padding, strides, transposed (odd)</td>
</tr>
<tr>
<td><img width="150px" src="../_assets/no_padding_strides_transposed.gif"></td>
<td><img width="150px" src="../_assets/padding_strides_transposed.gif"></td>
<td><img width="150px" src="../_assets/padding_strides_odd_transposed.gif"></td>
</tr>
</table>
### 空洞卷积
- 空洞卷积(Atrous Convolutions)也称扩张卷积(Dilated Convolutions)、膨胀卷积。
<div align="center"><img src="../_assets/conv_dilation.gif" height="200" /><br/>No padding, no strides.</div>
**空洞卷积的作用**
- 空洞卷积使 CNN 能够**捕捉更远的信息,获得更大的感受野**(NLP 中可理解为获取更长的上下文);同时不增加参数的数量,也不影响训练的速度。
- 示例:Conv1D + 空洞卷积
<div align="center"><img src="../_assets/普通卷积与膨胀卷积.png" height="200" /></div>
<!-- - 普通卷积在第三层时,每个节点只能捕捉到前后3个输入 -->
### 可分离卷积
- 可分离卷积(separable convolution)
- TODO
### Keras 实现
- Keras 中通过在卷积层中加入参数 `dilation_rate`实现
```Python
Conv1D(filters=config.filters,
kernel_size=config.kernel_size,
dilation_rate=2)
```
TODO: 维度变化
## 门卷积
> [卷积新用之语言模型](https://blog.csdn.net/stdcoutzyx/article/details/55004458) - CSDN博客
- 类似 LSTM 的过滤机制,实际上是卷积网络与**门限单元**(Gated Linear Unit)的组合
- 核心公式
<div align="center"><img src="../_assets/公式_20180720110804.png" /></div>
<!-- \boldsymbol{Y}=\text{Conv1D}_{(1)}(\boldsymbol{X}) \otimes \sigma\Big(\text{Conv1D}_{(2)}(\boldsymbol{X})\Big)dsymbol{X})\Big) -->
> 中间的运算符表示**逐位相乘**—— Tensorflow 中由 `tf.multiply(a, b)` 实现,其中 a 和 b 的 shape 要相同;后一个卷积使用`sigmoid`激活函数
- 一个门卷积 Block
<div align="center"><img src="../_assets/门卷积.jpg" height="" /></div>
> `W` 和 `V` 表明参数不共享
- 实践中,为了防止梯度消失,还会在每个 Block 中加入残差
### 门卷积的作用
- 减缓梯度消失
- 解决语言顺序依存问题(? TODO)
### 门卷积是如何防止梯度消失的
- 因为公式中有一个卷积没有经过激活函数,所以对这部分求导是个常数,所以梯度消失的概率很小。
- 如果还是担心梯度消失,还可以加入**残差**——要求输入输出的 shape 一致
<div align="center"><img src="../_assets/公式_20180720113735.png" /></div>
<!-- \boldsymbol{Y}={\color{Red} \boldsymbol{X} \,+\;} \text{Conv1D}_{(1)}(\boldsymbol{X}) \otimes \sigma\Big(\text{Conv1D}_{(2)}(\boldsymbol{X})\Big) -->
更直观的理解:
<div align="center"><img src="../_assets/公式_20180720120400.png" /></div>
<!-- \begin{aligned}\boldsymbol{Y}=&\,\boldsymbol{X} + {\color{Red}\text{Conv1D}_{(1)}(\boldsymbol{X})}\otimes \sigma\Big(\text{Conv1D}_{(2)}(\boldsymbol{X})\Big)\\=&\,\boldsymbol{X} + {\color{Red}\Big(\text{Conv1D}_{(1)}(\boldsymbol{X}) - \boldsymbol{X}\Big)}\otimes \sigma\Big(\text{Conv1D}_{(2)}(\boldsymbol{X})\Big)\\ =&\,\boldsymbol{X}\otimes \Big[1-\sigma\Big(\text{Conv1D}_{(2)}(\boldsymbol{X})\Big)\Big] + \text{Conv1D}_{(1)}(\boldsymbol{X}) \otimes \sigma\Big(\text{Conv1D}_{(2)}(\boldsymbol{X})\Big)\\ =&\,\boldsymbol{X}\otimes \Big(1-\boldsymbol{\sigma}\Big) + \text{Conv1D}_{(1)}(\boldsymbol{X}) \otimes \boldsymbol{\sigma} \end{aligned} -->
即信息以 `1-σ` 的概率直接通过,以 `σ` 的概率经过变换后通过——类似 GRU
> 因为`Conv1D(X)`没有经过激活函数,所以实际上它只是一个线性变化;因此与 `Conv1D(X) - X` 是等价的
>
> [基于CNN的阅读理解式问答模型:DGCNN](https://kexue.fm/archives/5409#门机制) - 科学空间|Scientific Spaces
## 其他
### 为什么使用 CNN 代替 RNN?
> [关于序列建模,是时候抛弃RNN和LSTM了](https://www.jiqizhixin.com/articles/041503) | 机器之心 [[原文]](https://towardsdatascience.com/the-fall-of-rnn-lstm-2d1594c74ce0)
**RNN/LSTM 存在的问题(3)**
1. RNN 与目前的硬件加速技术不匹配
> 训练 RNN 和 LSTM 非常困难,因为计算能力受到内存和带宽等的约束。简单来说,每个 LSTM 单元需要四个仿射变换,且每一个时间步都需要运行一次,这样的仿射变换会要求非常多的内存带宽。**添加更多的计算单元很容易,但添加更多的内存带宽却很难**——这与目前的硬件加速技术不匹配,一个可能的解决方案就是让计算在存储器设备中完成。
1. RNN 容易发生**梯度消失**,包括 LSTM
> 在长期信息访问当前处理单元之前,需要按顺序地通过所有之前的单元。这意味着它很容易遭遇梯度消失问题;LSTM 一定程度上解决了这个问题,但 LSTM 网络中依然存在顺序访问的序列路径;实际上,现在这些路径甚至变得更加复杂
1. **注意力机制模块**(记忆模块)的应用
- 注意力机制模块可以同时**前向预测**和**后向回顾**。
- **分层注意力编码器**(Hierarchical attention encoder)
<div align="center"><img src="../_assets/TIM截图20180720101423.png" height="250" /></div>
- 分层注意力模块通过一个**层次结构**将过去编码向量**汇总**到一个**上下文向量**`C_t` ——这是一种更好的**观察过去信息**的方式(观点)
- **分层结构**可以看做是一棵**树**,其路径长度为 `logN`,而 RNN/LSTM 则相当于一个**链表**,其路径长度为 `N`,如果序列足够长,那么可能 `N >> logN`
> [放弃 RNN/LSTM 吧,因为真的不好用!望周知~](https://blog.csdn.net/heyc861221/article/details/80174475) - CSDN博客
**任务角度(1)**
1. 从任务本身考虑,我认为也是 CNN 更有利,LSTM 因为能记忆比较长的信息,所以在推断方面有不错的表现(直觉);但是在事实类问答中,并不需要复杂的推断,答案往往藏在一个 **n-gram 短语**中,而 CNN 能很好的对 n-gram 建模。
## Reference
- [首次超越LSTM : Facebook 门卷积网络新模型能否取代递归模型?](http://www.dataguru.cn/article-10314-1.html) - 炼数成金
================================================
FILE: A-深度学习/B-专题-RNN.md
================================================
DL-专题-RNN
===
Index
---
<!-- TOC -->
- [RNN 的基本结构](#rnn-的基本结构)
- [RNN 常见的几种设计模式(3)](#rnn-常见的几种设计模式3)
- [RNN 的反向传播(BPTT) TODO](#rnn-的反向传播bptt-todo)
- [RNN 相关问题](#rnn-相关问题)
- [RNN 相比前馈网络/CNN 有什么特点?](#rnn-相比前馈网络cnn-有什么特点)
- [RNN 为什么会出现梯度消失/梯度爆炸?](#rnn-为什么会出现梯度消失梯度爆炸)
- [RNN 中能否使用 `ReLU` 作为激活函数?](#rnn-中能否使用-relu-作为激活函数)
- [如果使用 `ReLU` 作为 RNN 的激活函数,应该注意什么?](#如果使用-relu-作为-rnn-的激活函数应该注意什么)
- [梯度爆炸的解决方法](#梯度爆炸的解决方法)
- [梯度消失的解决方法(针对 RNN)](#梯度消失的解决方法针对-rnn)
- [LSTM 相关问题](#lstm-相关问题)
- [LSTM 的内部结构](#lstm-的内部结构)
- [完整的 LSTM 前向传播公式](#完整的-lstm-前向传播公式)
- [LSTM 是如何实现长短期记忆的?(遗忘门和输入门的作用)](#lstm-是如何实现长短期记忆的遗忘门和输入门的作用)
- [LSTM 里各部分使用了不同的激活函数,为什么?可以使用其他激活函数吗?](#lstm-里各部分使用了不同的激活函数为什么可以使用其他激活函数吗)
- [窥孔机制](#窥孔机制)
- [GRU 与 LSTM 的关系](#gru-与-lstm-的关系)
- [完整的 GRU 前向传播公式](#完整的-gru-前向传播公式)
<!-- /TOC -->
## RNN 的基本结构
- RNN 本质上是一个**递推函数**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{120}&space;\fn_cs&space;h^{(t)}=f({\color{Red}h^{(t-1)}};\theta)"><img src="../_assets/公式_20180829145525.png" height="" /></a></div>
- 考虑当前输入 `x(t)`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{120}&space;\fn_cs&space;h^{(t)}=f({\color{Red}h^{(t-1)},x^{(t)}};\theta)"><img src="../_assets/公式_20180829145336.png" height="" /></a></div>
- 以上计算公式可展开为如下**计算图**(无输出单元)
<div align="center"><img src="../_assets/TIM截图20180829145622.png" height="" /></div>
- RNN 的**前向传播**公式
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{120}&space;\fn_cs&space;\begin{aligned}&space;a^{(t)}&=W\cdot[h^{(t-1)};x^{(t)}]+b\\&space;h^{(t)}&=f(a^{(t)})&space;\end{aligned}"><img src="../_assets/公式_20180829150659.png" height="" /></a></div>
> 一般 `h(0)` 会初始化为 0 向量;并使用 `tanh` 作为激活函数 `f`
## RNN 常见的几种设计模式(3)
**RNN 一般包括以下几种设计模式**
- **每个时间步都有输出,且隐藏单元之间有循环连接**
- 即通常所说 RNN
- 这种结构会在每个时间步产生一个输出,所以通常用于“**Seq2Seq**”任务中,比如序列标注、机器翻译等。这些任务通常都比较复杂。
<div align="center"><img src="../_assets/TIM截图20180829133724.png" height="" /></div>
- **每个时间步都有输出,但是隐藏单元之间没有循环连接,只有当前时刻的输出到下个时刻的隐藏单元之间有循环连接**
- 这种模型的表示能力弱于第一种,但是它**更容易训练**
- 因为每个时间步可以与其他时间步单独训练,从而实现**并行化**
- 具体来说,就是使用 `y(t)` 代替 `o(t)` 输入下一个时间步。
<div align="center"><img src="../_assets/TIM截图20180829134331.png" height="" /></div>
- **隐藏单元之间有循环连接,但只有最后一个时间步有输出**
- 忽略模式 1 中的中间输出,即可得到这种网络;
- 这种网络一般用于**概括序列**。具体来说,就是产生**固定大小的表示**,用于下一步处理;
- 在一些“**Seq2One**”中简单任务中,这种网络用的比较多;因为这些任务只需要关注序列的全局特征。
<div align="center"><img src="../_assets/TIM截图20180829134659.png" height="" /></div>
> 其中前两种 RNN 分别被称为 Elman network 和 Jordan network;通常所说的 RNN 指的是前者
> <div align="center"><img src="../_assets/TIM截图20180808114753.png" height="" /></div>
>
>> [Recurrent neural network](https://en.wikipedia.org/wiki/Recurrent_neural_network#Elman_networks_and_Jordan_networks) - Wikipedia
## RNN 的反向传播(BPTT) TODO
## RNN 相关问题
### RNN 相比前馈网络/CNN 有什么特点?
- **前馈网络/CNN 处理序列数据时存在的问题:**
- 一般的**前馈网络**,通常接受一个**定长**向量作为输入,然后输出一个定长的表示;它需要一次性接收所有的输入,因而忽略了序列中的顺序信息;
- **CNN** 在处理**变长序列**时,通过**滑动窗口+池化**的方式将输入转化为一个**定长的向量表示**,这样做可以捕捉到序列中的一些**局部特征**,但是很难学习到序列间的**长距离依赖**。
- **RNN 处理时序数据时的优势:**
- RNN 很适合处理序列数据,特别是带有**时序关系**的序列,比如文本数据;
- RNN 把**每一个时间步**中的信息编码到**状态变量**中,使网络具有一定的记忆能力,从而更好的理解序列信息。
- 由于 RNN 具有对序列中时序信息的刻画能力,因此在处理序列数据时往往能得到更准确的结果。
- **展开后的 RNN**(**无输出**)
<div align="center"><img src="../_assets/TIM截图20180808110903.png" height="" /></div>
- 一个长度为 `T` 的 RNN 展开后,可以看做是一个 **T 层的前馈网络**;同时每一层都可以有**新的输入**
- 通过对当前输入 `x_t` 和上一层的隐状态 `h_{t-1}` 进行编码,**第 `t` 层的隐状态** `h_t` 记录了序列中前 `t` 个输入的信息。
> 普通的前馈网络就像火车的**一节车厢**,只有一个入口,一个出口;而 RNN 相当于**一列火车**,有多节车厢接收**当前时间步**的输入信息并输出**编码后的状态信息**(包括**当前的状态和之前的所有状态**)。
- **最后一层隐状态 `x_T`** 编码了整个序列的信息,因此可以看作**整个序列的压缩表示**。
- 常见的文本分类任务中,将 `h_T` 通过一个 Softmax 层,即可获得作为每个类别的概率:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cs&space;\large&space;\begin{aligned}&space;a_t&=Ux_t+Wh_{t-1}\\&space;h_t&=f(a_t)\\&space;y&=g(Vh_t)&space;\end{aligned}"><img src="../_assets/公式_20180828112616.png" height="" /></a></div>
其中
- `U` 为输入层到隐藏层的权重矩阵
- `W` 为隐藏层从上一时刻到下一时刻的状态转移权重矩阵
- `f` 为隐藏层激活函数,通常可选 `tanh` 或 `ReLU`;
- `g` 为输出层激活函数,可以采用 `Softmax`、`Sigmoid` 或线性函数(回归任务)
- 通常 `h_{-1}` 初始化为 0 向量。
### RNN 为什么会出现梯度消失/梯度爆炸?
- 最大步长为 `T` 的 RNN 展开后相当于一个**共享参数**的 T 层前馈网络
- RNN 的前向传播过程
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cs&space;\large&space;\begin{aligned}&space;a_t&=Ux_t+Wh_{t-1}\\&space;h_t&=f(a_t)&space;\end{aligned}"><img src="../_assets/公式_20180828174727.png" height="" /></a></div>
- 展开前一层
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cs&space;\large&space;\begin{aligned}&space;a_t&=Ux_t+Wh_{t-1}&space;\\&=Ux_t+W\cdot&space;f(Ux_{t-1}+Wh_{t-2})&space;\end{aligned}"><img src="../_assets/公式_20180828175013.png" height="" /></a></div>
- RNN 的梯度计算公式
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;\frac{\partial&space;a^{(t)}}{\partial&space;a^{(1)}}=\frac{\partial&space;a^{(t)}}{\partial&space;a^{(t-1)}}\cdot\frac{\partial&space;a^{(t-1)}}{\partial&space;a^{(t-2)}}\cdots\frac{\partial&space;a^{(2)}}{\partial&space;a^{(1)}}"><img src="../_assets/公式_20180925142404.png" height="" /></a></div>
其中
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{120}&space;\fn_jvn&space;\begin{aligned}&space;\frac{\partial&space;a^{(t)}}{\partial&space;a^{(t-1)}}&=\frac{\partial&space;a^{(t)}}{\partial&space;h^{(t-1)}}\cdot\frac{\partial&space;h^{(t-1)}}{\partial&space;a^{(t-1)}}\\&space;&=W\cdot&space;\mathrm{diag}[f'(a^{(t-1)})]\\&space;&=\begin{pmatrix}&space;w_{11}\cdot&space;f'(a_1^{(t-1)})&space;&\cdots&space;&w_{1n}\cdot&space;f'(a_n^{(t-1)})&space;\\&space;\vdots&space;&&space;\ddots&space;&\vdots&space;\\&space;w_{n1}\cdot&space;f'(a_1^{(t-1)})&space;&\cdots&space;&w_{nn}\cdot&space;f'(a_n^{(t-1)})&space;\end{pmatrix}&space;\end{aligned}"><img src="../_assets/公式_20180925143950.png" height="" /></a></div>
> 上标 `(t)` 表示时间步,下标 `n` 表示隐藏层的单元数(维度);`diag()` 为对角矩阵
#### RNN 中能否使用 `ReLU` 作为激活函数?
> [RNN中为什么要采用tanh而不是ReLu作为激活函数?](https://www.zhihu.com/question/61265076) - 知乎
- 答案是肯定的。但是会存在一些问题。
> 其实 ReLU 最早就是为了解决 RNN 中的**梯度消失**问题而设计的。
<!-- - 使用 ReLU 主要是为了解决**反向传播**时的**梯度消失**问题;
- 但是在 RNN 中使用 ReLU,反而可能在**前向传播**就时出现类似“梯度消失/爆炸”的**数值溢出问题**。 -->
- 假设使用 `ReLU` 并始终处于**激活状态**(`a_{t-1} > 0`),则 `f(x) = x`,即
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cs&space;\large&space;\begin{aligned}&space;a_t&=Ux_t+W\cdot&space;(Ux_{t-1}+Wh_{t-2})\\&space;&=Ux_t+W\cdot&space;Ux_{t-1}+W^2h_{t-2}&space;\end{aligned}"><img src="../_assets/公式_20180828175623.png" height="" /></a></div>
- 按照以上的步骤继续展开,最终结果中将包含 `t` 个 `W` 连乘,如果 `W` 不是单位矩阵,最终结果将趋于 `0` 或无穷。
- 因此,在 RNN 中使用 ReLU 应该注意使用**单位矩阵**来初始化权重矩阵。
> 为什么普通的前馈网络或 CNN 中不会出现这中现象?
>> 因为他们每一层的 `W` 不同,且在初始化时是独立同分布的,因此可以在一定程度相互抵消。即使多层之后一般也不会出现数值问题。
- **使用 `ReLU` 也不能完全避免 RNN 中的梯度消失/爆炸问题**,问题依然在于存在 `t` 个 `W` 的连乘项。
- 注意**最后一步**,假设所有神经元都处于**激活状态**,当 `ReLU` 作为 `f` 时,有
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;\begin{aligned}&space;&&\frac{\partial&space;a^{(t)}}{\partial&space;a^{(t-1)}}&=W\\&space;&\Rightarrow&space;&\frac{\partial&space;a^{(t)}}{\partial&space;a^{(0)}}&=W^t&space;\end{aligned}"><img src="../_assets/公式_20180828200604.png" height="" /></a></div>
- 可见**只要 `W` 不是单位矩阵**,还是可能会出现梯度消失/爆炸。
#### 如果使用 `ReLU` 作为 RNN 的激活函数,应该注意什么?
- 综上所述,RNN 因为每一个时间步都**共享参数**的缘故,容易出现**数值溢出问题**
- 因此,推荐的做法是将 `W` 初始化为**单位矩阵**。
- 有实践证明,使用单位矩阵初始化 `W` 并使用 `ReLU` 作为激活函数在一些应用中,与 LSTM 有相似的结果
> [RNN中为什么要采用tanh而不是ReLu作为激活函数? - chaopig 的回答](https://www.zhihu.com/question/61265076/answer/260492479) - 知乎
#### 梯度爆炸的解决方法
- 梯度截断
#### 梯度消失的解决方法(针对 RNN)
- 残差结构
- 门控机制(LSTM、GRU)
## LSTM 相关问题
> [Understanding LSTM Networks](http://colah.github.io/posts/2015-08-Understanding-LSTMs/) - colah's blog
### LSTM 的内部结构
- LSTM 在传统 RNN 的基础上加入了**门控机制**来限制**信息的流动**。
- LSTM (上)与传统 RNN(下) 的内部结构对比
<div align="center"><img src="../_assets/LSTM3-chain.png" height="200" /></div>
<div align="center"><img src="../_assets/LSTM3-SimpleRNN.png" height="200" /></div>
- 具体来说,LSTM 中加入了三个“门”:**遗忘门** `f`、**输入门** `i`、**输出门** `o`,以及一个内部记忆状态 `C`
- “**遗忘门 `f`**”控制前一步记忆状态中的信息有多大程度被遗忘;
<div align="center"><img src="../_assets/LSTM3-focus-f.png" height="200" /></div>
- “**输入门 `i`**”控制当前计算的新状态以多大的程度更新到**记忆状态**中;
<div align="center"><img src="../_assets/LSTM3-focus-i.png" height="200" /></div>
- “**记忆状态 `C`**”间的**状态转移**由输入门和遗忘门共同决定
<div align="center"><img src="../_assets/LSTM3-focus-C.png" height="200" /></div>
- “**输出门 `o`**”控制当前的输出有多大程度取决于当前的记忆状态
<div align="center"><img src="../_assets/LSTM3-focus-o.png" height="200" /></div>
#### 完整的 LSTM 前向传播公式
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cm&space;\large&space;\begin{aligned}&space;f_t&=\sigma(W_f\cdot[h_{t-1};x_t]+b_f)\\&space;i_t&=\sigma(W_i\cdot[h_{t-1};x_t]+b_i)\\&space;\tilde{C}_t&=\tanh(W_C\cdot[h_{t-1};x_t]+b_C)\\&space;C_t&=f_t\circ&space;C_{t-1}+i_t\circ\tilde{C}_t\\&space;o_t&=\sigma(W_o\cdot[h_{t-1};x_t]+b_o)\\&space;h_t&=o_t\circ\tanh(C_t)&space;\end{aligned}"><img src="../_assets/公式_20180828215204.png" height="" /></a></div>
> 其中运算符 `o`(`\circ`) 表示向量中的元素**按位相乘**;有的地方也使用符号 `⊙`(`\odot`)表示
### LSTM 是如何实现长短期记忆的?(遗忘门和输入门的作用)
- LSTM 主要通过**遗忘门**和**输入门**来实现长短期记忆。
- 如果当前时间点的状态中没有重要信息,遗忘门 `f` 中各分量的值将接近 1(`f -> 1`);输入门 `i` 中各分量的值将接近 0(`i -> 0`);此时过去的记忆将会被保存,从而实现**长期记忆**;
- 如果当前时间点的状态中出现了重要信息,且之前的记忆不再重要,则 `f -> 0`,`i -> 1`;此时过去的记忆被遗忘,新的重要信息被保存,从而实现**短期记忆**;
- 如果当前时间点的状态中出现了重要信息,但旧的记忆也很重要,则 `f -> 1`,`i -> 1`。
### LSTM 里各部分使用了不同的激活函数,为什么?可以使用其他激活函数吗?
- 在 LSTM 中,所有**控制门**都使用 sigmoid 作为激活函数(遗忘门、输入门、输出门);
- 在计算**候选记忆**或**隐藏状态**时,使用双曲正切函数 tanh 作为激活函数
**sigmoid 的“饱和”性**
- 所谓饱和性,即输入超过一定范围后,输出几乎不再发生明显变化了
- sigmoid 的值域为 `(0, 1)`,符合**门控**的定义:
- 当输入较大或较小时,其输出会接近 1 或 0,从而保证门的开或关;
- 如果使用非饱和的激活函数,将难以实现**门控/开关**的效果。
- sigmoid 是现代**门控单元**中的共同选择。
**为什么使用 tanh?**
- 使用 tanh 作为计算状态时的激活函数,主要是因为其**值域**为 `(-1, 1)`:
- 一方面,这与多数场景下特征分布以 0 为中心相吻合;
- 另一方面,可以避免在前向传播的时候发生**数值问题**(主要是上溢)
- 此外,tanh 比 sigmoid 在 0 附近有更大的梯度,通常会使模型收敛更快。
> 早期,使用 `h(x) = 2*sigmoid(x) - 1` 作为激活函数,该激活函数的值域也是 `(-1, 1)`
**Hard gate**
- 在一些对计算能力有限制的设备中,可能会使用 hard gate
- 因为 sigmoid 求指数时需要一定的计算量,此时会使用 0/1 门(hard gate)让门控输出 0 或 1 的离散值。
### 窥孔机制
> Gers F A, Schmidhuber J. Recurrent nets that time and count[C]. 2000.
- LSTM 通常使用输入 `x_t` 和上一步的隐状态 `h_{t-1}` 参与门控计算;
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cs&space;\large&space;g=\sigmoid(W\cdot[x_t;h_{t-1}]+b)"><img src="../_assets/公式_20180829114415.png" height="" /></a></div>
- **窥孔机制**指让记忆状态也参与门控的计算中
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cs&space;\large&space;g=\sigmoid(W\cdot[x_t;h_{t-1};c_{t-1}]+b)"><img src="../_assets/公式_20180829114459.png" height="" /></a></div>
### GRU 与 LSTM 的关系
- GRU 认为 LSTM 中的**遗忘门**和**输入门**的功能有一定的重合,于是将其合并为一个**更新门**。
> 其实,早期的 LSTM 中本来就是没有**遗忘门**的 [1],因为研究发现加入遗忘门能提升性能 [2],从而演变为如今的 LSTM.
>> [1] Hochreiter S, Schmidhuber J. Long short-term memory[J]. 1997.<br/>
>> [2] Gers F A, Schmidhuber J, Cummins F. Learning to forget: Continual prediction with LSTM[J]. 1999.
- GRU 相比 LSTM 的**改动**:
- GRU 把遗忘门和输入门合并为**更新门(update)** `z`,并使用**重置门(reset)** `r` 代替输出门;
- **合并**了记忆状态 `C` 和隐藏状态 `h`
<div align="center"><img src="../_assets/LSTM3-var-GRU.png" height="200" /></div>
其中
- **更新门** `z`用于控制前一时刻的状态信息被**融合**到当前状态中的程度
- **重置门** `r`用于控制忽略前一时刻的状态信息的程度
#### 完整的 GRU 前向传播公式
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cm&space;\large&space;\begin{aligned}&space;z_t&=\sigma(W_z\cdot[h_{t-1};x_t])\\&space;r_t&=\sigma(W_r\cdot[h_{t-1};x_t])\\&space;\tilde{h}_t&=\tanh(W_h\cdot[r_t\odot&space;h_{t-1};x_t])\\&space;h_t&=(1-z_t)\odot&space;h_{t-1}+z_t\odot\tilde{h}_t&space;\end{aligned}"><img src="../_assets/公式_20180829104207.png" height="" /></a></div>
> 遵从原文表示,没有加入偏置
================================================
FILE: A-深度学习/C-专题-优化算法.md
================================================
专题-优化算法
===
Reference
---
- 【**必读**】[An overview of gradient descent optimization algorithms](http://ruder.io/optimizing-gradient-descent/) - Sebastian Ruder
Index
---
<!-- TOC -->
- [梯度下降](#梯度下降)
- [随机梯度下降](#随机梯度下降)
- [小批量随机梯度下降](#小批量随机梯度下降)
- [小批量 SGD 的更新过程](#小批量-sgd-的更新过程)
- [“批”的大小对优化效果的影响](#批的大小对优化效果的影响)
- [随机梯度下降存在的问题](#随机梯度下降存在的问题)
- [随机梯度下降的改进方向](#随机梯度下降的改进方向)
- [动量(Momentum)算法](#动量momentum算法)
- [带动量的 SGD](#带动量的-sgd)
- [NAG 算法(Nesterov 动量)](#nag-算法nesterov-动量)
- [自适应学习率的优化算法](#自适应学习率的优化算法)
- [AdaGrad](#adagrad)
- [RMSProp](#rmsprop)
- [AdaDelta](#adadelta)
- [Adam](#adam)
- [AdaMax](#adamax)
- [Nadam](#nadam)
- [如何选择这些优化算法?](#如何选择这些优化算法)
- [各优化算法的可视化](#各优化算法的可视化)
- [基于二阶梯度的优化算法](#基于二阶梯度的优化算法)
- [牛顿法](#牛顿法)
- [为什么牛顿法比梯度下降收敛更快?](#为什么牛顿法比梯度下降收敛更快)
- [牛顿法的优缺点](#牛顿法的优缺点)
- [拟牛顿法 TODO](#拟牛顿法-todo)
<!-- /TOC -->
## 梯度下降
> ../数学/[梯度下降法](../C-数学/B-深度学习的核心#梯度下降法)
- 梯度下降是一种**优化算法**,通过**迭代**的方式寻找模型的**最优参数**;
- 所谓最优参数指的是使**目标函数**达到最小值时的参数;
- 当目标函数是**凸函数**时,梯度下降的解是全局最优解;但在一般情况下,**梯度下降无法保证全局最优**。
- 微积分中使用**梯度**表示函数增长最快的方向;因此,神经网络中使用**负梯度**来指示目标函数下降最快的方向。
- **梯度**实际上是损失函数对网络中每个参数的**偏导**所组成的向量;
- **梯度**仅仅指示了对于每个参数各自增长最快的方向;因此,梯度无法保证**全局方向**就是函数为了达到最小值应该前进的方向。
- **梯度**的具体计算方法即**反向传播**。
- **负梯度**中的每一项可以认为传达了**两个信息**:
- 正负号在告诉输入向量应该调大还是调小(正调大,负调小)
- 每一项的相对大小表明每个参数对函数值达到最值的**影响程度**;
<div align="center"><img src="../_assets/TIM截图20180703103757.png" height="" /></div>
## 随机梯度下降
- 基本的梯度下降法每次使用**所有训练样本**的**平均损失**来更新参数;
- 因此,经典的梯度下降在每次对模型参数进行更新时,需要遍历所有数据;
- 当训练样本的数量很大时,这需要消耗相当大的计算资源,在实际应用中基本不可行。
- **随机梯度下降**(SGD)每次使用单个样本的损失来近似平均损失
### 小批量随机梯度下降
- 为了降低随机梯度的**方差**,使模型迭代更加稳定,实践中会使用**一批**随机数据的损失来近似平均损失。
> ../机器学习基础/[偏差与方差](../A-机器学习/A-机器学习基础#偏差与方差)
- 使用批训练的另一个主要目的,是为了利用高度优化的**矩阵运算**以及**并行计算框架**。
### 小批量 SGD 的更新过程
1. 在训练集上抽取指定大小(batch_size)的一批数据 `{(x,y)}`
1. 【**前向传播**】将这批数据送入网络,得到这批数据的预测值 `y_pred`
1. 计算网络在这批数据上的损失,用于衡量 `y_pred` 和 `y` 之间的距离
1. 【**反向传播**】计算损失相对于所有网络中**可训练参数**的梯度 `g`
1. 将参数沿着**负梯度**的方向移动,即 `W -= lr * g`
> `lr` 表示学习率 learning rate
<div align="center"><img src="../_assets/TIM截图20180611195027.png" height="250" /></div>
### “批”的大小对优化效果的影响
> 《深度学习》 8.1.3 批量算法和小批量算法
- **较大的批能得到更精确的梯度估计**,但回报是小于线性的。
- **较小的批能带来更好的泛化误差**,泛化误差通常在批大小为 1 时最好。
- 原因可能是由于小批量在学习过程中带来了**噪声**,使产生了一些正则化效果 (Wilson and Martinez, 2003)
- 但是,因为梯度估计的高方差,小批量训练需要**较小的学习率**以保持稳定性,这意味着**更长的训练时间**。
- 当批的大小为 **2 的幂**时能充分利用矩阵运算操作,所以批的大小一般取 32、64、128、256 等。
<!-- - **内存消耗和批的大小成正比**,当批量处理中的所有样本可以并行处理时。
- 在某些硬件上使用特定大小可以减少运行时间。尤其是在使用 GPU 时,通常使用 **2 的幂数**作为批量大小可以获得更少的运行时间。一般,2 的幂数的**取值范围是 32 到 256**,16 有时在尝试大模型时使用。 -->
### 随机梯度下降存在的问题
- 随机梯度下降(SGD)放弃了**梯度的准确性**,仅采用一部分样本来估计当前的梯度;因此 SGD 对梯度的估计常常出现偏差,造成目标函数收敛不稳定,甚至不收敛的情况。
- 无论是经典的梯度下降还是随机梯度下降,都可能陷入**局部极值点**;除此之外,SGD 还可能遇到“**峡谷**”和“**鞍点**”两种情况
- **峡谷**类似一个带有**坡度**的狭长小道,左右两侧是“**峭壁**”;在**峡谷**中,准确的梯度方向应该沿着坡的方向向下,但粗糙的梯度估计使其稍有偏离就撞向两侧的峭壁,然后在两个峭壁间来回**震荡**。
- **鞍点**的形状类似一个马鞍,一个方向两头翘,一个方向两头垂,而**中间区域近似平地**;一旦优化的过程中不慎落入鞍点,优化很可能就会停滞下来。
<div align="center"><img src="../_assets/TIM截图20180826113534.png" height="200" /></div>
## 随机梯度下降的改进方向
- SGD 的改进遵循两个方向:**惯性保持**和**环境感知**
> 这两个提法来自《百面机器学习》
- **惯性保持**指的是加入**动量** SGD 算法;
> [动量(Momentum)方法](#动量momentum方法)
- **环境感知**指的是根据不同参数的一些**经验性判断**,**自适应**地确定**每个参数的学习速率**
> [自适应学习率的优化算法](#自适应学习率的优化算法)
**训练词向量的例子**
- 不同词出现的频率是不同的,**数据的稀疏性会影响其参数的稀疏性**;
- 具体来说,**对低频词如果不加措施**,其参数的梯度在多数情况下为 0;换言之,这些参数更新的频率很低,导致难以收敛。
- 在实践中,我们希望学习**低频词**的参数时具有**较大的学习率**,而高频词其参数的更新幅度可以小一些。
## 动量(Momentum)算法
### 带动量的 SGD
- 引入**动量**(Momentum)方法一方面是为了解决“峡谷”和“鞍点”问题;一方面也可以用于SGD 加速,特别是针对**高曲率**、小幅但是方向一致的梯度。
- 如果把原始的 SGD 想象成一个**纸团**在重力作用向下滚动,由于**质量小**受到山壁弹力的干扰大,导致来回震荡;或者在鞍点处因为**质量小**速度很快减为 0,导致无法离开这块平地。
- **动量**方法相当于把纸团换成了**铁球**;不容易受到外力的干扰,轨迹更加稳定;同时因为在鞍点处因为**惯性**的作用,更有可能离开平地。
- 动量方法以一种廉价的方式模拟了二阶梯度(牛顿法)
<div align="center"><img src="../_assets/TIM截图20180819110834.png" height="200" /></div>
- **参数更新公式**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;\begin{aligned}&space;&v_t=\alpha&space;v_{t-1}-\epsilon&space;g_t\\&space;&\Delta\boldsymbol{\theta}\,\,\,\leftarrow&space;v_t\\&space;&\boldsymbol{\theta}_{t+1}\leftarrow&space;\boldsymbol{\theta}_t+\Delta\boldsymbol{\theta}&space;\end{aligned}"><img src="../_assets/公式_20180826203915.png" height="" /></a></div>
- 从形式上看, 动量算法引入了变量 `v` 充当速度角色,以及相相关的超参数 `α`。
- 原始 SGD 每次更新的步长只是梯度乘以学习率;现在,步长还取决于**历史梯度序列**的大小和排列;当许多连续的梯度指向**相同的方向**时,步长会被不断增大;
- **动量算法描述**
<div align="center"><img src="../_assets/TIM截图20180611203427.png" height="250" /></div>
- 如果动量算法总是观测到梯度 `g`,那么它会在 `−g` 方向上不断加速,直到达到**最终速度**。
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;v\leftarrow&space;\alpha&space;v-\epsilon&space;g\quad&space;\Rightarrow&space;\quad&space;v\leftarrow&space;\frac{-\epsilon&space;g}{1-\alpha}"><img src="../_assets/公式_20180826161333.png" height="" /></a></div>
- 在实践中, `α` 的一般取 `0.5, 0.9, 0.99`,分别对应**最大** `2` 倍、`10` 倍、`100` 倍的步长
- 和学习率一样,`α` 也可以使用某种策略在训练时进行**自适应调整**;一般初始值是一个较小的值,随后会慢慢变大。
> [自适应学习率的优化方法](#自适应学习率的优化方法)
### NAG 算法(Nesterov 动量)
- **NAG 把梯度计算放在对参数施加当前速度之后**。
- 这个“**提前量**”的设计让算法有了对前方环境“**预判**”的能力。Nesterov 动量可以解释为往标准动量方法中添加了一个**修正因子**。
- **NAG 算法描述**
<div align="center"><img src="../_assets/TIM截图20180611211753.png" height="250" /></div>
## 自适应学习率的优化算法
> 《深度学习》 8.5 自适应学习率算法
### AdaGrad
> [Duchi et al., 2011](http://jmlr.org/papers/v12/duchi11a.html)
- 该算法的思想是独立地适应模型的每个参数:具有较大偏导的参数相应有一个较大的学习率,而具有小偏导的参数则对应一个较小的学习率
- 具体来说,每个参数的学习率会缩放各参数反比于其**历史梯度平方值总和的平方根**
- **AdaGrad 算法描述**
<div align="center"><img src="../_assets/TIM截图20180611214508.png" height="" /></div>
- 注意:全局学习率 `ϵ` 并没有更新,而是每次应用时被缩放
**AdaGrad 存在的问题**
- 学习率是单调递减的,训练后期学习率过小会导致训练困难,甚至提前结束
- 需要设置一个全局的初始学习率
### RMSProp
> Hinton, 2012
- RMSProp 主要是为了解决 AdaGrad 方法中**学习率过度衰减**的问题—— AdaGrad 根据平方梯度的**整个历史**来收缩学习率,可能使得学习率在达到局部最小值之前就变得太小而难以继续训练;
- RMSProp 使用**指数衰减平均**(递归定义)以丢弃遥远的历史,使其能够在找到某个“凸”结构后快速收敛;此外,RMSProp 还加入了一个超参数 `ρ` 用于控制衰减速率。
> ./术语表/[指数衰减平均](./备忘-术语表#指数加权平均指数衰减平均)
- 具体来说(对比 AdaGrad 的算法描述),即修改 `r` 为
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{aligned}&space;&r\leftarrow&space;\mathbb{E}[g^2]_t=\rho\cdot\mathbb{E}[g^2]_{t-1}+(1-\rho)\cdot&space;g^2&space;\end{aligned}"><img src="../_assets/公式_20180819204219.png" height="" /></a></div>
记
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{aligned}&space;RMS[g]_t=\sqrt{\mathbb{E}[g^2]_t+\delta}&space;\end{aligned}"><img src="../_assets/公式_20180819204052.png" height="" /></a></div>
则
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\Delta\theta_t=-\frac{\epsilon}{RMS[g]_t}\odot&space;g_t"><img src="../_assets/公式_20180819204612.png" height="" /></a></div>
> 其中 `E` 表示期望,即平均;`δ` 为平滑项,具体为一个小常数,一般取 `1e-8 ~ 1e-10`(Tensorflow 中的默认值为 `1e-10`)
- **RMSProp** 建议的**初始值**:全局学习率 `ϵ=1e-3`,衰减速率 `ρ=0.9`
- **RMSProp 算法描述**
<div align="center"><img src="../_assets/TIM截图20180611215422.png" height="" /></div>
- 带 **Nesterov 动量**的 **RMSProp**
<div align="center"><img src="../_assets/TIM截图20180611215923.png" height="" /></div>
- 经验上,RMSProp 已被证明是一种有效且实用的深度神经网络优化算法。
- RMSProp 依然需要设置一个全局学习率,同时又多了一个超参数(推荐了默认值)。
### AdaDelta
- AdaDelta 和 RMSProp 都是为了解决 AdaGrad 对学习率过度衰减的问题而产生的。
- AdaDelta 和 RMSProp 是独立发现的,AdaDelta 的前半部分与 RMSProp 完全一致;
- AdaDelta 进一步解决了 AdaGrad 需要设置一个全局学习率的问题
- 具体来说,即
<div align="center"><img src="../_assets/公式_20180819203034.png" height="" /></div>
此时,AdaDelta 已经不需要设置全局学习率了
> 关于 `RMS` 的定义,见 [RMSProp](#rmsprop)
### Adam
> Kingma and Ba, 2014
- Adam 在 RMSProp 方法的基础上更进一步:
- 除了加入**历史梯度平方的指数衰减平均**(`r`)外,
- 还保留了**历史梯度的指数衰减平均**(`s`),相当于**动量**。
- Adam 行为就像一个带有摩擦力的小球,在误差面上倾向于平坦的极小值。
> ./术语表/[指数衰减平均](./备忘-术语表#指数加权平均指数衰减平均)
- **Adam 算法描述**
<div align="center"><img src="../_assets/TIM截图20180611220109.png" height="" /></div>
**偏差修正**
- 注意到,`s` 和 `r` 需要初始化为 `0`;且 `ρ1` 和 `ρ2` 推荐的初始值都很接近 `1`(`0.9` 和 `0.999`)
- 这将导致在训练初期 `s` 和 `r` 都很小(偏向于 0),从而训练缓慢。
- 因此,Adam 通过修正偏差来抵消这个倾向。
### AdaMax
- Adam 的一个变种,对梯度平方的处理由**指数衰减平均**改为**指数衰减求最大值**
### Nadam
- Nesterov 动量版本的 Adam
## 如何选择这些优化算法?
- 各自适应学习率的优化算法表现不分伯仲,没有哪个算法能在所有任务上脱颖而出;
- 目前,最流行并且使用很高的优化算法包括 SGD、带动量的 SGD、RMSProp、带动量的 RMSProp、AdaDelta 和 Adam。
- 具体使用哪个算法取决于使用者对算法的熟悉程度,以便调节超参数。
### 各优化算法的可视化
- SGD 各优化方法在损失曲面上的表现
<div align="center"><img src="../_assets/contours_evaluation_optimizers.gif" height="250" /></div>
- SGD 各优化方法在**鞍点**处上的表现
<div align="center"><img src="../_assets/saddle_point_evaluation_optimizers.gif" height="300" /></div>
## 基于二阶梯度的优化算法
### 牛顿法
- 梯度下降使用的梯度信息实际上是**一阶导数**
- 牛顿法除了一阶导数外,还会使用**二阶导数**的信息
- 根据导数的定义,一阶导描述的是函数值的变化率,即**斜率**;二阶导描述的则是斜率的变化率,即曲线的弯曲程度——**曲率**
> 数学/[泰勒级数](../C-数学/B-微积分的本质#泰勒级数)
**牛顿法更新过程** TODO
> 《统计学习方法》 附录 B
#### 为什么牛顿法比梯度下降收敛更快?
> [常见的几种最优化方法(梯度下降法、牛顿法、拟牛顿法、共轭梯度法等)](https://www.cnblogs.com/shixiangwan/p/7532830.html) - 蓝鲸王子 - 博客园
**几何理解**
- 牛顿法就是用一个**二次曲面**去拟合你当前所处位置的局部曲面;而梯度下降法是用一个平面去拟合当前的局部曲面。
- 通常情况下,二次曲面的拟合会比平面更好,所以牛顿法选择的**下降路径**会更符合真实的最优下降路径。
**通俗理解**
- 比如你想找一条最短的路径走到一个盆地的最底部,
- 梯度下降法每次只从你当前所处位置选一个坡度最大的方向走一步;
- 牛顿法在选择方向时,不仅会考虑坡度是否够大,还会考虑你走了一步之后,坡度是否会变得更大。
- 所以,牛顿法比梯度下降法看得更远,能**更快**地走到最底部。
#### 牛顿法的优缺点
- **优点**
- 收敛速度快,能用更少的迭代次数找到最优解
- **缺点**
- 每一步都需要求解目标函数的 **Hessian 矩阵**的逆矩阵,计算复杂
> Hessian 矩阵即由二阶偏导数构成的方阵
### 拟牛顿法 TODO
- 用其他近似方法代替求解 **Hessian 矩阵**的逆矩阵
================================================
FILE: A-深度学习/D-专题-序列建模.md
================================================
专题-序列建模
===
**相关专题**
- [专题-RNN](./B-专题-RNN.md)
- [专题-RNN](./B-专题-RNN.md)
Index
---
<!-- TOC -->
- [序列建模简述](#序列建模简述)
- [Seq2Seq](#seq2seq)
- [解码方法(贪心、Beam Search、维特比算法)](#解码方法贪心beam-search维特比算法)
- [Beam Search(集束搜索)](#beam-search集束搜索)
- [维特比(Viterbi)算法 TODO](#维特比viterbi算法-todo)
- [其他最短路径算法](#其他最短路径算法)
- [构建 Seq2Seq 一般做法](#构建-seq2seq-一般做法)
- [序列的表示学习](#序列的表示学习)
- [学习任务无关的 Sentence Embedding](#学习任务无关的-sentence-embedding)
- [CNN 与序列建模](#cnn-与序列建模)
- [一维卷积](#一维卷积)
- [时间卷积网络(TCN)](#时间卷积网络tcn)
- [WaveNet](#wavenet)
- [因果卷积](#因果卷积)
- [空洞卷积](#空洞卷积)
- [Highway 网络](#highway-网络)
- [残差模块](#残差模块)
- [Reference](#reference)
<!-- /TOC -->
## 序列建模简述
> [从循环到卷积,探索序列建模的奥秘](https://mp.weixin.qq.com/s/f0sv7c-H5o5L_wy2sUonUQ) - 机器之心
- 序列建模就是将一个**输入/观测**序列映射到一个**输出/标记**序列
> 《统计学习方法》中称之为标注问题
- 在**传统机器学习**方法中,常用的模型有:隐马尔可夫模型(HMM),条件随机场(CRF)等
> 机器学习专题 TODO
- 在**深度学习领域**的很长一段时间里,RNN/LSTM 都是序列建模的首选。
> 《深度学习》 10 序列建模:循环和递归网络
- 最近,CNN 开始在序列建模领域流行,一个**关键想法**是——在一维时间序列上使用**一维卷积运算**
<div align="center"><img src="../_assets/TIM截图20180808105242.png" height="" /></div>
> [CNN for Sentence Classification](https://arxiv.org/abs/1408.5882) (Kim, 2014)
## Seq2Seq
- Seq2Seq 的核心思想是把一个输出序列,通过**编码**(Encode)和**解码**(Decode)两个过程映射到一个新的输出序列。
<div align="center"><img src="../_assets/seq2seq.png" height="" /></div>
> [Translation with a Sequence to Sequence Network and Attention](https://pytorch.org/tutorials/intermediate/seq2seq_translation_tutorial.html) — PyTorch
- 经典的 Seq2Seq 模型中,**编码器**(Encoder)和**解码器**(Decoder)都使用 **RNN** 进行建模
<!-- <div align="center"><img src="../_assets/seq2seq-text.jpg" height="250" /></div> -->
<div align="center"><img src="../_assets/TIM截图20180829162307.png" height="" /></div>
> 上图是一次**机器翻译**的过程,输入是一个源语言的一个句子 "A B C",Encoder 一次读入每个单词直到结束符 `<EOS>`(End of Sequence);<br/>
> 在解码的第一步,Decoder 先读取 **Encoder 的最终状态**,生成目标语言的第一个词 'W',接着 Decoder 读取第一步的输出 'W' 作为第二步的输入,进而生成第二个词 'X',如此直到生成 `<EOS>` 或达到指定**最大长度**。
>> Decoder 生成每个词还要结合当前时间步的隐状态(如果是 LSTM 还有 记忆状态),更深入的细节暂时略过。
- Seq2Seq 之所以流行,是因为它为不同的问题提供了一套**端到端**(End to End)的解决方案,免去了繁琐的中间步骤,从输入直接得到结果.
- 根据任务的输入输出差异,编码器和解码器的设计也不尽相同,但是“Encoder-Decoder”的结构都是一致的。
- **机器翻译**:输入源语言的一个句子,输出目标语言的句子;
- **机器问答**:输入问题/查询,输出答案;
- **文本摘要**:输入一个长句或段落,输出一个摘要短句;
- **语音识别**:输入是音频序列信号,输出为识别出的文本;
- **图像描述**:输入是图像经过视觉网络的特征,输出是图像的描述文本。
- ...
### 解码方法(贪心、Beam Search、维特比算法)
- Seq2Seq 中的解码方法主要有三种:**贪心**、**Beam Search**、**维特比算法**(动态规划)
- 这三种方法的思想本质上是一致的,假设选取相同的评价标准(比如概率最大、路径最短等)
- **贪心**每到达一个节点,只选择当前状态的**最优结果**,其他都忽略,直到最后一个节点;贪心法只能得到某个局部最优解;
- **Beam Search** 会在每个节点保存当前**最优的 k 个结果**(排序后),其他结果将被“剪枝”,因为每次都有 k 个分支进入下一个状态。Beam Search 也不能保证全局最优,但能以较大的概率得到全局最优解。
- **维特比算法**利用**动态规划**的方法可以保证得到全局最优解,但是当候选状态极大时,需要消耗大量的时间和空间搜索和保存状态,因此维特比算法只适合状态集比较小的情况。
#### Beam Search(集束搜索)
- Beam Search 是一种启发式算法
- 该方法会保存前 `beam_size` 个最佳状态,每次解码时会根据所有保存的状态进行下一步**扩展**和**排序**,依然只保留前 `beam_size` 个最佳状态;循环迭代至最后一步,保存最佳选择。
- Beam Search 图示
<div align="center"><img src="../_assets/TIM截图20180829172245.png" height="" /></div>
- 当 `beam_size = 1` 时,Beam Search 即退化为贪心搜索
- 一般为了计算资源和性能的平衡,`beam_size` 会选择一个适中的范围;通常 `beam_size` 取 `8~12` 即可(机器翻译、文本摘要)
#### 维特比(Viterbi)算法 TODO
> [维特比算法通俗理解](http://www.hankcs.com/program/algorithm/%E7%BB%B4%E7%89%B9%E6%AF%94%E7%AE%97%E6%B3%95%E9%80%9A%E4%BF%97%E7%90%86%E8%A7%A3.html)-码农场
- 利用**动态规划**可以求解任何图中的最短路径问题;
- **维特比算法**是针对一种特殊的图结构——“**篱笆网络**”——而提出的算法,用于在概率图模型中求解**概率最大路径**;
#### 其他最短路径算法
- Dijkstra 算法(迪杰斯特拉算法)
- 基于贪心
- 用于求解某个顶点到其他所有顶点之间的最短路径
- 时间复杂度 `O(N^2)`
- Dijkstra 算法的使用范围比 Viterbi 算法更广,可用于求解大部分图结构中的最短路径。
- Floyd 算法(弗洛伊德算法)
- 求解的是每一对顶点之间的最短路径
- 时间复杂度 `O(N^3)`
### 构建 Seq2Seq 一般做法
- 堆叠 RNN/CNN
> [CNN 与序列建模](#cnn-与序列建模)
- Dropout 机制
- **残差**连接
- **Attention 机制**
<!-- > [Attention 专题](./DL-C-专题-Attention.md) -->
## 序列的表示学习
- 序列的表示学习指学习单个序列的特征表示,通常作为另一个任务的子过程,或者用于迁移学习等。
- 整个学习的过程相当于 Seq2Seq 中的 Encoder 部分
### 学习任务无关的 Sentence Embedding
> [1703.03130] [A Structured Self-attentive Sentence Embedding](https://arxiv.org/abs/1703.03130)
**模型基本结构**,更多细节参考原文
- 待学习的句子
## CNN 与序列建模
- 一般认为 CNN 擅长处理**网格结构的数据**,比如图像(二维像素网络)
- 卷积层试图将神经网络中的每一小块进行更加深入的分析,从而得出抽象程度更高的特征。
- 一般来说通过卷积层处理的神经元结点矩阵会变得更深,即神经元的组织在第三个维度上会增加。
- **时序数据**同样可以认为是在时间轴上有规律地采样而形成的一维网格
<div align="center"><img src="../_assets/TIM截图20180808105242.png" height="" /></div>
> [CNN for Sentence Classification](https://arxiv.org/abs/1408.5882) (Kim, 2014)
### 一维卷积
- 适用于序列建模的卷积网络一般就是采用的是一维卷积
<div align="center"><img src="../_assets/TIM截图20180808135512.png" height="200" /></div>
- 最下层的 `x_i` 可视为句子的输入序列
- 最上层的 `g_j` 即输出序列
- 流行的网络中一般使用 **embedding** 作为输入,也就说每个 `x_i` 其实是一个多维向量 `v(x_i)`
> ../自然语言处理/[词向量](../B-自然语言处理/B-专题-词向量.md)
## 时间卷积网络(TCN)
### WaveNet
### 因果卷积
**Reference**
- [WaveNet: A Generative Model for Raw Audio](https://deepmind.com/blog/wavenet-generative-model-raw-audio/) | DeepMind
- ibab/[tensorflow-wavenet](https://github.com/ibab/tensorflow-wavenet) - GitHub
### 空洞卷积
### Highway 网络
- 一种门限机制
### 残差模块
> [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385) (He, et al., 2015)
## Reference
- 自然语言处理之序列模型 - 小象学院
- [从循环到卷积,探索序列建模的奥秘](https://mp.weixin.qq.com/s/f0sv7c-H5o5L_wy2sUonUQ) - 机器之心
================================================
FILE: A-深度学习/《深度学习》整理.md
================================================
**问题列表**
---
<!-- TOC -->
- [如何设置网络的初始值?*](#如何设置网络的初始值)
- [梯度爆炸的解决办法***](#梯度爆炸的解决办法)
- [神经网络(MLP)的万能近似定理*](#神经网络mlp的万能近似定理)
- [神经网络中,深度与宽度的关系,及其表示能力的差异**](#神经网络中深度与宽度的关系及其表示能力的差异)
- [在深度神经网络中,引入了隐藏层(非线性单元),放弃了训练问题的凸性,其意义何在?**](#在深度神经网络中引入了隐藏层非线性单元放弃了训练问题的凸性其意义何在)
- [稀疏表示,低维表示,独立表示*](#稀疏表示低维表示独立表示)
- [局部不变性(平滑先验)及其在基于梯度的学习上的局限性*](#局部不变性平滑先验及其在基于梯度的学习上的局限性)
- [为什么交叉熵损失相比均方误差损失能提高以 sigmoid 和 softmax 作为激活函数的层的性能?**](#为什么交叉熵损失相比均方误差损失能提高以-sigmoid-和-softmax-作为激活函数的层的性能)
- [分段线性单元(如 ReLU)代替 sigmoid 的利弊***](#分段线性单元如-relu代替-sigmoid-的利弊)
- [在做正则化过程中,为什么只对权重做正则惩罚,而不对偏置做权重惩罚*](#在做正则化过程中为什么只对权重做正则惩罚而不对偏置做权重惩罚)
- [列举常见的一些范数及其应用场景,如 L0、L1、L2、L∞、Frobenius等范数**](#列举常见的一些范数及其应用场景如-l0l1l2l∞frobenius等范数)
- [L1 和 L2 范数的异同***](#l1-和-l2-范数的异同)
- [为什么 L1 正则化可以产生稀疏权值,L2 正则化可以防止过拟合?**](#为什么-l1-正则化可以产生稀疏权值l2-正则化可以防止过拟合)
- [为什么 L1 正则化可以产生稀疏权值,而 L2 不会?](#为什么-l1-正则化可以产生稀疏权值而-l2-不会)
- [为什么 L1 和 L2 正则化可以防止过拟合?](#为什么-l1-和-l2-正则化可以防止过拟合)
- [简单介绍常用的激活函数,如 sigmoid、relu、softplus、tanh、RBF 及其应用场景***](#简单介绍常用的激活函数如-sigmoidrelusoftplustanhrbf-及其应用场景)
- [整流线性单元(ReLU)](#整流线性单元relu)
- [sigmoid 与 tanh(双曲正切函数)](#sigmoid-与-tanh双曲正切函数)
- [其他激活函数(隐藏单元)](#其他激活函数隐藏单元)
- [sigmoid 和 softplus 的一些性质](#sigmoid-和-softplus-的一些性质)
- [Jacobian 和 Hessian 矩阵及其在深度学习中的重要性*](#jacobian-和-hessian-矩阵及其在深度学习中的重要性)
- [信息熵、KL 散度(相对熵)与交叉熵**](#信息熵kl-散度相对熵与交叉熵)
- [自信息与信息熵](#自信息与信息熵)
- [相对熵(KL 散度)与交叉熵](#相对熵kl-散度与交叉熵)
- [如何避免数值计算中的上溢和下溢问题,以 softmax 为例*](#如何避免数值计算中的上溢和下溢问题以-softmax-为例)
- [训练误差、泛化误差;过拟合、欠拟合;模型容量,表示容量,有效容量,最优容量的概念; 奥卡姆剃刀原则*](#训练误差泛化误差过拟合欠拟合模型容量表示容量有效容量最优容量的概念-奥卡姆剃刀原则)
- [过拟合的一些解决方案***](#过拟合的一些解决方案)
- [高斯分布的广泛应用的原因**](#高斯分布的广泛应用的原因)
- [高斯分布(Gaussian distribution)](#高斯分布gaussian-distribution)
- [为什么推荐使用高斯分布?](#为什么推荐使用高斯分布)
- [表示学习、自编码器与深度学习**](#表示学习自编码器与深度学习)
- [L1、L2 正则化与 MAP 贝叶斯推断的关系*](#l1l2-正则化与-map-贝叶斯推断的关系)
- [什么是欠约束,为什么大多数的正则化可以使欠约束下的欠定问题在迭代过程中收敛*](#什么是欠约束为什么大多数的正则化可以使欠约束下的欠定问题在迭代过程中收敛)
- [为什么考虑在模型训练时对输入 (隐藏单元或权重) 添加方差较小的噪声?*](#为什么考虑在模型训练时对输入-隐藏单元或权重-添加方差较小的噪声)
- [多任务学习、参数绑定和参数共享***](#多任务学习参数绑定和参数共享)
- [多任务学习](#多任务学习)
- [参数绑定和参数共享](#参数绑定和参数共享)
- [Dropout 与 Bagging 集成方法的关系,Dropout 带来的意义与其强大的原因***](#dropout-与-bagging-集成方法的关系dropout-带来的意义与其强大的原因)
- [Bagging 集成方法](#bagging-集成方法)
- [Dropout](#dropout)
- [批梯度下降法(Batch SGD)更新过程中,批的大小会带来怎样的影响**](#批梯度下降法batch-sgd更新过程中批的大小会带来怎样的影响)
- [如何避免深度学习中的病态,鞍点,梯度爆炸,梯度弥散?***](#如何避免深度学习中的病态鞍点梯度爆炸梯度弥散)
- [病态(ill-conditioning)](#病态ill-conditioning)
- [鞍点(saddle point)](#鞍点saddle-point)
- [长期依赖与梯度爆炸、消失](#长期依赖与梯度爆炸消失)
- [SGD 以及学习率的选择方法、带动量的 SGD***](#sgd-以及学习率的选择方法带动量的-sgd)
- [(批)随机梯度下降(SGD)与学习率](#批随机梯度下降sgd与学习率)
- [带动量的 SGD](#带动量的-sgd)
- [自适应学习率算法:AdaGrad、RMSProp、Adam 等***](#自适应学习率算法adagradrmspropadam-等)
- [AdaGrad](#adagrad)
- [RMSProp](#rmsprop)
- [Adam](#adam)
- [基于二阶梯度的优化方法:牛顿法、共轭梯度、BFGS 等的做法*](#基于二阶梯度的优化方法牛顿法共轭梯度bfgs-等的做法)
- [批标准化(Batch Normalization)的意义**](#批标准化batch-normalization的意义)
- [神经网络中的卷积,以及卷积的动机:稀疏连接、参数共享、等变表示(平移不变性)***](#神经网络中的卷积以及卷积的动机稀疏连接参数共享等变表示平移不变性)
- [稀疏连接(sparse connectivity)](#稀疏连接sparse-connectivity)
- [参数共享(parameter sharing)](#参数共享parameter-sharing)
- [平移等变|不变性(translation invariant)](#平移等变不变性translation-invariant)
- [卷积中不同零填充的影响**](#卷积中不同零填充的影响)
- [基本卷积的变体:反卷积、空洞卷积***](#基本卷积的变体反卷积空洞卷积)
- [转置卷积|反卷积(Transposed convolution)](#转置卷积反卷积transposed-convolution)
- [空洞卷积|扩张卷积(Dilated convolution)](#空洞卷积扩张卷积dilated-convolution)
- [池化、池化(Pooling)的作用***](#池化池化pooling的作用)
- [卷积与池化的意义、影响(作为一种无限强的先验)**](#卷积与池化的意义影响作为一种无限强的先验)
- [RNN 的几种基本设计模式](#rnn-的几种基本设计模式)
- [RNN 更新方程(前向传播公式),包括 LSTM、GRU 等***](#rnn-更新方程前向传播公式包括-lstmgru-等)
- [BPTT(back-propagation through time,通过时间反向传播)**](#bpttback-propagation-through-time通过时间反向传播)
- [自编码器在深度学习中的意义*](#自编码器在深度学习中的意义)
- [自编码器一些常见的变形与应用:正则自编码器、稀疏自编码器、去噪自编码器*](#自编码器一些常见的变形与应用正则自编码器稀疏自编码器去噪自编码器)
- [半监督的思想以及在深度学习中的应用*](#半监督的思想以及在深度学习中的应用)
- [分布式表示的概念、应用,与符号表示(one-hot 表示)的区别***](#分布式表示的概念应用与符号表示one-hot-表示的区别)
- [什么是分布式表示?](#什么是分布式表示)
- [分布式表示为什么强大?——分布式表示与符号表示](#分布式表示为什么强大分布式表示与符号表示)
- [如何理解维数灾难?***](#如何理解维数灾难)
- [迁移学习相关概念:多任务学习、一次学习、零次学习、多模态学习**](#迁移学习相关概念多任务学习一次学习零次学习多模态学习)
- [图模型|结构化概率模型相关概念*](#图模型结构化概率模型相关概念)
- [深度生成模型、受限玻尔兹曼机(RBM)相关概念*](#深度生成模型受限玻尔兹曼机rbm相关概念)
- [深度学习在图像、语音、NLP等领域的常见作法与基本模型**](#深度学习在图像语音nlp等领域的常见作法与基本模型)
- [计算机视觉(CV)](#计算机视觉cv)
- [语音识别](#语音识别)
- [自然语言处理](#自然语言处理)
<!-- /TOC -->
# 如何设置网络的初始值?*
> 《深度学习》 8.4 参数初始化策略
一般总是使用服从(截断)高斯或均匀分布的随机值,具体是高斯还是均匀分布影响不大,但是也没有详细的研究。
但是,**初始值的大小**会对优化结果和网络的泛化能力产生较大的影响。
<!-- 更大的初始值有助于避免冗余的单元;但如果初始值太大,又会造成梯度爆炸。 -->
一些启发式初始化策略通常是根据输入与输出的单元数来决定初始权重的大小,比如 Glorot and Bengio (2010) 中建议建议使用的标准初始化,其中 m 为输入数,n 为输出数
[](http://www.codecogs.com/eqnedit.php?latex=W_{i,j}&space;\sim&space;U(-\sqrt{\frac{6}{m+n}},\sqrt{\frac{6}{m+n}}))
还有一些方法推荐使用随机正交矩阵来初始化权重 (Saxe et al., 2013)。
> 常用的初始化策略可以参考 Keras 中文文档:[初始化方法Initializers](http://keras-cn.readthedocs.io/en/latest/other/initializations/)
# 梯度爆炸的解决办法***
> [27. 如何避免深度学习中的病态,鞍点,梯度爆炸,梯度弥散?***](#27-如何避免深度学习中的病态鞍点梯度爆炸梯度弥散)
**梯度爆炸**:

1. **梯度截断**(gradient clipping)——如果梯度超过某个阈值,就对其进行限制
> 《深度学习》 10.11.1 截断梯度
下面是 Tensorflow 提供的几种方法:
- `tf.clip_by_value(t, clip_value_min, clip_value_max)`
- `tf.clip_by_norm(t, clip_norm)`
- `tf.clip_by_average_norm(t, clip_norm)`
- `tf.clip_by_global_norm(t_list, clip_norm)`
这里以`tf.clip_by_global_norm`为例:
```
To perform the clipping, the values `t_list[i]` are set to:
t_list[i] * clip_norm / max(global_norm, clip_norm)
where:
global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))
```
用法:
```
train_op = tf.train.AdamOptimizer()
params = tf.trainable_variables()
gradients = tf.gradients(loss, params)
clip_norm = 100
clipped_gradients, global_norm = tf.clip_by_global_norm(gradients, clip_norm)
optimizer_op = train_op.apply_gradients(zip(clipped_gradients, params))
```
> clip_norm 的设置视 loss 的大小而定,如果比较大,那么可以设为 100 或以上,如果比较小,可以设为 10 或以下。
2. 良好的参数初始化策略也能缓解梯度爆炸问题(权重正则化)
> [1. 如何设置网络的初始值?*](#1-如何设置网络的初始值)
3. 使用线性整流激活函数,如 ReLU 等
# 神经网络(MLP)的万能近似定理*
> 《深度学习》 6.4.1 万能近似性质和深度
一个前馈神经网络如果具有至少一个非线性输出层,那么只要给予网络足够数量的隐藏单元,它就可以以任意的精度来近似任何从一个有限维空间到另一个有限维空间的函数。
# 神经网络中,深度与宽度的关系,及其表示能力的差异**
> 《深度学习》 6.4 - 架构设计;这一节的内容比较分散,想要更好的回答这个问题,需要理解深度学习的本质——学习多层次组合(ch1.2),这才是现代深度学习的基本原理。
隐藏层的数量称为模型的**深度**,隐藏层的维数(单元数)称为该层的**宽度**。
**万能近似定理**表明一个单层的网络就足以表达任意函数,但是该层的维数可能非常大,且几乎没有泛化能力;此时,使用更深的模型能够减少所需的单元数,同时增强泛化能力(减少泛化误差)。参数数量相同的情况下,浅层网络比深层网络更容易过拟合。
# 在深度神经网络中,引入了隐藏层(非线性单元),放弃了训练问题的凸性,其意义何在?**
> 《深度学习》 6 深度前馈网络(引言) & 6.3 隐藏单元
放弃训练问题的凸性,简单来说,就是放弃寻求问题的最优解。
**非线性单元**的加入,使训练问题不再是一个**凸优化**问题。这意味着神经网络很难得到最优解,即使一个只有两层和三个节点的简单神经网络,其训练优化问题仍然是 NP-hard 问题 (Blum & Rivest, 1993).
> [深度学习的核心问题——NP-hard问题](http://baijiahao.baidu.com/s?id=1561255903377484&wfr=spider&for=pc%EF%BC%89) - 百家号
但即使如此,使用神经网络也是利大于弊的:
- 人类设计者只需要寻找正确的**函数族**即可,而不需要去寻找精确的函数。
- 使用简单的梯度下降优化方法就可以高效地找到足够好的局部最小值
- 增强了模型的学习/拟合能力,如原书中所说“ maxout 单元可以以任意精度近似任何凸函数”。至于放弃凸性后的优化问题可以在结合工程实践来不断改进。 “似乎传统的优化理论结果是残酷的,但我们可以通过**工程方法**和**数学技巧**来尽量规避这些问题,例如启发式方法、增加更多的机器和使用新的硬件(如GPU)。”
> [Issue #1](https://github.com/elviswf/DeepLearningBookQA_cn/issues/1#issuecomment-396061806) · elviswf/DeepLearningBookQA_cn
# 稀疏表示,低维表示,独立表示*
> 《深度学习》 5.8 无监督学习算法
无监督学习任务的目的是找到数据的“最佳”表示。“最佳”可以有不同的表示,但是一般来说,是指该表示在比本身表示的信息更简单的情况下,尽可能地保存关于 x 更多的信息。
低维表示、稀疏表示和独立表示是最常见的三种“简单”表示:1)低维表示尝试将 x 中的信息尽可能压缩在一个较小的表示中;2)稀疏表示将数据集嵌入到输入项大多数为零的表示中;3)独立表示试图分开数据分布中变化的来源,使得表示的维度是统计独立的。
这三种表示不是互斥的,比如主成分分析(PCA)就试图同时学习低维表示和独立表示。
表示的概念是深度学习的核心主题之一。
# 局部不变性(平滑先验)及其在基于梯度的学习上的局限性*
> 《深度学习》 5.11.2 局部不变性与平滑正则化
局部不变性:函数在局部小区域内不会发生较大的变化。
为了更好地**泛化**,机器学习算法需要由一些先验来引导应该学习什么类型的函数。
其中最广泛使用的“隐式先验”是平滑先验(smoothness prior),也称局部不变性先验(local constancy prior)。许多简单算法完全依赖于此先验达到良好的(局部)泛化,一个极端例子是 k-最近邻系列的学习算法。
但是仅依靠平滑先验**不足以**应对人工智能级别的任务。简单来说,区分输入空间中 O(k) 个区间,需要 O(k) 个样本,通常也会有 O(k) 个参数。最近邻算法中,每个训练样本至多用于定义一个区间。类似的,决策树也有平滑学习的局限性。
以上问题可以总结为:是否可以有效地表示复杂的函数,以及所估计的函数是否可以很好地泛化到新的输入。该问题的一个关键观点是,只要我们通过额外假设生成数据的分布来建立区域间的依赖关系,那么 O(k) 个样本足以描述多如 O(2^k) 的大量区间。通过这种方式,能够做到**非局部的泛化**。
> 一些其他的机器学习方法往往会提出更强的,针对特定问题的假设,例如周期性。通常,神经网络不会包含这些很强的针对性假设——深度学习的核心思想是假设数据由因素或特征组合产生,这些因素或特征可能来自一个层次结构的多个层级。许多其他类似的通用假设进一步提高了深度学习算法。这些很温和的假设允许了样本数目和可区分区间数目之间的**指数增益**。深度的分布式表示带来的指数增益有效地解决了维数灾难带来的挑战
>> 指数增益:《深度学习》 ch6.4.1、ch15.4、ch15.5
# 为什么交叉熵损失相比均方误差损失能提高以 sigmoid 和 softmax 作为激活函数的层的性能?**
> 《深度学习》 6.6 小结 中提到了这个结论,但是没有给出具体原因(可能在前文)。
简单来说,就是使用均方误差(MSE)作为损失函数时,会导致大部分情况下**梯度偏小**,其结果就是权重的更新很慢,且容易造成“梯度消失”现象。而交叉熵损失克服了这个缺点,当误差大的时候,权重更新就快,当误差小的时候,权重的更新才慢。
具体推导过程如下:
> https://blog.csdn.net/guoyunfei20/article/details/78247263 - CSDN 博客
>
> 这里给出了一个具体的[例子](https://blog.csdn.net/shmily_skx/article/details/53053870)
# 分段线性单元(如 ReLU)代替 sigmoid 的利弊***
> 《深度学习》 6.6 小结
- 当神经网络比较小时,sigmoid 表现更好;
- 在深度学习早期,人们认为应该避免具有不可导点的激活函数,而 ReLU 不是全程可导/可微的
- sigmoid 和 tanh 的输出是有界的,适合作为下一层的输入,以及整个网络的输出。实际上,目前大多数网络的输出层依然使用的 sigmoid(单输出) 或 softmax(多输出)。
> 为什么 ReLU 不是全程可微也能用于基于梯度的学习?——虽然 ReLU 在 0 点不可导,但是它依然存在左导数和右导数,只是它们不相等(相等的话就可导了),于是在实现时通常会返回左导数或右导数的其中一个,而不是报告一个导数不存在的错误。
>> 一阶函数:可微==可导
- 对于小数据集,使用整流非线性甚至比学习隐藏层的权重值更加重要 (Jarrett et al., 2009b)
- 当数据增多时,在深度整流网络中的学习比在激活函数具有曲率或两侧**饱和**的深度网络中的学习更容易 (Glorot et al., 2011a):传统的 sigmoid 函数,由于两端饱和,在传播过程中容易丢弃信息
- ReLU 的过程更接近生物神经元的作用过程
> 饱和(saturate)现象:在函数图像上表现为变得很平,对输入的微小改变会变得不敏感。
> https://blog.csdn.net/code_lr/article/details/51836153 - CSDN博客
>> 答案总结自该知乎问题:https://www.zhihu.com/question/29021768
# 在做正则化过程中,为什么只对权重做正则惩罚,而不对偏置做权重惩罚*
> 《深度学习》 7.1 参数范数惩罚
在神经网络中,参数包括每一层仿射变换的**权重**和**偏置**,我们通常只对权重做惩罚而不对偏置做正则惩罚。
精确拟合偏置所需的数据通常比拟合权重少得多。每个权重会指定两个变量如何相互作用。我们需要在各种条件下观察这两个变量才能良好地拟合权重。而每个偏置仅控制一个单变量。这意味着,我们不对其进行正则化也不会导致太大的方差。另外,正则化偏置参数可能会导致明显的欠拟合。
# 列举常见的一些范数及其应用场景,如 L0、L1、L2、L∞、Frobenius等范数**
> 《深度学习》 2.5 范数(介绍)
L0: 向量中非零元素的个数
L1: 向量中所有元素的绝对值之和
[](http://www.codecogs.com/eqnedit.php?latex=\left&space;\|&space;x&space;\right&space;\|_1=\sum_i{\left&space;|&space;x_i&space;\right&space;|})
L2: 向量中所有元素平方和的开放
[](http://www.codecogs.com/eqnedit.php?latex=\left&space;\|&space;x&space;\right&space;\|_2=\sqrt{\sum_i{\left&space;|&space;x_i&space;\right&space;|^2}})
其中 L1 和 L2 范数分别是 Lp (p>=1) 范数的特例:
[](http://www.codecogs.com/eqnedit.php?latex=\left&space;\|&space;x&space;\right&space;\|_p=(\sum_i{\left&space;|&space;x_i&space;\right&space;|^2})^{\frac{1}{p}})
L∞: 向量中最大元素的绝对值,也称最大范数
[](http://www.codecogs.com/eqnedit.php?latex=\left&space;\|&space;x&space;\right&space;\|_\infty=\max_i\left&space;|&space;x&space;\right&space;|)
Frobenius 范数:相当于作用于矩阵的 L2 范数
[](http://www.codecogs.com/eqnedit.php?latex=\left&space;\|&space;A&space;\right&space;\|_F=\sqrt{\sum_{i,j}A_{i,j}^2})
**范数的应用**:正则化——权重衰减/参数范数惩罚
**权重衰减的目的**
限制模型的学习能力,通过限制参数 θ 的规模(主要是权重 w 的规模,偏置 b 不参与惩罚),使模型偏好于权值较小的目标函数,防止过拟合。
> 《深度学习》 7.1 参数范数惩罚
# L1 和 L2 范数的异同***
> 《深度学习》 7.1.1 L2 参数正则化 & 7.1.2 - L1 参数正则化
**相同点**
- 限制模型的学习能力,通过限制参数的规模,使模型偏好于权值较小的目标函数,防止过拟合。
**不同点**
- L1 正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,可以用于特征选择;一定程度上防止过拟合
- L2 正则化主要用于防止模型过拟合
- L1 适用于特征之间有关联的情况;L2 适用于特征之间没有关联的情况
> [机器学习中正则化项L1和L2的直观理解](https://blog.csdn.net/jinping_shi/article/details/52433975) - CSDN博客
# 为什么 L1 正则化可以产生稀疏权值,L2 正则化可以防止过拟合?**
## 为什么 L1 正则化可以产生稀疏权值,而 L2 不会?
添加 L1 正则化,相当于在 L1范数的约束下求目标函数 J 的最小值,下图展示了二维的情况:

图中 J 与 L 首次相交的点就是最优解。L1 在和每个坐标轴相交的地方都会有“角”出现(多维的情况下,这些角会更多),在角的位置就会产生稀疏的解。而 J 与这些“角”相交的机会远大于其他点,因此 L1 正则化会产生稀疏的权值。
类似的,可以得到带有 L2正则化的目标函数在二维平面上的图形,如下:

相比 L1,L2 不会产生“角”,因此 J 与 L2 相交的点具有稀疏性的概率就会变得非常小。
> [机器学习中正则化项L1和L2的直观理解](https://blog.csdn.net/jinping_shi/article/details/52433975) - CSDN博客
## 为什么 L1 和 L2 正则化可以防止过拟合?
L1 & L2 正则化会使模型偏好于更小的权值。
简单来说,更小的权值意味着更低的模型复杂度,也就是对训练数据的拟合刚刚好(奥卡姆剃刀),不会过分拟合训练数据(比如异常点,噪声),以提高模型的泛化能力。
此外,添加正则化相当于为模型添加了某种**先验**(限制),规定了参数的分布,从而降低了模型的复杂度。模型的复杂度降低,意味着模型对于噪声与异常点的抗干扰性的能力增强,从而提高模型的泛化能力。
> [机器学习中防止过拟合的处理方法](https://blog.csdn.net/heyongluoyao8/article/details/49429629) - CSDN博客
# 简单介绍常用的激活函数,如 sigmoid、relu、softplus、tanh、RBF 及其应用场景***
> 《深度学习》 6.3 隐藏单元
## 整流线性单元(ReLU)
[](http://www.codecogs.com/eqnedit.php?latex=g(z)=\max(0,z))

整流线性单元(ReLU)通常是激活函数较好的默认选择。
整流线性单元易于优化,因为它们和线性单元非常类似。线性单元和整流线性单元的唯一区别在于整流线性单元在其一半的定义域上输出为零。这使得只要整流线性单元处于激活状态,它的导数都能保持较大。它的梯度不仅大而且一致。整流操作的二阶导数几乎处处为 0,并且在整流线性单元处于激活状态时,它的一阶导数处处为 1。这意味着相比于引入二阶效应的激活函数来说,它的梯度方向对于学习来说更加有用。
**ReLU 的拓展**
ReLU 的三种拓展都是基于以下变型:
[](http://www.codecogs.com/eqnedit.php?latex=g(z,\alpha)&space;=\max(0,z)+\alpha\min(0,z))
ReLU 及其扩展都是基于一个原则,那就是如果它们的行为更接近线性,那么模型更容易优化。
- 绝对值整流(absolute value rectification)
固定 α == -1,此时整流函数即一个绝对值函数
[](http://www.codecogs.com/eqnedit.php?latex=g(z)&space;=\left&space;|&space;z&space;\right&space;|)
绝对值整流被用于图像中的对象识别 (Jarrett et al., 2009a),其中寻找在输入照明极性反转下不变的特征是有意义的。
- 渗漏整流线性单元(Leaky ReLU, Maas et al., 2013)
固定 α 为一个类似于 0.01 的小值
- 参数化整流线性单元(parametric ReLU, PReLU, He et al., 2015)
将 α 作为一个参数学习
- maxout 单元 (Goodfellow et al., 2013a)
maxout 单元 进一步扩展了 ReLU,它是一个可学习的多达 k 段的分段函数
关于 maxout 网络的分析可以参考论文或网上的众多分析,下面是 Keras 中的实现:
```
# input shape: [n, input_dim]
# output shape: [n, output_dim]
W = init(shape=[k, input_dim, output_dim])
b = zeros(shape=[k, output_dim])
output = K.max(K.dot(x, W) + b, axis=1)
```
> [深度学习(二十三)Maxout网络学习](https://blog.csdn.net/hjimce/article/details/50414467) - CSDN博客
## sigmoid 与 tanh(双曲正切函数)
在引入 ReLU 之前,大多数神经网络使用 sigmoid 激活函数:
[](http://www.codecogs.com/eqnedit.php?latex=g(z)=\sigma(z)=\frac{1}{1+\exp(-z)})

或者 tanh(双曲正切函数):
[](http://www.codecogs.com/eqnedit.php?latex=g(z)&space;=&space;\tanh(z))
tanh 的图像类似于 sigmoid,区别在其值域为 (-1, 1).
这两个函数有如下关系:
[](http://www.codecogs.com/eqnedit.php?latex=\tanh(z)=2\sigma&space;(2z)-1)
**sigmoid 函数要点**:
- sigmoid 常作为输出单元用来预测二值型变量取值为 1 的概率
> 换言之,sigmoid 函数可以用来产生**伯努利分布**中的参数 ϕ,因为它的值域为 (0, 1).
- sigmoid 函数在输入取绝对值非常大的正值或负值时会出现**饱和**(saturate)现象,在图像上表现为开始变得很平,此时函数会对输入的微小改变会变得不敏感。仅当输入接近 0 时才会变得敏感。
> 饱和现象会导致基于梯度的学习变得困难,并在传播过程中丢失信息。——[为什么用ReLU代替sigmoid?](#8.-分段线性单元(如-ReLU)代替-sigmoid-的利弊)
- 如果要使用 sigmoid 作为激活函数时(浅层网络),tanh 通常要比 sigmoid 函数表现更好。
> tanh 在 0 附近与单位函数类似,这使得训练 tanh 网络更容易些。
## 其他激活函数(隐藏单元)
很多未发布的非线性激活函数也能表现的很好,但没有比流行的激活函数表现的更好。比如使用 cos 也能在 MNIST 任务上得到小于 1% 的误差。通常新的隐藏单元类型只有在被明确证明能够提供显著改进时才会被发布。
**线性激活函数**:
如果神经网络的每一层都由线性变换组成,那么网络作为一个整体也将是线性的,这会导致失去万能近似的性质。但是,仅**部分层是纯线性**是可以接受的,这可以帮助**减少网络中的参数**。
**softmax**:
softmax 单元常作为网络的输出层,它很自然地表示了具有 k 个可能值的离散型随机变量的概率分布。
**径向基函数(radial basis function, RBF)**:
[](http://www.codecogs.com/eqnedit.php?latex=h_i=\exp(-\frac{1}{\sigma_i^2}\left&space;\|&space;W_{:,i}-x&space;\right&space;\|^2))
在神经网络中很少使用 RBF 作为激活函数,因为它对大部分 x 都饱和到 0,所以很难优化。
**softplus**:
[](http://www.codecogs.com/eqnedit.php?latex=g(z)=\zeta(z)=\log(1+\exp(z)))

softplus 是 ReLU 的平滑版本。通常不鼓励使用 softplus 函数,大家可能希望它具有优于整流线性单元的点,但根据经验来看,它并没有。
> (Glorot et al., 2011a) 比较了这两者,发现 ReLU 的结果更好。
**硬双曲正切函数(hard tanh)**:
[](http://www.codecogs.com/eqnedit.php?latex=g(z)=\max(-1,\min(1,a)))
它的形状和 tanh 以及整流线性单元类似,但是不同于后者,它是有界的。
> Collobert, 2004
## sigmoid 和 softplus 的一些性质

> 《深度学习》 3.10 常用函数的有用性质
# Jacobian 和 Hessian 矩阵及其在深度学习中的重要性*
> 《深度学习》 4.3.1 梯度之上:Jacobian 和 Hessian 矩阵
# 信息熵、KL 散度(相对熵)与交叉熵**
> 《深度学习》 3.13 信息论
信息论的基本想法是一个不太可能的事件居然发生了,要比一个非常可能的事件发生,能提供更多的信息。
该想法可描述为以下性质:
1. 非常可能发生的事件信息量要比较少,并且极端情况下,确保能够发生的事件应该没有信息量。
2. 比较不可能发生的事件具有更高的信息量。
3. 独立事件应具有增量的信息。例如,投掷的硬币两次正面朝上传递的信息量,应该是投掷一次硬币正面朝上的信息量的两倍。
## 自信息与信息熵
自信息(self-information)是一种量化以上性质的函数,定义一个事件 x 的自信息为:
[](http://www.codecogs.com/eqnedit.php?latex=I(x)=-\log&space;P(x))
> 当该对数的底数为 e 时,单位为奈特(nats,本书标准);当以 2 为底数时,单位为比特(bit)或香农(shannons)
自信息只处理单个的输出。此时,用信息熵(Information-entropy)来对整个概率分布中的不确定性总量进行量化:
[](http://www.codecogs.com/eqnedit.php?latex=H(\mathrm{X})=\mathbb{E}_{\mathrm{X}&space;\sim&space;P}[I(x)]=-\sum_{x&space;\in&space;\mathrm{X}}P(x)\log&space;P(x))
> 信息熵也称香农熵(Shannon entropy)
>
> 信息论中,记 `0log0 = 0`
## 相对熵(KL 散度)与交叉熵
P 对 Q 的 **KL散度**(Kullback-Leibler divergence):
[](http://www.codecogs.com/eqnedit.php?latex=D_P(Q)=\mathbb{E}_{\mathrm{X}\sim&space;P}\left&space;[&space;\log&space;\frac{P(x)}{Q(x)}&space;\right&space;]=\sum_{x&space;\in&space;\mathrm{X}}P(x)\left&space;[&space;\log&space;P(x)-\log&space;Q(x)&space;\right&space;])
**KL 散度在信息论中度量的是那个直观量**:
在离散型变量的情况下, KL 散度衡量的是,当我们使用一种被设计成能够使得概率分布 Q 产生的消息的长度最小的编码,发送包含由概率分布 P 产生的符号的消息时,所需要的额外信息量。
**KL 散度的性质**:
- 非负;KL 散度为 0 当且仅当P 和 Q 在离散型变量的情况下是相同的分布,或者在连续型变量的情况下是“几乎处处”相同的
- 不对称;D_p(q) != D_q(p)
**交叉熵**(cross-entropy):
[](http://www.codecogs.com/eqnedit.php?latex=H_P(Q)=-\mathbb{E}_{\mathrm{X}\sim&space;P}\log&space;Q(x)=-\sum_{x&space;\in&space;\mathrm{X}}P(x)\log&space;Q(x))
> [信息量,信息熵,交叉熵,KL散度和互信息(信息增益)](https://blog.csdn.net/haolexiao/article/details/70142571) - CSDN博客
**交叉熵与 KL 散度的关系**:
[](http://www.codecogs.com/eqnedit.php?latex=H_P(Q)=H(P)+D_P(Q))
**针对 Q 最小化交叉熵等价于最小化 P 对 Q 的 KL 散度**,因为 Q 并不参与被省略的那一项。
最大似然估计中,最小化 KL 散度其实就是在最小化分布之间的交叉熵。
> 《深度学习》 ch5.5 - 最大似然估计
# 如何避免数值计算中的上溢和下溢问题,以 softmax 为例*
> 《深度学习》 4.1 上溢与下溢
- **上溢**:一个很大的数被近似为 ∞ 或 -∞;
- **下溢**:一个很小的数被近似为 0
必须对上溢和下溢进行**数值稳定**的一个例子是 **softmax 函数**:
[](http://www.codecogs.com/eqnedit.php?latex=\mathrm{softmax}(x)=\frac{\exp(x_i)}{\sum_{j=1}^n&space;\exp(x_j)})
因为 softmax 解析上的函数值不会因为从输入向量减去或加上**标量**而改变,
于是一个简单的解决办法是对 x:
[](http://www.codecogs.com/eqnedit.php?latex=x=x-\max_ix_i)
减去 `max(x_i)` 导致 `exp` 的最大参数为 `0`,这排除了上溢的可能性。同样地,分母中至少有一个值为 `1=exp(0)` 的项,这就排除了因分母下溢而导致被零除的可能性。
**注意**:虽然解决了分母中的上溢与下溢问题,但是分子中的下溢仍可以导致整体表达式被计算为零。此时如果计算 log softmax(x) 时,依然要注意可能造成的上溢或下溢问题,处理方法同上。
当然,大多数情况下,这是底层库开发人员才需要注意的问题。
# 训练误差、泛化误差;过拟合、欠拟合;模型容量,表示容量,有效容量,最优容量的概念; 奥卡姆剃刀原则*
> 《深度学习》 5.2 容量、过拟合和欠拟合
## 过拟合的一些解决方案***
- 参数范数惩罚(Parameter Norm Penalties)
- 数据增强(Dataset Augmentation)
- 提前终止(Early Stopping)
- 参数绑定与参数共享(Parameter Tying and Parameter Sharing)
- Bagging 和其他集成方法
- Dropout
- 批标准化(Batch Normalization)
# 高斯分布的广泛应用的原因**
> 《深度学习》 3.9.3 高斯分布
## 高斯分布(Gaussian distribution)
高斯分布,即正态分布(normal distribution):
[](http://www.codecogs.com/eqnedit.php?latex=N(x;\mu,\sigma^2)=\sqrt\frac{1}{2\pi\sigma^2}\exp\left&space;(&space;-\frac{1}{2\sigma^2}(x-\mu)^2&space;\right&space;))
概率密度函数图像:

其中峰的 `x` 坐标由 `µ` 给出,峰的宽度受 `σ` 控制;特别的,当 `µ = 0, σ = 1`时,称为标准正态分布
正态分布的均值 `E = µ`;标准差 `std = σ`,方差为其平方
## 为什么推荐使用高斯分布?
当我们由于缺乏关于某个实数上分布的先验知识而不知道该选择怎样的形式时,正态分布是默认的比较好的选择,其中有两个原因:
1. 我们想要建模的很多分布的真实情况是比较接近正态分布的。**中心极限定理**(central limit theorem)说明很多独立随机变量的和近似服从正态分布。这意味着在实际中,很多复杂系统都可以被成功地建模成正态分布的噪声,即使系统可以被分解成一些更结构化的部分。
2. 第二,在具有相同方差的所有可能的概率分布中,正态分布在实数上具有最大的不确定性。因此,我们可以认为正态分布是对模型加入的先验知识量最少的分布。
> 关于这一点的证明:《深度学习》 ch19.4.2 - 变分推断和变分学习
**多维正态分布**
正态分布可以推广到 n 维空间,这种情况下被称为**多维正态分布**。

参数 `µ` 仍然表示分布的均值,只不过现在是一个向量。参数 Σ 给出了分布的协方差矩阵(一个正定对称矩阵)。
# 表示学习、自编码器与深度学习**
> 《深度学习》 1 引言
**表示学习**:
对于许多任务来说,我们很难知道应该提取哪些特征。解决这个问题的途径之一是使用机器学习来发掘表示本身,而不仅仅把表示映射到输出。这种方法我们称之为**表示学习**(representation learning)。学习到的表示往往比手动设计的表示表现得更好。并且它们只需最少的人工干预,就能让AI系统迅速适应新的任务。
**自编码器**:
表示学习算法的典型例子是 自编码器(autoencoder)。自编码器由一个**编码器**(encoder)函数和一个**解码器**(decoder)函数组合而成。
- 编码器函数将输入数据转换为一种不同的表示;
- 解码器函数则将这个新的表示转换到原来的形式。
我们期望当输入数据经过编码器和解码器之后**尽可能多地保留信息**,同时希望新的表示有一些好的特性,这也是自编码器的训练目标。
**深度学习**:
深度学习(deep learning)通过简单的表示来表达复杂的表示,以解决表示学习中的核心问题。

深度学习模型的示意图
计算机难以理解原始感观输入数据的含义,如表示为像素值集合的图像,将一组像素映射到对象标识的函数非常复杂。深度学习将所需的复杂映射分解为一系列嵌套的简单映射(每个由模型的不同层描述)来解决这一难题。
输入展示在**可见层**(visible layer),这样命名的原因是因为它包含我们能观察到的变量。然后是一系列从图像中提取越来越多抽象特征的**隐藏层**(hidden layer),称为“隐藏”的原因是因为它们的值不在数据中给出。
模型必须确定哪些概念有利于解释观察数据中的关系。这里的图像是每个隐藏单元表示的特征的可视化。给定像素,**第一隐藏层**可以轻易地通过比较相邻像素的亮度来**识别边缘**。有了第一隐藏层描述的边缘,**第二隐藏层**可以容易地**搜索轮廓和角**。给定第二隐藏层中关于角和轮廓的图像描述,**第三隐藏层**可以找到轮廓和角的特定集合来**检测整个特定对象**。最后,根据图像描述中包含的对象部分,可以识别图像中存在的对象。
> 实际任务中并不一定具有这么清晰的可解释性,很多时候你并不知道每个隐藏层到底识别出了哪些特征。
学习数据的正确表示的想法是**解释深度学习**的一个视角。
> 另一个视角是深度促使计算机学习一个多步骤的计算机程序。——《深度学习》 ch1 - 引言
>
> 早期的深度学习称为神经网络,因为其主要指导思想来源于生物神经学。从神经网络向深度学习的术语转变也是因为指导思想的改变。
# L1、L2 正则化与 MAP 贝叶斯推断的关系*
> 《深度学习》 5.6.1 最大后验 (MAP) 估计
许多正则化策略可以被解释为 MAP 贝叶斯推断:
- L2 正则化相当于权重是高斯先验的 MAP 贝叶斯推断
- 对于 L1正则化,用于正则化代价函数的惩罚项与通过 MAP 贝叶斯推断最大化的**对数先验项**是等价的
# 什么是欠约束,为什么大多数的正则化可以使欠约束下的欠定问题在迭代过程中收敛*
> 《深度学习》 7.3 正则化与欠约束问题
# 为什么考虑在模型训练时对输入 (隐藏单元或权重) 添加方差较小的噪声?*
> 《深度学习》 7.5 噪声鲁棒性
对于某些模型而言,向输入添加方差极小的噪声等价于对权重施加范数惩罚 (Bishop, 1995a,b)。
在一般情况下,**注入噪声比简单地收缩参数强大**。特别是噪声被添加到**隐藏单元**时会更加强大,**Dropout** 方法正是这种做法的主要发展方向。
另一种正则化模型的噪声使用方式是将其加到**权重**。这项技术主要用于循环神经网络 (Jim et al., 1996; Graves, 2011)。这可以被解释为关于权重的贝叶斯推断的随机实现。贝叶斯学习过程将权重视为不确定的,并且可以**通过概率分布表示这种不确定性**。向权重添加噪声是反映这种不确定性的一种实用的随机方法。
# 多任务学习、参数绑定和参数共享***
> [45. 迁移学习相关概念](#45-迁移学习相关概念)
## 多任务学习
> 《深度学习》 7.7 多任务学习
多任务学习 (Caruana, 1993) 是通过**合并多个任务中的样例**(可以视为对参数施加软约束)来提高泛化的一种方式。
正如额外的训练样本能够将模型参数推向具有更好泛化能力的值一样,当**模型的一部分被多个额外的任务共享**时,这部分将被约束为良好的值(如果共享合理),通常会带来更好的泛化能力。
**多任务学习中一种普遍形式**:

多任务学习在深度学习框架中可以以多种方式进行,该图展示了一种普遍形式:任务共享相同输入但涉及不同语义的输出。
在该示例中,额外假设顶层隐藏单元 h(1) 和 h(2) 专用于不同的任务——分别预测 y(1) 和 y(2),而一些**中间层表示** h(shared) 在所有任务之间共享;h(3) 表示无监督学习的情况。
这里的基本假设是存在解释输入 x 变化的**共同因素池**,而每个任务与这些因素的**子集**相关联。
该模型通常可以分为两类相关的参数:
1. 具体任务的参数(只能从各自任务的样本中实现良好的泛化)
2. 所有任务共享的通用参数(从所有任务的汇集数据中获益)——参数共享
因为**共享参数**,其统计强度可大大提高(共享参数的样本数量相对于单任务模式增加的比例),并能改善泛化和泛化误差的范围 (Baxter, 1995)。
参数共享仅当不同的任务之间存在某些统计关系的假设是合理(意味着某些参数能通过不同任务共享)时才会发生这种情况
## 参数绑定和参数共享
> 《深度学习》 7.9 参数绑定和参数共享
**参数绑定**:
有时,我们可能无法准确地知道应该使用什么样的参数,但我们根据相关领域和模型结构方面的知识得知模型参数之间应该存在一些相关性。
考虑以下情形:我们有两个模型执行相同的分类任务(具有相同类别),但输入分布稍有不同。
形式地,我们有参数为 w(A) 的模型 A 和参数为 w(B) 的模型 B。这两种模型将输入映射到两个不同但相关的输出: y(A) = f(x;w(A)) 和 y(B) = f(x;w(B))
可以想象,这些任务会足够相似(或许具有相似的输入和输出分布),因此我们认为模型参数 w(A) 和 w(B) 应彼此靠近。具体来说,我们可以使用以下形式的参数范数惩罚(这里使用的是 L2 惩罚,也可以使用其他选择):
[](http://www.codecogs.com/eqnedit.php?latex=\Omega&space;(w^{(A)},w^{(B)})=\left&space;\|&space;w^{(A)}-w^{(B)}&space;\right&space;\|^2_2)
**参数共享**是这个思路下更流行的做法——强迫部分参数相等
和正则化参数使其接近(通过范数惩罚)相比,参数共享的一个显著优点是能够“减少内存”——只有参数(唯一一个集合)的子集需要被存储在内存中,特别是在 CNN 中。
# Dropout 与 Bagging 集成方法的关系,Dropout 带来的意义与其强大的原因***
## Bagging 集成方法
> 《深度学习》 7.11 Bagging 和其他集成方法
**集成方法**:
其主要想法是分别训练几个不同的模型,然后让所有模型表决测试样例的输出。这是机器学习中常规策略的一个例子,被称为**模型平均**(model averaging)。采用这种策略的技术被称为**集成方法**。
模型平均(model averaging)**奏效的原因**是不同的模型通常不会在测试集上产生完全相同的误差。平均上, 集成至少与它的任何成员表现得一样好,并且**如果成员的误差是独立的**,集成将显著地比其成员表现得更好。
**Bagging**:
Bagging(bootstrap aggregating)是通过结合几个模型降低泛化误差的技术 (Breiman, 1994)。
具体来说,Bagging 涉及构造 k 个**不同的数据集**。每个数据集从原始数据集中**重复采样**构成,和原始数据集具有**相同数量**的样例。这意味着,每个数据集以高概率缺少一些来自原始数据集的例子,还包含若干重复的例子(更具体的,如果采样所得的训练集与原始数据集大小相同,那所得数据集中大概有原始数据集 **2/3** 的实例)

**图像说明**:该图描述了 Bagging 如何工作。假设我们在上述数据集(包含一个 8、一个 6 和一个 9)上**训练数字 8** 的检测器。假设我们制作了两个不同的重采样数据集。 Bagging 训练程序通过有放回采样构建这些数据集。第一个数据集忽略 9 并重复 8。在这个数据集上,检测器得知数字**顶部有一个环就对应于一个 8**。第二个数据集中,我们忽略 6 并重复 9。在这种情况下,检测器得知数字**底部有一个环就对应于一个 8**。这些单独的分类规则中的每一个都是不可靠的,但如果我们平均它们的输出,就能得到鲁棒的检测器,**只有当 8 的两个环都存在时才能实现最大置信度**。
## Dropout
> 《深度学习》 7.12 Dropout
**Dropout 的意义与强大的原因**:
简单来说,Dropout (Srivastava et al., 2014) 通过**参数共享**提供了一种廉价的 **Bagging** 集成近似,能够训练和评估**指数级数量**的神经网络。

Dropout 训练的集成包括所有从基础网络除去部分单元后形成的子网络。具体而言,只需将一些单元的**输出乘零**就能有效地删除一个单元。
通常,**隐藏层**的采样概率为 0.5,**输入**的采样概率为 0.8;超参数也可以采样,但其采样概率一般为 1
**Dropout与Bagging的不同点**:
- 在 Bagging 的情况下,所有模型都是独立的;而在 Dropout 的情况下,所有模型**共享参数**,其中每个模型继承父神经网络参数的不同子集。
- 在 Bagging 的情况下,每一个模型都会在其相应训练集上训练到收敛。而在 Dropout 的情况下,通常大部分模型都没有显式地被训练;取而代之的是,在单个步骤中我们训练一小部分的子网络,参数共享会使得剩余的子网络也能有好的参数设定。
**权重比例推断规则**:
简单来说,如果我们使用 0.5 的包含概率(keep prob),权重比例规则相当于在训练结束后**将权重除 2**,然后像平常一样使用模型;等价的,另一种方法是在训练期间将单元的状态乘 2。
无论哪种方式,我们的目标是确保在测试时一个单元的期望总输入与在训练时该单元的期望总输入是大致相同的(即使近半单位在训练时丢失)。
# 批梯度下降法(Batch SGD)更新过程中,批的大小会带来怎样的影响**
> 《深度学习》 8.1.3 批量算法和小批量算法
特别说明:本书中,“**批量**”指使用使用全部训练集;“**小批量**”才用来描述小批量随机梯度下降算法中用到的小批量样本;而**随机梯度下降**(SGD)通常指每次只使用单个样本
**批的大小**通常由以下几个因素决定:
- **较大的批能得到更精确的梯度估计**,但回报是小于线性的。
- **较小的批能带来更好的泛化误差**,泛化误差通常在批大小为 1 时最好。但是,因为梯度估计的高方差,小批量训练需要**较小的学习率**以保持稳定性,这意味着**更长的训练时间**。
> 可能是由于小批量在学习过程中加入了噪声,它们会有一些正则化效果 (Wilson and Martinez, 2003)
- **内存消耗和批的大小成正比**,如果批量处理中的所有样本可以并行地处理(通常确是如此)。
- 在某些硬件上使用特定大小可以减少运行时间。尤其是在使用 GPU 时,通常使用 **2 的幂数**作为批量大小可以获得更少的运行时间。一般,2 的幂数的**取值范围是 32 到 256**,16 有时在尝试大模型时使用。
- 小批量更容易利用**多核架构**,但是太小的批并不会减少计算时间,这促使我们使用一些**绝对最小批量**
很多机器学习上的优化问题都可以分解成并行地计算不同样本上单独的更新。换言之,我们在计算小批量样本 X 上最小化 J(X) 的更新时,同时可以计算其他小批量样本上的更新。
> 异步并行分布式方法 -> 《深度学习》 12.1.3 大规模的分布式实现
# 如何避免深度学习中的病态,鞍点,梯度爆炸,梯度弥散?***
> 《深度学习》 8.2 神经网络优化中的挑战
## 病态(ill-conditioning)
> 《深度学习》 8.2.1 病态
**什么是病态?**
> [神经网络优化中的病态问题](https://blog.csdn.net/foolsnowman/article/details/51614862) - CSDN博客
>
> [什么是 ill-conditioning 对SGD有什么影响?](https://www.zhihu.com/question/56977045) - 知乎
简单来说,深度学习中的病态问题指的就是学习/优化变的困难,需要更多的迭代次数才能达到相同的精度。
> 病态问题普遍存在于数值优化、凸优化或其他形式的优化中 -> ch4.3.1 - 梯度之上:Jacobian 和 Hessian 矩阵
更具体的,导致病态的原因是问题的**条件数**(condition number)非常大,其中`条件数 = 函数梯度最大变化速度 / 梯度最小变化速度`(对于二阶可导函数,条件数的严格定义是:Hessian矩阵最大特征值的上界 / 最小特征值的下界)。
**条件数大**意味着目标函数在有的地方(或有的方向)变化很快、有的地方很慢,比较不规律,从而很难用当前的局部信息(梯度)去比较准确地预测最优点所在的位置,只能一步步缓慢的逼近最优点,从而优化时需要更多的迭代次数。
**如何避免病态?**
知道了什么是病态,那么所有有利于**加速训练**的方法都属于在避免病态,其中最主要的还是优化算法。
深度学习主要使用的优化算法是**梯度下降**,所以避免病态问题的关键是改进梯度下降算法:
- 随机梯度下降(SGD)、批量随机梯度下降
- 动态的学习率
- **带动量的 SGD**
> [28. SGD 以及学习率的选择方法,带动量的 SGD 对于 Hessian 矩阵病态条件及随机梯度方差的影响***](#28-sgd-以及学习率的选择方法带动量的-sgd-对于-hessian-矩阵病态条件及随机梯度方差的影响)
## 鞍点(saddle point)
对于很多高维非凸函数(神经网络)而言,局部极小值/极大值事实上都**远少于**另一类梯度为零的点:鞍点
**什么是鞍点?**
二维和三维中的鞍点:


> 《深度学习》 4.3 基于梯度的优化方法
**鞍点激增对于训练算法来说有哪些影响?**
对于只使用梯度信息的一阶优化算法(随机梯度下降)而言,目前情况还不清楚。不过,虽然鞍点附近的梯度通常会非常小,但是 Goodfellow et al. (2015) 认为连续的梯度下降**会逃离而不是吸引到鞍点**。
对于牛顿法(二阶梯度)而言,鞍点问题会比较明显。不过神经网络中很少使用二阶梯度进行优化。
## 长期依赖与梯度爆炸、消失
> 《深度学习》 10.11 优化长期依赖
当计算图变得很深时(循环神经网络),神经网络优化算法会面临的另外一个难题就是**长期依赖**,由于变深的结构使模型丧失了学习到先前信息的能力,让优化变得极其困难;具体来说,就是会出现**梯度消失**和**梯度爆炸**问题。
**如何避免梯度爆炸?**
> [2. 梯度爆炸的解决办法***](#2-梯度爆炸的解决办法)
**如何缓解梯度消失?**
梯度截断有助于处理爆炸的梯度,但它无助于梯度消失。
一个想法是:在展开循环架构的计算图中,沿着与弧边相关联的梯度乘积接近 1 的部分创建路径——LSTM, GRU 等**门控机制**正是该想法的实现。
> 《深度学习》 10.10 长短期记忆和其他门控 RNN
另一个想法是:正则化或约束参数,以引导“信息流”;或者说,希望**梯度向量**在反向传播时能维持其幅度。形式上,我们要使
[](http://www.codecogs.com/eqnedit.php?latex=(\nabla_{h^{(t)}}L)\frac{\partial&space;h^{(t)}}{\partial&space;h^{(t-1)}})
与梯度向量
[](http://www.codecogs.com/eqnedit.php?latex=\nabla_{h^{(t)}}L)
一样大。
**一些具体措施**:
1. 批标准化(Batch Normalization)
> [31. 批标准化(Batch Normalization)的意义**](#31-批标准化batch-normalization的意义)
2. 在这个目标下, Pascanu et al. (2013a) 提出了以下正则项:

这种方法的一个主要弱点是,在处理数据冗余的任务时如语言模型,它并不像 LSTM 一样有效。
# SGD 以及学习率的选择方法、带动量的 SGD***
> 《深度学习》 8.3 基本算法
## (批)随机梯度下降(SGD)与学习率

SGD 及相关的小批量亦或更广义的基于梯度优化的在线学习算法,一个重要的性质是每一步更新的计算时间不依赖训练样本数目的多寡。因为它每个 step 的样本数是固定的。
所以即使训练样本数目非常大时,它们也能收敛。对于足够大的数据集, SGD 可能会在处理整个训练集之前就收敛到最终测试集误差的某个固定容差范围内。
**SGD 与学习率**
SGD 算法中的一个关键参数是学习率。在实践中,有必要**随着时间的推移逐渐降低学习率**。
实践中,一般会线性衰减学习率直到第 τ 次迭代:
[](http://www.codecogs.com/eqnedit.php?latex=\epsilon_k=(1-\alpha)\epsilon_0+\alpha\epsilon_\tau)
其中 α=k/τ。在 τ 步迭代之后,一般使 ϵ 保持常数。
使用线性策略时,需要选择的参数有 ϵ_0, ϵ_τ 和 τ
- 通常 τ 被设为需要反复遍历训练集几百次的迭代次数(?)
- 通常 ϵ_τ 应设为大约 ϵ_0 的 1%
**如何设置 ϵ_0?**
若 ϵ_0 太大,学习曲线将会剧烈振荡,代价函数值通常会明显增加。温和的振荡是良好的,容易在训练随机代价函数(例如使用 Dropout 的代价函数)时出现。**如果学习率太小**,那么学习过程会很缓慢。**如果初始学习率太低**,那么学习可能会卡在一个相当高的代价值。通常,就总训练时间和最终代价值而言,最优初始学习率会高于大约迭代 100 次左右后达到最佳效果的学习率。**因此,通常最好是检测最早的几轮迭代,选择一个比在效果上表现最佳的学习率更大的学习率,但又不能太大导致严重的震荡。**
学习率可通过试验和误差来选取,通常最好的选择方法是**监测目标函数值随时间变化的学习曲线**——与**其说是科学,这更像是一门艺术**。
> [29. 自适应学习率算法: AdaGrad,RMSProp,Adam 等***](#29-自适应学习率算法-adagradrmspropadam-等)
## 带动量的 SGD

从形式上看, 动量算法引入了变量 v 充当速度角色——它代表参数在参数空间移动的方向和速率。速度被设为负梯度的指数衰减平均。
之前,步长只是梯度范数乘以学习率。现在,步长取决于梯度序列的大小和排列。当许多连续的梯度指向相同的方向时,步长最大。如果动量算法总是观测到梯度 g,那么它会在方向 −g 上不停加速,直到达到最终速度,其中步长大小为
[](http://www.codecogs.com/eqnedit.php?latex=\frac{\epsilon\left\|g\right\|}{1-\alpha})
在实践中,α 的一般取值为 0.5, 0.9 和 0.99,分别对应**最大速度** 2倍,10倍和100倍于普通的 SGD 算法。和学习率一样, α 也应该随着时间不断调整(变大),但没有收缩 ϵ 重要。
**为什么要加入动量?**
加入的动量主要目的是解决两个问题: Hessian 矩阵的**病态**条件和**随机梯度的方差**。简单来说,就是为了加速学习。
虽然动量的加入有助于缓解这些问题,但其代价是引入了另一个超参数。
> [29. 自适应学习率算法: AdaGrad,RMSProp,Adam 等***](#29-自适应学习率算法-adagradrmspropadam-等)
带有动量的 SGD(左/上) 和不带动量的 SGD(右/下):


> 《深度学习》 4.3.1 梯度之上: Jacobian 和 Hessian 矩阵
此图说明动量如何克服病态的问题:等高线描绘了一个二次损失函数(具有病态条件的 Hessian 矩阵)。一个病态条件的二次目标函数看起来像一个长而窄的山谷或具有陡峭边的峡谷。带动量的 SGD 能比较正确地纵向穿过峡谷;而普通的梯度步骤则会浪费时间在峡谷的窄轴上来回移动,因为梯度下降无法利用包含在 Hessian 矩阵中的曲率信息。
**Nesterov 动量**
受 Nesterov 加速梯度算法 (Nesterov, 1983, 2004) 启发, Sutskever et al. (2013) 提出了动量算法的一个变种。其更新规则如下:

其中参数 α 和 ϵ 发挥了和标准动量方法中类似的作用。Nesterov 动量和标准动量之间的**区别体现在梯度计算**上。下面是完整的 Nesterov 动量算法:

Nesterov 动量中,梯度计算在施加当前速度之后。因此,Nesterov 动量可以解释为往标准动量方法中添加了一个校正因子。
在凸批量梯度的情况下, Nesterov 动量将额外误差收敛率从 O(1/k) 改进到 O(1/k^2)。可惜,在随机梯度的情况下, Nesterov 动量没有改进收敛率。
# 自适应学习率算法:AdaGrad、RMSProp、Adam 等***
> 《深度学习》 8.5 自适应学习率算法
Delta-bar-delta (Jacobs, 1988) 是一个早期的自适应学习率算法。该方法基于一个很简单的想法,如果损失对于某个给定模型参数的偏导保持相同的符号,那么学习率应该增加。如果对于该参数的偏导变化了符号,那么学习率应减小。当然,这种方法只能应用于全批量优化中(?)。
最近,提出了一些增量(或者基于小批量)的算法来自适应模型参数的学习率。
## AdaGrad

AdaGrad 会独立地适应所有模型参数的学习率。具体来说,就是缩放每个参数反比于其所有梯度历史平方值总和的平方根 (Duchi et al., 2011)。效果上具有损失最大偏导的参数相应地有一个快速下降的学习率,而具有小偏导的参数在学习率上有相对较小的下降。
**不过**,对于训练深度神经网络模型而言,**从训练开始时**就积累梯度平方会导致有效学习率过早和过量的减小。AdaGrad 在某些深度学习模型上效果不错,但不是全部。
## RMSProp

RMSProp 修改自 AdaGrad。AdaGrad 旨在应用于**凸问题**时快速收敛,而 RMSProp 在**非凸**设定下效果更好,改变梯度积累为指数加权的移动平均。
RMSProp 使用指数衰减平均以丢弃遥远过去的历史,使其能够在找到凸碗状结构后快速收敛,它就像一个初始化于该碗状结构的 AdaGrad 算法实例。
相比于 AdaGrad,使用移动平均引入了一个**新的超参数 ρ**,用来控制移动平均的长度范围。
经验上, RMSProp 已被证明是一种有效且实用的深度神经网络优化算法。目前它是深度学习从业者经常采用的优化方法之一。
**结合 Nesterov 动量的 RMSProp**

## Adam

Adam (Kingma and Ba, 2014) 是另一种学习率自适应的优化算法。
首先,在 Adam 中,动量直接并入了梯度一阶矩(指数加权)的估计。将动量加入 RMSProp 最直观的方法是将动量应用于缩放后的梯度。但是结合缩放的动量使用没有明确的理论动机。其次, Adam 包括偏置修正,修正从原点初始化的一阶矩(动量项)和(非中心的)二阶矩的估计。RMSProp 也采用了(非中心的)二阶矩估计,然而缺失了修正因子。因此,不像 Adam, RMSProp 二阶矩估计可能在训练初期有很高的偏置。Adam 通常被认为对超参数的选择相当鲁棒,尽管学习率有时需要从建议的默认修改。
**如何选择自适应学习率算法?**
目前在这一点上没有明确的共识。选择哪一个算法似乎主要取决于使用者对算法的熟悉程度(以便调节超参数)。
如果不知道选哪个,就用 AdamSGD 吧。
# 基于二阶梯度的优化方法:牛顿法、共轭梯度、BFGS 等的做法*
> 《深度学习》 8.6 二阶近似方法:8.6.1 牛顿法,8.6.2 共轭梯度,8.6.3 BFGS
推导很难实际上也很少用,如果你不是数学系的,可以跳过这部分。
# 批标准化(Batch Normalization)的意义**
> 《深度学习》 8.7.1 批标准化
批标准化(Batch Normalization, BN, Ioffe and Szegedy, 2015)是为了克服神经网络**层数加深导致难以训练**而出现的一个算法。
说到底,BN 还是为了解决**梯度消失/梯度爆炸**问题,特别是梯度消失。
**BN 算法**:

BN 算法需要学习两个参数 γ 和 β.
> Ioffe and Szegedy, 2015, Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
**批标准化为什么有用?**
> [深度学习(二十九)Batch Normalization 学习笔记](https://blog.csdn.net/hjimce/article/details/50866313) - CSDN博客
>
> [深度学习中 Batch Normalization为什么效果好?](https://www.zhihu.com/question/38102762/answer/85238569) - 知乎
# 神经网络中的卷积,以及卷积的动机:稀疏连接、参数共享、等变表示(平移不变性)***
> 《深度学习》 9.2 动机
注意:本书所谈的卷积,是包括卷积层、激活层和池化层的统称
**神经网络中的卷积**:
当我们在神经网络中提到卷积时,通常是指由**多个并行卷积**组成的运算。一般而言,每个核只用于提取一种类型的特征,尽管它作用在多个空间位置上。而我们通常希望网络的每一层能够在多个位置提取多种类型的特征。
> 《深度学习》 9.5 基本卷积函数的变体
卷积的一些基本概念:通道(channel)、卷积核(kernel、filter)、步幅(stride,下采样)、填充(padding)
> [33. 卷积中零填充的影响,基本卷积的变体](#33-卷积中零填充的影响基本卷积的变体)
**为什么使用卷积?(卷积的动机)**
卷积运算通过三个重要的思想来帮助改进机器学习系统:**稀疏交互**(sparseinteractions)、**参数共享**(parameter sharing)、**等变表示**(equivariant representations)。
## 稀疏连接(sparse connectivity)
稀疏连接,也称稀疏交互、稀疏权重。
传统的神经网络中每一个输出单元会与每一个输入单元都产生交互。卷积网络改进了这一点,使具有稀疏交互的特征。CNN 通过使核(kernel、filter)的大小远小于输入的大小来达到的这个目的。

举个例子,当处理一张图像时,输入的图像可能包含成千上万个像素点,但是我们可以通过只占用几十到上百个像素点的核来**检测一些小的、有意义的特征**,例如图像的边缘。
**稀疏交互的好处**:
- 提高了模型的统计效率:原本一幅图像只能提供少量特征,现在每一块像素区域都可以提供一部分特征
- 减少了模型的存储需求和计算量,因为参数更少
如果有 m 个输入和 n 个输出,那么矩阵乘法需要 `m × n` 个参数并且相应算法的时间复杂度为 `O(m × n)`;如果限制每一个输出拥有的连接数为 k,那么稀疏的连接方法只需要 `k × n` 个参数以及 `O(k × n)` 的运行时间。而在实际应用中,**k 要比 m 小几个数量级**。
虽然看似减少了隐藏单元之间的交互,但实际上处在深层的单元可以间接地连接到全部或者大部分输入。

## 参数共享(parameter sharing)
参数共享是指在一个模型的多个函数中使用相同的参数。作为参数共享的同义词,我们可以说
一个网络含有**绑定的权重**(tied weights)
在传统的神经网络中,当计算一层的输出时,权重矩阵的每一个元素只使用一次,当它乘以输入的一个元素后就再也不会用到了。卷积运算中的参数共享保证了我们只需要学习一个参数集合,而不是对于每一位置都需要学习一个单独的参数集合。
考虑一个具体的例子——**边缘检测**——来体会稀疏连接+参数共享带来的效率提升:

两个图像的高度均为 280 个像素。输入图像的宽度为 320 个像素,而输出图像的宽度为 319 个像素(padding='VALID')。对于边缘检测任务而言,只需要一个包含**两个元素的卷积核**就能完成;而为了用矩阵乘法描述相同的变换,需要一个包含 320 × 280 × 319 × 280 ≈ 80亿个元素的矩阵(40亿倍)。
同样,使用卷积只需要 319 × 280 × 3 = 267,960 次浮点运算(每个输出像素需要两次乘法和一次加法);而直接运行矩阵乘法的算法将执行超过 160 亿次浮点运算(60000倍)
## 平移等变|不变性(translation invariant)
(局部)平移不变性是一个很有用的性质,尤其是当我们关心某个特征**是否出现**而不关心它出现的具体位置时。
**参数共享**(和池化)使卷积神经网络具有一定的**平移不变性**。这就意味着即使图像经历了一个小的平移,依然会产生相同的特征。例如,分类一个 MNIST 数据集的数字,对它进行任意方向的**平移**(不是旋转),无论最终的位置在哪里,都能正确分类。
> 池化操作也能够帮助加强网络的平移不变性 > [35. 池化、池化(Pooling)的作用***](#35-池化池化pooling的作用)
**什么是等变性?**
- 如果一个函数满足**输入改变,输出也以同样的方式改变**这一性质,我们就说它是等变 (equivariant) 的。
- 对于卷积来说,如果令 g 是输入的任意平移函数,那么卷积函数对于 g 具有等变性。
当处理**时间序列数据**时,这意味着通过卷积可以得到一个由输入中出现不同特征的时刻所组成的时间轴。如果我们把输入中的一个事件向后延时,在输出中仍然会有完全相同的表示,只是时间延后了。
图像与之类似,卷积产生了一个 2 维映射来表明某些特征在输入中出现的位置。如果我们移动输入中的对象,它的表示也会在输出中移动同样的量。
卷积对其他的一些变换并不是天然等变的,例如对于图像的**放缩**或者**旋转**变换,需要其他的一些机制来处理这些变换。
> [池化的不变性](http://ufldl.stanford.edu/wiki/index.php/%E6%B1%A0%E5%8C%96#.E6.B1.A0.E5.8C.96.E7.9A.84.E4.B8.8D.E5.8F.98.E6.80.A7) - Ufldl
# 卷积中不同零填充的影响**
> 《深度学习》 9.5 基本卷积函数的变体
在任何卷积网络的实现中都有一个重要性质,那就是能够隐含地**对输入用零进行填充**使得它加宽。如果没有这个性质,会极大得限制网络的表示能力。
三种零填充设定,其中 `m` 和 `k` 分别为图像的宽度和卷积核的宽度(高度类似):
1. 有效(valid)卷积——不使用零填充,卷积核只允许访问那些图像中能够**完全包含整个核**的位置,输出的宽度为 `m − k + 1`.
- 在这种情况下,输出的所有像素都是输入中相同数量像素的函数,这使得输出像素的表示更加规范。
- 然而,输出的大小在每一层都会缩减,这限制了网络中能够包含的卷积层的层数。(一般情况下,影响不大,除非是上百层的网络)
2. 相同(same)卷积——只进行足够的零填充来**保持输出和输入具有相同的大小**,即输出的宽度为 `m`.
- 在这种情况下,只要硬件支持,网络就能包含任意多的卷积层。
- 然而,输入像素中靠近边界的部分相比于中间部分对于输出像素的影响更小。这可能会导致边界像素存在一定程度的欠表示。
3. 全(full)卷积——进行足够多的零填充使得每个像素都能被访问 k 次(非全卷积只有中间的像素能被访问 k 次),最终输出图像的宽度为 `m + k − 1`.
- 因为 same 卷积可能导致边界像素欠表示,从而出现了 Full 卷积;
- 但是在这种情况下,输出像素中靠近边界的部分相比于中间部分是更少像素的函数。这将导致学得的卷积核不能再所有所有位置表现一致。
- 事实上,很少使用 Full 卷积
> 注意:如果以“全卷积”作为关键词搜索,返回的是一个称为 FCN(Fully Convolutional Networks)的卷积结构,而不是这里描述的填充方式。
通常**零填充的最优数量**(对于测试集的分类正确率)处于 “有效卷积”和 “相同卷积” 之间。
# 基本卷积的变体:反卷积、空洞卷积***
原书中也描述一些基本卷积的变体:局部卷积、平铺卷积;

> 从上到下一次为局部卷积、平铺卷积和标准卷积;
>
> 《深度学习》 9.5 基本卷积函数的变体
不过这跟我想的“变体”不太一样(百度都搜不到这两种卷积),下面介绍的是一些我认识中比较流行的卷积变体:
## 转置卷积|反卷积(Transposed convolution)

> No padding, no strides, transposed
> [如何理解深度学习中的deconvolution networks?](https://www.zhihu.com/question/43609045) - 知乎
## 空洞卷积|扩张卷积(Dilated convolution)

> No padding, no stride, dilation
> [如何理解空洞卷积(dilated convolution)?](https://www.zhihu.com/question/54149221) - 知乎
> 卷积、转置卷积、空洞卷积动图演示:vdumoulin/[conv_arithmetic](https://github.com/vdumoulin/conv_arithmetic): A technical report on convolution arithmetic in the context of deep learning
# 池化、池化(Pooling)的作用***
> 《深度学习》 9.3 池化
一次典型的卷积包含三层:第一层并行地计算多个卷积产生一组线性激活响应;第二层中每一个线性激活响应将会通过一个非线性的激活函数;第三层使用**池化函数**(pooling function)来进一步调整这一层的输出。
```
# Keras
from keras.layers import Input, Conv2D, Activation, MaxPooling2D
net = Input([in_w, in_h, input_dim])
net = Conv2D(output_dim, kernel_size=(3, 3))(net)
net = Activation('relu')(net)
net = MaxPooling2D(pool_size=(2, 2))(net)
"""
卷积层中,一般 strides=1, padding='valid'
池化层中,一般 strides=pool_size, padding='valid'
"""
```
池化函数使用某一位置的相邻输出的**总体统计特征**来代替网络在该位置的输出。
常见的池化函数:
- *最大池化(Max pooling)
- *平均值池化(Mean pooling)
- L2 范数
- 基于中心像素距离的加权平均
池化操作有助于卷积网络的平移不变性
> [32.3. 平移等变/不变性(translation invariant)](#323-平移等变不变性translation-invariant)
**使用池化可以看作是增加了一个无限强的先验**:这一层学得的函数必须具有对少量平移的不变性。当这个假设成立时,池化可以极大地提高网络的统计效率。
(最大)池化对平移是天然不变的,但池化也能用于学习其他不变性:

这三个过滤器都旨在检测手写的数字 5。每个过滤器尝试匹配稍微**不同方向**的 5。当输入中出现 5 时,无论哪个探测单元被激活,最大池化单元都将产生较大的响应。
这种多通道方法只在学习其他变换时是必要的。这个原则在 maxout 网络 (Goodfellow et al., 2013b) 和其他卷积网络中更有影响。
池化综合了区域内的 k 个像素的统计特征而不是单个像素,这种方法提高了网络的计算效率,因为下一层少了约 k 倍的输入。
在很多任务中,池化还有助于对于处理不同大小的输入:例如我们想对不同大小的图像进行分类时,分类层的输入必须是固定的大小,而这通常通过调整池化区域的偏置大小来实现。
其他参考:
- 一些理论工作对于在不同情况下应当使用哪种池化函数给出了一些指导 (Boureau et al., 2010)
- 将特征一起动态地池化:对于感兴趣特征的位置运行聚类算法 (Boureau et al., 2011)、先学习一个单独的池化结构,再应用到全部的图像中 (Jia et al., 2012)
- 《深度学习》 20.6 卷积玻尔兹曼机、20.10.6 卷积生成网络
# 卷积与池化的意义、影响(作为一种无限强的先验)**
> 《深度学习》 9.4 卷积与池化作为一种无限强的先验
一个无限强的先验需要对一些参数的概率置零并且完全禁止对这些参数赋值,无论数据对于这些参数的值给出了多大的支持。
如果把卷积网络类比成全连接网络,那么对于这个全连接网络的权重有一个无限强的先验:隐藏单元的权重必须和它邻居的权重相同,但可以在空间上移动;同时要求除了那些处在“感受野”内的权重以外,其余的权重都为零。
类似的,使用**池化**也是一个无限强的先验:每一个单元都具有对少量平移的不变性。
**卷积与池化作为一种无限强先验的影响**:
1. 卷积和池化可能导致**欠拟合**
- 与任何其他先验类似,卷积和池化只有当先验的假设合理且正确时才有用。
- 如果一项任务涉及到要**对输入中相隔较远的信息进行合并**时,那么卷积所利用的先验可能就不正确了。
- 如果一项任务依赖于保存**精确的空间信息**,那么在所有的特征上使用池化将会增大训练误差。
> 因此,一些卷积网络结构 (Szegedy et al., 2014a) 为了既获得具有较高不变性的特征又获得当平移不变性不合理时不会导致欠拟合的特征,被设计成在一些通道上使用池化而在另一些通道上不使用。
2. 当我们比较卷积模型的统计学习表现时,只能以基准中的其他卷积模型作为比较的对象
> 《深度学习》 5.6 贝叶斯统计(先验概率分布)
# RNN 的几种基本设计模式
> 《深度学习》 10.2 循环神经网络
循环神经网络中一些重要的设计模式包括以下几种:
1. (*)每个时间步都有输出,并且隐藏单元之间有循环连接的循环网络

- 将 x 值的输入序列映射到输出值 o 的对应序列
- 损失 L 衡量每个 o 与相应的训练目标 y 的距离
- 损失 L 内部计算 y^ = softmax(o),并将其与目标 y 比较
- 输入 x 到隐藏 h 的连接由权重矩阵 U 参数化
- 隐藏 h(t-1) 到隐藏 h(t) 的循环连接由权重矩阵 W 参数化
- 隐藏到输出的连接由权重矩阵 V 参数化
2. 每个时间步都产生一个输出,只有当前时刻的输出到下个时刻的隐藏单元之间有循环连接的循环网络

- 此类 RNN 的唯一循环是从输出 o 到隐藏层 h 的反馈连接
- 表示能力弱于 RNN_1,单更容易训练
3. 隐藏单元之间存在循环连接,但读取整个序列后产生单个输出的循环网络

这样的网络可以用于概括序列并产生用于进一步处理的固定大小的表示
一般所说的 RNN(循环神经网络)指的是**第一种**设计模式
这些循环网络都将一个输入序列映射到**相同长度**的输出序列
# RNN 更新方程(前向传播公式),包括 LSTM、GRU 等***
> 《深度学习》 10 序列建模:循环和递归网络
>
> [RNN, LSTM, GRU 公式总结](https://blog.csdn.net/zhangxb35/article/details/70060295) - CSDN博客
**基本 RNN**
> [Recurrent neural network](https://en.wikipedia.org/wiki/Recurrent_neural_network#Elman_networks_and_Jordan_networks) - Wikipedia
根据隐层 h(t) 接受的是上时刻的隐层 h(t−1) 还是上时刻的输出 y(t−1),分为两种 RNN:
- Elman RNN
[](http://www.codecogs.com/eqnedit.php?latex=\begin{aligned}&space;h^{(t)}&=\tanh\left(&space;W_hx^{(t)}+U_hh^{(t-1)}+b_h&space;\right)\\&space;y^{(t)}&={\rm&space;softmax}\left(&space;W_yh^{(t)}+b_y&space;\right)\\&space;\end{aligned})
- Jordan RNN
[](http://www.codecogs.com/eqnedit.php?latex={\displaystyle&space;{\begin{aligned}&space;h^{(t)}&=\tanh\left(&space;W_hx^{(t)}+U_hy^{(t-1)}+b_h&space;\right)\\&space;y^{(t)}&={\rm&space;softmax}\left(&space;W_yh^{(t)}+b_y&space;\right)\&space;\end{aligned}}})
> 《深度学习》 默认的 RNN 是 Elman RNN > [37. RNN(循环神经网络) 的几种基本设计模式**](#37-rnn循环神经网络-的几种基本设计模式)
**门限 RNN**(LSTM、GRU)与基本 RNN 的主要区别在于 Cell 部分
**LSTM**
> [Long short-term memory](https://en.wikipedia.org/wiki/Long_short-term_memory#Variants) - Wikipedia
[](http://www.codecogs.com/eqnedit.php?latex={\displaystyle&space;{\begin{aligned}&space;f_{t}&=\sigma(W_{f}x_{t}+U_{f}h_{t-1}+b_{f})\\&space;i_{t}&=\sigma(W_{i}x_{t}+U_{i}h_{t-1}+b_{i})\\&space;\tilde{c}_{t}&=\tanh(W_{c}x_{t}+U_{c}h_{t-1}+b_{c})\\&space;c_{t}&=f_{t}\circ&space;c_{t-1}+i_{t}\circ&space;\tilde{c}_{t}\\&space;o_{t}&=\sigma(W_{o}x_{t}+U_{o}h_{t-1}+b_{o})\\&space;h_{t}&=o_{t}\circ&space;\tanh(c_{t})&space;\end{aligned}}})
- 其中 f 为遗忘门(forget),i 为输入门(input),o 为输出门(output)。
- 每个门的输入都是 x 和 h,但是参数都是独立的(参数数量是基本 RNN 的 4 倍)
- c 表示 cell state(如果用过 tensorflow 中的 RNN,会比较熟悉)
- 如果遗忘门 f 取 0 的话,那么上一时刻的状态就会全部被清空,只关注此时刻的输入
- 输入门 i 决定是否接收此时刻的输入
- 输出门 o 决定是否输出 cell state
类似基本 RNN,LSTM 也有另一个版本,将公式中所有 h(t-1) 替换为 c(t-1),但不常见
**GRU**
> [Gated recurrent unit](https://en.wikipedia.org/wiki/Gated_recurrent_unit#Architecture) - Wikipedia
[](http://www.codecogs.com/eqnedit.php?latex={\displaystyle&space;{\begin{aligned}&space;z_{t}&=\sigma(W_{z}x_{t}+U_{z}h_{t-1}+b_{z})\\&space;r_{t}&=\sigma(W_{r}x_{t}+U_{r}h_{t-1}+b_{r})\\&space;\tilde{h}_t&=\tanh(W_{h}x_{t}+U_{h}(r_{t}\circ&space;h_{t-1})+b_{h})\\&space;h_{t}&=(1-z_{t})\circ&space;h_{t-1}+z_{t}\circ&space;\tilde{h}_t&space;\end{aligned}}})
- 其中 z 为更新门(update),r 为重置门(reset)
- GRU 可以看作是将 LSTM 中的遗忘门和输入门合二为一了
# BPTT(back-propagation through time,通过时间反向传播)**
> 《深度学习》 10.2.2 计算循环神经网络的梯度
# 自编码器在深度学习中的意义*
**自编码器的意义**:
- 传统自编码器被用于降维或特征学习
- 近年来,自编码器与潜变量模型理论的联系将自编码器带到了生成式建模的前沿
- 几乎任何带有潜变量并配有一个推断过程(计算给定输入的潜在表示)的生成模型,都可以看作是自编码器的一种特殊形式。
> 《深度学习》 20 深度生成模型,20.10.3 变分自编码器,20.12 生成随机网络
**自编码器的一般结构**

- 自编码器有两个组件:**编码器** f(将 x 映射到 h)和**解码器** g(将 h 映射到 r)
- 一个简单的自编码器试图学习 `g(f(x)) = x`;换言之,自编码器尝试将输入复制到输出
- 单纯将输入复制到输出没什么用,相反,训练自编码器的目标是获得有用的特征 h。
自编码器的学习过程就是最小化一个损失函数:
[](http://www.codecogs.com/eqnedit.php?latex=L(\boldsymbol{x},g(f(\boldsymbol{x}))))
# 自编码器一些常见的变形与应用:正则自编码器、稀疏自编码器、去噪自编码器*
> [40. 自编码器在深度学习中的意义](#40-自编码器在深度学习中的意义)
>
> 《深度学习》 14.2 正则自编码器
**欠完备自编码器**
- 从自编码器获得有用特征的一种方法是**限制 h 的维度比 x 小**,这种编码维度小于输入维度的自编码器称为**欠完备**(undercomplete)自编码器;
- 相反,如果 h 的维度大于 x,此时称为过完备自编码器。
- **学习欠完备的表示将强制自编码器捕捉训练数据中最显著的特征**
- 当解码器是线性的且 L 是均方误差,欠完备的自编码器会学习出与 PCA 相同的生成子空间
- 而拥有**非线性**编码器函数 f 和**非线性**解码器函数 g 的自编码器能够学习出更强大的 PCA 非线性推广
- 但如果编码器和解码器被赋予**过大的容量**,自编码器会执行复制任务而捕捉不到任何有关**数据分布**的有用信息。
- 过完备自编码器就可以看作是被赋予过大容量的情况
**正则自编码器**
- 通过加入正则项到损失函数可以限制模型的容量,同时鼓励模型学习除了复制外的其他特性。
- 这些特性包括稀疏表示、表示的小导数、以及对噪声或输入缺失的鲁棒性。
- 即使模型的容量依然大到足以学习一个无意义的恒等函数,正则自编码器仍然能够从数据中学到一些关于数据分布的信息。
**稀疏自编码器**
- 稀疏自编码器一般用来学习特征
- 稀疏自编码器简单地在训练时结合编码层的**稀疏惩罚** Ω(h) 和重构误差:
[](http://www.codecogs.com/eqnedit.php?latex=L(\boldsymbol{x},g(f(\boldsymbol{x})))+\Omega(\boldsymbol{h})&space;=&space;L(\boldsymbol{x},g(f(\boldsymbol{x})))+\lambda\sum_i\left|h_i\right|)
- 稀疏惩罚不算是一个正则项。这仅仅影响模型关于潜变量的分布。这个观点提供了训练自编码器的另一个动机:这是近似训练生成模型的一种途径。这也给出了为什么自编码器学到的特征是有用的另一个解释:它们描述的潜变量可以解释输入。
> 《深度学习》 14.2.1 稀疏自编码器
**去噪自编码器(DAE)**
- 去噪自编码器试图学习**更具鲁棒性的**特征
- 与传统自编码器不同,去噪自编码器(denoising autoencoder, DAE)最小化:
[](http://www.codecogs.com/eqnedit.php?latex=L(\boldsymbol{x},g(f(\boldsymbol{\tilde{x}}))))
- 这里的 x~ 是**被某种噪声损坏**的 x 的副本,去噪自编码器需要预测原始未被损坏数据
- 破坏的过程一般是以某种概率分布(通常是二项分布)将一些值置 0.

> 《深度学习》 14.2.2 去噪自编码器,14.5 去噪自编码器
**为什么DAE有用?**
- 对比使用非破损数据进行训练,破损数据训练出来的权重噪声比较小——在破坏数据的过程中去除了真正的噪声
- 破损数据一定程度上减轻了训练数据与测试数据的代沟——使训练数据更接近测试数据
> [降噪自动编码器(Denoising Autoencoder)](https://www.cnblogs.com/neopenx/p/4370350.html) - Physcal - 博客园
>> 感觉这两个理由很牵强,但是从数据分布的角度讲太难了
# 半监督的思想以及在深度学习中的应用*
> 《深度学习》 15.3 半监督解释因果关系
# 分布式表示的概念、应用,与符号表示(one-hot 表示)的区别***
> 《深度学习》 15.4 分布式表示
## 什么是分布式表示?
- 所谓分布式表示就是用不同的特征,通过**组合**来表示不同的概念


(左)是 one-hot 表示(一种稀疏表示),(右)为分布式表示
> [神经网络如何学习分布式表示](http://baijiahao.baidu.com/s?id=1593632865778730392) - 百家号
## 分布式表示为什么强大?——分布式表示与符号表示
分布式表示之所以强大,是因为它能用具有 `d` 个值的 `n` 个**线性阀值特征**去描述 `d^n` 个不同的概念——换言之,在输入维度是 d 的一般情况下,具有 n 个特征的分布式表示可以给 O(n^d) 个不同区域分配唯一的编码
> **线性阀值特征**:本身是一个**连续值**,通过划分阈值空间来获得对应的离散特征
**符号表示**
- 如果我们没有对数据做任何假设,并且每个区域使用唯一的符号来表示,每个符号使用单独的参数去识别空间中的对应区域,那么指定 `O(n^d)` 个区域需要 `O(n^d)` 个样本/参数。
- 举个例子:作为纯符号,“猫”和“狗”之间的距离和任意其他两种符号的距离是一样。
然而,如果将它们与**有意义的分布式表示**相关联,那么关于猫的很多特点可以推广到狗,反之亦然——比如,某个分布式表示可能会包含诸如“具有皮毛”或“腿的数目”这类在猫和的**嵌入/向量**上具有相同值的项
**分布式表示与符号表示**(最近邻):


- 两者都在学习如何将输入空间分割成多个区域
- 在输入维度相同的情况下,分布式表示能够比非分布式表示多分配指数级的区域——这一特性可用于解决**维度灾难**问题
> [44. 如何理解维数灾难?](#44-如何理解维数灾难)
**非线性特征**:
上面假设了**线性阀值特征**,然而更一般的,分布式表示的优势还体现在其中的每个特征可以用非线性算法——**神经网络**——来提取。简单来说,表示能力又提升了一个级别。
一般来说,无论我们使用什么算法,需要学习的空间区域数量是固定的;但是使用分布式表示有效的减少了参数的数量——从 `O(n^d)` 到 `O(nd)`——这意味着我们需要拟合参数更少,因此只需要更少的训练样本就能获得良好的泛化。
**一些非分布式表示算法**:
- 聚类算法,比如 k-means 算法
- k-最近邻算法
- 决策树
- 支持向量机
- 基于 n-gram 的语言模型
**什么时候应该使用分布式表示能带来统计优势?**
当一个明显复杂的结构可以**用较少参数紧致地表示**时,使用分布式表示就会具有统计上的优势(避免维数灾难)。
> [44. 如何理解维数灾难?](#44-如何理解维数灾难)
一些传统的非分布式学习算法仅仅在**平滑先验**的情况下能够泛化。
# 如何理解维数灾难?***
> 《深度学习》 5.11.1 维数灾难
概括来说,就是当数据维数很高时,会导致学习变得困难。
这里的“困难”体现在两方面:
1. 当数据较多时,会使训练的周期变得更长
2. 当数据较少时,对新数据的泛化能力会更弱,甚至失去泛化能力
> 这两点对于任何机器学习算法都是成立的;但在维数灾难的背景下,会加剧这两个影响
对于第二点,书中使用了另一种描述:“由维数灾难带来的一个问题是统计挑战,所谓统计挑战指的是 **x 的可能配置数目远大于训练样本的数目**”。
为了充分理解这个问题,我们假设输入空间如图所示被分成单元格。

- 当数据的维度增大时(从左向右),我们感兴趣的配置数目会随指数级增长。
- 当空间是低维时,我们可以用由少量单元格去描述这个空间。泛化到新数据点时,通过检测和单元格中的训练样本的相似度,我们可以判断如何处理新数据点。
- 当空间的维数很大时,很可能发生大量单元格中没有训练样本的情况。此时,基于“**平滑先验**”的简单算法将无力处理这些新的数据。
> [7. 局部不变性(平滑先验)及其在基于梯度的学习上的局限性*](#7-局部不变性平滑先验及其在基于梯度的学习上的局限性)
- 更一般的,O(nd) 个参数(d 个特征,每个特征有 n 种表示)能够明确表示输入空间中 O(n^d) 个不同区域。如果我们没有对数据做任何假设,并且**每个区域使用唯一的符号来表示**,每个符号使用单独的参数去识别空间中的对应区域,那么指定 O(n^d) 个区域将需要 O(n^d) 个样本。
> 《深度学习》 15.4 分布式表示
**如何解决维数灾难?**
> [43.3. 什么时候应该使用分布式表示能带来统计优势?](#433-什么时候应该使用分布式表示能带来统计优势)
# 迁移学习相关概念:多任务学习、一次学习、零次学习、多模态学习**
> 《深度学习》 15.2 迁移学习和领域自适应
**什么是迁移学习?**
- 迁移学习和领域自适应指的是利用一个任务(例如,分布 P1)中已经学到的内容去改善另一个任务(比如分布 P2)中的泛化情况。
- 例如,我们可能在第一个任务中学习了一组视觉类别,比如猫和狗,然后在第二种情景中学习一组不同的视觉类别,比如蚂蚁和黄蜂。
- 除了共享**输出语义**(上面这个例子),有时也会共享**输出语义**
- 例如,语音识别系统需要**在输出层产生有效的句子**,但是输入附近的较低层可能需要识别相同音素或子音素发音的不同版本(这取决于说话人)
**迁移学习与多任务学习**
- 因为目前迁移学习更流行,因此不少博客简介上,会将多任务学习归属于迁移学习的子类或者迁移学习的相关领域。
- 迁移学习与多任务学习的一些结构:


> (左)> 《深度学习》 15.2 迁移学习和领域自适应;(右)> 《深度学习》 7.7 多任务学习
- 这两种都可能是迁移学习或者多任务学习的结构。~~迁移学习的输入在每个任务上具有不同的意义(甚至不同的维度),但是输出在所有的任务上具有**相同的语义**;多任务学习则相反~~
**迁移学习与领域自适应**
- 相比于迁移学习和多任务学习,领域自适应的提法比较少,也更简单一些,其在每个情景之间任务(和最优的输入到输出的映射)都是相同的,但是**输入分布**稍有不同。
- 例如,考虑情感分析的任务:网上的评论有许多类别。在书、视频和音乐等媒体内容上训练的顾客评论情感预测器,被用于分析诸如电视机或智能电话的消费电子产品的评论时,领域自适应情景可能会出现。可以想象,存在一个潜在的函数可以判断任何语句是正面的、中性的还是负面的,但是词汇和风格可能会因领域而有差异
**one-shot learning 和 zero-shot learning**
- 迁移学习的两种极端形式是**一次学习**(one-shot learning)和**零次学习**(zero-shot learning)
- 只有少量标注样本的迁移任务被称为 one-shot learning;没有标注样本的迁移任务被称为 zero-shot learning.
- **one-shot learning**
- one-shot learning 稍微简单一点:在大数据上学习 general knowledge,然后在特定任务的小数据上有技巧的 fine tuning。
- **zero-shot learning**
- 相比 one-shot,zero-shot learning 要更复杂。
- 先来看一个 zero-shot 的例子:假设学习器已经学会了关于动物、腿和耳朵的概念。如果已知猫有四条腿和尖尖的耳朵,那么学习器可以在没有见过猫的情况下猜测该图像中的动物是猫。
- (TODO)
**多模态学习(multi-modal learning)**
- 与 zero-shot learning 相同的原理可以解释如何能执行**多模态学习**(multimodal learning)

> 《深度学习》 15.2 迁移学习和领域自适应 图 15.3
# 图模型|结构化概率模型相关概念*
> 《深度学习》 16 深度学习中的结构化概率模型
>
> 答案不完整,更多相关概念请阅读本章
**有向图模型**
- 有向图模型(directed graphical model)是一种结构化概率模型,也被称为**信念网络**(belief network)或者**贝叶斯网络**(Bayesian network)
- 描述接力赛例子的有向图模型

- Alice 在 Bob 之前开始,所以 Alice 的完成时间 t0 影响了 Bob 的完成时间 t1。
- Carol 只会在 Bob 完成之后才开始,所以 Bob 的完成时间 t1 直接影响了 Carol 的完成时间 t2。
- 正式地说,变量 x 的有向概率模型是通过有向无环图 G(每个结点都是模型中的随机变量)和一系列**局部条件概率分布**(local conditional probability distribution)来定义的,x 的概率分布可以表示为:

- 其中 大P 表示结点 xi 的所有父结点
- 上述接力赛例子的概率分布可表示为:

**无向图模型**
- 无向图模型(undirected graphical Model),也被称为**马尔可夫随机场**(Markov random field, MRF)或者是**马尔可夫网络**(Markov network)
- 当相互的作用并没有本质性的指向,或者是明确的双向相互作用时,使用无向模型更加合适。
**图模型的优点**
1. 减少参数的规模
- 通常意义上说,对每个变量都能取 k 个值的 n 个变量建模,**基于查表的**方法需要的复杂度是 `O(k^n)`,如果 m 代表图模型的单个条件概率分布中最大的变量数目,那么对这个有向模型建表的复杂度大致为 `O(k^m)`。只要我们在设计模型时使其满足 `m ≪ n`,那么复杂度就会被大大地减小;换一句话说,只要图中的每个变量都只有少量的父结点,那么这个分布就可以用较少的参数来表示。
1. 统计的高效性
- 相比图模型,**基于查表的**模型拥有天文数字级别的参数,为了准确地拟合,相应的训练集的大小也是相同级别的。
1. 减少运行时间
- 推断的开销:计算分布时,避免对整个表的操作,比如求和
- 采样的开销:类似推断,避免读取整个表格
> 《深度学习》 16.3 从图模型中采样
**图模型如何用于深度学习**
- 受限玻尔兹曼机(RBM)
- RBM 是图模型如何用于深度学习的典型例子
- RBM 本身不是一个深层模型,它有一层潜变量,可用于学习输入的表示。但是它可以被用来构建许多的深层模型。
**其他相关名词**:
- 信念网络(有向图模型)
- 马尔可夫网络(无向图模型)
- 配分函数
- 能量模型(无向图模型)
- 分离(separation)/d-分离
- 道德图(moralized graph)、弦图(chordal graph)
- 因子图(factor graph)
- Gibbs 采样
- 结构学习(structure learning)
# 深度生成模型、受限玻尔兹曼机(RBM)相关概念*
> 《深度学习》 16.7.1 实例:受限玻尔兹曼机、20.1 玻尔兹曼机、20.2 受限玻尔兹曼机
# 深度学习在图像、语音、NLP等领域的常见作法与基本模型**
> 《深度学习》 12 应用
## 计算机视觉(CV)
> 12.2 计算机视觉
**预处理**
许多应用领域需要复杂精细的预处理,但是 CV 通常只需要相对少的预处理。
通常,**标准化**是图像唯一必要的预处理——将图像格式化为具有相同的比例,比如 [0,1] 或者 [-1,1].
许多框架需要图像缩放到标准的尺寸。但这不是必须的,一些卷积模型接受可变大小的输入并动态地调整它们的池化区域大小以保持输出大小恒定。
其他预处理操作:
**对比度归一化**
- 在许多任务中,对比度是能够安全移除的最为明显的变化源之一。简单地说,对比度指的是图像中亮像素和暗像素之间差异的大小。
- 整个图像的对比度可以表示为:
,其中
,整个图片的平均强度
**全局对比度归一化**(Global contrast normalization, GCN)
- GCN 旨在通过从每个图像中减去其平均值,然后重新缩放其使得其像素上的标准差等于某个常数 s 来防止图像具有变化的对比度。定义为:

- 从大图像中剪切感兴趣的对象所组成的数据集不可能包含任何强度几乎恒定的图像。此时,设置 λ = 0 来忽略小分母问题是安全的。(Goodfellow et al. 2013c)
- 随机剪裁的小图像更可能具有几乎恒定的强度,使得激进的正则化更有用。此时可以加大 λ (ϵ = 0, λ = 10; Coates et al. 2011)
- 尺度参数 s 通常可以设置为 1 (Coates et al. 2011),或选择使所有样本上每个像素的标准差接近 1 (Goodfellow et al. 2013c)
- **GCN 的意义**
- 式中的标准差可以看作是对图片 L2 范数的重新缩放(假设移除了均值),但我们倾向于标准差而不是 L2 范数来定义 GCN,是因为标准差包括除以像素数量这一步,从而基于标准差的 GCN 能够使用与图像大小无关的固定的 s.
- 而将标准差视为 L2 范数的缩放,可以将 GCN 理解成到球壳的一种映射。这可能是一个有用的属性,因为神经网络往往更好地响应空间方向,而不是精确的位置。

- (左) 原始的输入数据可能拥有任意的范数。
- (中) λ = 0 时候的 GCN 可以完美地将所有的非零样本投影到球上。这里我们令 s = 1, ϵ = 10−8。由于我们使用的 GCN 是基于归一化标准差而不是 L2 范数,所得到的球并不是单位球。
- (右) λ > 0 的正则化 GCN 将样本投影到球上,但是并没有完全地丢弃其范数中变化。 s 和 ϵ 的取值与之前一样。
- GCN 的问题:
- 全局对比度归一化常常不能突出我们想要突出的图像特征,例如边缘和角。
- 例子:如果我们有一个场景,包含了一个大的黑暗区域和一个大的明亮的区域(例如一个城市广场有一半的区域处于建筑物的阴影之中),则全局对比度归一化将确保暗区域的亮度与亮区域的亮度之间存在大的差异。然而,它不能确保暗区内的边缘突出。
**局部对比度归一化**(local contrast normalization, LCN)
- GCN 存在的问题催生了 LCN
- LCN 确保对比度在每个小窗口上被归一化,而不是作为整体在图像上被归一化。

- LCN 通常可以通过使用可分离卷积来计算特征映射的局部平均值和局部标准差,然后在不同的特征映射上使用逐元素的减法和除法。
- LCN 是可微分的操作,并且还可以作为一种非线性作用应用于网
络隐藏层,以及应用于输入的预处理操作。
**数据集增强**
数据集增强可以被看作是一种**只对训练集**做预处理的方式。
## 语音识别
> 12.3 语音识别
>
> 本章没什么实际内容,主要介绍了各阶段的主流模型
自动语音识别(Automatic Speech Recognition, ASR)任务指的是构造一个函数 f*,使得它能够在给定声学序列 X 的情况下计算最有可能的语言序列 y.
令 X = (x(1), x(2), ..., x(T)) 表示语音的输入向量,传统做法以 20ms 左右为一帧分割信号;y = (y1, y2, ..., yN) 表示目标的输出序列(通常是一个词或者字符的序列。
许多语音识别的系统通过特殊的手工设计方法预处理输入信号,从而提取声学特征;也有一些深度学习系统 (Jaitly and Hinton, 2011) 直接从原始输入中学习特征。
## 自然语言处理
> 12.4 自然语言处理
相关术语:
- n-gram 语言模型
- 神经语言模型(Neural Language Model, NLM)
- 结合 n-gram 和神经语言模型
- 分层 Softmax
- 神经机器翻译
- 注意力机制
**n-gram 语言模型**
- 语言模型(language model)定义了自然语言中**标记序列**的概率分布。根据模型的设计,标记可以是词、字符、甚至是字节。标记总是离散的实体。
- n-gram 是最早成功的语言模型
- 一个 n-gram 是一个包含 n 个**标记**的序列。
- 基于 n-gram 的模型定义一个条件概率——给定前 n − 1 个标记后的第 n 个标记的条件概率:

- 训练 n-gram 模型很简单,因为最大似然估计可以通过简单地统计每个可能的 n-gram 在训练集中**出现的频数**来获得。
- 通常我们同时训练 n-gram 模型和 n − 1 gram 模型。这使得下式可以简单地通过查找两个存储的概率来计算。

- n-gram 模型的缺点:
- **稀疏问题**——n-gram 模型最大似然的基本限制是,在许多情况下从训练集计数估计得到的 Pn 很可能为零。由此产生了各种**平滑算法**。
- **维数灾难**——经典的 n-gram 模型特别容易引起维数灾难。因为存在 |V|^n 可能的 n-gram,而且 |V| 通常很大。
**神经语言模型**(Neural Language Model, NLM)
- NLM 是一类用来克服维数灾难的语言模型,它使用词的**分布式表示**对自然语言序列建模
- NLM 能在识别两个相似词的同时,不丧失将词编码为不同的能力。神经语言模型共享一个词(及其上下文)和其他类似词的统计强度。模型为每个词学习的分布式表示,允许模型处理具有类似共同特征的词来实现这种共享。因为这样的属性很多,所以存在许多泛化的方式,可以将信息从每个训练语句传递到指数数量的语义相关语句。
- 例如,如果词 dog 和词 cat 映射到具有许多属性的表示,则包含词 cat 的句子可以告知模型对包含词 dog 的句子做出预测,反之亦然。
- 使用分布式表示来改进自然语言处理模型的基本思想不必局限于神经网络。它还可以用于图模型,其中分布式表示是多个潜变量的形式 (Mnih and Hinton, 2007)。
**词嵌入**(word embedding)
- 词的分布时表示称为词嵌入,在这个解释下,我们将原始符号视为维度等于词表大小的空间中的点。词表示将这些点**嵌入到较低维的特征空间**中。
- 在原始空间中,每个词由一个one-hot向量表示,因此每对词彼此之间的欧氏距离都是 √2。
- 在**嵌入空间**中,经常出现在类似上下文中的词彼此接近。这通常导致具有相似含义的词变得邻近。

- 这些嵌入是为了可视化才表示为 2 维。在实际应用中,嵌入通常具有更高的维度并且可以同时捕获词之间多种相似性。
**高维输出**
- 对于大词汇表,由于词汇量很大,在词的选择上表示输出分布的计算和存储成本可能非常高。
- 表示这种分布的朴素方法是应用一个仿射变换,将隐藏表示转换到输出空间,然后应用 softmax 函数。因为 softmax 要在所有输出之间归一化,所以需要执行全矩阵乘法,这是高计算成本的原因。因此,输出层的高计算成本在训练期间(计算似然性及其梯度)和测试期间(计算所有或所选词的概率)都有出现。
- **一些解决方案**
- 使用**短列表**——简单来说,就是限制词表的大小
- **分层 Softmax**
- **重要采样**——负采样就是一种简单的重要采样方式
**分层 Softmax**
- 减少大词汇表 V 上高维输出层计算负担的经典方法 (Goodman, 2001) 是**分层地分解概率**。|V| 因子可以降低到 log|V| 一样低,而无需执行与 |V| 成比例数量(并且也与隐藏单元数量成比例)的计算。
- 我们可以认为这种层次结构是先建立词的类别,然后是词类别的类别,然后是词类别的类别的类别等等。这些嵌套类别构成一棵树,其叶子为词。
- 选择一个词的概率是由路径(从树根到包含该词叶子的路径)上的每个节点通向该词分支概率的乘积给出。
**重要采样**/负采样
- 加速神经语言模型训练的一种方式是,避免明确地计算所有未出现在下一位置的词对梯度的贡献。
- 每个不正确的词在此模型下具有低概率。枚举所有这些词的计算成本可能会很高。相反,我们可以仅采样词的子集。
**结合 n-gram 和神经语言模型**
- n-gram 模型相对神经网络的主要优点是具有更高的模型容量(通过存储非常多的元组的频率),并且处理样本只需非常少的计算量。
- 相比之下,将神经网络的参数数目加倍通常也大致加倍计算时间。
- 增加神经语言模型容量的一种简单方法是将之与 n-gram 方法结合,集成两个模型
**神经机器翻译**(NMT)
- 编码器和解码器的想法 (Allen 1987; Chrisman 1991; Forcada and Ñeco 1997)很早就应用到了 NMT 中。

- 基于 MLP 方法的缺点是需要将序列预处理为固定长度。为了使翻译更加灵活,我们希望模型允许可变的输入长度和输出长度。所以大量的 NMT 模型使用 RNN 作为基本单元。
**注意力(Attention)机制**
- 使用固定大小的表示概括非常长的句子(例如 60 个词)的所有语义细节是非常困难的。这需要使用足够大的 RNN。这会带来一些列训练问题。
- 更高效的方法是先读取整个句子或段落(以获得正在表达的上下文和焦点),然后一次翻译一个词,每次聚焦于输入句子的不同部分来收集产生下一个输出词所需的语义细节 (Bahdanau et al., 2015)——**Attention** 机制

- 由 Bahdanau et al. (2015) 引入的现代注意力机制,本质上是**加权平均**。
**其他应用**:
- 推荐系统
- 知识表示、推理和回答
================================================
FILE: A-深度学习/备忘-术语表.md
================================================
术语表
===
Index
---
<!-- TOC -->
- [指数加权平均(指数衰减平均)](#指数加权平均指数衰减平均)
- [偏差修正](#偏差修正)
<!-- /TOC -->
## 指数加权平均(指数衰减平均)
> [什么是指数加权平均、偏差修正? - 郭耀华](http://www.cnblogs.com/guoyaohua/p/8544835.html) - 博客园
- **加权平均**
- 假设 `θi` 的权重分别为 `ρi`,则 `θi` 的加权平均为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;v=\sum_{i=1}^t\rho_i\theta_i,\quad&space;where\&space;\sum_{i=1}^t\rho_i=1"><img src="../_assets/公式_20180903213109.png" height="" /></a></div>
- **指数加权平均**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;v_t=\rho&space;v_{t-1}+(1-\rho)\theta_t"><img src="../_assets/公式_20180903203229.png" height="" /></a></div>
> 注意到越久前的记录其权重呈**指数衰减**,因此指数加权平均也称**指数衰减平均**
- **示例**:设 `ρ=0.9, v0=0`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{aligned}&space;v_t&=0.1\theta_t+0.9{\color{Red}v_{t-1}}\\&space;&=0.1\theta_t+0.1*0.9\theta_{t-1}+0.9^2{\color{Red}v_{t-2}}\\&space;&=0.1\theta_t+0.1*0.9\theta_{t-1}+0.1*0.9^2\theta_{t-2}+\cdots+0.1*0.9^{t-1}\theta_1&space;\end{aligned}"><img src="../_assets/公式_20180903210625.png" height="" /></a></div>
> 其中 `v_t` 可以**近似**认为是最近 `1/1-ρ` 个值的滑动平均(`ρ=0.9`时,`0.1 * 0.9^9 ≈ 0.038`),更久前的记录其权重已近似为 0。
### 偏差修正
- 指数加权平均在前期会存在较大的**误差**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\sum_{i=1}^t0.1*0.9^{i-1}=0.1\cdot\frac{1-0.9^t}{1-0.9}=1-0.9^t"><img src="../_assets/公式_20180903212935.png" height="" /></a></div>
- 注意到只有当 `t -> ∞` 时,所有权重的和才接近 1,当 `t` 比较小时,并不是标准的加权平均
- **示例**:设 `ρ=0.9, v0=0`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\begin{aligned}&space;v_t&=0.1\theta_t+0.9{\color{Red}v_{t-1}}\\&space;&=0.1\theta_t+0.1*0.9\theta_{t-1}+0.9^2{\color{Red}v_{t-2}}\\&space;&=0.1\theta_t+0.1*0.9\theta_{t-1}+0.1*0.9^2\theta_{t-2}+\cdots+0.1*0.9^{t-1}\theta_1&space;\end{aligned}"><img src="../_assets/公式_20180903210625.png" height="" /></a></div>
- 当 `t` 较小时,与希望的加权平均结果差距较大
- **引入偏差修正**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;\frac{v_t}{1-\rho^t}"><img src="../_assets/公式_20180903213410.png" height="" /></a></div>
- 偏差修正只对**前期**的有修正效果,**后期**当 `t` 逐渐增大时 `1-ρ^t -> 1`,将不再影响 `v_t`,与期望相符
================================================
FILE: B-自然语言处理/A-NLP发展趋势.md
================================================
NLP 发展趋势
===
Index
---
<!-- TOC -->
- [【2018.11】预见未来|NLP将迎来黄金十年(MSRA)](#201811预见未来|nlp将迎来黄金十年msra)
- [NLP 新的发展基础](#nlp-新的发展基础)
- [NLP 的研究热点](#nlp-的研究热点)
- [NLP 技术的重要进展](#nlp-技术的重要进展)
- [值得关注的 NLP 技术](#值得关注的-nlp-技术)
- [【2019.02】对话 MSRA 副院长周明:回望过去,展望未来,NLP有哪些发展趋势?](#201902对话-msra-副院长周明回望过去展望未来nlp有哪些发展趋势)
- [MSRA 的重点](#msra-的重点)
- [NLP 领域进展](#nlp-领域进展)
- [中文 NLP 的突破](#中文-nlp-的突破)
- [2019 研究热点](#2019-研究热点)
<!-- /TOC -->
## 【2018.11】预见未来|NLP将迎来黄金十年(MSRA)
> https://www.toutiao.com/a6628158223692071427 - 今日头条
### NLP 新的发展基础
- 来自各个行业的文本大数据将会更好地采集、加工、入库;
- 来自搜索引擎、客服、商业智能、语音助手、翻译、教育、法律、金融等领域对NLP的需求会大幅度上升,对NLP质量也提出更;要求;
- 文本数据和语音、图像数据的多模态融合成为未来机器人的刚需。
### NLP 的研究热点
1. 将知识和常识引入目前基于数据的学习系统中;
1. 低资源的NLP任务的学习方法;
1. 上下文建模、多轮语义理解;
1. 基于语义分析、知识和常识的可解释 NLP。
### NLP 技术的重要进展
- 神经机器翻译
- (Hassan et al., 2018)高效利用大规模单语数据的联合训练、对偶学习技术;解决曝光偏差问题的一致性正则化技术、推敲网络
- 智能人机交互
- 聊天系统架构
<div align="center"><img src="../_assets/TIM截图20190212145247.png" height="" /></div>
- 三层引擎:
- 第一层,通用聊天机器人;
- 第二层,搜索和问答(Infobot);
- 第三层,面向特定任务对话系统(Bot)
- 机器阅读理解
- NL-Net
- BERT
- 机器创作
- 对联、
- **歌词**的机器创作过程:
- 确定主题,比如希望创作一首与“秋”、“岁月”、“沧桑”、“感叹”相关的歌;
- 利用词向量表示技术找到相关的词,有“秋风”、“流年”、“岁月”、“变迁”等;
- 通过序列到序列的神经网络,用歌词的上一句去生成下一句;如果是第一句,则用一个特殊的序列作为输入去生成第一句歌词
- **谱曲**:类似一个翻译过程,但更为严格
### 值得关注的 NLP 技术
- 预训练神经网络
- ElMo、BERT 等模型
- 在什么粒度(word,sub-word,character)上进行预训练,用什么结构的语言模型(LSTM,Transformer等)训练,在什么样的数据上(不同体裁的文本)进行训练,以及如何将预训练的模型应用到具体任务,都是需要继续研究的问题。
- 低资源 NLP 任务
- 无监督、半监督学习
- 迁移学习、多任务学习
- 迁移学习
- 不同的 NLP 任务虽然采用各自不同类型的数据进行模型训练,但在编码器(Encoder)端往往是同构的,即都会将输入的词或句子转化为对应的向量表示,然后再使用各自的解码器完成后续翻译、改写和答案生成等任务。
- 因此,可以将通过不同任务训练得到的编码器看作是不同任务对应的一种向量表示模型;然后通过迁移学习(Transfer Learning)的方式将这类信息迁移到目前关注的目标任务上来
- 多任务学习
- 多任务学习(Multi-task Learning)可通过端到端的方式,直接在主任务中引入其他辅助任务的监督信息,用于保证模型能够学到不同任务间共享的知识和信息;
- McCann 等提出了利用**问答框架**使用多任务学习训练十项自然语言任务
> [一个模型搞定十大自然语言任务](https://www.toutiao.com/a6569393480089469454)
- 知识和常识的引入
- 应用:机器阅读理解、语义分析
- 领域知识:维基百科、知识图谱
- 常识的引入(缺乏深入研究)
- 多模态学习
- 视觉问答
- 基于问题生成的视觉问答方法(Li et al., 2018)
- 基于场景图生成的视觉问答方法(Lu et al., 2018)
- 视频问答
## 【2019.02】对话 MSRA 副院长周明:回望过去,展望未来,NLP有哪些发展趋势?
> https://www.toutiao.com/i6656937082805551624 - 头条
### MSRA 的重点
- 机器阅读理解(MRC)
- 神经机器翻译(NMT)
- 联合训练、对偶学习
- 一致性规范、推敲网络
- 语法检查(Grammar Check)
- 自动生成训练语料、多次解码逐轮求优
- 文本语音转换(Text To Speech, TTS)
- 机器创作(写诗、谱曲、新闻)
### NLP 领域进展
- 新的神经 NLP 模型
- 以 BERT 为首的**预训练模型**
- 大规模语料所蕴含的普遍语言知识与具体应用场景相结合的潜力
- **低资源** NLP 任务
### 中文 NLP 的突破
- 中文阅读理解
- 以中文为中心的机器翻译
- 聊天系统
- 多模态聊天(小冰)
- 语音对话
- 搜索引擎、语音助手、智能音箱、物联网、电子商务、智能家居等
### 2019 研究热点
> [NLP将迎来黄金十年](#2019预见未来|nlp将迎来黄金十年)一文中有更详细的介绍,包括最新的论文推荐
1. 预训练模型
- 上下文建模
1. 基于语义分析、知识和常识的可解释 NLP
- 将知识和常识引入到目前基于数据的学习模型中
1. 多模态融合
- 文本数据和语音、图像数据的多模态融合是未来机器人的刚需
1. 低资源 NLP 任务(无语料或者小语料的场景)
- 半监督、无监督学习方法
- Transfer Learning、Multi-task Learning
- 语言学在 NLP 研究中的作用
> 语言学家在自然语言处理研究中大有可为 - 冯志伟
1. 多模态融合
- 在神经网络的框架下,可以用统一的模式来对多模态(语言、文字、图像、视频)进行建模(编码和解码),从而实现端到端的学习
- 应用:Capturing、CQA/VQA、机器创作
================================================
FILE: B-自然语言处理/A-自然语言处理基础.md
================================================
NLP-NLP基础
===
Index
---
<!-- TOC -->
- [NLP 概述](#nlp-概述)
- [解决 NLP 问题的一般思路](#解决-nlp-问题的一般思路)
- [NLP 的历史进程](#nlp-的历史进程)
- [Seq2Seq 模型](#seq2seq-模型)
- [评价机制](#评价机制)
- [困惑度 (Perplexity, PPX)](#困惑度-perplexity-ppx)
- [BLEU](#bleu)
- [ROUGE](#rouge)
- [语言模型](#语言模型)
- [XX 模型的含义](#xx-模型的含义)
- [概率/统计语言模型 (PLM, SLM)](#概率统计语言模型-plm-slm)
- [参数的规模](#参数的规模)
- [可用的概率模型](#可用的概率模型)
- [N-gram 语言模型](#n-gram-语言模型)
- [可靠性与可区别性](#可靠性与可区别性)
- [OOV 问题](#oov-问题)
- [平滑处理 TODO](#平滑处理-todo)
- [神经概率语言模型 (NPLM)](#神经概率语言模型-nplm)
- [N-gram 神经语言模型](#n-gram-神经语言模型)
- [N-gram 神经语言模型的网络结构](#n-gram-神经语言模型的网络结构)
- [模型参数的规模与运算量](#模型参数的规模与运算量)
- [相比 N-gram 模型,NPLM 的优势](#相比-n-gram-模型nplm-的优势)
- [NPLM 中的 OOV 问题](#nplm-中的-oov-问题)
<!-- /TOC -->
# NLP 概述
> 自然语言处理之序列模型 - 小象学院
## 解决 NLP 问题的一般思路
```tex
这个问题人类可以做好么?
- 可以 -> 记录自己的思路 -> 设计流程让机器完成你的思路
- 很难 -> 尝试从计算机的角度来思考问题
```
## NLP 的历史进程
- **规则系统**
- 正则表达式/自动机
- 规则是固定的
- **搜索引擎**
```tex
“豆瓣酱用英语怎么说?”
规则:“xx用英语怎么说?” => translate(XX, English)
“我饿了”
规则:“我饿(死)了” => recommend(饭店,地点)
```
- **概率系统**
- 规则从数据中**抽取**
- 规则是有**概率**的
- 概率系统的一般**工作方式**
```tex
流程设计
收集训练数据
预处理
特征工程
分类器(机器学习算法)
预测
评价
```
<div align="center"><img src="../_assets/TIM截图20180807203305.png" height="200" /></div>
- 最重要的部分:数据收集、预处理、特征工程
- 示例
```tex
任务:
“豆瓣酱用英语怎么说” => translate(豆瓣酱,Eng)
流程设计(序列标注):
子任务1: 找出目标语言 “豆瓣酱用 **英语** 怎么说”
子任务2: 找出翻译目标 “ **豆瓣酱** 用英语怎么说”
收集训练数据:
(子任务1)
“豆瓣酱用英语怎么说”
“茄子用英语怎么说”
“黄瓜怎么翻译成英语”
预处理:
分词:“豆瓣酱 用 英语 怎么说”
抽取特征:
(前后各一个词)
0 茄子: < _ 用
0 用: 豆瓣酱 _ 英语
1 英语: 用 _ 怎么说
0 怎么说: 英语 _ >
分类器:
SVM/CRF/HMM/RNN
预测:
0.1 茄子: < _ 用
0.1 用: 豆瓣酱 _ 英语
0.7 英语: 用 _ 怎么说
0.1 怎么说: 英语 _ >
评价:
准确率
```
- 概率系统的优/缺点
- `+` 规则更加贴近于真实事件中的规则,因而效果往往比较好
- `-` 特征是由专家/人指定的;
- `-` 流程是由专家/人设计的;
- `-` 存在独立的**子任务**
- **深度学习**
- 深度学习相对概率模型的优势
- 特征是由专家指定的 `->` 特征是由深度学习自己提取的
- 流程是由专家设计的 `->` 模型结构是由专家设计的
- 存在独立的子任务 `->` End-to-End Training
## Seq2Seq 模型
- 大部分自然语言问题都可以使用 Seq2Seq 模型解决
<div align="center"><img src="../_assets/TIM截图20180807210029.png" height="200" /></div>
- **“万物”皆 Seq2Seq**
<div align="center"><img src="../_assets/TIM截图20180807210133.png" height="300" /></div>
## 评价机制
### 困惑度 (Perplexity, PPX)
> [Perplexity](https://en.wikipedia.org/wiki/Perplexity) - Wikipedia
- 在信息论中,perplexity 用于度量一个**概率分布**或**概率模型**预测样本的好坏程度
> ../机器学习/[信息论](../A-机器学习/A-机器学习基础#信息论)
<h3>基本公式</h3>
- **概率分布**(离散)的困惑度
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{150}&space;{\displaystyle&space;2^{H(p)}=2^{-\sum&space;_{x}p(x)\log&space;_{2}p(x)}}"><img src="../_assets/公式_20180728195601.png" /></a></div>
> 其中 `H(p)` 即**信息熵**
- **概率模型**的困惑度
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{150}&space;{\displaystyle&space;b^{-{\frac&space;{1}{N}}\sum&space;_{i=1}^{N}\log&space;_{b}q(x_{i})}}"><img src="../_assets/公式_20180728201614.png" /></a></div>
> 通常 `b=2`
- **指数部分**也可以是**交叉熵**的形式,此时困惑度相当于交叉熵的指数形式
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{150}&space;2^{H(\tilde{p},q)}&space;=&space;2^{-\sum_x\tilde{p}(x)\log_{2}q(x)}"><img src="../_assets/公式_20180728202629.png" /></a></div>
> 其中 `p~` 为**测试集**中的经验分布——`p~(x) = n/N`,其中 `n` 为 x 的出现次数,N 为测试集的大小
**语言模型中的 PPX**
- 在 **NLP** 中,困惑度常作为**语言模型**的评价指标
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{150}&space;\begin{aligned}&space;\mathrm{PPX}(W_{test})&space;&=2^{-\sum_{i=1}^{|V|}\tilde{p}(w_i)\log_{2}q(w_i)}\\&space;&=2^{-\sum_{i=1}^{|V|}\frac{\mathrm{cnt}(w_i)}{N}\log_{2}q(w_i)}&space;\end{aligned}"><img src="../_assets/公式_20180728205525.png" /></a></div>
- 直观来说,就是下一个**候选词数目**的期望值——
如果不使用任何模型,那么下一个候选词的数量就是整个词表的数量;通过使用 `bi-gram`语言模型,可以将整个数量限制到 `200` 左右
### BLEU
> [一种机器翻译的评价准则——BLEU](https://blog.csdn.net/qq_21190081/article/details/53115580) - CSDN博客
- 机器翻译评价准则
- 计算公式
<div align="center"><img src="../_assets/TIM截图20180728212554.png" height="" /></div>
其中
<div style="position:relative;left:25%"><img src="../_assets/TIM截图20180728215749.png" height="" /></div>
<div style="position:relative;left:25%"><img src="../_assets/TIM截图20180728212444.png" height="" /></div>
<!-- <div style="position:relative;left:25%"><img src="../_assets/TIM截图20180728212444.png" height="" /></div> -->
> `c` 为生成句子的长度;`r` 为参考句子的长度——目的是**惩罚**长度过短的候选句子
- 为了计算方便,会加一层 `log`
<div align="center"><img src="../_assets/TIM截图20180728213300.png" height="" /></div>
> 通常 `N=4, w_n=1/4`
### ROUGE
> [自动文摘评测方法:Rouge-1、Rouge-2、Rouge-L、Rouge-S](https://blog.csdn.net/qq_25222361/article/details/78694617) - CSDN博客
- 一种机器翻译/自动摘要的评价准则
> [BLEU,ROUGE,METEOR,ROUGE-浅述自然语言处理机器翻译常用评价度量](https://blog.csdn.net/joshuaxx316/article/details/58696552) - CSDN博客
# 语言模型
## XX 模型的含义
- 如果能使用某个方法对 XX **打分**(Score),那么就可以把这个方法称为 “**XX 模型**”
- **篮球明星模型**: `Score(库里)`、`Score(詹姆斯)`
- **话题模型**——对一段话是否在谈论某一话题的打分
```
Score( NLP | "什么 是 语言 模型?" ) --> 0.8
Score( ACM | "什么 是 语言 模型?" ) --> 0.05
```
## 概率/统计语言模型 (PLM, SLM)
- **语言模型**是一种对语言打分的方法;而**概率语言模型**把语言的“得分”通过**概率**来体现
- 具体来说,概率语言模型计算的是**一个序列**作为一句话可能的概率
```
Score("什么 是 语言 模型") --> 0.05 # 比较常见的说法,得分比较高
Score("什么 有 语言 模型") --> 0.01 # 不太常见的说法,得分比较低
```
- 以上过程可以形式化为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(W)=p(w_1^T)=p(w_1,w_2,...,w_T"><img src="../_assets/公式_20180805204149.png" height="" /></a></div>
根据贝叶斯公式,有
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(w_1^T)=p(w_1)\cdot&space;p(w_2|w_1)\cdot&space;p(w_3|w_1^2)\cdots&space;p(w_T|w_1^{T-1})"><img src="../_assets/公式_20180805211530.png" height="" /></a></div>
- 其中每个条件概率就是**模型的参数**;如果这个参数都是已知的,那么就能得到整个序列的概率了
### 参数的规模
- 设词表的大小为 `N`,考虑长度为 `T` 的句子,理论上有 `N^T` 种可能的句子,每个句子中有 `T` 个参数,那么参数的数量将达到 `O(T*N^T)`
### 可用的概率模型
- 统计语言模型实际上是一个概率模型,所以常见的概率模型都可以用于求解这些参数
- 常见的概率模型有:N-gram 模型、决策树、最大熵模型、隐马尔可夫模型、条件随机场、神经网络等
- 目前常用于语言模型的是 N-gram 模型和神经语言模型(下面介绍)
## N-gram 语言模型
- 马尔可夫(Markov)假设——未来的事件,只取决于有限的历史
- 基于马尔可夫假设,N-gram 语言模型认为一个词出现的概率只与它前面的 n-1 个词相关
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(w_k|w_1,..,w_{k-1})\approx&space;p(w_k|w_{k-n+1},..,w_{k-1})"><img src="../_assets/公式_20180805211644.png" height="" /></a></div>
- 根据**条件概率公式**与**大数定律**,当语料的规模足够大时,有
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(w_k|w_{k-n+1}^{k-1})=\frac{p(w_{k-n+1}^k)}{p(w_{k-n+1}^{k-1})}\approx&space;\frac{\mathrm{count}(w_{k-n+1}^k)}{\mathrm{count}(w_{k-n+1}^{k-1})}"><img src="../_assets/公式_20180805211936.png" height="" /></a></div>
- 以 `n=2` 即 bi-gram 为例,有
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(w_k|w_{k-1})=\frac{p(w_{k-1},w_k)}{p(w_{k-1})}\approx&space;\frac{\mathrm{count}(w_{k-1},w_k)}{\mathrm{count}(w_{k-1})}"><img src="../_assets/公式_20180805212222.png" height="" /></a></div>
- 假设词表的规模 `N=200000`(汉语的词汇量),模型参数与 `n· 的关系表
<div align="center"><img src="../_assets/TIM截图20180805212441.png" height="" /></div>
### 可靠性与可区别性
- 假设没有计算和存储限制,`n` 是不是越大越好?
- 早期因为计算性能的限制,一般最大取到 `n=4`;如今,即使 `n>10` 也没有问题,
- 但是,随着 `n` 的增大,模型的性能增大却不显著,这里涉及了**可靠性与可区别性**的问题
- 参数越多,模型的可区别性越好,但是可靠性却在下降——因为语料的规模是有限的,导致 `count(W)` 的实例数量不够,从而降低了可靠性
### OOV 问题
- OOV 即 Out Of Vocabulary,也就是序列中出现了词表外词,或称为**未登录词**
- 或者说在测试集和验证集上出现了训练集中没有过的词
- 一般**解决方案**:
- 设置一个词频阈值,只有高于该阈值的词才会加入词表
- 所有低于阈值的词替换为 UNK(一个特殊符号)
- 无论是统计语言模型还是神经语言模型都是类似的处理方式
> [NPLM 中的 OOV 问题](#nplm-中的-oov-问题)
### 平滑处理 TODO
- `count(W) = 0` 是怎么办?
- 平滑方法(层层递进):
- Add-one Smoothing (Laplace)
- Add-k Smoothing (k<1)
- Back-off (回退)
- Interpolation (插值法)
- Absolute Discounting (绝对折扣法)
- Kneser-Ney Smoothing (KN)
- Modified Kneser-Ney
> [自然语言处理中N-Gram模型的Smoothing算法](https://blog.csdn.net/baimafujinji/article/details/51297802) - CSDN博客
## 神经概率语言模型 (NPLM)
> [专题-词向量](./B-专题-词向量)
- 神经概率语言模型依然是一个概率语言模型,它通过**神经网络**来计算概率语言模型中每个参数
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(w|{\color{Red}\text{context}(w)})=g(i_w,{\color{Red}V_{context}})"><img src="../_assets/公式_20180806100950.png" height="" /></a></div>
- 其中 `g` 表示神经网络,`i_w` 为 `w` 在词表中的序号,`context(w)` 为 `w` 的上下文,`V_context` 为上下文构成的特征向量。
- `V_context` 由上下文的**词向量**进一步组合而成
### N-gram 神经语言模型
> [A Neural Probabilistic Language Model](http://www.jmlr.org/papers/volume3/bengio03a/bengio03a.pdf) (Bengio, et al., 2003)
- 这是一个经典的神经概率语言模型,它沿用了 N-gram 模型中的思路,将 `w` 的前 `n-1` 个词作为 `w` 的上下文 `context(w)`,而 `V_context` 由这 `n-1` 个词的词向量拼接而成,即
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=p(w_k|{\color{Red}w_{k-n+1}^{k-1}})=g(i_{w_k},{\color{Red}[c(w_{k-n+1});...;c(w_{k-1})]})"><img src="../_assets/公式_20180806102047.png" height="" /></a></div>
- 其中 `c(w)` 表示 `w` 的词向量
- 不同的神经语言模型中 `context(w)` 可能不同,比如 Word2Vec 中的 CBOW 模型
- 每个训练样本是形如 `(context(w), w)` 的二元对,其中 `context(w)` 取 w 的前 `n-1` 个词;当不足 `n-1`,用特殊符号填充
- 同一个网络只能训练特定的 `n`,不同的 `n` 需要训练不同的神经网络
#### N-gram 神经语言模型的网络结构
- 【**输入层**】首先,将 `context(w)` 中的每个词映射为一个长为 `m` 的词向量,**词向量在训练开始时是随机的**,并**参与训练**;
- 【**投影层**】将所有上下文词向量**拼接**为一个长向量,作为 `w` 的特征向量,该向量的维度为 `m(n-1)`
- 【**隐藏层**】拼接后的向量会经过一个规模为 `h` 隐藏层,该隐层使用的激活函数为 `tanh`
- 【**输出层**】最后会经过一个规模为 `N` 的 Softmax 输出层,从而得到词表中每个词作为下一个词的概率分布
> 其中 `m, n, h` 为超参数,`N` 为词表大小,视训练集规模而定,也可以人为设置阈值
- 训练时,使用**交叉熵**作为损失函数
- **当训练完成时**,就得到了 N-gram 神经语言模型,以及副产品**词向量**
- 整个模型可以概括为如下公式:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=y=U\cdot\tanh(Wx+p)+q"><img src="../_assets/公式_2018080695721.png" height="" /></a></div><br/>
<div align="center"><img src="../_assets/TIM截图20180805234123.png" height="200" /></div>
> 原文的模型还考虑了投影层与输出层有有边相连的情形,因而会多一个权重矩阵,但本质上是一致的:
>> <div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=y=U\cdot\tanh(W_1x+p)+W_2x+q"><img src="../_assets/公式_2018080695819.png" height="" /></a></div><br/>
>> <div align="center"><img src="../_assets/TIM截图20180805231056.png" height="" /></div>
### 模型参数的规模与运算量
- 模型的超参数:`m, n, h, N`
- `m` 为词向量的维度,通常在 `10^1 ~ 10^2`
- `n` 为 n-gram 的规模,一般小于 5
- `h` 为隐藏的单元数,一般在 `10^2`
- `N` 位词表的数量,一般在 `10^4 ~ 10^5`,甚至 `10^6`
- 网络参数包括两部分
- 词向量 `C`: 一个 `N * m` 的矩阵——其中 `N` 为词表大小,`m` 为词向量的维度
- 网络参数 `W, U, p, q`:
```
- W: h * m(n-1) 的矩阵
- p: h * 1 的矩阵
- U: N * h 的矩阵
- q: N * 1 的矩阵
```
- 模型的运算量
- 主要集中在隐藏层和输出层的矩阵运算以及 SoftMax 的归一化计算
- 此后的相关研究中,主要是针对这一部分进行优化,其中就包括 **Word2Vec** 的工作
### 相比 N-gram 模型,NPLM 的优势
- 单词之间的相似性可以通过词向量来体现
> 相比神经语言模型本身,作为其副产品的词向量反而是更大的惊喜
>
> [词向量的理解](./B-专题-词向量#词向量的理解)
- 自带平滑处理
### NPLM 中的 OOV 问题
- 在处理语料阶段,与 N-gram 中的处理方式是一样的——将不满阈值的词全部替换为 UNK
**神经网络**中,一般有如下几种处理 UNK 的思路
- 为 UNK 分配一个随机初始化的 embedding,并**参与训练**
> 最终得到的 embedding 会有一定的语义信息,但具体好坏未知
- 把 UNK 都初始化成 0 向量,**不参与训练**
> UNK 共享相同的语义信息
- 每次都把 UNK 初始化成一个新的随机向量,**不参与训练**
> 常用的方法——因为本身每个 UNK 都不同,随机更符合对 UNK 基于最大熵的估计
>> [How to add new embeddings for unknown words in Tensorflow (training & pre-set for testing)](https://stackoverflow.com/questions/45113130/how-to-add-new-embeddings-for-unknown-words-in-tensorflow-training-pre-set-fo) - Stack Overflow
>>
>> [Initializing Out of Vocabulary (OOV) tokens](https://stackoverflow.com/questions/45495190/initializing-out-of-vocabulary-oov-tokens) - Stack Overflow
- 基于 Char-Level 的方法
> PaperWeekly 第七期 -- [基于Char-level的NMT OOV解决方案](https://zhuanlan.zhihu.com/p/22700538?refer=paperweekly)
================================================
FILE: B-自然语言处理/B-专题-句嵌入.md
================================================
专题-句嵌入(Sentence Embedding)
===
Reference
---
- [The Current Best of Universal Word Embeddings and Sentence Embeddings](https://medium.com/huggingface/universal-word-sentence-embeddings-ce48ddc8fc3a)
Index
---
<!-- TOC -->
- [基线模型](#基线模型)
- [基于统计的词袋模型(BoW)](#基于统计的词袋模型bow)
- [基于词向量的词袋模型](#基于词向量的词袋模型)
- [均值模型](#均值模型)
- [加权模型](#加权模型)
- [基于 RNN(任务相关)](#基于-rnn任务相关)
- [基于 CNN(任务相关)](#基于-cnn任务相关)
- [词袋模型](#词袋模型)
- [[2018] Power Mean 均值模型](#2018-power-mean-均值模型)
- [[2017] SIF 加权模型](#2017-sif-加权模型)
- [[]](#)
- [无监督模型](#无监督模型)
- [[2015] Skip-Thought Vector](#2015-skip-thought-vector)
- [[2018] Quick-Thought Vectors](#2018-quick-thought-vectors)
- [有监督模型](#有监督模型)
- [[2017] InferSent](#2017-infersent)
- [[2017] Self-Attention](#2017-self-attention)
- [[2015] DAN & RecNN](#2015-dan--recnn)
- [多任务学习](#多任务学习)
- [[2018] 基于多任务的 Sentence Embedding(微软)](#2018-基于多任务的-sentence-embedding微软)
- [[2018] Universal Sentence Encoder(谷歌)](#2018-universal-sentence-encoder谷歌)
- [参考文献](#参考文献)
<!-- /TOC -->
## 基线模型
### 基于统计的词袋模型(BoW)
- 单个词的 One-Hot 表示
- 基于频数的词袋模型
- 基于 TF-IDF 的词袋模型
- ...
### 基于词向量的词袋模型
#### 均值模型
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;s=\frac{1}{N}\sum_{i=1}^N&space;v_i"><img src="../_assets/公式_2018091402442.png" height="" /></a></div>
> 其中 `v_i` 表示维度为 `d` 的词向量,均值指的是对所有词向量**按位求和**后计算每一维的均值,最后 `s` 的维度与 `v` 相同。
#### 加权模型
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;s=\sum_{i=1}^N&space;\alpha_i\cdot&space;v_i"><img src="../_assets/公式_2018091402658.png" height="" /></a></div>
> 其中 `α` 可以有不同的选择,但一般应该遵循这样一个准则:**越常见的词权重越小**
>> [[2017] SIF 加权模型](#2017-sif-加权模型)
### 基于 RNN(任务相关)
- 以最后一个隐状态作为整个句子的 Embedding
<div align="center"><img src="../_assets/TIM截图20180914013219.png" height="" /></div>
- 基于 RNN 的 Sentence Embedding 往往用于特定的有监督任务中,**缺乏可迁移性**,在新的任务中需要重新训练;
- 此外,由于 RNN 难以并行训练的缺陷,导致开销较大。
### 基于 CNN(任务相关)
- 卷积的优势在于提取**局部特征**,利用 CNN 可以提取句子中类似 n-gram 的局部信息;
- 通过整合不同大小的 n-gram 特征作为整个句子的表示。
<div align="center"><img src="../_assets/TIM截图20180914013449.png" height="" /></div>
## 词袋模型
### [2018] Power Mean 均值模型
> [4]
- 本文是均值模型的一种推广;通过引入“幂均值”(Power Mean)来捕捉序列中的其他信息;
- 记句子 `s=(x_1, x_2, ..., x_n)`
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_cm&space;\large&space;s_p=\left&space;(&space;\frac{x_1^p+\cdots+x_n^p}{n}&space;\right&space;)^{\frac{1}{p}},\quad&space;p\in\mathbb{R}\cup\{\pm\infty\}"><img src="../_assets/公式_20180914232209.png" height="" /></a></div>
- `x_i` 为每个词的词向量,维度为 `d`
- 普通的均值模型即 `p=1` 时的特例;
- 特别说明,`±∞` 实际上指的是 `max`/`min`,而不是绝对值最大/最小
- 本文通过**拼接**的方式来保留不同 `p` 的信息
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;s=[s_{p_1};s_{p_2};...;s_{p_k}]"><img src="../_assets/公式_20180914232558.png" height="" /></a></div>
> 此时,Sentence Embedding 的维度应该是 **`K * d`**
- 进一步的,文本还加入了在**不同词嵌入空间**上的词向量,依然通过**拼接**的方式保留信息
- 所谓**不同词嵌入空间**,指的就是使用不同算法在不同语料上训练得到的词向量
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\fn_jvn&space;\large&space;\begin{array}{ll}&space;s^{(i)}&space;&=[s_{p_1}^{(i)};s_{p_2}^{(i)};...;s_{p_k}^{(i)}]&space;\\&space;s&space;&=[s^{(1)};s^{(2)};...;s^{(L)}]&space;\\&space;\end{array}"><img src="../_assets/公式_20180915135024.png" height="" /></a></div>
> 此时,Sentence Embedding 的维度应该是 **`K * L * d`**
- 本文使用了如下 **4 种词向量**:
- GloVe embeddings (GV) trained on Common Crawl
- Word2Vec trained on GoogleNews (GN)
- Attract-Repel (AR) (Mrksic et al., 2017)
- MorphSpecialized (MS) (Vulic et al., 2017)
### [2017] SIF 加权模型
- **文献 [1]** 提出了一个简单但有效的**加权词袋模型 SIF** (**Smooth Inverse Frequency**),其性能超过了简单的 RNN/CNN 模型
- **SIF** 的计算分为两步:<br/>
**1)** 对句子中的每个词向量,乘以一个权重 `a/(a+p_w)`,其中 `a` 是一个常数(原文取 `0.0001`),`p_w` 为该词的词频;对于出现频率越高的词,其权重越小;<br/>
**2)** 计算**句向量矩阵**的第一个主成分 `u`,让每个句向量减去它在 `u` 上的投影(类似 PCA);
- **完整算法描述**
<div align="center"><img src="../_assets/TIM截图20180914010334.png" height="" /></div>
<!--
<details><summary><b>Numpy 示例(点击展开)</b></summary>
```python
```
</details>
-->
### []
## 无监督模型
### [2015] Skip-Thought Vector
> [2]
- 类似 Word2Vec/语言模型 的思想,Sentence Embedding 作为模型的副产品。
- 给定一个三元组 `s_{i-1}, s_i, s_{i+1}` 表示 3 个连续的句子。
- 模型使用 Encoder-Decoder 框架;
- 训练时,由 Encoder 对 `s_i` 进行编码;然后分别使用两个 Decoder 生成前一句 `s_{i-1}` 和下一句 `s_{i+1}`
<div align="center"><img src="../_assets/TIM截图20180914133101.png" height="" /></div>
- **Encoder**(GRU)
<div align="center"><img src="../_assets/TIM截图20180914151435.png" height="" /></div>
- **Decoder**(带窥孔的 GRU)
<div align="center"><img src="../_assets/TIM截图20180914151535.png" height="" /></div>
> 其中 `h_i` 为 Encoder 的输出,即表示 `s_i` 的 Sentence Embedding
- **Decoder** 可以看作是以 **Encoder** 输出为条件的**神经语言模型**
<div align="center"><img src="../_assets/TIM截图20180914151641.png" height="" /></div>
> 语言模型,`v` 表示词向量
- **目标函数**
<div align="center"><img src="../_assets/TIM截图20180914152110.png" height="" /></div>
- OOV 词的处理 TODO
### [2018] Quick-Thought Vectors
> [4]
- 本文是基于 Skip-Thought Vector 的改进
- Skip-Thought Vector 中给出前一句**生成**上一句和下一句的任务,被重新描述为一个**分类任务**:Decoder 作为分类器从一组候选句子中选择正确的上一个/下一个句子。
- **生成模型**(Skip-Thought Vector)
<div align="center"><img src="../_assets/TIM截图20180915151749.png" height="" /></div>
- **分类模型**(Quick-Thought Vectors)
<div align="center"><img src="../_assets/TIM截图20180915151811.png" height="" /></div>
- 该模型的一个主要优点是**训练速度**比 Skip-Thought Vector 快,后者需要训练 3 个 RNN 模块。
- **一些细节**:
- `batch size = 400`,即一个 batch 为 400 个连续的句子;
- `context size = 3`,即对给定句子,预测其上一句和下一句;
- **负采样**:同一 batch 中除上下文句子,均作为 负例;
- 开始训练时,词向量被初始化为 `[-0.1, 0.1]`,没有使用预训练的词向量;
## 有监督模型
### [2017] InferSent
> [5]
- 本文使用有监督的方法,在**自然语言推理**(NLI)数据集上训练 Sentence Embedding;
- 本文认为从 **NLI 数据集**(比如 **SNLI**)中训练得到的句向量也适合**迁移**到其他 NLP 任务中。
- 就像在各种 **CV 任务**中使用基于 ImageNet 的模型(VGG, ResNet 等)来得到图像特征一样,在处理 **NLP 任务**之前可以先使用**本文公开的模型**来计算句子的特征。
- **基本模型**
- 在 NLI 任务中,每个样本由三个元素构成 `(u, v, l)`——其中 `u` 表示前提(premise),`v` 表示假设(hypothesis),`l` 为类标(entailment 1, contradiction 2, neutral 3)
- 本文比较了 7 种编码器:1)LSTM, 2)GRU, 3)bi-GRU, 4)bi-LSTM(mean pooling), 5)bi-LSTM(max pooling), 6)self-attention, 7)CNN
<div align="center"><img src="../_assets/TIM截图20180915160225.png" height="" /></div>
- 注意:在 NLI 数据集中,句子 `u` 和 `v` 的地位不是等价的
### [2017] Self-Attention
> [3]
- 本文提出使用**二维矩阵**作为句子表征,矩阵的行表示在句子不同位置的关注度,以解决句子被压缩成一维向量时的信息损失。
<div align="center"><img src="../_assets/TIM截图20180914153455.png" height="" /></div>
### [2015] DAN & RecNN
> [9]
- 原文模型仅用于分类,但也可用于有监督的学习 Sentence Embedding
> [Universal Sentence Encoder(谷歌)](#2018-universal-sentence-encoder谷歌)
- 基本模型,其中比较常用的是 DAN
- DAN(Deep Averaging Network)
<div align="center"><img src="../_assets/TIM截图20180915211556.png" height="" /></div>
- RecNN
<div align="center"><img src="../_assets/TIM截图20180915211635.png" height="" /></div>
## 多任务学习
- InferSent 模型的成功,使大家开始探索不同的有监督任务中得到的 Sentence Embedding 在下游任务中的效果。
- 多任务学习试图在一次训练中组合不同的训练目标。
### [2018] 基于多任务的 Sentence Embedding(微软)
> [6]
- 本文认为为了能够推广到各种不同的任务,需要对同一句话的多个方面进行编码。
- 简单来说,模型同时在**多个任务**和**多个数据源**上进行训练,但是**共享**相同的 Sentence Embedding。
- 任务及数据集包括:
- Skip-Thought(预测上一句/下一句)——BookCorpus
- 神经机器翻译(NMT)——En-Fr (WMT14) + En-De (WMT15)
- 自然语言推理(NLI)——SNLI + MultiNLI
- Constituency Parsing——PTB + 1-billion word
- 本文模型与 [Skip-Thought Vector](#2015-skip-thought-vector) 基本一致
- **主要区别**在于本文的 Encoder 部分使用的是 **Bi-GRU**,而 Decoder 部分完全一致;
- 使用 GRU 而非 LSTM 的原因主要是为了速度;
### [2018] Universal Sentence Encoder(谷歌)
> [7]
- 本文的目的是动态地适应各种的 NLP 任务,通过在不同的数据集和不同的任务上同时训练。
- 本文使用**类似的多任务框架**,区别在于使用的 Encoder 不同。
> [[2018] 基于多任务的 Sentence Embedding(微软)](#2018-基于多任务的-sentence-embedding微软)
- 本文以两种模型作为 Encoder
- **Transformer** [8]——更高的精度
- **DAN** (Deep Averaging Network) [9]——更快的速度
- 一个可用的预训练版本
```python
embed = hub.Module("https://tfhub.dev/google/universal-sentence-encoder/2")
embeddings = embed([
"The quick brown fox jumps over the lazy dog.",
"I am a sentence for which I would like to get its embedding"])
sess.run(embeddings)
```
> TensorFlow Hub | [universal-sentence-encoder](https://www.tensorflow.org/hub/modules/google/universal-sentence-encoder/2)
## 参考文献
- [1] A Simple but Tough-to-Beat Baseline for Sentence Embeddings, ICLR 2016.
- [2] Skip-Thought Vectors, NIPS 2015.
- [3] A Structured Self-attentive Sentence Embedding, ICLR 2017.
- [4] An efficient framework for learning sentence representations, ICLR 2018.
- [5] Supervised Learning of Universal Sentence Representations from Natural Language Inference Data, ACL 2017.
- [6] Learning General Purpose Distributed Sentence Representations via Large Scale Multi-task Learning, ICLR 2018.
- [7] Universal Sentence Encoder, arXiv 2018.
- [8] Attention is all you need, NIPS 2017.
- [9] Deep unordered composition rivals syntactic methods for text classification, 2015 ACL.
================================================
FILE: B-自然语言处理/B-专题-词向量.md
================================================
NLP-词向量
===
Index
---
<!-- TOC -->
- [背景知识](#背景知识)
- [神经语言模型](#神经语言模型)
- [什么是词向量/词嵌入](#什么是词向量词嵌入)
- [词向量的理解 TODO](#词向量的理解-todo)
- [Word2Vec](#word2vec)
- [基于层次 SoftMax 的 CBOW 模型](#基于层次-softmax-的-cbow-模型)
- [层次 SoftMax 的正向传播](#层次-softmax-的正向传播)
- [为什么层次 SoftMax 能加速](#为什么层次-softmax-能加速)
- [层次 Softmax 的反向传播 TODO](#层次-softmax-的反向传播-todo)
- [基于层次 Softmax 的 Skip-gram 模型](#基于层次-softmax-的-skip-gram-模型)
- [---](#---)
- [基于负采样的 CBOW 和 Skip-gram](#基于负采样的-cbow-和-skip-gram)
- [负采样算法](#负采样算法)
- [Word2Vec 中的做法](#word2vec-中的做法)
- [一些源码细节](#一些源码细节)
- [`σ(x)` 的近似计算](#σx-的近似计算)
- [低频词的处理](#低频词的处理)
- [高频词的处理](#高频词的处理)
- [自适应学习率](#自适应学习率)
- [参数初始化](#参数初始化)
- [GloVe](#glove)
- [共现矩阵](#共现矩阵)
- [构架共现矩阵的细节](#构架共现矩阵的细节)
- [GloVe 的基本思想](#glove-的基本思想)
- [GloVe 的目标函数](#glove-的目标函数)
- [GloVe 目标函数的推导过程](#glove-目标函数的推导过程)
- [GloVe 与 Word2Vec 的区别](#glove-与-word2vec-的区别)
- [FastText](#fasttext)
- [`gensim.models.FastText` 使用示例](#gensimmodelsfasttext-使用示例)
- [获取单个词的 ngrams 表示](#获取单个词的-ngrams-表示)
- [计算一个未登录词的词向量](#计算一个未登录词的词向量)
- [WordRank TODO](#wordrank-todo)
- [CharCNN 字向量](#charcnn-字向量)
- [其他实践](#其他实践)
- [一般 embedding 维度的选择](#一般-embedding-维度的选择)
<!-- /TOC -->
# 背景知识
## 神经语言模型
> [神经语言模型](./A-自然语言处理基础#神经概率语言模型-nplm)
## 什么是词向量/词嵌入
- 词向量(word embedding)是一个固定长度的实值向量
- 词向量是神经语言模型的**副产品**。
- 词向量是针对“词”提出的。事实上,也可以针对更细或更粗的粒度来进行推广——比如字向量、句向量、文档向量等
## 词向量的理解 TODO
> [word2vec 中的数学原理详解(三)背景知识](https://blog.csdn.net/itplus/article/details/37969817) - CSDN博客
- 在 NLP 任务中,因为机器无法直接理解自然语言,所以首先要做的就是将语言**数学化**——词向量就是一种将自然语言数学化的方法。
**One-hot 表示**
- TODO
**分布式表示** (distributed representation)
- 分布式假设
- TODO
- 常见的分布式表示方法
- 潜在语义分析 (Latent Semantic Analysis, LSA)
- SVD 分解
- 隐含狄利克雷分布 (Latent Dirichlet Allocation, LDA),主题模型
- 神经网络、深度学习
# Word2Vec
- Word2Vec 本质上也是一个神经语言模型,但是它的目标并不是语言模型本身,而是词向量;因此,其所作的一系列优化,都是为了更快更好的得到词向量
- Word2Vec 提供了两套模型:**CBOW** 和 **Skip-Gram**(SG)
- CBOW 在已知 `context(w)` 的情况下,预测 `w`
- SG 在已知 `w` 的情况下预测 `context(w)`
- 从训练集的构建方式可以更好的理解和区别 **CBOW** 和 **SG** 模型
- 每个训练样本为一个二元组 `(x, y)`,其中 `x`为特征,`y`为标签
假设上下文窗口的大小 `context_window =5`,即
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\{w_{t-2},w_{t-1},{\color{Red}w_t},w_{t+1},w_{t+2}\}"><img src="../_assets/公式_20180806115820.png" height="" /></a></div>
或者说 `skip_window = 2`,有 `context_window = skip_window*2 + 1`
- CBOW 的训练样本为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=(\{w_{t-2},w_{t-1},w_{t+1},w_{t+2}\},&space;{\color{Red}w_t})"><img src="../_assets/公式_20180806120054.png" height="" /></a></div>
- SG 的训练样本为:
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=({\color{Red}w_t},w_i),\quad&space;i\in\{t-2,&space;t-1,&space;t+1,&space;t+2\}"><img src="../_assets/公式_20180806120247.png" height="" /></a></div>
- 一般来说,`skip_window <= 10`
- 除了两套模型,Word2Vec 还提供了两套优化方案,分别基于 Hierarchical Softmax (层次SoftMax) 和 Negative Sampling (负采样)
## 基于层次 SoftMax 的 CBOW 模型
- 【**输入层**】将 `context(w)` 中的词映射为 `m` 维词向量,共 `2c` 个
- 【**投影层**】将输入层的 `2c` 个词向量累加求和,得到新的 `m` 维词向量
- 【**输出层**】输出层对应一棵**哈夫曼树**,以词表中词作为叶子节点,各词的出现频率作为权重——共 `N` 个叶子节点,`N-1` 个非叶子节点
<div align="center"><img src="../_assets/TIM截图20180806141616.png" height="400" /></div>
- 对比 [N-gram 神经语言模型的网络结构](#n-gram-神经语言模型的网络结构)
- 【输入层】前者使用的是 `w` 的前 `n-1` 个词,后者使用 `w` 两边的词
> 这是后者词向量的性能优于前者的主要原因
- 【投影层】前者通过拼接,后者通过**累加求和**
- 【隐藏层】后者无隐藏层
- 【输出层】前者为线性结构,后者为树形结构
- 模型改进
- 从对比中可以看出,CBOW 模型的主要改进都是为了**减少计算量**——取消隐藏层、使用**层Softmax**代替基本Softmax
### 层次 SoftMax 的正向传播
- 层 Softmax 实际上是把一个超大的多分类问题转化成一系列二分类问题
- 示例:求 `P("足球"|context("足球"))`
<div align="center"><img src="../_assets/TIM截图20180806144052.png" height="400" /></div>
- 从根节点到“足球”所在的叶子节点,需要经过 4 个分支,每次分支相当于一次**二分类**(逻辑斯蒂回归,二元Softmax)
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\dpi{120}&space;\begin{aligned}&space;p(0|x_w;\theta)&=\sigma(x_w^{\top}\theta)=\frac{1}{1+e^{-x_w^{\top}\theta}}\\&space;p(1|x_w;\theta)&=1-\sigma(x_w^{\top}\theta)&space;\end{aligned}"><img src="../_assets/公式_20180806150816.png" height="" /></a></div>
> 这里遵从原文,将 0 作为正类,1 作为负类
- 而 `P("足球"|context("足球"))` 就是每次分类正确的概率之积,即
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=({\color{Red}w_t},w_i),\quad&space;i\in\{t-2,&space;t-1,&space;t+1,&space;t+2\}"><img src="../_assets/公式_20180806150727.png" height="" /></a></div>
> 这里每个非叶子都对应一个参数 `θ_i`
#### 为什么层次 SoftMax 能加速
- Softmax 大部分的计算量在于分母部分,它需要求出所有分量的和
- 而层次 SoftMax 每次只需要计算两个分量,因此极大的提升了速度
### 层次 Softmax 的反向传播 TODO
> [word2vec 中的数学原理详解(四)基于 Hierarchical Softmax 的模型](https://blog.csdn.net/itplus/article/details/37969979) - CSDN博客
## 基于层次 Softmax 的 Skip-gram 模型
- 这里保留了【投影层】,但实际上只是一个恒等变换
<div align="center"><img src="../_assets/TIM截图20180806151406.png" height="400" /></div>
- 从模型的角度看:CBOW 与 SG 模型的区别仅在于 `x_w` 的构造方式不同,前者是 `context(w)` 的词向量累加;后者就是 `w` 的词向量
- 虽然 SG 模型用中心词做特征,上下文词做类标,但实际上两者的地位是等价的
## ---
## 基于负采样的 CBOW 和 Skip-gram
- 层次 Softmax 还不够简单,于是提出了基于负采样的方法进一步提升性能
- 负采样(Negative Sampling)是 NCE(Noise Contrastive Estimation) 的简化版本
> [噪音对比估计(NCE)](https://blog.csdn.net/littlely_ll/article/details/79252064) - CSDN博客
- CBOW 的训练样本是一个 `(context(w), w)` 二元对;对于给定的 `context(w)`,`w` 就是它的正样本,而其他所有词都是负样本。
- 如果不使用**负采样**,即 N-gram 神经语言模型中的做法,就是对整个词表 Softmax 和交叉熵
- 负采样相当于选取所有负例中的一部分作为负样本,从而减少计算量
- Skip-gram 模型同理
## 负采样算法
- 负采样算法,即对给定的 `w` ,生成相应负样本的方法
- 最简单的方法是随机采样,但这会产生一点问题,词表中的词出现频率并不相同
- 如果不是从词表中采样,而是从语料中采样;显然,那些高频词被选为负样本的概率要大于低频词
- 在词表中采样时也应该遵循这个
- 因此,负采样算法实际上就是一个**带权采样**过程
<div align="center"><img src="../_assets/TIM截图20180806161221.png" height="200" /></div>
### Word2Vec 中的做法
- 记
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=l_0=0,\cdots,l_k=\sum_{j=1}^k&space;len(w_j),\quad&space;k=1,2,\cdots,N"><img src="../_assets/公式_20180806165417.png" height="" /></a></div>
- 以这 `N+1` 个点对区间 `[0,1]` 做非等距切分
- 引入的一个在区间 `[0,1]` 上的 `M` 等距切分,其中 `M >> N`
<div align="center"><img src="../_assets/TIM截图20180806165750.png" height="" /></div>
> 源码中取 `M = 10^8`
- 然后对两个切分做投影,得到映射关系
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex={\color{Red}\mathrm{Hash}(i)=w_k},\quad&space;\text{where}\&space;\&space;m_i\in&space;I_k,\quad&space;i=1,2,\cdots,M-1"><img src="../_assets/公式_20180806170618.png" height="" /></a></div>
- 采样时,每次生成一个 `[1, M-1]` 之间的整数 `i`,则 `Table(i)` 就对应一个样本;当采样到正例时,跳过(**拒绝采样**)。
- 特别的,Word2Vec 在计算 `len(w)` 时做了一些改动——为 `count(·)` 加了一个**指数**
<div align="center"><a href="http://www.codecogs.com/eqnedit.php?latex=\mathrm{len}(w)=\frac{\mathrm{count}(w)^\frac{3}{4}}{\sum_{u\in&space;V}\mathrm{count}(u)^\frac{3}{4}}"><img src="../_assets/公式_20180806162119.pn
gitextract_37cdkksy/
├── .gitignore
├── A-机器学习/
│ ├── A-机器学习基础.md
│ ├── A-机器学习实践.md
│ ├── A-机器学习算法.md
│ └── C-专题-集成学习.md
├── A-深度学习/
│ ├── A-深度学习基础.md
│ ├── A-深度学习实践.md
│ ├── B-专题-CNN.md
│ ├── B-专题-RNN.md
│ ├── C-专题-优化算法.md
│ ├── D-专题-序列建模.md
│ ├── 《深度学习》整理.md
│ └── 备忘-术语表.md
├── B-自然语言处理/
│ ├── A-NLP发展趋势.md
│ ├── A-自然语言处理基础.md
│ ├── B-专题-句嵌入.md
│ ├── B-专题-词向量.md
│ ├── C-专题-多模态.md
│ ├── D-视觉问答-1_综述.md
│ └── 深度查询理解/
│ └── A-综述.md
├── B-计算机视觉/
│ └── B-专题-基本模型.md
├── C-数学/
│ ├── A-概率论.md
│ ├── B-微积分的本质.md
│ ├── B-深度学习的核心.md
│ └── README.md
├── C-算法/
│ ├── README.md
│ ├── 专题-A-字符串.md
│ ├── 专题-A-数据结构.md
│ ├── 专题-A-数据结构_Advanced.md
│ ├── 专题-B-动态规划.md
│ ├── 专题-B-双指针.md
│ ├── 专题-C-区间问题.md
│ ├── 专题-C-排列组合.md
│ ├── 专题-C-数学问题.md
│ ├── 专题-C-洗牌、采样、随机数.md
│ ├── 专题-D-大数运算.md
│ ├── 专题-D-海量数据处理.md
│ ├── 备忘-IO模板.md
│ ├── 备忘-必备算法.md
│ ├── 题解-LeetCode.md
│ ├── 题解-剑指Offer.md
│ └── 题解-面试真题.md
├── C-编程语言/
│ ├── Cpp-A-基础.md
│ ├── Cpp-A-面向对象.md
│ ├── Cpp-C-左值与右值.md
│ ├── Python-A-基础.md
│ └── README.md
├── D-笔试面经/
│ ├── README.md
│ ├── 笔试-360-180827.md
│ ├── 笔试-iHandy-180927.md
│ ├── 笔试-作业帮-180925.md
│ ├── 笔试-字节跳动-180812.md
│ ├── 笔试-小米-180920.md
│ ├── 笔试-度小满-180913.md
│ ├── 笔试-快手-180910.md
│ ├── 笔试-招行-180830.md
│ ├── 笔试-搜狐畅游-180915.md
│ ├── 笔试-滴滴-180918.md
│ ├── 笔试-爱奇艺-180915.md
│ ├── 笔试-百度-180911.md
│ ├── 笔试-百度-180914.md
│ ├── 笔试-百词斩-180920.md
│ ├── 笔试-腾讯-180916.md
│ ├── 笔试-迅雷-180912.md
│ └── 笔试-顺丰-180917.md
├── Jobs.md
├── README.md
├── ToDo.md
├── _codes/
│ ├── README.md
│ ├── cpp/
│ │ └── 面向对象-不通过继承实现多态-动态序列.cpp
│ ├── machine_learning/
│ │ └── KMeans/
│ │ ├── data.txt
│ │ └── kmeans.py
│ ├── model/
│ │ └── 倒排索引/
│ │ ├── data/
│ │ │ ├── a.txt
│ │ │ ├── b.txt
│ │ │ └── c.txt
│ │ └── inverse_index.py
│ ├── my_nlp/
│ │ ├── data/
│ │ │ ├── sentences.txt
│ │ │ ├── vocab.txt
│ │ │ └── wv.txt
│ │ └── src/
│ │ ├── __init__.py
│ │ ├── sentence2vec/
│ │ │ ├── __init__.py
│ │ │ └── sif.py
│ │ └── utils/
│ │ ├── __init__.py
│ │ └── vocab.py
│ ├── my_tensorflow/
│ │ ├── README.md
│ │ ├── src/
│ │ │ ├── __init__.py
│ │ │ ├── activations/
│ │ │ │ ├── __init__.py
│ │ │ │ └── relu.py
│ │ │ ├── initializers/
│ │ │ │ └── __init__.py
│ │ │ ├── layers/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── attention.py
│ │ │ │ ├── cnn.py
│ │ │ │ ├── dense.py
│ │ │ │ ├── embedding/
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── char_cnn.py
│ │ │ │ ├── highway.py
│ │ │ │ └── match/
│ │ │ │ ├── __init__.py
│ │ │ │ └── attention_flow.py
│ │ │ ├── regularizers/
│ │ │ │ ├── L1L2.py
│ │ │ │ └── __init__.py
│ │ │ └── utils/
│ │ │ ├── __init__.py
│ │ │ ├── array_op.py
│ │ │ └── math_op.py
│ │ └── test_layer.ipynb
│ └── 工具库/
│ └── gensim/
│ └── FastText.py
└── _notes/
├── 专题-Bash命令.md
├── 图示.pptx
├── 备忘-Markdown小技巧.md
├── 备忘-Python相关工具.md
├── 备忘-工具库.md
└── 备忘-常用子函数.md
SYMBOL INDEX (70 symbols across 17 files)
FILE: _codes/cpp/面向对象-不通过继承实现多态-动态序列.cpp
class num_sequence (line 4) | class num_sequence {
type ns_type (line 11) | enum ns_type {
method num_sequence (line 16) | num_sequence(): _pmf(func_tbl[ns_fibonacci]) { }
method set_sequence (line 19) | void set_sequence(ns_type nst) {
method print (line 29) | void print(int n) {
method fibonacci (line 34) | void fibonacci(int n) {
method square (line 42) | void square(int n) {
function main (line 58) | int main() {
FILE: _codes/machine_learning/KMeans/kmeans.py
function load_data (line 11) | def load_data(file_path):
function score_euclidean (line 24) | def score_euclidean(a, b):
function rand_center (line 30) | def rand_center(data, k):
function k_means (line 36) | def k_means(data, k, max_iter=100, score=score_euclidean, e=1e-6):
function _test (line 87) | def _test():
FILE: _codes/model/倒排索引/inverse_index.py
function word_clean (line 23) | def word_clean(word):
function create_inverse_index (line 30) | def create_inverse_index(files_list):
function search_tokens (line 70) | def search_tokens(tokens, inverse_index, word_freq=None):
function search (line 81) | def search(txt, inverse_index, word_freq=None):
function printy (line 108) | def printy(ret):
FILE: _codes/my_nlp/src/utils/__init__.py
function get_w2v (line 6) | def get_w2v(file_path):
FILE: _codes/my_nlp/src/utils/vocab.py
function set_vocab (line 4) | def set_vocab(sentences, save_path=None):
function get_vocab (line 12) | def get_vocab(file_path):
FILE: _codes/my_tensorflow/src/activations/__init__.py
function linear (line 6) | def linear(x):
function identity (line 11) | def identity(x):
function sigmoid (line 16) | def sigmoid(x):
function hard_sigmoid (line 21) | def hard_sigmoid(x):
function tanh (line 32) | def tanh(x):
function softplus (line 37) | def softplus(x):
function softsign (line 42) | def softsign(x):
function softmax (line 49) | def softmax(x, axis=-1):
function elu (line 65) | def elu(x):
function selu (line 70) | def selu(x):
FILE: _codes/my_tensorflow/src/activations/relu.py
function relu (line 8) | def relu(x):
function relu6 (line 15) | def relu6(x):
function crelu (line 22) | def crelu(x, axis=-1):
function leaky_relu (line 28) | def leaky_relu(x, alpha=0.1):
function clip_relu (line 35) | def clip_relu(x, max_value):
function parametric_relu (line 44) | def parametric_relu(x, channel_shared=False, alpha_init=constant(0.), na...
FILE: _codes/my_tensorflow/src/layers/attention.py
function attention_for_dense (line 16) | def attention_for_dense(x, name=None, reuse=None):
function attention_for_rnn (line 41) | def attention_for_rnn(x, n_step=None, name=None, reuse=None, use_mean_at...
FILE: _codes/my_tensorflow/src/layers/cnn.py
function conv1d (line 13) | def conv1d():
function conv2d (line 17) | def conv2d(x, kernel_size, out_channels,
FILE: _codes/my_tensorflow/src/layers/dense.py
function dense (line 15) | def dense(x, n_unit, act_fn=relu, name=None, reuse=None):
function multi_dense (line 37) | def multi_dense(x, n_unit_ls, act_fn=relu, name=None):
function linear_dense (line 56) | def linear_dense(x, n_unit, name=None, reuse=None):
class Dense (line 70) | class Dense(object):
method __init__ (line 73) | def __init__(self, n_unit, act_fn=relu, name=None):
method _build (line 81) | def _build(self, n_input):
method _call (line 86) | def _call(self, x):
method __call__ (line 91) | def __call__(self, x):
FILE: _codes/my_tensorflow/src/layers/embedding/char_cnn.py
function char_cnn_embedding (line 13) | def char_cnn_embedding(x, c_embed_size=8, share_cnn_weights=True, name="...
FILE: _codes/my_tensorflow/src/layers/highway.py
function highway_dense (line 15) | def highway_dense(x, act_fn=relu, carry_bias=-1.0, name=None):
function multi_highway_dense (line 39) | def multi_highway_dense(x, n_layer, act_fn=relu, carry_bias=-1.0, name=N...
function highway_conv2d (line 51) | def highway_conv2d(x, kernel_size,
function multi_highway_conv2d (line 89) | def multi_highway_conv2d(x, kernel_size, n_layer,
FILE: _codes/my_tensorflow/src/layers/match/attention_flow.py
function attention_flow_self (line 17) | def attention_flow_self(h, u, T=None, J=None, d=None, name=None, reuse=N...
function attention_flow (line 62) | def attention_flow(h, u, T=None, J=None, d=None, name=None, reuse=None):
FILE: _codes/my_tensorflow/src/regularizers/L1L2.py
class L1L2Regularizer (line 11) | class L1L2Regularizer(object):
method __init__ (line 19) | def __init__(self, l1=0., l2=0.):
method __call__ (line 28) | def __call__(self, x):
FILE: _codes/my_tensorflow/src/utils/__init__.py
function foo (line 22) | def foo():
function get_shape (line 26) | def get_shape(x):
function get_wb (line 39) | def get_wb(shape,
function get_w (line 54) | def get_w(shape,
function get_params_dict (line 64) | def get_params_dict():
function print_params_dict (line 73) | def print_params_dict():
function get_params_number (line 87) | def get_params_number():
function print_params_number (line 93) | def print_params_number():
FILE: _codes/my_tensorflow/src/utils/array_op.py
function permute (line 12) | def permute(x, perm):
function repeat (line 29) | def repeat(x, n):
FILE: _codes/my_tensorflow/src/utils/math_op.py
function dot (line 10) | def dot(x, y):
Condensed preview — 111 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,071K chars).
[
{
"path": ".gitignore",
"chars": 248,
"preview": "# IDE\n.idea/\n.vscode/\n\n# folder\n__*/\n.ipynb_checkpoints/\nout/\n\n# file\n-*\n*.zip\n*.tgz\nUntitled.ipynb\nMyCV.pdf\nMyCV.md\nGSD"
},
{
"path": "A-机器学习/A-机器学习基础.md",
"chars": 5693,
"preview": "ML-机器学习基础\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [偏差与方差](#偏差与方差)\n - [导致偏差和方差的原因](#导致偏差和方差的原因)\n - [深度学习中的偏差与方差](#深度学习中的偏差与方"
},
{
"path": "A-机器学习/A-机器学习实践.md",
"chars": 8200,
"preview": "专题-机器学习实践\n===\n\nReference\n---\n- [CS229 课程讲义(中文)](https://github.com/Kivy-CN/Stanford-CS-229-CN) - Kivy-CN - GitHub\n\nIndex"
},
{
"path": "A-机器学习/A-机器学习算法.md",
"chars": 35325,
"preview": "**RoadMap**\n---\n- [逻辑斯蒂回归](#逻辑斯蒂回归)\n- [支持向量机](#支持向量机)\n- [决策树](#决策树)\n- [AdaBoost 算法](#adaboost-算法)\n - [梯度提升决策树 GBDT](#梯度"
},
{
"path": "A-机器学习/C-专题-集成学习.md",
"chars": 3810,
"preview": "ML-专题-集成学习\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [集成学习基本问题](#集成学习基本问题)\n - [集成学习的基本思想](#集成学习的基本思想)\n - [集成学习为什么有效?](#集成学习为什么有效)"
},
{
"path": "A-深度学习/A-深度学习基础.md",
"chars": 16386,
"preview": "深度学习基础\n===\n\n相关专题\n---\n- [《深度学习》整理](./《深度学习》整理)\n- [CNN 专题](./B-专题-CNN)\n- [RNN 专题](./B-专题-RNN)\n- [优化算法专题](./C-专题-优化算法)\n "
},
{
"path": "A-深度学习/A-深度学习实践.md",
"chars": 436,
"preview": "深度学习实践\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [加速训练的方法](#加速训练的方法)\n - [内部方法](#内部方法)\n - [外部方法](#外部方法)\n\n<!-- /TOC -->\n\n## 加速训"
},
{
"path": "A-深度学习/B-专题-CNN.md",
"chars": 12805,
"preview": "DL-专题-CNN\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [CNN 的基本特征](#cnn-的基本特征)\n - [动机](#动机)\n - [意义](#意义)\n- [卷积的内部实现](#卷积的内部实现)\n - ["
},
{
"path": "A-深度学习/B-专题-RNN.md",
"chars": 12306,
"preview": "DL-专题-RNN\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [RNN 的基本结构](#rnn-的基本结构)\n- [RNN 常见的几种设计模式(3)](#rnn-常见的几种设计模式3)\n- [RNN 的反向传播(BPTT"
},
{
"path": "A-深度学习/C-专题-优化算法.md",
"chars": 9517,
"preview": "专题-优化算法\n===\n\nReference\n---\n- 【**必读**】[An overview of gradient descent optimization algorithms](http://ruder.io/optimizin"
},
{
"path": "A-深度学习/D-专题-序列建模.md",
"chars": 5303,
"preview": "专题-序列建模\n===\n\n**相关专题**\n- [专题-RNN](./B-专题-RNN.md)\n- [专题-RNN](./B-专题-RNN.md)\n\nIndex\n---\n<!-- TOC -->\n\n- [序列建模简述](#序列建模简述)\n-"
},
{
"path": "A-深度学习/《深度学习》整理.md",
"chars": 54053,
"preview": "**问题列表**\n---\n<!-- TOC -->\n\n- [如何设置网络的初始值?*](#如何设置网络的初始值)\n- [梯度爆炸的解决办法***](#梯度爆炸的解决办法)\n- [神经网络(MLP)的万能近似定理*](#神经网络mlp的万能近"
},
{
"path": "A-深度学习/备忘-术语表.md",
"chars": 2416,
"preview": "术语表\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [指数加权平均(指数衰减平均)](#指数加权平均指数衰减平均)\n - [偏差修正](#偏差修正)\n\n<!-- /TOC -->\n\n## 指数加权平均(指数衰减平均)"
},
{
"path": "B-自然语言处理/A-NLP发展趋势.md",
"chars": 3116,
"preview": "NLP 发展趋势\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [【2018.11】预见未来|NLP将迎来黄金十年(MSRA)](#201811预见未来|nlp将迎来黄金十年msra)\n - [NLP 新的发展基础]("
},
{
"path": "B-自然语言处理/A-自然语言处理基础.md",
"chars": 12118,
"preview": "NLP-NLP基础\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [NLP 概述](#nlp-概述)\n - [解决 NLP 问题的一般思路](#解决-nlp-问题的一般思路)\n - [NLP 的历史进程](#nl"
},
{
"path": "B-自然语言处理/B-专题-句嵌入.md",
"chars": 9186,
"preview": "专题-句嵌入(Sentence Embedding)\n===\n\nReference\n---\n- [The Current Best of Universal Word Embeddings and Sentence Embeddings]("
},
{
"path": "B-自然语言处理/B-专题-词向量.md",
"chars": 18184,
"preview": "NLP-词向量\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [背景知识](#背景知识)\n - [神经语言模型](#神经语言模型)\n - [什么是词向量/词嵌入](#什么是词向量词嵌入)\n - [词向量的理"
},
{
"path": "B-自然语言处理/C-专题-多模态.md",
"chars": 163,
"preview": "专题-多模态\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [多模态词向量](#多模态词向量)\n - [Papers](#papers)\n\n<!-- /TOC -->\n\n# 多模态词向量\n\n## Papers\n> [p"
},
{
"path": "B-自然语言处理/D-视觉问答-1_综述.md",
"chars": 23041,
"preview": "视觉问答(VQA)综述\n===\n\n**相关论文**\n- [2016].Visual Question Answering\n - 本文从**数据集**、**评价方法**、**算法**等方面讨论了 VQA 的现状及存在的问题,以及 VQA"
},
{
"path": "B-自然语言处理/深度查询理解/A-综述.md",
"chars": 4129,
"preview": "DQU 综述\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [Introduction](#introduction)\n - [不同时期的搜索](#不同时期的搜索)\n - [查询理解系统的特点](#查询理解系统的"
},
{
"path": "B-计算机视觉/B-专题-基本模型.md",
"chars": 1367,
"preview": "专题-基本模型\n===\n> [Applications](https://keras.io/applications/) - Keras Documentation \n\n- [2015] VGGNet(16/19) [2]\n- [2015]"
},
{
"path": "C-数学/A-概率论.md",
"chars": 1727,
"preview": "概率论\n===\n- 面试时如果被问了一个概率题,那就要小心了,面试官可能要刷人了!\n- 面试概率题的特点:\n - 题面不复杂\n - 短时间可以解答\n - 会者不难\n\nRoadMap\n---\n- [概率论基础](#概率论基础"
},
{
"path": "C-数学/B-微积分的本质.md",
"chars": 21960,
"preview": "**说明**\n---\n- 整理自“[3Blue1Brown - 微积分的本质系列视频](https://www.bilibili.com/video/av24325548)”\n- 本系列的视频**目的**在于帮助你建立关于**微积分的基本直"
},
{
"path": "C-数学/B-深度学习的核心.md",
"chars": 23075,
"preview": "**说明**\n---\n该文档为“**3Blue1Brown - 深度学习系列视频**”的整理,主要包括三个视频\n- [神经网络的结构](https://www.bilibili.com/video/av15532370)\n- [梯度下降法]"
},
{
"path": "C-数学/README.md",
"chars": 1150,
"preview": "**知识回顾**\n---\n- [微积分的本质](./微积分的本质.md)\n- [深度学习的核心-梯度下降与反向传播](./深度学习的核心.md)\n\n**数学问题**\n---\n<!-- TOC -->\n\n- [1. 在圆环上随机选取 3 个点"
},
{
"path": "C-算法/README.md",
"chars": 2027,
"preview": "**题解**\n---\n- [剑指Offer 题解](./题解-剑指Offer.md)\n- [Leetcode 题解](./题解-LeetCode.md)\n\n**专题**\n---\n- A\n - [数据结构](./专题-A-数据结构)\n "
},
{
"path": "C-算法/专题-A-字符串.md",
"chars": 7538,
"preview": "专题-字符串\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [模式匹配 TODO](#模式匹配-todo)\n- [进制转换](#进制转换)\n - [10进制转任意进制](#10进制转任意进制)\n - [任意进制转"
},
{
"path": "C-算法/专题-A-数据结构.md",
"chars": 30172,
"preview": "专题-数据结构\n===\n\n- 数据结构相关基本是**现场面试**中出现频率最高的问题。\n - 因为现场面试的时间限制,更难的问题需要大量的思考时间,所以一般只要求需要阐述思路(比如动态规划);\n - 而**数据结构**相关的问题"
},
{
"path": "C-算法/专题-A-数据结构_Advanced.md",
"chars": 6615,
"preview": "专题-数据结构_Advanced\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [树状数组](#树状数组)\n - [树状数组的构建(以区间和问题为例)](#树状数组的构建以区间和问题为例)\n - [树状数组的特点"
},
{
"path": "C-算法/专题-B-动态规划.md",
"chars": 36090,
"preview": "专题-动态规划\n===\n\nDP 问题的一般思路\n---\n- **DP 定义** ——有时 DP 的更新很难严格遵循定义,需要额外变量保存全局最优结果\n- **初始化** ——初始值可以通过一个简单的特例来确定\n- **递推公式** + **"
},
{
"path": "C-算法/专题-B-双指针.md",
"chars": 33748,
"preview": "专题-双指针\n===\n- 双指针问题无论在笔试还是面试中出现的频率都非常高;是性价比非常高的一类问题。\n\n模板小结\n---\n- **首尾双指针**\n <div align=\"center\"><img src=\"../_assets/T"
},
{
"path": "C-算法/专题-C-区间问题.md",
"chars": 4270,
"preview": "专题-区间问题\n===\n\n基本方法\n---\n- **双指针**(滑动窗口)\n - 定长滑动\n - 变长滑动\n- **扫描线算法**\n\nIndex\n---\n<!-- TOC -->\n\n- [会议室](#会议室)\n- [会议室 II(扫描线"
},
{
"path": "C-算法/专题-C-排列组合.md",
"chars": 17777,
"preview": "专题-排列组合\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [排列](#排列)\n - [下一个排列](#下一个排列)\n - [上一个排列](#上一个排列)\n - [STL 提供的实现(下一个排列、上一个排列) TOD"
},
{
"path": "C-算法/专题-C-数学问题.md",
"chars": 1580,
"preview": "专题-数学\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [直线上最多的点数](#直线上最多的点数)\n\n<!-- /TOC -->\n\n### 直线上最多的点数\n> LeetCode - [149. 直线上最多的点数](htt"
},
{
"path": "C-算法/专题-C-洗牌、采样、随机数.md",
"chars": 11961,
"preview": "专题-洗牌、采样、随机数\n===\n\nReference\n---\n- [关于乱序(shuffle)与随机采样(sample)的一点探究](https://www.cnblogs.com/xybaby/p/8280936.html) - xyb"
},
{
"path": "C-算法/专题-D-大数运算.md",
"chars": 2098,
"preview": "专题-大数运算\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [大数取模](#大数取模)\n - [取模运算的性质](#取模运算的性质)\n - [快速幂取模](#快速幂取模)\n- [大数加/减/乘/除](#大数加减乘除)\n"
},
{
"path": "C-算法/专题-D-海量数据处理.md",
"chars": 1483,
"preview": "专题-海量数据处理\n===\n\n备忘\n---\n- `1 GB`: 十亿个字节(Byte)\n > `1(B) * 10*10^8 / 1024 / 1024 ≈ 953.67(MB) ≈ 1000(MB) ≈ 1(GB)`\n- `400 MB"
},
{
"path": "C-算法/备忘-IO模板.md",
"chars": 2791,
"preview": "备忘-IO 模板\n===\n- 不少网络笔试不像 LeetCode 帮你完成 I/O,需要手动完成\n- 如果没有 ACM 经验,很可能会在这上面浪费不少时间\n- 这里总结了几种常见的 IO 模板,分别提供了 C/C++ 和 Python(TO"
},
{
"path": "C-算法/备忘-必备算法.md",
"chars": 2404,
"preview": "备忘-必备算法\n===\n- 一些必备算法,主要是 C++ 版本\nIndex\n---\n<!-- TOC -->\n\n- [二分查找](#二分查找)\n - [离散版](#离散版)\n - [`my_binary_search(vector<"
},
{
"path": "C-算法/题解-LeetCode.md",
"chars": 13263,
"preview": "题解-LeetCode\n===\n\nRoadMap\n---\n- [二叉树](#二叉树)\n - [DFS](#dfs)\n- [数组](#数组)\n - [双指针](#双指针)\n - [多级排序](#多级排序)\n - [其他](#其他)\n-"
},
{
"path": "C-算法/题解-剑指Offer.md",
"chars": 84236,
"preview": "**说明**\n---\n- 主要编程语言为 C/C++\n- 涉及**字符串**的问题可能会使用 Python\n- 题目编号以原书为准,如“**面试题 3:数组中重复的数字**”\n - 因为题目不多,所以就不做分类了\n- 所有代码均通过 OJ"
},
{
"path": "C-算法/题解-面试真题.md",
"chars": 602,
"preview": "题解-面试真题\n===\n- 记录一些暂时没找到原型的面试真题\n\nIndex\n---\n<!-- TOC -->\n\n- [给定 `n` 个`[0,n)`区间内的数,统计每个数出现的次数,不使用额外空间](#给定-n-个0n区间内的数统计每个数出"
},
{
"path": "C-编程语言/Cpp-A-基础.md",
"chars": 10639,
"preview": "**RoadMap**\n---\n<!-- TOC -->\n\n- [指针与引用](#指针与引用)\n - [左值引用与右值引用](#左值引用与右值引用)\n- [static 与 const](#static-与-const)\n - "
},
{
"path": "C-编程语言/Cpp-A-面向对象.md",
"chars": 2167,
"preview": "C++-面向对象编程\n===\n\n面向对象编程概述\n---\n- 面向对象编程的两个主要特征:**继承**、**多态**\n- C++ 中是通过间接利用“**指向父类**”的**指针**或**引用**来操作其子类对象,从而达到多态的目的;如果直接"
},
{
"path": "C-编程语言/Cpp-C-左值与右值.md",
"chars": 14631,
"preview": "C++中的左值与右值\n===\n\n说明\n---\n- 这一部分内容只是帮助理解 C++(11) 中左值与右值的概念。\n- 在编程实践中,因为**编译器优化**的存在,特别是其中的**返回值优化**(Return Value Optimizati"
},
{
"path": "C-编程语言/Python-A-基础.md",
"chars": 319,
"preview": "Python-基础知识\n===\n\nIndex\n---\n\n<!-- TOC -->\n\n- [Python 中的垃圾回收机制](#python-中的垃圾回收机制)\n- [字符串格式化输出](#字符串格式化输出)\n - [旧式(%)](#旧"
},
{
"path": "C-编程语言/README.md",
"chars": 172,
"preview": "编程语言\n===\n- 以 C++ 和 Python 为主\n\n**Index**\n---\n- **C/C++**\n - [左值与右值](./Cpp-C-左值与右值)\n\n## Reference\n- - huihut/[interview"
},
{
"path": "D-笔试面经/README.md",
"chars": 7376,
"preview": "笔试面经\n===\n\n**回答一个面试问题的基本要点**\n- 是什么、\n- 为什么(动机)、\n- 怎么做(原理)、\n- 使用场景、\n- 一些细节(如果使用过的话)\n\nReference\n---\n- [BAT机器学习面试1000题系列(第1~3"
},
{
"path": "D-笔试面经/笔试-360-180827.md",
"chars": 2419,
"preview": "笔试-360-180827\n===\n- 40 道选择题,范围包括大学所有课程...\n- 3 道编程题\n\nIndex\n---\n<!-- TOC -->\n\n- [城市修建](#城市修建)\n- [看花](#看花)\n- [Array(选做)](#a"
},
{
"path": "D-笔试面经/笔试-iHandy-180927.md",
"chars": 1438,
"preview": "笔试-iHandy-180927\n===\n- 单项选择题 8 道,不定项选择题 5 道,问答题 2 道,编程题 1 道\n\nIndex\n---\n<!-- TOC -->\n\n- [【问答】射击(概率题)](#问答射击概率题)\n- [【编程】比大"
},
{
"path": "D-笔试面经/笔试-作业帮-180925.md",
"chars": 1838,
"preview": "笔试-作业帮-180925\n===\n- 单选 5,填空 5,编程 2,问答 2\n- 编程不允许跳出页面\n\nIndex\n---\n<!-- TOC -->\n\n- [1. 点对距离](#1-点对距离)\n- [2. 扩展型表达式求值](#2-扩展型"
},
{
"path": "D-笔试面经/笔试-字节跳动-180812.md",
"chars": 4956,
"preview": "笔试-字节跳动-180812\n===\n共 5 道编程题\n\nReference\n---\n- [官方题解](https://m.toutiao.com/i6589920344075665928/?wxshare_count=2&pbid=658"
},
{
"path": "D-笔试面经/笔试-小米-180920.md",
"chars": 2492,
"preview": "笔试-小米-180920\n===\n- 单选 10,多选 10,编程 2\n\nReference\n---\n- **小米大礼包**:https://blog.csdn.net/amusi1994/article/details/82793376\n"
},
{
"path": "D-笔试面经/笔试-度小满-180913.md",
"chars": 1895,
"preview": "笔试-度小满-180913\n===\n- 机器学习研发\n- 选择 30,编程 2\n\nIndex\n---\n<!-- TOC -->\n\n- [火车站台](#火车站台)\n- [商品交易](#商品交易)\n\n<!-- /TOC -->\n\n## 火车站台"
},
{
"path": "D-笔试面经/笔试-快手-180910.md",
"chars": 2819,
"preview": "笔试-快手-180910\n===\n- 单选 20;编程 3\n\n\nIndex\n---\n<!-- TOC -->\n\n- [字符串归一化](#字符串归一化)\n- [魔法深渊](#魔法深渊)\n- [善变的同伴](#善变的同伴)\n\n<!-- /TOC"
},
{
"path": "D-笔试面经/笔试-招行-180830.md",
"chars": 654,
"preview": "笔试-招行-180830\n===\n15道单选、5道多选、3道问答、2道编程\n\nIndex\n---\n<!-- TOC -->\n\n- [重叠的装饰](#重叠的装饰)\n- [推倒吧骨牌](#推倒吧骨牌)\n\n<!-- /TOC -->\n\n## 重叠"
},
{
"path": "D-笔试面经/笔试-搜狐畅游-180915.md",
"chars": 1680,
"preview": "笔试-搜狐畅游-180915\n===\n\n- 考试题型:\n - 基础能力-单选题 10 道,\n - 基础能力-资料分析题一 5 道,\n - 基础能力-资料分析题二 5 道,\n - 专业能力-单选题 10 道,\n - 专业能力-多选题"
},
{
"path": "D-笔试面经/笔试-滴滴-180918.md",
"chars": 6265,
"preview": "笔试-滴滴-180918\n===\n- 选择 30,编程 2\n\n\nIndex\n---\n<!-- TOC -->\n\n- [排列小球](#排列小球)\n- [交通轨迹分析](#交通轨迹分析)\n\n<!-- /TOC -->\n\n## 排列小球\n<div"
},
{
"path": "D-笔试面经/笔试-爱奇艺-180915.md",
"chars": 1251,
"preview": "笔试-爱奇艺-180915\n===\n- 单选 20,编程 2\n\nIndex\n---\n<!-- TOC -->\n\n- [局长的食物](#局长的食物)\n- [库特君的面条](#库特君的面条)\n\n<!-- /TOC -->\n\n## 局长的食物\n<"
},
{
"path": "D-笔试面经/笔试-百度-180911.md",
"chars": 428,
"preview": "笔试-百度-180911\n===\n\n\nIndex\n---\n\n## 1. \n<div align=\"center\"><img src=\"../_assets/TIM截图20180911212613.png\" height=\"\" /></div"
},
{
"path": "D-笔试面经/笔试-百度-180914.md",
"chars": 1131,
"preview": "笔试-百度-180914\n===\n- 选择 30,简答 2,编程 2\n\n\nIndex\n---\n<!-- TOC -->\n\n- [字符串计数](#字符串计数)\n- [寻寻觅觅](#寻寻觅觅)\n\n<!-- /TOC -->\n\n\n## 字符串计数"
},
{
"path": "D-笔试面经/笔试-百词斩-180920.md",
"chars": 775,
"preview": "笔试-百词斩-180920\n===\n- 编程 4\n\nIndex\n---\n\n\n## 1. 时钟的转动\n<div align=\"center\"><img src=\"../_assets/TIM截图20180920203251.png\" heig"
},
{
"path": "D-笔试面经/笔试-腾讯-180916.md",
"chars": 3315,
"preview": "笔试-腾讯-180916\n===\n- 不定项 25,编程 3\n\n\nIndex\n---\n<!-- TOC -->\n\n- [字符串系数](#字符串系数)\n- [小Q与牛牛的游戏](#小q与牛牛的游戏)\n- [三元组](#三元组)\n\n<!-- /"
},
{
"path": "D-笔试面经/笔试-迅雷-180912.md",
"chars": 924,
"preview": "笔试-迅雷-180912\n===\n- 单选 10,多选 10,编程 2\n\nIndex\n---\n<!-- TOC -->\n\n- [AI-A-01](#ai-a-01)\n- [AI-A-02](#ai-a-02)\n\n<!-- /TOC -->\n"
},
{
"path": "D-笔试面经/笔试-顺丰-180917.md",
"chars": 1796,
"preview": "笔试-顺丰-180917\n===\n- 选择 30,编程 2\n\n\nIndex\n---\n<!-- TOC -->\n\n- [编辑距离](#编辑距离)\n- [分发糖果](#分发糖果)\n\n<!-- /TOC -->\n\n## 编辑距离\n> LeetCo"
},
{
"path": "Jobs.md",
"chars": 11032,
"preview": "**RoadMap**\n---\n<!-- TOC -->\n\n- [机器学习/AI/算法](#机器学习ai算法)\n - [网易游戏-智能运维算法工程师](#网易游戏-智能运维算法工程师)\n - [远景-算法工程师-最优化/深度学习(上海)"
},
{
"path": "README.md",
"chars": 4045,
"preview": "算法/深度学习/NLP面试笔记\n===\n**GitHub** 地址:https://github.com/imhuay/Algorithm_Interview_Notes-Chinese\n\nRoadMap\n---\n\n<!-- | A | B"
},
{
"path": "ToDo.md",
"chars": 2929,
"preview": "Updates Log\n===\n\n## ToDo\n- Tensorflow - char embedding layer\n- Tensorflow - Pointer Layer\n- 机器学习 - 专题-XGBoost\n- 深度学习 - G"
},
{
"path": "_codes/README.md",
"chars": 0,
"preview": ""
},
{
"path": "_codes/cpp/面向对象-不通过继承实现多态-动态序列.cpp",
"chars": 1416,
"preview": "#include <iostream>\nusing namespace std;\n\nclass num_sequence {\npublic:\n // PtrType 是一个指针,指向 num_sequence 的成员函数,\n /"
},
{
"path": "_codes/machine_learning/KMeans/data.txt",
"chars": 1520,
"preview": "1.658985\t4.285136\n-3.453687\t3.424321\n4.838138\t-1.151539\n-5.379713\t-3.362104\n0.972564\t2.924086\n-3.567919\t1.531611\n0.45061"
},
{
"path": "_codes/machine_learning/KMeans/kmeans.py",
"chars": 2301,
"preview": "\"\"\"\nK-Means\n\"\"\"\nimport logging as log\nimport numpy as np\nimport random\n\nlog.basicConfig(format=\"%(message)s\", level=log."
},
{
"path": "_codes/model/倒排索引/data/a.txt",
"chars": 15,
"preview": "a b cb,f h f ds"
},
{
"path": "_codes/model/倒排索引/data/b.txt",
"chars": 10,
"preview": "html a b c"
},
{
"path": "_codes/model/倒排索引/data/c.txt",
"chars": 10,
"preview": "abc h html"
},
{
"path": "_codes/model/倒排索引/inverse_index.py",
"chars": 3187,
"preview": "\"\"\"\n倒排索引\n\n没有任何优化,只是展示一下什么是“倒排索引”\n\"\"\"\n\nimport os\n\nfrom itertools import combinations\n\nfrom nltk.tokenize import RegexpTok"
},
{
"path": "_codes/my_nlp/data/sentences.txt",
"chars": 67,
"preview": "this is an example sentence\nthis is another sentence that is longer"
},
{
"path": "_codes/my_nlp/data/vocab.txt",
"chars": 64,
"preview": "this 2\nis 3\nan 1\nexample 1\nsentence 2\nanother 1\nthat 1\nlonger 1\n"
},
{
"path": "_codes/my_nlp/data/wv.txt",
"chars": 1873,
"preview": "UNK 0.47473686064391796 0.2551379454015914 -0.09549180462608997 0.3525185101533437 -0.38921288549115596 0.09504760365238"
},
{
"path": "_codes/my_nlp/src/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "_codes/my_nlp/src/sentence2vec/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "_codes/my_nlp/src/sentence2vec/sif.py",
"chars": 161,
"preview": "\"\"\"\nSmooth Inverse Frequency(SIF)\n\nReferences:\n A Simple but Tough-to-Beat Baseline for Sentence Embeddings, 2016\n "
},
{
"path": "_codes/my_nlp/src/utils/__init__.py",
"chars": 51,
"preview": "\"\"\"\n\n\"\"\"\n\n\ndef get_w2v(file_path):\n \"\"\"提取词向量\"\"\"\n"
},
{
"path": "_codes/my_nlp/src/utils/vocab.py",
"chars": 208,
"preview": "\"\"\"\"\"\"\n\n\ndef set_vocab(sentences, save_path=None):\n \"\"\"\"\"\"\n\n if save_path is not None:\n with open(save_path"
},
{
"path": "_codes/my_tensorflow/README.md",
"chars": 96,
"preview": "my_tensorflow\n===\n\nRequirements\n---\n- Tensorflow 1.0+ (1.8)\n\nReference\n---\n- Keras\n- TensorLayer"
},
{
"path": "_codes/my_tensorflow/src/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "_codes/my_tensorflow/src/activations/__init__.py",
"chars": 1247,
"preview": "\"\"\"激活函数\"\"\"\n\nfrom .relu import *\n\n\ndef linear(x):\n \"\"\"\"\"\"\n return x\n\n\ndef identity(x):\n \"\"\"\"\"\"\n return tf.ide"
},
{
"path": "_codes/my_tensorflow/src/activations/relu.py",
"chars": 1207,
"preview": "\"\"\"ReLU 系列激活函数\"\"\"\nimport tensorflow as tf\n\nfrom ..utils import get_w, get_shape\nfrom ..initializers import constant\n\n\nde"
},
{
"path": "_codes/my_tensorflow/src/initializers/__init__.py",
"chars": 302,
"preview": "\"\"\"变量初始化器\"\"\"\n\nimport tensorflow as tf\n\n\n'''常用的 Tensorflow 基本初始化器'''\n# 零\nzeros = tf.initializers.zeros\n# 常量\nconstant = tf"
},
{
"path": "_codes/my_tensorflow/src/layers/__init__.py",
"chars": 129,
"preview": "\"\"\"常见层与常用层的写法\n\"\"\"\n\nfrom .dense import *\nfrom .cnn import *\nfrom .highway import *\nfrom .attention import *\nfrom .match i"
},
{
"path": "_codes/my_tensorflow/src/layers/attention.py",
"chars": 3336,
"preview": "\"\"\"Attention 层\n\n作用与 highway 类似\n经过 Attention 层后维度应该保持一致\n\nReferences:\n https://github.com/philipperemy/keras-attention-"
},
{
"path": "_codes/my_tensorflow/src/layers/cnn.py",
"chars": 1295,
"preview": "\"\"\"卷积层\n\nReferences:\n tensorlayer.layers.Conv2dLayer\n\"\"\"\nimport tensorflow as tf\n\nfrom ..activations import relu\nfrom "
},
{
"path": "_codes/my_tensorflow/src/layers/dense.py",
"chars": 2257,
"preview": "\"\"\"\n全连接层\n\nReferences:\n tensorlayer.layers.DenseLayer\n keras.layers.Dense\n\"\"\"\nimport tensorflow as tf\n\nfrom ..utils"
},
{
"path": "_codes/my_tensorflow/src/layers/embedding/__init__.py",
"chars": 31,
"preview": "\"\"\"\"\"\"\n\nfrom .char_cnn import *"
},
{
"path": "_codes/my_tensorflow/src/layers/embedding/char_cnn.py",
"chars": 835,
"preview": "\"\"\"CharCNN Embedding Layer\n\nReferences:\n [1509.01626] Character-level Convolutional Networks for Text Classification "
},
{
"path": "_codes/my_tensorflow/src/layers/highway.py",
"chars": 3188,
"preview": "\"\"\"高速网络 Highway Network\n\n注意 x 经过 Highway 之后维度应该保持不变\n\nReferences:\n https://github.com/fomorians/highway-fcn\n https:"
},
{
"path": "_codes/my_tensorflow/src/layers/match/__init__.py",
"chars": 41,
"preview": "\"\"\"匹配层\"\"\"\n\nfrom .attention_flow import *\n"
},
{
"path": "_codes/my_tensorflow/src/layers/match/attention_flow.py",
"chars": 5780,
"preview": "\"\"\"Attention Flow 匹配层\n\nAttention flow layer is responsible for linking and fusing information from the context and the q"
},
{
"path": "_codes/my_tensorflow/src/regularizers/L1L2.py",
"chars": 1079,
"preview": "\"\"\"\nL1 和 L2 正则化\n\nReferences:\n keras.regularizers\n\"\"\"\nimport tensorflow as tf\nimport numpy as np\n\n\nclass L1L2Regulariz"
},
{
"path": "_codes/my_tensorflow/src/regularizers/__init__.py",
"chars": 164,
"preview": "\"\"\"\n正则化函数\n `Tensor -> Tensor or None`\n\nExamples:\n l2_regularizer = l2(0.01)\n tf.get_variable(..., regularizer=l"
},
{
"path": "_codes/my_tensorflow/src/utils/__init__.py",
"chars": 2481,
"preview": "\"\"\"\n工具函数\n\"\"\"\nfrom pprint import pprint\nfrom functools import reduce\nfrom operator import mul\n\nfrom .array_op import *\nfr"
},
{
"path": "_codes/my_tensorflow/src/utils/array_op.py",
"chars": 895,
"preview": "\"\"\"Tensor Transformations\n\nReferences:\n https://www.tensorflow.org/api_guides/python/array_ops\n keras.backend\n\"\"\"\n"
},
{
"path": "_codes/my_tensorflow/src/utils/math_op.py",
"chars": 773,
"preview": "\"\"\"Math\n\nReferences:\n https://www.tensorflow.org/api_guides/python/math_ops\n\"\"\"\n\nimport tensorflow as tf\n\n\ndef dot(x,"
},
{
"path": "_codes/my_tensorflow/test_layer.ipynb",
"chars": 25289,
"preview": "{\n \"cells\": [\n {\n \"cell_type\": \"code\",\n \"execution_count\": 4,\n \"metadata\": {\n \"scrolled\": true\n },\n \"outpu"
},
{
"path": "_codes/工具库/gensim/FastText.py",
"chars": 3713,
"preview": "\"\"\"\n`gensim.models.FastText` 使用示例\n\"\"\"\n# gensim 示例\nimport gensim\nimport numpy as np\nfrom gensim.test.utils import common_"
},
{
"path": "_notes/专题-Bash命令.md",
"chars": 386,
"preview": "专题-Bash命令\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [Bash 必背命令](#bash-必背命令)\n - [wc/sed/awk/grep/sort/uniq/paste/cat/head/tail](#wc"
},
{
"path": "_notes/备忘-Markdown小技巧.md",
"chars": 1950,
"preview": "备忘-Markdown小技巧\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [自动更新目录](#自动更新目录)\n- [图片居中](#图片居中)\n- [隐藏代码块](#隐藏代码块)\n- [HTML 表格](#html-表格)\n"
},
{
"path": "_notes/备忘-Python相关工具.md",
"chars": 1400,
"preview": "备忘-IPython小技巧\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [IPython](#ipython)\n - [自动重新加载模块](#自动重新加载模块)\n- [Anaconda](#anaconda)\n - ["
},
{
"path": "_notes/备忘-工具库.md",
"chars": 682,
"preview": "专题-工具库\n===\n\nIndex\n---\n<!-- TOC -->\n\n- [工具列表](#工具列表)\n- [jieba 分词](#jieba-分词)\n - [分词](#分词)\n\n<!-- /TOC -->\n\n# 工具列表\n- Stanf"
},
{
"path": "_notes/备忘-常用子函数.md",
"chars": 2587,
"preview": "**RoadMap**\n---\n<!-- TOC -->\n\n- [暴力搜索](#暴力搜索)\n - [遍历所有子集](#遍历所有子集)\n - [遍历所有正因子](#遍历所有正因子)\n- [二分查找](#二分查找)\n - [离散模板](#"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the DiHiera/Algorithm_Interview_Notes-Chinese-master GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 111 files (689.2 KB), approximately 321.7k tokens, and a symbol index with 70 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.