1. shape

简表:

名称 nn. 输入参数 输入shape 输出shape
激活函数 Relu \ * *
展平层 Flatten [start_dim=1, end_dim=-1] [batch_size, *] [batch_size, \prod *]
线性层 Linear in_features, out_features [*, in_features] [*, out_features]
互相关 Conv2d in_channels, out_channels, kernel_size [NN, in_channels, hh, w] [NN, out_channels, houth_{out}, woutw_{out}]
汇聚层 Pool2d kernel_size [NN, CC, hh, ww] [NN, CC, houth_{out}, woutw_{out}]
归一化 BatchNorm2d channels [NN, CC, HH, WW] [NN, CC, HH, WW]

表的一些约定

2. 激活函数

3. 损失函数

一般使用LL是我简化后的表达式,使用\ell是pytorch官方的表达式。

  1. CrossEntropyLoss
    L=lnextargetcCexcL = -\text{ln} \frac {e^{x_{target}}} {\sum_{c \in C} e^{x_c}}
    (x,y)=L={l1,,lN},ln=wynlogexp(xn,yn)c=1Cexp(xn,c)1{ynignoreindex}\ell(x,y)=L=\{l_1,\ldots,l_N\}^\top,\quad l_n=-w_{y_n}\log\frac{\exp(x_{n,y_n})}{\sum_{c=1}^C\exp(x_{n,c})}\cdot1\{y_n\neq\text{ignore}_\text{index}\}
y = torch.LongTensor([0])
z = torch.Tensor([[0.2, 0.1, -0.1]])
criterion = torch.nn.CrossEntropyLoss()
loss = criterion(z, y)
print(loss)  # tensor(0.9729)
p = torch.exp(z[0, y]) / torch.sum(torch.exp(z[0]))  # tensor([0.3780])
loss = -math.log(p.item())
print(loss)  # 0.9729189784937841

4. 优化器

5. 正则化

6. 批标准化

7. 经典网络

7.1 AlexNet

7.2 VGG

7.3 GoogLeNet

7.4 ResNet

7.5 DenseNet

7.6 SENet

7.7 UNet

8. 深度学习模型

8.1. MLP

Multi-Layer Perceptron多层感知机

8.2. CNN

Convolutional Neural Network卷积神经网络

8.3. RNN

Recurrent Neural Network循环神经网络

1. 基本的RNN

之前都是默认数据来自于某种分布,并且所有样本都是独立同分布的。序列信息需要RNN来处理。
对于nn元语言模型 P(xtxt1,...,x1)P(x_t\left|x_{t-1},...,x_1\right),若词表大小是V\left|V\right|,则其成本是Vn\left|V\right|^n,所以需要简化为:P(xtxt1,,x1)P(xtht1)P(x_t\left|x_{t-1},\ldots,x_1\right)\approx P(x_t\left|h_{t-1}\right),并使用ht=f(xt,ht1)h_t=f(x_t,h_{t-1})更新隐状态。
对于具体的RNN模型:
隐藏层输出HtRn×hH_t \in\mathbb{R}^{n\times h}的计算公式如下:
Ht=ϕ(XtWxh+Ht1Whh+bh){H}_t=\phi({X}_t{W}_{xh}+{H}_{t-1}{W}_{hh}+{b}_h)式中,DD是输入维度,hh是隐状态维度,nn是批量大小,tt是时间步,XtRn×DX_t \in\mathbb{R}^{n\times D}是输入,HtRn×hH_t \in\mathbb{R}^{n\times h}是隐状态,WxhRD×hW_{xh} \in\mathbb{R}^{D\times h}WhhRh×hW_{hh} \in\mathbb{R}^{h\times h}是权重,bhR1×hb_h \in\mathbb{R}^{1\times h}是偏置(求和时使用广播机制),ϕ\phi是激活函数。需要注意的是,不同时间步的权重是一样的,所以Wxh,Whh,bhW_{xh},W_{hh},b_h是共享的。
输出层的输出的计算公式如下:
Ot=HtWhq+bq{O}_t={H}_t{W}_{hq}+{b}_q式中,OtRn×qO_t \in\mathbb{R}^{n\times q}是输出,WhqRh×qW_{hq} \in\mathbb{R}^{h\times q}是权重,bqR1×qb_q \in\mathbb{R}^{1\times q}是偏置(求和时使用广播机制)。同样的,Whq,bqW_{hq},b_q是共享的。
网络结构如下:

