【1】Talking-Heads Attention

论文标题:Talking-Heads Attention - Arxiv2020

原文传送门:

https://arxiv.org/abs/2003.02436https://arxiv.org/abs/2003.02436%E2%80%8Barxiv.org

1. Abstract & Introduction

作者引入了一种MultiHead变种 —“talking-heads attention”:在 softmax 之前和之后,跨注意力头维度的引入线性映射。虽然只附加了少量参数和适量计算,其会带来掩码语言建模任务的更好困惑度,以及在迁移学习到语言理解和问答任务时的更好质量。

3 Multi-Head Attention

4 Talking-Heads Attention

7 Experiments

7.1 Text-to-Text Transfer Transformer (T5)

选择迁移学习上[Raffel et al., 2019],测试MultiHead Attn和Talking-heads Attn,在 SQUAD [Rajpurkar et al., 2016]、GLUE [Wang et al., 2018] 和 SuperGlue [Wang et al., 2019] 的示例上对每个模型进行微调。

结论:对于每个头数,在所有质量指标上,谈话头注意力都优于多头注意力。

7.2 ALBERT

[Lan et al., 2019] 介绍了 ALBERT,和 BERT的主要区别在于:

1) ALBERT 在所有层之间共享层参数,显着减少了参数数量。

2) ALBERT 将词嵌入分解为两个基数较小的矩阵的乘积,再次显着减少了参数计数。

3) ALBERT 还使用句序预测(SOP)来代替 BERT 中的下一句预测(NSP)。

数据集:the English Wikipedia and book corpus datasets [Devlin et al., 2018]

任务:the SQuAD task (SQuAD1.1, SQuAD2.0 dev set) and various tasks (MNLI, SST-2, RACE) from the GLUE benchmark

结论:随着头数超过12 ,并且键和值的维度小于64,MultiHead Attn的性能会下降,而Talking-heads Attn的性能不断提高。

消融实验表明: logit和weight映射缺一不可,单独用不会带来显著改善。

7.3 BERT

数据集:与 [Devlin et al., 2018] 相同的数据集

设置:预训练 12 个 Transformer 层, 简化的相对位置嵌入 [Raffel et al., 2019]

任务:对 SQuAD1.1 任务和来自 GLUE 数据集的 MNLI 进行微调。

结论:将头数增加到 768,并将键和值的维度降低到1时,质量还在提高。

7.4 Visualizing the Projection Matrices of Talking-Heads

为了说明不同头部如何相互交换信息,可视化12 层 BERT 的投影矩阵(Pl, Pw 和Pl × Pw):

几点发现:

1. 投影矩阵的主对角线没有比其他条目显着更大的值。(个人理解:token没有出现只focus自己情况)

2. 所有投影矩阵均分布良好,行列式大于10-9,最小特征值大于10-3。(个人理解:保证任意token均或多或少被关注到)

3. 未出现对角线或稀疏矩阵,表明不同注意力头之间存在重要的数据交换。

8 Conclusions and Future Work

1. Talking-heads Attn 性能极具希望;

2. 需要优化大维度矩阵乘法;

         ----构建更擅长小维矩阵乘法的硬件;

        ----减少为每个查询位置考虑的内存位置的数量; (线性和稀疏Self-attn范畴)

### 多头注意力机制概念 多头注意力机制是注意力机制的一种扩展形式,在深度学习领域被广泛应用。通过将输入的查询(Q)、键(K)和值(V)分成多个部分,即所谓的“头部”,从而允许模型关注来自不同表示子空间的信息[^1]。 ### 工作原理 具体来说,对于给定的一组输入序列,这些输入会被线性变换映射到不同的低维空间形成各自的 Q、K 和 V 向量。接着,每个这样的三元组都会经历标准缩放点积注意计算过程: \[ \text{Attention}(Q,K,V)=\text{softmax}\left(\frac{Q K^{T}}{\sqrt {d_k}}\right)V \] 其中 \( d_k \) 是键向量维度大小。此操作会在每一个头上独立执行多次,最终得到的结果会再次拼接起来并通过另一个线性转换层来获得最后输出[^3]。 ### 实现方法 下面是一个简单的 Python 代码片段展示如何构建一个多头自注意力模块: ```python import torch.nn as nn import math class MultiHeadAttention(nn.Module): def __init__(self, embed_size, num_heads): super(MultiHeadAttention, self).__init__() self.embed_size = embed_size self.num_heads = num_heads assert (embed_size % num_heads == 0), "Embed size needs to be divisible by heads" self.depth = embed_size // num_heads self.w_q = nn.Linear(embed_size, embed_size) self.w_k = nn.Linear(embed_size, embed_size) self.w_v = nn.Linear(embed_size, embed_size) self.fc_out = nn.Linear(embed_size, embed_size) def forward(self, queries, keys, values, mask=None): N = queries.shape[0] query_len, key_len, value_len = queries.shape[1], keys.shape[1], values.shape[1] # Split the embedding into `num_heads` different pieces. queries = self.split_heads(self.w_q(queries)) keys = self.split_heads(self.w_k(keys)) values = self.split_heads(self.w_v(values)) energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys]) if mask is not None: energy = energy.masked_fill(mask == 0, float("-1e20")) attention = torch.softmax(energy / (self.depth ** 0.5), dim=3) out = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape( N, query_len, self.embed_size ) return self.fc_out(out) def split_heads(self, x): batch_size, seq_length, _ = x.size() return ( x.view(batch_size, seq_length, self.num_heads, self.depth) .transpose(1, 2) ) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值