【机器学习】李宏毅——自注意力机制(Self-attention)
前面我们所讲的模型,输入都是一个向量,但有没有可能在某些场景中输入是多个向量,即一个向量集合,并且这些向量的数目并不是固定的呢?
这一类的场景包括文字识别、语音识别、图网络等等。
那么先来考虑输出的类型,如果对于输入是多个数目不定的向量,可以有以下这几种输出方式:
- 每个向量对应一个输出:输出的数目与输入向量的数目一致,例如下图的词性识别、语调识别、状态识别等等:
- 只有单个输出:这种应用于例如判断一段话的正负面作用、语音辨认说话者等等,如下图:
- 机器自己决定输出多少个结果(seq2seq):如翻译、语音转文字等等。
Sequence Labeling(输入输出数目一致)
最简单的思路当然是将每一个向量单独作为一个输入,然后将其丢入到一个全连接之中,每个单独产生结果。但是这种方法的问题在于没办法考虑前后向量之间的联系。那么转换另一个思路就是开一个window,每次将window中的向量一起输入到全连接网络中,如下图:
这种方式的问题在于如果遇到某些场景需要全部向量都考虑,但是我们无法事先知道这个场景中向量的数目,我们也就很难调整我们的window去适应。在这种情况下就需要用到自注意力机制了。
Self-attention
可以将自注意力机制看成一层,其接受所有向量的输入,然后输出的数目跟输入的数目的是一样的,可以认为它的每个输出都是考虑了整个向量集之后的结果,之后再将这些输出每个单独放入一个全连接网络中来得到输出,这样可以显著的降低全连接网络的参数量。并且这个也可以多次使用,自注意力后FC再自注意力再FC等等。
那么接下来的问题就是这个机制如何接受输入并作出相应的输出。这边以第一个向量对应的第一个输出为例:
- 计算每个输入向量之间的关联性:计算关联性\(\alpha\)有很多种方法:
最常见的是这种Dot-product,就是将两个向量分别乘以一个矩阵,得到新的向量,然后再进行点乘得到一个数值,也就是\(\alpha\)
计算出两两向量之间的相关性后进行Sortmax:如下图:
对每个向量再乘以一个另外的矩阵得到一个新的向量,再进行加权和得到结果:
哪一个向量对应的\(\alpha\)(attention score)越大,那么得到的b就越接近于它所计算出来的\(v\),这就是最终结果了。
从矩阵角度理解全过程
- 由于每一个输入向量都需要计算\(q,k,v\)三个向量,因此可以利用矩阵的形式更加简洁方便的进行计算:
- 计算\(\alpha\)也是同理:
- 计算b也是转换成矩阵操作:
而经过上述的分析,可以看到需要学习的参数只有\(W^q,W^k,W^v\)而已。
Multi-head Self-attention
这是认为不同的输入向量之间可能不止有一种相关性,因此:
各种参数都有多重,只不过各自算各自的。
Position embedding
在前面的自注意力过程中,我们并没有关注到各个输入向量之间的位置信息!这在一些场景里面是很关键的一部分信息,但是我们只是计算了各自的相关性没有考虑到位置信息,因此需要加上Position embedding:
只需要在每个输入向量上加上一个\(e^i\)即可,这个里面就包含了具体的位置信息,而如何产生\(e^i\)仍然是一个在研究的问题。
CNN与Self-attention
事实上,CNN是受限制的Self-attention,也就是Self-attention的特例,Self-attention可以通过某些设计和限制就可以变成CNN,完成和CNN同样的任务。
RNN与Self-attention
RNN也是处理输入是向量序列问题的算法,其具体过程就是一开始有一个memory,它和第一个输入向量一起输入到RNN中将会输出一个向量,该向量一方面放入全连接网络中得到一个输出,另一方面和下一个输入向量一起作为下一个RNN的输入,以此类推。
而它们的区别在于:
- 对不同位置的考虑:在RNN中如果最后一个黄色的输出向量希望它能够与第一个输入的蓝色向量有关,那么就需要蓝色向量从一开始输入就一直被记得,直到最后一个;而在Self-attention则不用考虑到这个问题,计算就已经是统筹兼顾了
- 计算的平行性:RNN是无法进行平行计算的,而Self-attention是可以的。
最新文章
- C++读写文件ofstream,ifstream,fstream)[转]
- 27Spring_的事务管理_银行转账业务加上事务控制_基于tx.aop进行声明式事务管理
- Datagrid扩展方法onClickCell{easyui-datagrid-扩充-支持单元格编辑}
- C3P0连接池详解及配置
- cojs QAQ的序列 解题报告
- 使用@RequestParam绑定请求参数到方法参数
- php intval()函数
- 关于Spring中AOP的理解
- return的用处
- C primer plus 读书笔记第二章
- Android 自己定义 TextView drawableTop 图标与文字左对齐(效果图)
- BZOJ 2789: [Poi2012]Letters( BIT )
- LKNotification控件-通知控件
- SPOJ DQUERY D-query(主席树 区间不同数个数)
- HDFS的上传与下载(put &; get)
- DataGridView导出数据到Excel
- 关于Vue数组操作
- C#深度学习の枚举类型(IEnumerator,IEnumerable)
- python自动化开发-[第二十四天]-高性能相关与初识scrapy
- Confluence 6 手动安装语言包和找到更多语言包
热门文章
- 安装 loki 轻量级日志监控系统
- Xcode模拟器simulators安装
- Libgdx游戏学习(1)——环境配置及demo运行
- 【强烈推荐】用glob库的一行命令显著加速批量读取处理数据
- 生成随机数的几种方法、Math.random()随机数的生成、Random()的使用
- Windows10 + Eclipse C/C++开发环境配置极简教程
- etcd定时任务脚本执行失败
- vulnhub靶场之THALES: 1
- HAProxy反向代理实例
- 19_Vue如何监测到对象类型数据发生改变的?