评价语言模型的标准是困惑度(perplexity),对于一篇长度为nn的文本W=(x1,x2,,xn)W=(x_1,x_2,\ldots,x_n),困惑度的计算公式如下:
perplexity(W)=exp(1nt=1nlogP(xtxt1,,x1))\text{perplexity}(W)=\exp\left(-\frac1n\sum_{t=1}^n\log P(x_t\mid x_{t-1},\ldots,x_1)\right)当困惑度为kk时,表示有kk个等可能的词来预测下一个词。

RNN的不同变种:

2. GRU

gated recurrent unit门控循环单元

重置门RRn×hR\in \mathbb{R}^{n\times h}允许我们控制可能还想记住的过去状态的数量;更新门ZRn×hZ\in \mathbb{R}^{n\times h}将允许我们控制新状态中有多少个是旧状态的副本。简而言之:

计算公式如下:
Rt=σ(XtWxr+Ht1Whr+br)(0,1)Zt=σ(XtWxz+Ht1Whz+bz)(0,1)\begin{aligned} {R}_t&=\sigma({X}_t{W}_{xr}+{H}_{t-1}{W}_{hr}+{b}_r)\in (0,1)\\ {Z}_t&=\sigma({X}_t{W}_{xz}+{H}_{t-1}{W}_{hz}+{b}_z)\in (0,1)\end{aligned}其中,σ\sigma是sigmoid函数,Wxr,Whr,br,Wxz,Whz,bzW_{xr},W_{hr},b_r,W_{xz},W_{hz},b_z的维度是D×h,h×h,1×hD\times h,h\times h,1\times h并且参数共享。下面的H~t\tilde{H}_t公式里的W,bW,b也是如此。
候选隐状态H~tRn×h\tilde{H}_t\in \mathbb{R}^{n\times h}的计算公式如下:
H~t=tanh(XtWxh+(RtHt1)Whh+bh)(1,1)\tilde{{H}}_t=\tanh({X}_t{W}_{xh}+({R}_t\odot{H}_{t-1}){W}_{hh}+{b}_h)\in (-1,1)该式与RNN的隐状态计算公式基本一致,只是使用tanh\tanh激活函数(为了保证输出在(1,1)(-1,1)之间)并且多了一个重置门(当RtR_t接近1时与普通的RNN一致,当RtR_t接近0时会忽略掉Ht1H_{t-1})。
最终的隐状态HtRn×hH_t\in \mathbb{R}^{n\times h}的计算公式如下:
Ht=ZtHt1+(1Zt)H~tH_t=Z_t\odot{H}_{t-1}+(1-Z_t)\odot\tilde{H}_t这个式子的意思是,如果更新门ZtZ_t接近1,那么新的隐状态HtH_t就会接近于旧的隐状态Ht1H_{t-1};如果更新门ZtZ_t接近于0,那么HtH_t就会接近于候选隐状态H~t\tilde{H}_t

3. LSTM

Long Short-Term Memory长短期记忆

输入门IRn×hI\in \mathbb{R}^{n\times h}允许我们控制新输入的数量;遗忘门FRn×hF\in \mathbb{R}^{n\times h}允许我们控制过去状态的数量;输出门ORn×hO\in \mathbb{R}^{n\times h}允许我们控制输出的数量。简而言之:

