讨论 2019-11-11 = # 关于Transformer的技术探讨 本次讨论的主要内容是从纯技术角度来探讨Transformer模型的性质和特点,技术角度即指不做延伸的解释和猜想,只从定义和实验出发来分析。 ## 什么是Transformer(广义) 由多层self-attention层叠加而成的模型,可以搭配全连接层,卷积层。attention机制也可以从多种实现中挑选任意一种。 ![](https://i.imgur.com/vnMGY4L.png) ## 什么是Transformer(狭义) Transformer远不止一个模型,更提出了相应的训练框架,优化方法。 ![](https://i.imgur.com/E4Gg1eB.png) ## 动机和实现的差异 Transformer主要有两个优势,一是速度快,并行度高,二是可以轻易访问相距很远的节点,解决了CNN和RNN常提到的local,non-local问题。可反观Transformer的设计,其中不乏很多“多余”之举。下面通过几个小例子来看看这些设计会否真的“多余”。 ```python= import torch import torch.nn as nn import tqdm import numpy as np BATCH_SIZE = 16 D_MODEL = 256 N_HEAD = 4 N_LAYER = 6 IN_LEN = 10 IN_DIM = 50 class Trans(nn.Module): def __init__(self): super(Trans, self).__init__() self.trans = nn.TransformerEncoder(nn.TransformerEncoderLayer(D_MODEL, N_HEAD), N_LAYER) self.in_fc = nn.Linear(IN_DIM*2, D_MODEL) self.out_fc = nn.Linear(D_MODEL, IN_DIM) def forward(self, x): h = self.in_fc(x) h = self.trans(h) y = self.out_fc(h) return y def run(model, test=False): model.train() losses = [] lr = 1e-3 optimizer = torch.optim.Adam(model.parameters(), lr=lr) with tqdm.trange(1000) as tq: for i,_ in enumerate(tq): a = torch.randn((BATCH_SIZE, IN_LEN, IN_DIM)).cuda() b = torch.randn((BATCH_SIZE, IN_LEN, IN_DIM)).cuda() tar = (a+1)**2 + b y = model(torch.cat([a,b], -1)) loss = (0.5*(y-tar)**2).mean() model.zero_grad() if not test: loss.backward() optimizer.step() tq.set_postfix({'loss':loss.item()}) losses.append(loss.item()) if test: print('AVG Loss', np.mean(losses)) if __name__ == '__main__': model = Trans() model.cuda() run(model) run(model, True) ``` |Setting|MSE| |-|-| |lr=1e-3, no warm-up| 3.37| |lr=1e-4, no warm-up| 0.56| |lr=1e-5, no warm-up| 2.31| |lr=1e-3, 1% warm-up| 0.10| |Setting|MSE| |-|-| |default| 0.097| |xavier_uniform| 0.191| |xavier_normal| 0.189| |normal 0.02| 0.66| |normal 0.002| 2.95| |normal 0.1| 3.50| |uniform +-0.05| 3.50| |uniform +-0.01| 0.424| |uniform +-0.001| 3.44| |kaiming_uniform| 3.50| |kaiming_normal| 3.50| |Setting|MSE| |-|-| |kaiming_normal 2 layer| 0.524| |kaiming_uniform 2 layer| 0.531| |xavier_uniform 2 layer| 0.124| |default 2 layer| 0.092| |uniform +-0.01 2 layer| 0.117| |Setting|MSE| |-|-| |lr=1e-3, no warm-up 2 layer| 0.086| |lr=1e-4, no warm-up 2 layer | 0.614| |Setting|MSE| |-|-| |lr=1e-3, no warm-up batch_size 64| 0.037| ## 多测试但不要放大结论 由于Transformer是一个对调参很敏感的模型,在对其改造时,通常需要一些简单的实验来验证正确性,但切不能放大在简单实验中得到的结论,很多规律都是随任务场景,数据集规模发生改变的。 ## Transformer 有什么用 机器翻译 ![](https://i.imgur.com/b2TDv9p.png) 语言模型 ![](https://i.imgur.com/09gewf1.png) BERT ![](https://i.imgur.com/dDnd8Yw.png) ## 一些常识(见板书) - Multi-Head Attention 怎么写 - Layer Norm 怎么加 - Attention Mask - FFN 是什么