本周主要进行深度学习的学习,李沐 Pytorch 入门,以及论文的阅读和参加学术会议。
学习内容
1.吴恩达深度学习 Ch1 3.1-4.8,Ch2 1.1-1.4
2.李沐 Pytorch 熟悉了矩阵的处理,比如 reshape 等方法
3.论文
4.第四届 SLAM 技术论坛
学习时间
2023.7.15 — 2023.7.23
学习笔记
1.深度学习
3.1 神经网络概览(Neural Network Overview)
使用 方括号 来表示当前是哪一层。
其中的每一个节点都可以由 sigmoid 函数构成。
包括正向与反向传播,计算出相关的导数。
3.2 神经网络的表示(Neural Network Representation)
一个神经网络会分为好几层,一般输入数据的层为输入层(Input Layer),中间的是隐藏层(Hidden Layer),因为数值不可见。最后一层是输出层(Output Layer)。在神经网络中,输入层一般不算在内,称下图神经网络为两层(当然,也可以把 Input Layer 称为第 0 层)。
我们用 a 来表示神经网络的 Layer,a 表示激活的意思,意味着网络中不同层的值会传递到它们后面的层中,superscript square bracket 表示当前是第几层,subscript 表示本层的第几个单元。
a 会代表几个参数之间的运算,这些参数 w,b 也都是矩阵。Hidden Layer 的 w 是 4x3 的,因为有 4 个节点所以有 4 行,而输入是 3x1,相乘会得到 4x1,因此 Hidden Layer 的 b 也是 4x1,而 Output Layer 是 1x1,因此 w 是 1x4,b 是 1x1。
3.3 计算神经网络的输出(Computing a Neural Network’s Output)
左侧为输入样本的数量,实际上就是一个 n 维的列向量,得到的 a^{[1]} 将被用在下一层的运算,即 1x4 的矩阵 w^{[2]} 与 a^{[1]} 相乘,然后 +b^{[2]} 得到 a^{[2]},即 yhat。
其实一次迭代就是运行以下 4 行计算:
z
[
1
]
=
W
[
1
]
⋅
a
[
0
]
+
b
[
1
]
a
[
1
]
=
σ
(
z
[
1
]
)
z
[
2
]
=
W
[
2
]
⋅
a
[
1
]
+
b
[
2
]
a
[
2
]
=
σ
(
z
[
2
]
)
z^{[1]}=W^{[1]}\cdot a^{[0]}+b^{[1]}\\ a^{[1]}=\sigma(z^{[1]})\\ z^{[2]}=W^{[2]}\cdot a^{[1]}+b^{[2]}\\ a^{[2]}=\sigma(z^{[2]})
z[1]=W[1]⋅a[0]+b[1]a[1]=σ(z[1])z[2]=W[2]⋅a[1]+b[2]a[2]=σ(z[2])
3.4 多样本向量化(Vectorizing across multiple examples)
对于多个样本,如何去掉 for-loop?实际上很简单,就像上一章逻辑回归向量化中的一样,直接把所有样本水平拼凑为一个新的矩阵,这个矩阵按照向量化的方式去计算即可。
水平方向上,对应不同的样本,竖直方向上,对应不同的 hidden unit
3.5 向量化实现的解释(Justification for vectorized implementation)
其实就是矩阵乘法
感悟:线性代数和高等数学真的是深度学习的基础,从反向传播到向量化,已经体现出了这些在深度学习中的运用,我对深度学习的内容真的感觉到了兴奋不已,沉醉其中。
3.6 激活函数(Activation functions)
tanh 即双曲正切函数,可以替代 sigmoid 函数,且在所有场合都优于它。因为其均值接近 0 而不是 0.5。除非要输出的结果需要位于 0 到 1 之间,这种情况下才在最后一层(Output Layer)上使用 sigmoid 函数。
此外,当上述两个函数的值非常大的时候,斜率会很小,不利于使用梯度下降法,因此可以使用线性修正单元,即 ReLu 函数来作为激活函数使用。速度会比较快,因为其斜率恒定。
Leaky ReLu 是 ReLu 的强化版本,在函数为负值时也可以进行迭代,这个斜率的值可以由自己来定,一般设为 0.01。
当不确定哪个激活函数更好时,可以都试试,来得出结果并分析原因。
3.7 为什么需要非线性激活函数(why need a nonlinear activation function)
如下图右边的计算,如果在隐藏层中使用线性激活函数,那么得到的结果仍然是通过线性计算出来的。即图中的 w’ 和 b‘。相当于只使用了一次,那么中间的隐藏层将变得没有意义。
3.8 激活函数的导数
简单的导数问题,这里就涉及到了求导的内容。
可以看到 sigmoid 函数的斜率始终不如 tanh,即使在 x=0 的位置上,斜率也比 sigmoid 大。
3.9 神经网络的梯度下降(Gradient descent for neural networks)
下图说明了正向传播中矩阵的维度,以及梯度下降法的实现。
右侧是反向传播的实现代码,就是各种求导与求偏导
3.10 直观理解反向传播(Backpropagation intuition)
链导法的反向求导,需要注意的还有两点:
写代码的时候要清楚的知道矩阵的规模,方便进行调整。
一下所有矩阵与他的导数,规模一定相同。
下图为代码实现,为什么 db 要累加?因为与 1/m 相乘求平均值
3.11 随机初始化(Random Initialization)
如果把矩阵 W 初始化为 0,那么会导致其导数相同,在迭代中,两个神经元做着相同的计算,导致每一行都一样,失去了训练的意义。
而 b 不存在这样的问题,因为只要 W 是非 0 的,那么 Z 的每一行也都不一致,不影响 b 的迭代计算。
解决的方式是随机初始化矩阵 W,用 np.random.randn((2,2))*0.01 来初始化(乘 0.01 是为了让斜率更大,易于梯度下降)。
4.1 深层神经网络(Deep Neural Networks)
神经网络的层数:不算 Input Layer,只算 Hidden Layer 和 Output Layer 的数量。
下图为神经网络中的一些符号定义。
n 表示当前层神经元的数量,a 表示经过激活函数得到的值(也是传给下层的值),w 和 b 表示计算 z 时的权重。
4.2 前向传播与反向传播(Forward and Backward Propagation)
前向传播中,输入是 a^{[l-1]},输出是 a^{[l]},缓存为 z^{[l]},w 和 b 也可以缓存,更容易在不同环节调用函数。
反向传播主要计算 dz,dw,db,da(-1),就能够实现反向传播,核心是函数的求导。
4.3 深层网络中的前向传播(Forward propagation in a Deep Network)
在本节中,正向传播中的层数是需要 for-loop 的,并且不能省略。实际上,深层网络的前向传播就是在多次迭代中实现的。
4.4 核对矩阵的维数(Getting your Matrix dimension right)
以下为一些比较重要的矩阵维数。合成大矩阵后,把其中的 1 换为 m。
这些维度都可以一步一步通过神经网络推出来。
4.5 为什么使用深层表示?(Why deep representations)
深度网络解决问题时,都是从局部到整体。比如图片,他会先检测一些边缘或特征,然后逐渐放大。
音频也是同理,先是一些简单的音频波形,比如音调是高了还是低了,分辨白噪音。然后探测音位(词汇发音时,比如,‘cat’ 这个单词,c 的 ‘‘磕’’ 就是一个音位),有了单词以后组成句子,这样一步一步识别。
深层的网络中,隐藏层多,每层的隐藏单元少,如果减少隐藏层数可能导致每层单元数量呈指数增长。
当遇到新的问题时,建议把神经网络的层数作为超参数来进行调试,找到合适的深度。
4.6 搭建神经网络块(Building blocks of deep neural networks)
正向传播中,每层输入后得到 z 要进行 cache,因为在反向传播中会用于计算,下图为正向与反向的输入输出,以及一些相关的参数。w 和 b 会被更新。在更新后,一次迭代就完毕。
4.7 参数 VS 超参数(Parameters vs Hyperparameters)
如我们的例子, w 和 b 属于参数。
而学习率 alpha,hidden layer 的层数,神经元的个数等属于超参数。
在取得结果的过程中,我们可以反复尝试以获得最佳的结果,但是这些结果可能会变,因为 CPU,GPU,数据集等外部因素在不断变化。每隔一段时间,最佳结果可能就会改变。
感悟:实际上就是锻炼一种直觉,我“觉得”这个值会很好,然后再去找原因。
1.1 训练,验证,测试集(Train/Dev/Test sets)
训练集用于训练,验证集用于迭代,测试集用于评估。
在训练中,尽量保证数据集同源。(比如拍摄设备相同,图片质量类似等)
在某些情况下,可以不要测试集。
1.2 偏差,方差(Bias/Variance)
Bias: 指的是对于基准错误率而言,越接近,偏差越小。
Variance: 当训练集上的错误率远小于验证集时,方差越大。
1.3 机器学习基础(Basic Recipe for Machine Learning)
算法偏差高——评估训练集的性能——选择新的网络(更多隐藏层或隐藏单元)——改进优化算法
方差高——加数据量,或正则化来减少过拟合
1.4 正则化(Regularization)
如何解决高方差的问题?一个是准备更多数据,还有一个是正则化。
正则化的实现如下:将成本函数 J 加一截,本质是让损失函数的权重降低。
多加的这一项的 w 平方部分,是 Frobenius 范数,指的是该矩阵中所有元素的平方和。(为什么不用 b?答:w 是高维参数矢量,已经可以表达高偏差的问题)这种方法被称为 L2 正则化。如果用 L1 正则化,最后的 w 会是稀疏的。
使用该范数实现梯度下降时,在原先的 dW 的基础上加上一项,使 wL 项的系数小于 1(即 1 - αλ/m),因此 L2 正则化也被称为权重衰减。
J
(
w
,
b
)
=
1
m
∑
i
=
1
m
L
(
y
^
(
i
)
,
y
(
i
)
)
+
λ
2
m
∑
l
=
1
L
∣
∣
w
[
l
]
∣
∣
F
2
d
w
[
l
]
=
f
r
o
m
b
a
c
k
p
r
o
p
+
λ
m
⋅
w
[
l
]
w
[
l
]
=
w
[
l
]
−
α
⋅
d
w
[
l
]
J(w,b)=\frac{1}{m}\sum^{m}_{i=1}L(\hat{y}^{(i)},y^{(i)})+\frac{\lambda}{2m}\sum^{L}_{l=1}||w^{[l]}||^{2}_{F}\\ dw^{[l]}=from\ backprop+\frac{\lambda}{m}\cdot w^{[l]}\\ w^{[l]}=w^{[l]}-\alpha\cdot dw^{[l]}
J(w,b)=m1i=1∑mL(y^(i),y(i))+2mλl=1∑L∣∣w[l]∣∣F2dw[l]=from backprop+mλ⋅w[l]w[l]=w[l]−α⋅dw[l]
2.SLAM 论坛
本次参会收获颇丰。具体如下:
1.了解到了很多的专业术语,或者是一些关键词。就像李沐所说的,很多时候学习无法开始就是因为不了解该领域的某些专业术语。包括但不限于:MLP;各种 NeRF 和 SLAM 的算法,例如 SC-NeRF,ORB-SLAM3;以及一些数据集:LLFF,Tanks and Temple,ScanNet,TUM,EuRo,RGB-D,Oxford Robotcar,NCLT。
2.除了 SLAM 以外,对于点云也有一些收获。比如王程博士的激光雷达三维重建,完成了激光雷达在城市中的定位,了解到网络结构:输入—— Encoder —— Memory Function ——输出;还有周晓巍博士提及的 LoFTR,SIFT 等;以及高翔博士一文中提到的使用 **DR 对激光点云去畸变…**这些内容与我正在做的非常符合。除此之外,虽然可能听不懂教授们实现的细节,但是能大概明白是在做什么。
3.本次会议中,有时能在 PPT 上看到一些实现的细节,例如:在 Loss 的构造中,我发现大家都喜欢选择使用 Frobenious 范数;还有 Siamese 架构;让我在会议当中能够看到自己刚刚学习的知识,这是让人无比兴奋的。
4.经过这次会议,我不敢说我提升多么多么大,但是至少,我能够更加清晰的看到自己正在前进的方向。
激光雷达三维重建,完成了激光雷达在城市中的定位,了解到网络结构:输入—— Encoder —— Memory Function ——输出;还有周晓巍博士提及的 LoFTR,SIFT 等;以及高翔博士一文中提到的使用 **DR 对激光点云去畸变…**这些内容与我正在做的非常符合。除此之外,虽然可能听不懂教授们实现的细节,但是能大概明白是在做什么。
3.本次会议中,有时能在 PPT 上看到一些实现的细节,例如:在 Loss 的构造中,我发现大家都喜欢选择使用 Frobenious 范数;还有 Siamese 架构;让我在会议当中能够看到自己刚刚学习的知识,这是让人无比兴奋的。
4.经过这次会议,我不敢说我提升多么多么大,但是至少,我能够更加清晰的看到自己正在前进的方向。