计算公式如下:
It=σ(XtWxi+Ht1Whi+bi)(0,1)Ft=σ(XtWxf+Ht1Whf+bf)(0,1)Ot=σ(XtWxo+Ht1Who+bo)(0,1)\begin{aligned} {I}_t&=\sigma({X}_t{W}_{xi}+{H}_{t-1}{W}_{hi}+{b}_i)\in (0,1)\\ {F}_t&=\sigma({X}_t{W}_{xf}+{H}_{t-1}{W}_{hf}+{b}_f)\in (0,1)\\ {O}_t&=\sigma({X}_t{W}_{xo}+{H}_{t-1}{W}_{ho}+{b}_o)\in (0,1)\end{aligned}其中,σ\sigma是sigmoid函数,Wxi,Whi,bi,Wxf,Whf,bf,Wxo,Who,boW_{xi},W_{hi},b_i,W_{xf},W_{hf},b_f,W_{xo},W_{ho},b_o的维度是D×h,h×h,1×hD\times h,h\times h,1\times h并且参数共享。下面的C~t\tilde{C}_t公式里的W,bW,b也是如此。
候选记忆元C~tRn×h\tilde{C}_t\in \mathbb{R}^{n\times h}的计算公式如下:
C~t=tanh(XtWxc+Ht1Whc+bc)\tilde{{C}}_t=\tanh({X}_t{W}_{xc}+{H}_{t-1}{W}_{hc}+{b}_c)该式与RNN的隐状态计算公式基本一致,只是使用tanh\tanh激活函数(为了保证输出在(1,1)(-1,1)之间)。
记忆元CtRn×hC_t\in \mathbb{R}^{n\times h}的计算公式如下:
Ct=FtCt1+ItC~tC_t=F_t\odot{C}_{t-1}+I_t\odot\tilde{C}_t这个式子的意思是,如果遗忘门FtF_t接近1,那么新的记忆元CtC_t就会接近于旧的记忆元Ct1C_{t-1};如果遗忘门FtF_t接近于0,那么CtC_t就会接近于候选记忆元C~t\tilde{C}_t
最终的隐状态HtRn×hH_t\in \mathbb{R}^{n\times h}的计算公式如下:
Ht=Ottanh(Ct)H_t=O_t\odot\tanh(C_t)这个式子的意思是,输出门OtO_t控制着细胞状态CtC_t的信息流向隐状态HtH_t

4. 深度循环神经网络

深度循环神经网络的隐藏层输出Ht(l)Rn×h(l)H_t^{(l)}\in\mathbb{R}^{n\times h^{(l)}}的计算公式如下:
Ht(l)=ϕl(Ht(l1)Wxh(l)+Ht1(l)Whh(l)+bh(l)){H}_t^{(l)}=\phi_l({H}_t^{(l-1)}{W}_{xh}^{(l)}+{H}_{t-1}^{(l)}{W}_{hh}^{(l)}+{b}_h^{(l)})其中Ht(l)Rn×h(l)H_t^{(l)}\in\mathbb{R}^{n\times h^{(l)}}是第ll层的隐状态,Wxh(l)Rh(l1)×h(l)W_{xh}^{(l)}\in\mathbb{R}^{h^{(l-1)}\times h^{(l)}}Whh(l)Rh(l)×h(l)W_{hh}^{(l)}\in\mathbb{R}^{h^{(l)}\times h^{(l)}}是第ll层的权重,bh(l)R1×h(l)b_h^{(l)}\in\mathbb{R}^{1\times h^{(l)}}是第ll层的偏置,ϕl\phi_l是第ll层的激活函数,Ht(0)=XtRn×DH_t^{(0)}=X_t\in\mathbb{R}^{n\times D}是输入,Ht(L)Rn×h(L)H_t^{(L)}\in\mathbb{R}^{n\times h^{(L)}}是输出,LL是层数。
输出层的输出的计算公式如下:
Ot=Ht(L)Whq+bq{O}_t={H}_t^{(L)}{W}_{hq}+{b}_q其中OtRn×qO_t\in\mathbb{R}^{n\times q}是输出,WhqRh(L)×qW_{hq}\in\mathbb{R}^{h^{(L)}\times q}是权重,bqR1×qb_q\in\mathbb{R}^{1\times q}是偏置。

5. 双向循环神经网络

