深度学习是机器学习的一个子领域,深度学习通过神经网络模拟人脑神经元的连接来进行复杂数据的学习与预测。其中,卷积神经网络(CNN)主要用于计算机视觉任务;循环神经网络(RNN)则适用于处理序列数据。今天介绍CV和NLP领域一些重要模型。
后台回复abh获取文中视频和原版英文。
[RNN] 手书动画 ✍️
0. 初始化
输入序列
参数矩阵:
参数矩阵是通过训练得到的,图中虽然列了4个节点,但其实是同一个节点按照时间步展开的,这也是RNN经常被误解的地方。
RNN隐状态和输出的计算公式:
根据隐状态计算公式,当新的输入进来时,RNN不仅考虑当前的输入,还结合之前保存的隐状态来做出新的判断。隐状态在RNN中相当于记忆或上下文,它保存了从前面输入序列中学到的信息。
初始隐藏状态:
1.第一个时间步
输入
计算隐藏状态:
计算输出:
2.第一个时间步
输入
计算隐藏状态:
计算输出:
计算隐藏状态:
计算输出:
输入
计算隐藏状态:
计算输出:
[Deep RNN] 手书动画 ✍️
Deep RNN 在普通 RNN 的基础上增加了更多的层,类似MLP的多个隐藏层,每一层可以提取更加复杂和抽象的特征,通过增加层数,Deep RNN 能够更好地捕捉序列中的复杂模式和长距离依赖关系,提升处理长序列的能力。
Deep RNN是如何工作的?
[1] 给定
一个包含四个输入X1,X2,X3, X4的序列,以及通过训练得到隐藏层和输出层权重。
[2] 初始化隐藏状态
将a0, b0, c0初始化为零
— 处理X1 (t = 1)—
[3] 第一隐藏层 (a) : a0 → a1
输入权重:
隐状态权重:
偏置:
权重是通过训练过程得到的,图中四个节点其实是同一个节点按照时间展开的,所以共享同一套参数。
输入权重、隐藏状态权重和偏置的水平拼接成一个变换矩阵,视觉上表示为 [ | | ] 。
状态矩阵是输入X1、之前的隐藏状态a0和一个额外的1的垂直拼接,视觉上表示为 [ ; ; 1]。
将这两个矩阵相乘得到新的隐藏状态a1 = [0 ; 1]。
[4] 第二隐藏层 (b) : b0 → b1
第一层的a1 成为输入。
变换矩阵视觉上表示为 [ | | ]。
输入权重:
隐状态权重 :
偏置:
状态矩阵是a1, b0和1的组合,视觉上表示为 [; ; 1]。
将这两个矩阵相乘得到新的隐藏状态b1 = [1; -1]。
[5] 第三隐藏层 (c) : c0 → c1
第二层的b 成为输入。
变换矩阵视觉上表示为 [ | | ]。
输入权重:
隐状态权重 :
偏置:
状态矩阵是b1, c0和1的组合,视觉上表示为 [ ; ; 1]。
将这两个矩阵相乘得到新的隐藏状态b1 = [1; -1]。
[6] 输出层 (Y)
变换矩阵视觉上表示为 [ | ]。
状态矩阵是c1和1的组合,视觉上表示为 [; 1]。
将这两个矩阵相乘得到输出Y1 = [3; 0; 3]。
— 处理X2 (t = 2)—
[7] 之前的隐藏状态
复制a1, b1, c1的值。
[8] 隐藏 + 输出
重复步骤[3]-[6],得到输出Y2 = [5; 0; 4]
— 处理X3 (t = 3)—
[9] 之前的隐藏状态
复制a2, b2, c2的值。
[10] 隐藏 + 输出
重复步骤[3]-[6],得到输出Y3 = [13; -1; 9]
— 处理X4 (t = 4)—
[11] 之前的隐藏状态
复制a3, b3, c3的值。
[12] 隐藏 + 输出
重复步骤[3]-[6],得到输出Y4 = [15; 7; 2]
[LSTM] 手书动画 ✍️
LSTM曾经是处理长序列数据最有效的架构,直到Transformers的出现改变了这一切。
LSTM属于广义的循环神经网络(RNN)家族,以循环的方式顺序处理数据。
另一方面,Transformers放弃了循环,转而使用自注意力机制,以并行的方式同时处理数据。
最近,由于人们意识到自注意力在处理极长序列(如几十万的tokens)时并不具有可扩展性,因此对循环机制又重新产生了兴趣。Mamba就是一个将循环机制带回的好例子。
突然之间,研究LSTM又变得时髦了。
LSTM是如何工作的?
[1] 给定
↳ 🟨 输入序列 X1, X2, X3 (d = 3)
↳ 🟩 隐藏状态 h (d = 2)
↳ 🟦 记忆 C (d = 2)
↳ 权重矩阵 Wf, Wc, Wi, Wo
处理 t = 1
[2] 初始化
↳ 随机设置之前的隐藏状态h0为 [1, 1],记忆单元C0为 [0.3, -0.5]
[3] 线性变换
↳ 将四个权重矩阵与当前输入(X1)和之前的隐藏状态(h0)的拼接相乘。
↳ 结果是特征值,每个特征值都是当前输入和隐藏状态的线性组合。
[4] 非线性变换
↳ 应用sigmoid σ来获得门控值(在0到1之间)。
• 遗忘门 (f1): [-4, -6] → [0, 0]
• 输入门 (i1): [6, 4] → [1, 1]
• 输出门 (o1): [4, -5] → [1, 0]
↳ 应用tanh来获得候选记忆值(在-1到1之间)
• 候选记忆 (C’1): [1, -6] → [0.8, -1]
[5] 更新记忆
↳ 遗忘 (C0 .* f1): 逐元素地将当前记忆与遗忘门值相乘。
↳ 输入 (C’1 .* o1): 逐元素地将“候选”记忆与输入门值相乘。
↳ 通过将上述两项相加来更新记忆到C1:C0 .* f1 + C’1 .* o1 = C1
[6] 候选输出
↳ 对新的记忆C1应用tanh获得候选输出o’1。
[0.8, -1] → [0.7, -0.8]
[7] 更新隐藏状态
↳ 输出 (o’1 .* o1 → h1): 逐元素地将候选输出与输出门相乘。
↳ 结果是更新后的隐藏状态h1
↳ 同时,这也是第一次输出。
处理 t = 2
[8] 初始化
↳ 复制之前的隐藏状态h1和记忆C1
[9] 线性变换
↳ 重复步骤[3]
[10] 更新记忆 (C2)
↳ 重复步骤[4]和[5]
[11] 更新隐藏状态 (h2)
↳ 重复步骤[6]和[7]
处理 t = 3
[12] 初始化
↳ 复制之前的隐藏状态h2和记忆C2
[13] 线性变换
↳ 重复步骤[3]
[14] 更新记忆 (C3)
↳ 重复步骤[4]和[5]
[15] 更新隐藏状态 (h3)
↳ 重复步骤[6]和[7]
[U-Net] 手书动画 ✍️
[Graphic Convolutional Network] 手书动画✍️
-- 𝗚𝗼𝗮𝗹 目标 --
预测图中节点是否为 X。
[1] 给定
↳ 一个包含五个节点 A、B、C、D、E 的图
[2] 🟩 邻接矩阵:邻居
↳ 为每条边的邻居加 1
↳ 在两个方向上重复(例如,A->C,C->A)
↳ 对两个 GCN 层重复此操作
[3] 🟩 邻接矩阵:自环
↳ 为每个自环添加 1
↳ 等同于添加单位矩阵
↳ 对两个 GCN 层重复此操作
[4] 🟪 GCN1:信息传递
↳ 将节点嵌入 🟨 与权重和偏置相乘
↳ 应用 ReLU(负值 → 0)
↳ 结果是每个节点的一条信息
[5] 🟪 GCN1:池化
↳ 将信息与邻接矩阵相乘
↳ 目的是从每个节点的邻居以及节点本身汇集信息。
↳ 结果是每个节点的新特征
[6] 🟪 GCN1:可视化
↳ 对于节点 1,可视化如何汇集信息以获得新特征以便更好地理解
↳ [3,0,1] + [1,0,0] = [4,0,1]
[7] 🟪 GCN2:信息传递
↳ 将节点特征与权重和偏置相乘
↳ 应用 ReLU(负值 → 0)
↳ 结果是每个节点的一条信息
[8] 🟪 GCN2:池化
↳ 将信息与邻接矩阵相乘
↳ 结果是每个节点的新特征
[9] 🟪 GCN2:可视化
↳ 对于节点 3,可视化如何汇集信息以获得新特征以便更好地理解
↳ [1,2,4] + [1,3,5] + [0,0,1] = [2,5,10]
[10] 🟦 FCN:线性 1 + ReLU
↳ 将节点特征与权重和偏置相乘
↳ 应用 ReLU(负值 → 0)
↳ 结果是每个节点的新特征
↳ 与 GCN 层不同,不包含来自其他节点的信息。
[11] 🟦 FCN:线性 2
↳ 将节点特征与权重和偏置相乘
[12] 🟦 FCN:Sigmoid
↳ 应用 Sigmoid 激活函数
↳ 目的是为每个节点获得一个概率值
↳ 一种手动计算 Sigmoid ✍️ 的方法是使用以下近似值:
• >= 3 → 1
• 0 → 0.5
• <= -3 → 0
-- 𝗢𝘂𝘁𝗽𝘂𝘁𝘀 输出 --
A:0(非常不可能)
B:1(非常可能)
C:1(非常可能)
D:1(非常可能)
E:0.5(中立)