文章目录
1. 本周学习主要内容
- transformer经典论文精读
- NLP基础知识及实现
1.1 transformer经典论文精读
- 架构
- 公式
- 优势
1.2 机器学习特征工程复习
1.3 pytorch实现NLP中的一些基础
2.下周学习内容与问题
代办
- 2.1 继续精读经典论文
- 2.2 学习基于pytorch框架的实现
- 2.3 python基础的回顾
问题
- 2.4 NLP比CV需要更强的算力与数据
- 2.5 经典架构的数学流程与原理掌握困难
- 2.6 网上有些代码读起来比较困难
3.本周重点
3.1 transformer精读笔记
1.标题 + 作者
Transformer 开创了继 MLP 、CNN和 RNN 之后的第四大类模型 。
标题:Attention is all you need.
作者:8个来自谷歌公司的共同一作。
2.摘要内容:
sequence transduction:序列转录,指序列到序列的生成。
2.1:包括一个encoder和一个decoder的RNN或CNN架构
2.2 :表现好的序列转录在encoder与decoder中使用了attention机制
2.3 :本文提出基于attention的Transformer
2.4:实验总结了并行化的作用、减少的训练时间
2.5 :两个实验
- 英语-德语:提高2BLEU
- 英语-法语:SOTA,41.8BLEU,需要8GPUs的3.5天训练
2.6:能很好的泛化到其他任务比如CV、视频处理
3.结论
3.1 介绍了transformer模型,第一个仅使用注意力、做序列转录的模型,把之前encoder-decoder的结构换成了multi-headed self-attention
3.2 是机器翻译领域的SOTA,比其他结构训练速度快
3.3 纯注意力模型应用于非NLP任务
4 导言
4.1 提出之前序列模型常用为RNN、LSTM、GRU
4.2 RNN缺点:难以并行、容易遗忘历史信息
4.3 目前attention已经用于于一些RNN模型
4.4 本文transformer网络不再使用循环结构,而是使用纯attention、并行度高,并在较短时间达到很好的效果
5 相关工作
5.1 介绍模型结构与现有结构的关系,比如可以在NN中的局部像素和多通道,self-attention机制,memory network
5.2 transformer仅依赖于self-attention 没有使用RNN和卷积
5.3 transformer的multi-head self-attention模拟CNNs多通道输出的效果
注:self-attention是其他人提出的
6.模型(最重要的章节)
由于涉及很多NLP基础知识与公式,周报只做简单概述
6.1 介绍encoder-decoder架构和+auto-regressive in decoder
6.2 介绍encoder-decoder架构
6.3 介绍数据归一化的方法layerNorm(注意分析与BatchNorm的关系)
6.4 介绍encoder的注意力层
6.5 decoder的masked multi-head attention
6.6 position-wise feed-forward network(相当于一个MLP)
FFN:linear+Relu+linear
6.7 embeddings 和softmax
6.8 介绍positional encoding
6.9 介绍self-attention的重要性
模型结构与意义与理念
一个翻译成中文的架构图
7.transformer用于的实验
7.1 介绍使用的数据集及硬件
7.2 优化器是Adam算法
bete2常见为0.99或0.999
7.3 使用Dropout层,P drop为0.1
7.4 使用Inceptionv3
7.5 使用softmax很难趋近为1,输出值很大,才会激活为1.故softmax的输出为0.1即可
7.6 训练分数为perplexity,困惑度,log(loss)
可以更好提高accuracy 和 BLEU score
8 评论
8.1 写作技巧简单,意在简洁、清楚
8.2 transformer 不仅在NLP上表现出色,在CV和Video上也有很好的应用
8.3 最关键的attention 用了更广泛的inductive bias归置偏置。使attention没有用空间上得假设,与CNN一样可取的较好的结果
8.4 缺点:需要的数据更多、模型更大
3.2 词元化的一个小实验实现
核心代码
class Vocab: #@save
"""⽂本词表"""
def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):
if tokens is None:
tokens = []
if reserved_tokens is None:
reserved_tokens = []
# 按出现频率排序
counter = count_corpus(tokens)
self._token_freqs = sorted(counter.items(), key=lambda x: x[1],
reverse=True)
# 未知词元的索引为0
self.idx_to_token = ['<unk>'] + reserved_tokens
self.token_to_idx = {token: idx
for idx, token in enumerate(self.idx_to_token)}
for token, freq in self._token_freqs:
if freq < min_freq:
break
if token not in self.token_to_idx:
self.idx_to_token.append(token)
self.token_to_idx[token] = len(self.idx_to_token) - 1
def __len__(self):
return len(self.idx_to_token)
def __getitem__(self, tokens):
if not isinstance(tokens, (list, tuple)):
return self.token_to_idx.get(tokens, self.unk)
return [self.__getitem__(token) for token in tokens]
def to_tokens(self, indices):
if not isinstance(indices, (list, tuple)):
return self.idx_to_token[indices]
return [self.idx_to_token[index] for index in indices]
@property
def unk(self): # 未知词元的索引为0
return 0
@property
def token_freqs(self):
return self._token_freqs
def count_corpus(tokens): #@save
"""统计词元的频率"""
# 这⾥的tokens是1D列表或2D列表
if len(tokens) == 0 or isinstance(tokens[0], list):
# 将词元列表展平成⼀个列表
tokens = [token for line in tokens for token in line]
return collections.Counter(tokens)