双向循环神经网络的隐藏层输出Ht(f)Rn×hH_t^{(f)}\in\mathbb{R}^{n\times h}(正向,也记为Ht\overrightarrow{H}_t)和Ht(b)Rn×hH_t^{(b)}\in\mathbb{R}^{n\times h}(反向,也记为Ht\overleftarrow{H}_t)的计算公式如下:
Ht=ϕ(XtWxh(f)+Ht1Whh(f)+bh(f))Ht=ϕ(XtWxh(b)+Ht+1Whh(b)+bh(b))\begin{aligned} \overrightarrow{{H}}_{t}&=\phi({X}_t{W}_{xh}^{(f)}+\overrightarrow{{H}}_{t-1}{W}_{hh}^{(f)}+{b}_h^{(f)})\\ \overleftarrow{{H}}_{t}&=\phi({X}_t{W}_{xh}^{(b)}+\overleftarrow{{H}}_{t+1}{W}_{hh}^{(b)}+{b}_h^{(b)})\end{aligned}其中W,b的shape和上面的一样,是D×h,h×h,1×hD\times h,h\times h,1\times hϕ\phi是激活函数。最终的隐状态HtRn×2hH_t\in\mathbb{R}^{n\times 2h}的计算公式如下:
Ht=[Ht,Ht]H_t=[\overrightarrow{H}_t,\overleftarrow{H}_t]输出层的输出的计算公式如下:
Ot=HtWhq+bq{O}_t={H}_t{W}_{hq}+{b}_q其中OtRn×qO_t\in\mathbb{R}^{n\times q}是输出,WhqR2h×qW_{hq}\in\mathbb{R}^{2h\times q}是权重,bqR1×qb_q\in\mathbb{R}^{1\times q}是偏置。
需要注意的是,实际使用中不一定能得到Ht\overleftarrow{H}_t,所以将不会得到很好的精度。并且训练速度很慢,梯度链过长。可以用于填充缺失的单词、词元注释等。

6. 编码器-解码器架构

