深入浅出Transformer
Transformer
Transformer是NLP的颠覆者,它创造性地用非序列模型来处理序列化的数据,而且还获得了大成功。更重要的是,NLP真的可以“深度”学习了,各种基于transformer的模型层出不穷,如BERT、GPT-2、T-NLG,而且模型参数量呈指数级增长。
Transformer之前,大家的思路都是在改进序列模型,从RNN到LSTM、GRU、Seq2Seq。如果你看过我之前写的深入浅出RNN就会知道,序列模型要靠遍历seq_len来处理data,效率低是显而易见的。不仅如此,深层网络很难收敛,因此,即使像google这样的大公司也只能堆叠10层左右的LSTM。
就在大家都认为“NLP本该如此”时,Transformer横空出世,它通过self-attention实现了对序列化数据的并行处理,不仅提高了计算效率,还打开深度学习的潘多拉魔盒,放出后“大魔王”BERT。从某种程度上说,Transformer的意义比BERT更重大。
Attention
self-attention是attention的进阶版,后者最早出现在机器翻译模型--Seq2Seq中。Figure 2是英文 to 德文的seq2seq模型,encoder和decoder都是RNN(LSTM或GRU),decoder主要是靠encoder提供的hidden state来生成output。
我们知道,RNN的hidden state会随着time step的递进而变化,一旦time step数量较多,也就是seq_len较大时,那么当前的hidden state -- \(h_t\)和早先的hidden state -- \(h_1\),它们的值可能会相差甚远甚至截然相反。这种情况称为记忆遗忘,LSTM虽然在一定程度上能够减轻这种遗忘,但这样还不够。
RNN的每个time step都会有一个output,但它们都没有被用到decoder的训练中。attention的作用就是为了能让这些output能够物尽其用。
如果将encoder的所有output一股脑儿丢给decoder,那效果肯定不好。最好的办法是能知道对于当前这个time step来说,哪些output有用哪些没用,然后取其精华去其糟粕。
attention的做法是给每个output一个权重,然后对所有的output做个加权求和,其计算结果--\(C_t\)将作为参数传给decoder。
Figure 3中最关键的地方就是\(a_t\)的计算,也就是如何为output添加权重。Effective Approaches to Attention-based Neural Machine Translation这篇paper给出了下面三条公式,其中任一条公式都能够用来计算权重,请你记住\(dot\ product\)这条公式,后面会用到。
Multi-Head Attention
Transformer的那篇论文--attention-is-all-you-need是用大白话来写的,没什么难度,如果你能它通读一遍,再搭配代码--The Annotated Transformer学习,那基本上你对它的理解就差不多了。因此,本文只分析它的核心模块--Multi-Head Attention,其他内容不再赘述。
如Figure 4所示,Multi-Head指的是将data均分成N份,再对每个sub-data分别做scaled dot-product attention,最后将所有的计算结果拼接起来。实验表明,multi-attention效果比single attention的效果要好。
\(dk\)是单个attention的隐层神经元数量,等于d_model / n_heads,而d_model是multi-head attention的总的隐层神经元数量,它不需要和hidden_size一致,可以通过linear layer来进行hidden_size和d_model之间的转换。
前面提过,attention layer的重点是为encoder的output添加权重。Scaled dot-product attention,顾名思义,就是以dot-product的方式来计算权重:\(h^T_th^-_s\)。既然Transformer是非序列模型,那就可以并行计算每个time step的attention权重,即:\(QK^T\)。
\(dk\)越大,dot-product的值就越大,而softmax的导数则会越小,这样不利于模型训练,因此,Transformer会将attention的权重不仅要乘以scale -- \(1/\sqrt {d_k}\)。
除了不能太大外,\(dk\)太小也不行。\(dk\)小了,就意味着head数量少了,这样一来,每个attention要处理的seq_len就会变长。实验表明,attention处理短seq_len的精度更高,因此,head数不宜过小。
Q、K、V虽然是三个不同数值的矩阵,但它们都是由同一个data(x或y)分别经过三个不同的Linear layer得到的,因此scaled dot-product attention也称为self-attention,不仅如此,它还可以应用于encoder中。
End
深入浅出Transformer的更多相关文章
- 深入浅出腾讯BERT推理模型--TurboTransformers
Overview TurboTransformers是腾讯最近开源的BERT推理模型,它的特点就是一个字,快.本人用BERT(huggingface/transformers)在V100上做了测试,测 ...
- 深入浅出 Jest 框架的实现原理
English Version | 中文版 深入浅出 Jest 框架的实现原理 https://github.com/Wscats/jest-tutorial 什么是 Jest Jest 是 Face ...
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 【深入浅出jQuery】源码浅析2--奇技淫巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 深入浅出Struts2+Spring+Hibernate框架
一.深入浅出Struts2 什么是Struts2? struts2是一种基于MVC的轻量级的WEB应用框架.有了这个框架我们就可以在这个框架的基础上做起,这样就大大的提高了我们的开发效率和质量,为公司 ...
- DOM 事件深入浅出(二)
在DOM事件深入浅出(一)中,我主要给大家讲解了不同DOM级别下的事件处理程序,同时介绍了事件冒泡和捕获的触发原理和方法.本文将继续介绍DOM事件中的知识点,主要侧重于DOM事件中Event对象的属性 ...
- DOM 事件深入浅出(一)
在项目开发时,我们时常需要考虑用户在使用产品时产生的各种各样的交互事件,比如鼠标点击事件.敲击键盘事件等.这样的事件行为都是前端DOM事件的组成部分,不同的DOM事件会有不同的触发条件和触发效果.本文 ...
- 深入浅出node(2) 模块机制
这部分主要总结深入浅出Node.js的第二章 一)CommonJs 1.1CommonJs模块定义 二)Node的模块实现 2.1模块分类 2.2 路径分析和文件定位 2.2.1 路径分析 2.2.2 ...
- IOS 网络-深入浅出(一 )-> 三方SDWebImage
首要我们以最为常用的UIImageView为例介绍实现原理: 1)UIImageView+WebCache: setImageWithURL:placeholderImage:options: 先显 ...
随机推荐
- Linux服务器程序--大数据量高并发系统设计
在Linux服务器程序中,让系统能够提供以更少的资源提供更多的并发和响应效率决定了程序设计价值!怎样去实现这个目标,它其实是这么多年以来一直追逐的东西.最开始写代码时候,省去一个条件语句.用 ...
- 泛微 e-cology远程代码执行漏洞
影响版本:泛微 e-cology<=9.0 漏洞分析: 问题出现在 resin 下 lib 中的 bsh.jar 文件里,问题类 bsh.servlet.BshServlet,可 doGet 方 ...
- Function's dict
众所周知,Python是没有switch的,那么只能使用 if else来进行判断,但是if else比较冗长, 使用太多的if else 代码看起来不简洁,如下 student.py def stu ...
- jchdl - GSL Port
https://mp.weixin.qq.com/s/DVmMrCFgNLuZDtssQ85w7A org.jchdl.model.gsl.core.meta.Port.java gen ...
- Java实现 LeetCode 327 区间和的个数
327. 区间和的个数 给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper. 区间和 S(i, j) 表示在 nums 中,位置从 i ...
- Java中System的详细用法
System.arraycopy System.arraycopy的函数原型是: public static void arraycopy(Object src, int srcPos, Object ...
- Java实现 LeetCode 23 合并K个排序链表
23. 合并K个排序链表 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输 ...
- Java实现 蓝桥杯 算法训练 二进制数数
试题 算法训练 二进制数数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 给定L,R.统计[L,R]区间内的所有数在二进制下包含的"1"的个数之和. 如5的二进 ...
- Java实现8枚硬币问题(减治法)
1 问题描述 在8枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重.可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测这枚假币. 2.1 减 ...
- Java实现 洛谷 P1601 A+B Problem(高精)
import java.util.*; import java.math.*; public class Main { public static void main(String args[]) { ...