查看全课大纲(第 80 / 82 节)
- 1.函数与数据泛化
- 2.向量:从几何直觉到高维空间
- 3.矩阵与张量
- 4.特征值与特征向量:矩阵变换的不动方向
- 5.凸函数:从向量求导的矩阵记号到好优化的函数形状
- 6.概率与统计:机器学习的数学基础
- 7.独立性与随机变量:贝叶斯公式与二项分布
- 8.期望、方差与协方差:随机变量的数字画像
- 9.联合概率:当一条轴不够用的时候
- 10.概率分布(一):从伯努利到伽马函数
- 11.概率分布(二):贝塔、泊松、正态与两个贝叶斯故事
- 12.机器学习的模型:找输入与输出的关系
- 13.机器学习的应用
- 14.过拟合
- 15.机器学习的分类
- 16.有监督学习:从房价预测说起
- 17.损失函数
- 18.梯度下降(上):更新规则与学习速率
- 19.梯度下降(2)
- 20.牛顿方法
- 21.KNN简介
- 22.距离测算
- 23.朴素贝叶斯
- 24.朴素贝叶斯的实际应用
- 25.信息熵:决策树构建的度量基础
- 26.信息增益与决策树的构建
- 27.ID3算法
- 28.决策树节点的划分
- 29.CART树
- 30.Bagging
- 31.Boosting:自适应提升算法
- 32.Gradient Boosting
- 33.线性模型:回归与分类的同一副骨架
- 34.最小二乘:把最优参数直接解出来
- 35.最小二乘法的几何与概率视角
- 36.极大似然:给最小二乘一个概率出身
- 37.逻辑回归(1):把线性模型接到分类上
- 38.逻辑回归(2):损失函数与多分类
- 39.---- 手造数据: 5 个样本, 2 个特征; x2 几乎 = 2*x1 (偏差手工指定, 无随机) ----
- 40.讲师例: 向量 "23014" -- 三把范数尺子量同一个向量
- 41.优化方法(1):坐标下降与前向选择
- 42.优化方法(2):前向策略与最小角回归
- 43.拉格朗日乘子法(1):从无约束到等式约束
- 44.拉格朗日乘子法(2):等式约束下的平行条件与拉格朗日函数
- 45.拉格朗日乘子法(3):不等式约束与 KKT 条件
- 46.最大间隔:把分类问题变成优化问题
- 47.拉格朗日对偶问题:把 w 和 b 全部换成 α
- 48.支持向量:边界上的少数派
- 49.SVM 计算过程:一笔到底算完,再走进核方法
- 50.贝叶斯公式:概率即信念
- 51.隐含变量和概率模型:给看不见的原因建模
- 52.EM 算法:期望与最大化的迭代
- 53.琴生不等式:EM 的数学钥匙
- 54.三个硬币问题:EM 的复盘与衔接
- 55.高斯混合模型:用隐变量解释双峰数据
- 56.隐马尔可夫模型
- 57.隐马尔可夫模型(2):前向算法与动态混合模型
- 58.隐马尔可夫模型在 NLP 中的运用
- 59.EM 算法:把「为什么收敛」推到底
- 60.HMM 在 NLP 中的运用:从分词到机器翻译
- 61.HMM 参数估计:Baum-Welch 的三块拉格朗日
- 62.高维下的高斯模型
- 63.主题模型:从词袋到隐含主题
- 64.Dirichlet 分布(1)
- 65.Dirichlet 分布(2)
- 66.统计学习内容回顾
- 67.K-means 算法
- 68.PCA 降维
- 69.SVD 降维
- 70.从聚类到流形
- 71.局部线性嵌入
- 72.随机邻域嵌入:SNE 与 t-SNE
- 73.无参模型:让数据自己说话
- 74.高斯过程:函数空间里的正态分布
- 75.高斯过程(2):噪声、正则化与核的线性组合
- 76.神经网络简介:从感知器到自编码器
- 77.反向传播:把误差一层层传回去
- 78.卷积神经网络(CNN):让特征自己学出来
- 79.循环神经网络(RNN):给网络装上记忆
- 80.深度学习回顾:静态一类,动态一类
- 81.增强学习(1):蒙特卡洛、树搜索与 Q-learning
- 82.强化学习(2):从乌鸦吃核桃到井字棋的 value 回传
深度学习回顾:静态一类,动态一类
约 36 分钟
小象实战讲义 · 机器学习算法精讲
这一节是深度学习的收官回顾。先把最基础的神经网络再压一遍——它是万能的函数模拟逼近器;然后换一个新角度复习隐马尔可夫链——把它看成一个动态的混合模型,再看 RNN 怎么从它过渡出来:状态转移和释放矩阵不再用概率,而是用神经网络来实现。中间补两件上次没展开的事:Elman 与 Jordan 两种结构的 trade-off、矩阵尺寸到底怎么数。LSTM 这边只抓定性——细胞状态这条传送带能不能跳过节点,决定了 long term 还是 short term。最后收束成本节的总纲:深度学习的模型,无外乎静态一类(网络结构上层层考虑)、动态一类(时间上考虑关系);并给下一个大题「增强学习」开一个头。
💡 核心导读
- 先收底:普通前馈神经网络 = 线性关系加非线性激活,交替堆叠;初级深度学习常用两大类——CNN 与 RNN。
- HMM 的新视角:隐马尔可夫链本身是一个动态的混合模型——状态间按转移矩阵跳转、每个状态下按高斯采样释放观测。
- RNN 的本质:还是那个普通神经网络(结构、权重跨时态共享),特殊只在一处——隐层与上一时刻的隐层直连。
- Elman vs Jordan:传「第一手的隐层信息」还是传「经输出层加工后的宏观组合」,各有得失。
- LSTM 定性版:C 是传送带;保留得住就跳过节点(long term dependency),被更新掉就只剩短期。
- 收束与开题:静态/动态两大类;增强学习处在监督与非监督之间,学习方式最接近人类。
先收个底:神经网络与深度学习的两大类
上次课讲了最基础的神经网络。讲师先定调:Deep Learning 本身是一个完全新的东西、一个很大的单独领域——所以我们不讲那么多;但神经网络作为机器学习的一个简单模型、作为一种非线性函数的逼近,这一点大家要清楚。
一个普通的前馈神经网络:由最开始的线性关系,加上非线性激活函数组成;激活之后的数值,又可以作为下一轮的输入——再经过线性关系、再过非线性激活,变成新的输入转输出,输入再变下一层的输出。这种循环不断的关系,就是基本的神经网络。深度学习里边常用的,简单讲有两大类:初级的深度学习,主要就是 Convolutional(CNN,卷积神经网络) 和 RNN(recurrent neural networks,循环神经网络——有的时候也叫「递归神经网络」)。在普通网络里如果有局部连接、权重共享、用里边算卷积,那就是 ConvNet;今天要复习的,是另一个。
换个角度复习 HMM:动态的混合模型
讲师给的复习角度很妙:隐马尔可夫链,你甚至可以看成一个动态的混合模型。如果大家对以前学的还有印象——我们有三个状态,每一个状态沿时间有马尔可夫的特性,而每一个状态会对应一个可被观察到的输出。状态记作 ,输出记作 。如果状态是有限个数——比如天气只有晴天、雨天——那状态转移就是一个 2×2 的矩阵。
把生成过程慢动作走一遍:最开始先选定一个状态(比如 ),下一次它可以迁移到 、也可以迁移到 、也可以保持自己——这就是状态转移矩阵(transitional probability)。假设每个状态上挂一个高斯分布: 的分布里采样一个点,出来的就是 ;下一次若迁移到 ——另外一个高斯——再取一个点,得到 。整个生成 的过程,就是在几个状态里不断跳转,每到一个状态、就按它给定的正态分布生成一个 。状态跳转是转移矩阵;给定状态 时生成 的概率,就是释放矩阵(emission probability)。阴影部分的 是可被观察的结果, 是观察不到的隐含变量。
为什么说是「混合模型」?把这些正态分布画大一点,你会发现它们并不完全独立,而是有交叉的——这正是第 13、14 章讲过的混合模型味道;而混合成分(状态)之间随时间动态变化,所以是「动态的」混合模型。把这套采样跑成代码:
import random, math
rng = random.Random(42)
def gauss(mu, sigma):
"""Box-Muller 正态采样, 再平移缩放。"""
u1, u2 = rng.random(), rng.random()
z = math.sqrt(-2.0 * math.log(u1)) * math.cos(2 * math.pi * u2)
return mu + sigma * z
# 两个隐状态: 0=晴天, 1=雨天
states = ["晴天", "雨天"]
A = [[0.7, 0.3], # 状态转移矩阵: A[i][j] = P(S_t = j | S_{t-1} = i)
[0.4, 0.6]]
emission = [{"mu": 25.0, "sigma": 3.0}, # 释放: 每个状态挂一个高斯
{"mu": 15.0, "sigma": 3.0}]
s = 0 # 从晴天出发
path, obs = [], []
for t in range(8):
y = gauss(emission[s]["mu"], emission[s]["sigma"]) # 当前状态的高斯里采样 -> 释放观测
path.append(states[s])
obs.append(y)
r = rng.random() # 按转移矩阵跳到下一状态
s = 0 if r < A[s][0] else 1
print("HMM 生成 8 步(隐状态跳转 + 高斯释放), 晴天高斯中心 25, 雨天 15:")
for t in range(8):
print(f" t={t}: 隐状态={path[t]} 观测 y={obs[t]:6.2f}")HMM 生成 8 步(隐状态跳转 + 高斯释放), 晴天高斯中心 25, 雨天 15:
t=0: 隐状态=晴天 观测 y= 27.80
t=1: 隐状态=晴天 观测 y= 24.56
t=2: 隐状态=晴天 观测 y= 26.22
t=3: 隐状态=晴天 观测 y= 26.56
t=4: 隐状态=晴天 观测 y= 27.55
t=5: 隐状态=晴天 观测 y= 25.61
t=6: 隐状态=晴天 观测 y= 26.95
t=7: 隐状态=雨天 观测 y= 13.63看着这八行,把两套参数分开读:谁在跳——隐状态从前 7 步的晴天跳到第 8 步的雨天,走的是转移矩阵(晴天自留概率 0.7、转雨 0.3);谁在出数——每个观测都从当前状态挂的那个高斯里采出来:晴天时 都在 25 附近晃(24.56~27.80),一切到雨天, 立刻掉到 13.63(中心 15)。我们观察到的只是 这一列,状态那一列是藏在背后的。
RNN:普通神经网络的动态变形
今天的 RNN,跟这个隐马尔可夫链非常相似——甚至简单可以说,就是一个类似的模型。区别只有一句:它的状态转移、释放矩阵,都是用神经网络来实现的,不是普通的概率。如果对 Deep Learning 还有模糊的地方,从 HMM 与 RNN 的这层关系入手,就清楚了。
把结构图再走一遍。先画一个最简单的三层网络:输入节点 、隐藏节点、输出 。到下一个时态,还是这个网络——注意这不只是说结构一样(还是两节点、两节点、一节点),它们之间的权重也是一样的:这一份网络里红色的权重、绿色的权重,到了下一个时态原样沿用。再下一个时态,权重仍然一样。这一点一定要确定。
那「动态」体现在哪?在隐层。、、 这些状态之间,通过隐层连接: 这个网络的隐层,它的输入不但来源于两个输入节点,还来源于上一时刻的隐层——上一时刻隐层的输出,也接了进来当输入;这一时刻的隐层,又接着喂给下一时刻。隐层与隐层之间有一组专门的权重(板书记作 ——上一层隐层到下一层隐层,4 个): 到 用的是这四个, 到 还是这四个, 到 仍然是这四个——同样共享。因为我们手里有很多持续的数据,需要把这四个参数、连同整个给定结构的神经网络参数,根据一长串时间序列训练到收敛,让它们满足整个时间序列上的关系需求。这些 也可以看成正常被调整的权重,训练方式同样是 back propagation。
展开成那条熟悉的链: 三个时刻,隐层 (每个节点实际代表一排隐层节点,数目都一样)。矩阵尺寸具体数一遍(讲师的板书数例):隐层节点 个,那隐层之间的关系矩阵 就是 4×4;输入是 7 个节点,输入到隐层的 就是 7 进 4 出(板书记 7×4;按矩阵乘法「行乘列」写就是 4 行 7 列——行数跟着隐层数走);输出节点只有 1 个、最后得一个数,隐层到输出的 就是 4×1。如果不止一层,那就是 级联更复杂的矩阵组——但真正区分 RNN 与其他网络的,是横向的这条时间关系。跑一遍这条尺寸链:
import math
def matvec(M, v):
"""矩阵乘向量(纯列表实现)。"""
return [sum(m * x for m, x in zip(row, v)) for row in M]
def tanh_vec(v):
return [math.tanh(x) for x in v]
U = [[0.1, -0.1, 0.2, 0.05, 0.0, 0.15, -0.2], # 输入到隐层: 7 个输入进 4 个隐节点
[0.2, 0.05, -0.1, 0.1, 0.15, 0.0, 0.1],
[-0.15, 0.2, 0.05, 0.0, -0.1, 0.1, 0.2],
[0.05, -0.2, 0.1, 0.15, 0.2, -0.1, 0.0]]
W = [[0.2, -0.1, 0.05, 0.1], # 隐层到隐层(循环): 4x4
[-0.1, 0.15, 0.2, 0.0],
[0.05, 0.1, -0.2, 0.15],
[0.1, 0.0, 0.15, -0.1]]
V = [[0.3, -0.2, 0.25, 0.15]] # 隐层到输出: 4 个隐节点 -> 1 个输出
print("输入 7 个节点, 隐层 4 个, 输出 1 个:")
print(f" U(输入7->隐层4) 形状 {len(U)}x{len(U[0])}, W(隐层->隐层) {len(W)}x{len(W[0])}, V(隐层4->输出1) {len(V)}x{len(V[0])}")
S = [0.0, 0.0, 0.0, 0.0] # 初始隐藏状态
for t, x_t in enumerate([[1, 0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0]]):
S = tanh_vec([a + b for a, b in zip(matvec(U, x_t), matvec(W, S))])
o = matvec(V, S)
print(f" t={t}: S_t = [{', '.join(f'{s_:+.3f}' for s_ in S)}] -> 输出 o = {o[0]:+.4f}")输入 7 个节点, 隐层 4 个, 输出 1 个:
U(输入7->隐层4) 形状 4x7, W(隐层->隐层) 4x4, V(隐层4->输出1) 1x4
t=0: S_t = [+0.100, +0.197, -0.149, +0.050] -> 输出 o = -0.0393
t=1: S_t = [-0.102, +0.040, +0.256, -0.214] -> 输出 o = -0.0066
t=2: S_t = [+0.166, -0.033, -0.034, +0.149] -> 输出 o = +0.0698看 那一行:输入换到了第二个位置(one-hot 的 ),但 并不是 的重播——因为 把 的 ()也乘了进来; 同理,带着 的状态继续往前走。每一份网络都是同一个(权重共享),变化的信息只靠 这条线往下传——这就是「动态」的全部来源。
顺带把能力对比说透:RNN 的 capability(模型复杂度)所能处理的情况,要比 HMM 好。退一万步讲,今天用 HMM 的话,里边的这些概率完全可以用一个神经网络进行逼近——所以只要数据比较多,几乎任何以前用 HMM 做的应用,循环神经网络可能都会比 HMM 稍好一些;代价是它的计算复杂度比 HMM 大很多。以前我们曾经尝试用 HMM 做的事情,现在都可以用循环神经网络来做。
Elman 还是 Jordan:一个有意思的 trade-off
循环神经网络有两种基本结构。Elman network(Elman 最先做出来)就是刚才讲的:上一层的隐层信息,全输到目前这个隐层里。Jordan network 结构稍有变化:隐藏我们不关心——把上一时刻真正的输出 ,作为下一时刻隐藏的输入;我们关心的是「上一时刻输出」与「下一时刻隐藏」的关系,而不是「上一时刻隐层」与「这一时刻隐层」的关系。输入输出节点比较少的话,矩阵可以小一点;数目一样的话,整个矩阵数目也一样。
有意思的是这个 trade-off。用 Jordan(传 ): 是把 之间的关系考虑得更好的另一种集合——一种宏观的组合信息;用 Elman(直接传 ):隐层是第一手的信息。但一旦通过多一层网络, 之间的关系信息就丢失了。所以——想对上一时刻的信息保留更多,Elman 会好一些;更关心隐藏之间的宏观组合关系,Jordan 会好一点。谁好谁坏并不确定,可以在不同情况里去尝试,有些效果是类似的。
抓不住的 long term dependency
到这里要泼一盆冷水:跟 HMM 一样,RNN 目前的状态只跟前一时刻的隐藏相关——所以它没法讨论一类问题,叫 long term dependency(长期的关联关系)。
什么是 long term dependency?看看以前用 HMM 的那些阵地:语音识别、POS tagging(part of speech tagging,词性标注)、甚至机器翻译,以前都用隐马尔可夫链。但很多时候、尤其在机器翻译里,会有这样的问题——讲师的例子:“I grew up in France, so I speak fluent French”。这句话当然也可以是 “I grew up in China, so I speak fluent Chinese”、或者 “I grew up in UK, so I speak very good English”。对 French 这个词,真正最大的关联恰恰不是它前面一个词、两个词、三个词,而是前面很长一段时间的那个 France。这就是 long term dependency。
我们以前讲 HMM 也好、还有 N-gram model(最传统、最 classical 的自然语言处理方法,也确实很好用)也好,关键都是当前情况和前一状态之间的关系。但人说话并不只跟前一个相关——有 long term dependency、有各种变形和特例、包括语义的关联。原先的模型不够好,于是有人提出一种新的神经网络:long short term memory(LSTM)。
LSTM 定性版:一条可以跳过节点的传送带
先定性、不定量——讲师明确说:deep learning 的课程里会详细介绍,这里只简单过一遍,从定性上了解这个网络。LSTM 首先是 RNN 的一个特殊变形:它本身仍然是循环神经网络(输入、节点、隐层、输出都一样),但每个单元里边构造的关系更复杂,使整个模型的 capability 得到提升、能处理更多更复杂的情况——普通 RNN 处理不了的 long term dependency,它来想办法。
办法是在里边设置一些门(gate),由门决定:很长时间以前的信息,到现在能不能得以保留。核心是设计了一个 变量——把整个网络看成一条传送带:信息经过每一个部分的时候,决定旧 有多大程度被保留、多少要被更新。
- 如果被保留:这个时刻的 可以跳过当前节点、直接对后面产生影响——这就是 long term dependency;
- 如果 在节点处被更新掉:对当前情况而言就不存在 long term dependency。
所以 LSTM 既可 model short term、也可 model long term——是一种更自由的网络。什么时候该 long、什么时候该 short?我们不用关心:模型有了这个 capability 之后,根据训练数据调整里边这些参数,就会知道某些情况下是 long term dependency、有些时候是 short term。
具体到门(只点名最重要的):forget 门是最核心的部分——上一层的隐层和这一层的输入过一个 sigmoid,得到 0~1 的 ,可以简单当成概率。这里有个必须诚实标注的地方:讲师口播先说反了一次(「如果它是一的话, 完全消失」),随后自己更正—— 时 ,上一时刻的信息完整传送过来; 时旧信息被丢弃。以后者为准,与上一节及课件一致( 直接乘在 上:1 是完全保留、0 是完全丢弃)。input 门负责生成新的 信息,output 门给出下一时刻的输出。还有一种更省的耦合变体:把 forget 乘上一个负一、加进输入门(输入门 ),直接用 forget 门的大小对 做控制。把「跳过节点」跑出来看:
def belt(forgets, c0, c_tildes):
"""C 传送带(耦合门变体: i = 1-f): 每步 C_t = f*C_{t-1} + (1-f)*c_tilde。"""
c = c0
cs = [c]
for f, ct in zip(forgets, c_tildes):
c = f * c + (1 - f) * ct
cs.append(round(c, 4))
return cs
c0, c_tildes = 0.9, [0.05, -0.08, 0.06] # 传送带上已有重要信息(比如"France"); 新来的候选都不重要
print("初始 C=0.9(重要信息), 三个时间步的候选值都是小信息 [0.05, -0.08, 0.06]:")
print(" f=[1, 1, 1] (每步全保留, C 跳过节点):", belt([1.0, 1.0, 1.0], c0, c_tildes))
print(" f=[0, 0, 0] (每步被更新掉): ", belt([0.0, 0.0, 0.0], c0, c_tildes))
print(" f=[0.8]*3 (每步八分保留): ", belt([0.8, 0.8, 0.8], c0, c_tildes))初始 C=0.9(重要信息), 三个时间步的候选值都是小信息 [0.05, -0.08, 0.06]:
f=[1, 1, 1] (每步全保留, C 跳过节点): [0.9, 0.9, 0.9, 0.9]
f=[0, 0, 0] (每步被更新掉): [0.9, 0.05, -0.08, 0.06]
f=[0.8]*3 (每步八分保留): [0.9, 0.73, 0.568, 0.4664]第一行就是「跳过节点」:遗忘门全开, 从 0.9 原样穿过三个节点——开头写进去的 France,到第三个节点还是 0.9 的 France,这就是 long term dependency。第二行是反面:每步都被候选值顶替,传送带上只剩最新的小信息——short term。中间行更接近真实训练的常态:0.73、0.568、0.4664,每步放掉两成——信息在衰减,但三个节点之后还认得出大半;到底放多少,由训练数据把 调出来。
从 AutoEncoder 到 Seq2Seq:名字对着 pix2pix 起
再往下走一步。还记得 AutoEncoder(自动编码器):输入节点和输出节点个数一样,中间通过隐藏层做「加密」压缩。如果把 LSTM 做成这样一个有输入有输出的 AutoEncoder——输入层带时序关系(一个循环神经网络),输出层也带关系(另一个循环神经网络)——输入是一个有时间关系的序列、输出是另一个序列,这就叫 sequence to sequence model。最常用的应用之一就是机器翻译:输入 ABC 一种语言(比如中文),输出 xyz 另一种语言(比如英文)——中文里边谁在前谁在后的语法关系,是通过一个 LSTM 去做的;输出所对应的英文关系,是通过另一个 LSTM 去做的。
它起这个名字,是因为对应着 pix2pix:用卷积神经网络之间做的一个 AutoEncoder——输入一张完整的图片,经过自动编码器,输出另一张图片,靠调整输入层和输出层之间的权重,找到两张图片之间对应的复杂关系,可以做风格转移、可以做分割、可以做很多的事情。为什么图像那边可以直接卷积?因为图像的节点都是 Pixel,不存在任何时间序列的关系;而我们这边——语音、语言、视频——都存在时序关系,order matters(谁先谁后,这个顺序很重要),所以才变成 sequence to sequence 这种变形。至于 attention mechanism、用它生成诗歌和评论这些,这里就不讲那么多了——属于深度学习的内容。
一句话收束:两大类
把深度学习这块收个总。神经网络是一个万能的函数模拟逼近器;它可以按我们以前学过的、类似 HMM 的方式,把隐藏直接相连,做成一个有持续关系的新神经网络——这就是 RNN;而目前最常用的形态是 LSTM(把时序里的 long term 和 short term 的 capability 都增强),此外还有 bidirectional RNN(两个方向的 RNN)、RCNN(带时间序列的深度卷积网络)等等各种造型。深度学习今天还在蓬勃发展:你可以去设计、去构造不同的神经网络结构来满足需求——但无外乎两类:静态模型,在网络结构上一层一层考虑事情;动态模型,在时间方面考虑关系。目前来讲,可以简单地分成这两大类。
下一个大题:增强学习,开个头
最后留一小块,给下一个大题开个头。讲师翻出一份以前用的旧 PowerPoint——「给大家简单地看一下,我们并不 follow」。Reinforcement Learning(增强学习/强化学习),实际上处在以前说的监督学习和非监督学习之间。学期机器学习的时候,基本分成四大块:supervised learning、unsupervised learning、semi-supervised learning、reinforcement learning。
增强学习最近受关注特别多,主要是阿尔法狗(AlphaGo)的缘故。其实它的资历很老:十几年前讲师读书的时候,所有学机器学习的人,reinforcement learning 都是必学的一章;后来一段时间它逐渐走弱——因为大家并没有发现它里边真正好的应用。但它的学习方式,是最接近我们人的方式的——当然,它的机制比我们人的大脑简单得多得多,只是表象上有些类似。比如一个小宝宝:他做对事情的时候,家长就给他奖赏——「宝宝真乖」、给他鼓掌——他就会觉得这件事是对的;那做错了呢?下节接着讲(下一节从蒙特卡洛逼近说起)。
📝 动手练一练
- 混合模型视角:用「动态的混合模型」这个视角,说明 HMM 与 RNN 的异同;再回答:为什么讲师说「只要数据比较多,几乎任何以前用 HMM 做的应用,RNN 都可能稍好一些」?代价是什么?
👉 点击查看参考答案
相同:两者都是时序模型,都有观察不到的隐含状态层、都有可被观察的输出;HMM 里状态沿转移矩阵跳转、每状态按高斯释放观测(正文代码块 1 的两列),RNN 里隐层状态跨时刻传递、经权重映射到输出——结构上同构。
不同:HMM 的「转移」和「释放」是固定的概率矩阵;RNN 把这两件事都用神经网络实现——隐层之间的 对应状态转移、隐层到输出的 对应释放,且每个时刻还有新的 输入进来。
为什么 RNN 稍好:HMM 里的概率完全可以用一个神经网络逼近——神经网络的 capability(模型复杂度)更大,能刻画更复杂的非线性关系,所以数据充足时效果通常更好。代价:计算复杂度比 HMM 大很多。
- 衰减多快:把正文代码块 3 的传送带改成每步 、候选值可忽略(约等于 0),初始 。手算经过 3 个时间步后 还剩多少?若 呢?这两个数各对应 long / short term 的哪种倾向?
👉 点击查看参考答案
:每步砍半,——三步后只剩 ,信息迅速衰减,倾向 short term。:——三步之后还保有近 85%,信息跳过节点基本无损,倾向 long term。对照正文:forget 门就是「这条信息要在传送带上走多远」的总闸,训练数据负责把每个节点的 调到合适的位置。
本章小结
本节把深度学习收成一张地图。底座:普通前馈神经网络 = 线性关系加非线性激活的交替堆叠,一个万能的函数模拟逼近器;初级深度学习两大类——CNN 与 RNN。复习 HMM:一个动态的混合模型——状态按转移矩阵跳转、每状态挂一个高斯释放观测(代码块 1 的 8 步采样)。RNN:还是那个网络(结构、权重跨时态共享),特殊只在隐层与上一时刻隐层直连;矩阵按节点数数——输入 7、隐层 4、输出 1,对应 (7 进 4 出)、(4×4)、(4×1);capability 比 HMM 强、算得也贵。Elman vs Jordan:第一手隐层信息 vs 经输出层加工的宏观组合,各有胜负。LSTM: 传送带 + 门——保留得住就跳过节点(long term)、被更新掉就只剩短期(代码块 3),什么时候该长该短由训练数据调参数;forget 门最核心( 完全保留、 完全丢弃)。Seq2Seq:输入层一个 LSTM、输出层一个 LSTM 的 AutoEncoder,名字对着 pix2pix 起——图像无时序可直接卷积、语音语言视频 order matters。总纲:静态模型在网络结构上层层考虑、动态模型在时间上考虑关系。下一大题:增强学习——处于监督与非监督之间、机器学习四大块之一,阿尔法狗把它带回视野;它的学习方式最接近人类,下节从蒙特卡洛逼近讲起。
📋 行动清单
- 手推一遍 HMM 生成:对照代码块 1,在纸上画出两状态、两个高斯、一个 2×2 转移矩阵,口述「跳转」和「释放」各由哪个参数控制。
- 画 Elman 与 Jordan:两张结构图并排画,标出那条「往前传」的线分别从哪里出发、到哪里结束。
- 改代码做实验:把代码块 1 的转移矩阵改成雨天更常见(比如
[[0.3, 0.7], [0.6, 0.4]]),再跑,看隐状态路径和观测怎么变。 - 给应用分分类:手写数字识别、股价预测、图像风格迁移、聊天机器人、视频动作识别——各属静态类还是动态类,为什么。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载第20章课件:强化学习