讨论 2019-11-11
=
# 关于Transformer的技术探讨
本次讨论的主要内容是从纯技术角度来探讨Transformer模型的性质和特点,技术角度即指不做延伸的解释和猜想,只从定义和实验出发来分析。
## 什么是Transformer(广义)
由多层self-attention层叠加而成的模型,可以搭配全连接层,卷积层。attention机制也可以从多种实现中挑选任意一种。

## 什么是Transformer(狭义)
Transformer远不止一个模型,更提出了相应的训练框架,优化方法。

## 动机和实现的差异
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 有什么用
机器翻译

语言模型

BERT

## 一些常识(见板书)
- Multi-Head Attention 怎么写
- Layer Norm 怎么加
- Attention Mask
- FFN 是什么