输入序列X=x1,x2,...,xTX = {x_1, x_2, ..., x_T},其中 xtRdx_t \in \mathbb{R}^d 表示时间步 tt 的输入向量,dd 是输入向量的维度。
编码器将输入序列映射到隐状态序列H=h1,h2,...,hT=Encoder(X)H={h_1, h_2, ..., h_T} = \text{Encoder}(X),其中htRhh_t \in \mathbb{R}^h表示时间步tt的隐状态。
解码器接收编码器的隐状态(解码器的初始隐状态通常是编码器最后一个时间步的隐状态,也可以是全部隐状态的函数c=q(h1,...,hT)c=q(h_1,...,h_T)),并生成目标序列y1,y2,...,yT{y_1, y_2, ..., y_{T'}},其中ytRdy_t \in \mathbb{R}^d表示时间步tt的输出向量。
输出序列Y=y1,y2,...,yT=Decoder(H)Y = {y_1, y_2, ..., y_{T'}} = \text{Decoder}(H),其中TT'是输出序列的长度。
图中右侧的输入指的是解码器在每个时间步接收的前一时间步的输出yt1y_{t-1}

7. seq2seq

eos表示序列结束词元,一旦输出序列生成此词元,模型就会停止预测。
bos表示序列开始词元,它是解码器的输入序列的第一个词元。

遵循编码器-解码器架构的设计原则,循环神经网络编码器使用长度可变的序列作为输入,将其转换为固定形状的隐状态。换言之,输入序列的信息被编码到循环神经网络编码器的隐状态中。
为了连续生成输出序列的词元,独立的循环神经网络解码器是基于输入序列的编码信息和输出序列已经看见的或者生成的词元来预测下一个词元。可以使用循环神经网络编码器最终的隐状态来初始化解码器的隐状态,也可以让编码器最终的隐状态在每一个时间步都作为解码器的输入序列的一部分。

训练时解码器的输入是已知序列(强制教学teacher forcing),而预测时解码器的输入是模型生成的上一步输出。

在预测时,如果每次选择概率最大的词元,那么模型可能会陷入重复循环的输出序列中,并且贪心本来就不能保证概率最大化。为了解决这个问题,可以使用束搜索beam search,它在每个时间步都会保留kk(束宽)个当前概率最大的备选输出序列,直到生成了eos词元。贪心搜索可以束宽为1的束搜索。

8.4. 注意力机制

分为:

自主性提示被称为查询query。给定任何查询,注意力机制通过注意力汇聚attention pooling将选择引导至感官输入sensory inputs(例如中间特征表示)。在注意力机制中,这些感官输入被称为值value。更通俗的解释,每个值都与一个键key配对,这可以想象为感官输入的非自主提示:

1. 非参数注意力汇聚 Nadaraya-Watson核回归

f(x)=i=1nK(xxi)j=1nK(xxj)yi=i=1nα(x,xi)yif(x)=\sum_{i=1}^n\frac{K(x-x_i)}{\sum_{j=1}^nK(x-x_j)}y_i=\sum_{i=1}^n\alpha(x,x_i)y_i式中,KK是核函数,α\alpha是注意力权重(xxxix_i的相似度),xx是查询,(xi,yi)(x_i,y_i)是键值对。查询xx的输出是值yiy_i的加权和。
将高斯核K(u)=12πexp(u22)K(u)=\frac1{\sqrt{2\pi}}\exp(-\frac{u^2}2)代入可得:
f(x)=i=1nexp((xxi)22)j=1nexp((xxj)22)yi=i=1nsoftmax(12(xxi)2)yi\begin{aligned} f(x)&=\sum_{i=1}^n\frac{\exp(-\frac{(x-x_i)^2}2)}{\sum_{j=1}^n\exp(-\frac{(x-x_j)^2}2)}y_i\\ &=\sum_{i=1}^n\text{softmax}\left(-\frac12(x-x_i)^2\right)y_i\end{aligned}

2. 带参数注意力汇聚

以高斯核为例,带参数的注意力汇聚的计算公式如下:
f(x)=i=1nsoftmax(12((xxi)w)2)yif(x)=\sum_{i=1}^n\text{softmax}\left(-\frac12\left((x-x_i)w\right)^2\right)y_i
为了与q,k,vq,k,v对应,将其改写为:
f(q)=i=1nsoftmax(12((qki)w)2)vif(q)=\sum_{i=1}^n\text{softmax}\left(-\frac12\left((q-k_i)w\right)^2\right)v_i

3. 注意力评分函数

注意力评分函数就是计算查询和键之间的相似度的函数。比如上文的12((qki)w)2-\frac12\left((q-k_i)w\right)^2就是一个评分函数a(q,k)a(q,k)。注意力权重α\alpha是由注意力评分函数a(q,k)a(q,k)通过softmax操作得到的:
α(q,ki)=softmax(a(q,ki))=exp(a(q,ki))j=1nexp(a(q,kj))\alpha(q,k_i)=\text{softmax}(a(q,k_i))=\frac{\exp(a(q,k_i))}{\sum_{j=1}^n\exp(a(q,k_j))}
常用的评分函数有:

给定查询qRn×dqq\in\mathbb{R}^{n\times d_q}、键kRm×dkk\in\mathbb{R}^{m\times d_k}和值vRm×dvv\in\mathbb{R}^{m\times d_v},输出oRn×doo\in\mathbb{R}^{n\times d_o}的计算公式如下:
o=softmax(qkdk)vo=\text{softmax}\left(\frac{qk^\top}{\sqrt{d_k}}\right)v
在多头注意力机制中,我们可以计算hh个不同的输出oio_i,并将它们连接在一起并通过另一个线性变换得到最终的输出。具体来说,给定查询qRn×dqq\in\mathbb{R}^{n\times d_q}、键kRm×dkk\in\mathbb{R}^{m\times d_k}和值vRm×dvv\in\mathbb{R}^{m\times d_v},输出oRn×h×doo\in\mathbb{R}^{n\times h\times d_o}的计算公式如下:
oi=softmax(qWiQ(kWiK)dk)WiVo_i=\text{softmax}\left(\frac{qW_i^Q(kW_i^K)^\top}{\sqrt{d_k}}\right)W_i^V
其中WiQRdq×dk,WiKRdq×dk,WiVRdq×dvW_i^Q\in\mathbb{R}^{d_q\times d_k},W_i^K\in\mathbb{R}^{d_q\times d_k},W_i^V\in\mathbb{R}^{d_q\times d_v}是第ii个注意力头的权重参数。最终的输出oRn×h×doo\in\mathbb{R}^{n\times h\times d_o}hh个头的输出连接在一起并通过另一个线性变换得到的。

9. 我的一些想法

1. 象形字->embedding

使用汉字的象形字图片转化为其embedding。