【大模型算法自学笔记01】NLP基础知识(1.1 自注意力)

NLP基础知识(1.1 自注意力)

    • [1.1.1 self-attention原理](#1.1.1 self-attention原理)
    • [1.1.2 self-attention改进](#1.1.2 self-attention改进)
    • [1.1.3 self-attention代码](#1.1.3 self-attention代码)
    • 参考资料

1.1.1 self-attention原理

  self-attention是一种将单个序列的不同位置关联起来以计算同一序列的表示的注意机制。可以把self-attention理解为感受野可以自学习的CNN,CNN是self-attention的特例。self-attention在数据量大时表现优于CNN。

全局建模能力对比

  • 自注意力: 在全局建模能力上,自注意力机制具有明显的优势,因为它可以显式地捕捉序列中任意两个元素之间的关系,无论它们之间的距离。这使得自注意力机制在处理长距离依赖和全局信息方面非常强大。
  • CNN: CNN在局部特征提取方面非常有效,但在全局建模能力上可能不如自注意力机制。然而,通过设计特定的网络结构(如使用全局池化层或多尺度卷积),CNN也可以在一定程度上捕捉全局信息

  self attention会考虑一整个sequence的上下文,输入几个vector(向量)就输出几个vector。self-attention可以与FC(全连接层)叠加使用,self-attention处理整个sequence的上下文,FC处理某个vector。

  原理 :输入是一个sequence,可能是网络输入或者隐藏层的输出,输出的b是考虑了整个sequence的结果。

  怎么产生b1向量?

  1️⃣ 找出这个sequence里面a1相关的其他向量。关联程度用 α \alpha α 表示,将两个向量作为输入,常见计算方式有:

  • 点积(transformer使用):a1和a2乘两个矩阵 W q W^q Wq 和 W k W^k Wk ,得到q和k,再作点积

  • Additive:将q和k串起来放入激活函数

  2️⃣ 怎么把上面生成的 α \alpha α 套用在self attention里面?

   α 1 , 1 = q 1 k ˙ 1 \alpha_{1,1}=q^1 \dot k^1 α1,1=q1k˙1,经过softmax进行normalize,(q k对应query和key, q 1 k 2 q^1 k^2 q1k2 表示第二个向量对第一个向量的影响)

  转化成矩阵格式,带学习的参数 W q W k W v W^q W^k W^v WqWkWv,注意A'就是注意力矩阵,乘以V得到self-attention的输出O。

  公式( d k d_k dk 是Q,K矩阵的列数,即向量维度):

A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V) = softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V

  除以 d k \sqrt{d_k} dk 是为了平滑softmax的结果,防止进入了softmax的饱和区,导致梯度值太小而难以训练。

self-attention 与 RNN/LSTM 对比:

  • 引入Self Attention后会更容易捕获句子中长距离的相互依赖的特征。RNN或者LSTM虽然也能捕获长距离的特征,但是对于远距离的相互依赖的特征,要经过若干时间步步骤的信息累积才能将两者联系起来,而距离越远,有效捕获的可能性越小。
  • self-attention和RNN都能处理时序数据,每个向量都考虑了整个sequence,但RNN需要按顺序计算,无法并行;self-attention可以并行计算。

  

1.1.2 self-attention改进

  位置编码 :Self-Attention虽然考虑了所有的输入向量,但没有考虑到向量的位置信息。可以通过位置编码(Positional Encoding)来解决这个问题,就是把位置信息添加到输入序列中,让输入数据本身就带有位置信息。

  上面的a是无序的,需要对a加上位置向量e,e可以通过多种方法产生(sinusodial、position embedding、floater、rnn等)。

  多头注意力:把输入序列投影为多组不同的Query,Key,Value,并行分别计算后,再把各组计算的结果合并作为最终的结果。类似CNN中的多个channel,生成多个W\^q W\^k W\^v $。(V,K,Q)三个矩阵通过h个线性变换,分别得到h组(V,K,Q)矩阵,每一组(V,K,Q)经过Attention计算,得到h个Attention output并进行拼接(Concat),最后通过一个线性变换得到输出,其维度与输入词向量的维度一致,其中h就是多头注意力机制的"头数"。

  

1.1.3 self-attention代码

python 复制代码
import torch.nn as nn
import numpy as np
import torch
import math
# 多头注意力     
class MHA(nn.Module):
    def __init__(self, num_head, dimension_k, dimension_v, d_k, d_v, d_o):
        # d_k表示head dimension,d_k * num_head 就是embedding的长度
        super().__init__()
        self.num_head = num_head
        self.d_k = d_k
        self.d_v = d_v
        self.d_o = d_o
        self.fc_q = nn.Linear(dimension_k, num_head * d_k)
        self.fc_k = nn.Linear(dimension_k, num_head * d_k)
        self.fc_v = nn.Linear(dimension_v, num_head * d_v)
        self.fc_o = nn.Linear(num_head * d_v, d_o)
        self.softmax = nn.Softmax(dim=2)
        
        
    def forward(self, q, k, v, mask):
        
        batch, n_q, dimension_q = q.size()
        batch, n_k, dimension_k = k.size()
        batch, n_v, dimension_v = v.size()
          
        q = self.fc_q(q)
        k = self.fc_k(k)
        v = self.fc_v(v)
        q = q.view(batch, n_q, self.num_head, self.d_k).permute(2, 0, 1, 3).contiguous().view(-1, n_q, self.d_k)
        k = k.view(batch, n_k, self.num_head, self.d_k).permute(2, 0, 1, 3).contiguous().view(-1, n_k, self.d_k)
        v = v.view(batch, n_v, self.num_head, self.d_v).permute(2, 0, 1, 3).contiguous().view(-1, n_v, self.d_v)
        
        attention = torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(self.d_k)
        mask = mask.repeat(self.num_head, 1, 1)
        attention = attention + mask
        attention = self.softmax(attention)
        
        output = torch.matmul(attention, v)
        output = output.view(self.num_head, batch, n_q, self.d_v).permute(1, 2, 0, 3).contiguous().view(batch, n_q, -1)
        output = self.fc_o(output)
        return attention, output
# Multi query attention
class MQA(nn.Module):
    def __init__(self, num_head, dimension_k, dimension_v, d_k, d_v, d_o):
        super().__init__()
        self.num_head = num_head
        self.d_k = d_k
        self.d_v = d_v
        self.d_o = d_o
        self.fc_q = nn.Linear(dimension_k, num_head * d_k)
        self.fc_k = nn.Linear(dimension_k, d_k)
        self.fc_v = nn.Linear(dimension_v, d_v)
        self.fc_o = nn.Linear(num_head * d_v, d_o)
        self.softmax = nn.Softmax(dim=2)
        
        
    def forward(self, q, k, v, mask):
        
        batch, n_q, dimension_q = q.size()
        batch, n_k, dimension_k = k.size()
        batch, n_v, dimension_v = v.size()
          
        q = self.fc_q(q)
        k = self.fc_k(k)
        v = self.fc_v(v) 
        q = q.view(batch, n_q, self.num_head, self.d_k).permute(2, 0, 1, 3).contiguous().view(-1, n_q, self.d_k)       
        k = k.repeat(self.num_head, 1, 1)
        v = v.repeat(self.num_head, 1, 1)
        
        attention = torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(self.d_k)
        mask = mask.repeat(self.num_head, 1, 1)
        attention = attention + mask
        attention = self.softmax(attention)
        
        output = torch.matmul(attention, v)
        output = output.view(self.num_head, batch, n_q, self.d_v).permute(1, 2, 0, 3).contiguous().view(batch, n_q, -1)
        output = self.fc_o(output)
        return attention, output

batch = 10
num_head = 8
n_q, n_k, n_v = 2, 4, 4 # sequence 长度
dimension_q, dimension_k, dimension_v = 128, 128, 64 # embedding的长度
d_k, d_v, d_o = 16, 16, 8
q = torch.randn(batch, n_q, dimension_q)
k = torch.randn(batch, n_k, dimension_k)
v = torch.randn(batch, n_v, dimension_v)
mask  = torch.full((batch, n_q, n_k), -np.inf)    
mask = torch.triu(mask,diagonal=1)
mha = MHA(num_head, dimension_k, dimension_v, d_k, d_v, d_o)
attention, output = mha(q, k, v, mask)
print(attention.size(), output.size())

mqa = MQA(num_head, dimension_k, dimension_v, d_k, d_v, d_o)
attention, output = mqa(q, k, v, mask)
print(attention.size(), output.size())

  

参考资料

  

相关推荐
loulanyue_1 小时前
Context Is All You Need:读千问办公CEO陈宇森2026云栖演讲
人工智能·智能体·千问办公
零基础1231 小时前
深度强化学习驱动的 Agent 后训练:原理、实践与前沿路线
人工智能·python·机器学习
一缕82年的清风1 小时前
从 Cursor 杀回命令行:当 AI 接管终端,CLI 会取代 IDE 吗?
人工智能
夏文强1 小时前
国产开源反攻海外:GLM-5.3 进 Cursor,CursorBench 开放权重第一
人工智能·开源·大模型·glm·智谱
Yyyyyy~1 小时前
【机器学习】Numpy
人工智能·机器学习·numpy
高洁011 小时前
数字孪生驱动大模型工业知识库
人工智能·python·深度学习·机器学习·transformer
大模型真好玩1 小时前
DeepSeek Harness 桌面端来啦!更便捷更安全的选择
人工智能·agent·deepseek
远航计算机1 小时前
AI 爬虫分三种,你 robots.txt 里挡的是哪一种?
人工智能·爬虫·aigc
2603_954708311 小时前
微能网的核心硬件协调控制装置有哪些功能?
大数据·运维·人工智能·架构·能源