ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

人工智能-注意力模型

2026/8/25 10:02:16 拓冰建站 浏览量
人工智能-注意力模型 注意力就是观察事物的发力点着重点。当然你观察的重点不代表就是别人观察的重点。因为人的喜好是不同的。机器学习的引入注意力模型也是为了发现一些不同的关注点或者是认为重要的信息。注意力可以观察外界也可以自省。这里主要介绍自注意力模型自注意力模型只有自身一份数据。主要分为单头注意力模型和多头注意力模型。区别就是这份数据是一个观察者还是多个观察者当然从理论上说多个观察者更能发现不一样的东西。关于注意力模型可以去看这个人博客注意力模型 但是这个例子中多头拆分方式和下面代码方式不一致所以看起来可能对应不上有时候说的是一套做的是一套所以很蛋疼。我下面主要是贴一个单头和多头注意力模型的pytorch代码这里声明一下这个代码也是别人写的我加了一些注释方便理解共大家参考共勉。有些时候看图表文字比较清晰有些时候感觉看代码更容易如果两者都看一下那应该才会理解更深刻。1 单头自注意力模型代码import torch import math import einops.layers.torch as elt vocab_size 1024 #字符的种类 embedding_dim 312 hidden_dim 256 seq torch.tensor([1,3,4,5,0,0,0]) mask torch.not_equal(seq,0).float() #5是批次80是一个句子对应的token向量一个token对应一行 80列 token torch.ones(size(5,80),dtypeint) #创建一个输入embedding值 [5, 80, 312] #Embedding vocab_size构造了一个词汇表是embedding_dim代表了一个词用多长的像表示 #转化的过程就是80列中的每一列代表一个词所以都要通过查词汇表全部替换 结果一个token 就变成了80 * 312长度 input_embedding torch.nn.Embedding(num_embeddingsvocab_size,embedding_dimembedding_dim)(token) #对输入的input_embedding进行修正这里进行了简写 [5, 80, 256]querykeyvalue是不相等的Linear每次都会随机初始化权重 #[5, 80, 256]5序列长度 80 token长度 256 隐藏层输出 312变成了256 query torch.nn.Linear(embedding_dim,hidden_dim)(input_embedding) key torch.nn.Linear(embedding_dim,hidden_dim)(input_embedding) value torch.nn.Linear(embedding_dim,hidden_dim)(input_embedding) #[5, 80, 256] X [5, 256, 80] [5, 80, 80] key elt.Rearrange(b l d - b d l)(key) #计算query与key之间的权重系数因为query和key都是通过input_embedding线性变化而来 #所以叫做自注意力 attention_prob torch.matmul(query,key) #使用softmax对权重系数进行归一化计算-1表示对最后一个维度进行计算 #attention_prob mask * -1e5 attention_prob torch.softmax(attention_prob,dim-1) #计算权重系数与value的值从而获取注意力值 [5, 80, 80] * [5, 80, 256] [5, 80, 256] attention_score torch.matmul(attention_prob,value)2 多头自注意力模型import torch import einops.layers.torch as elt class Attention(torch.nn.Module): def __init__(self,embedding_dim 312,hidden_dim 312,n_head 6): super().__init__() self.n_head n_head self.query_layer torch.nn.Linear(embedding_dim, hidden_dim) self.key_layer torch.nn.Linear(embedding_dim, hidden_dim) self.value_layer torch.nn.Linear(embedding_dim, hidden_dim) def forward(self,embedding,mask): #embedding (5,16,312) input_embedding embedding # query shape [5, 16, 312] query self.query_layer(input_embedding) key self.key_layer(input_embedding) value self.value_layer(input_embedding) #n_head 6 query_splited [5, 6, 16, 52] 最后一个维度数据分成了6份 query_splited self.splite_tensor(query,self.n_head) key_splited self.splite_tensor(key,self.n_head) value_splited self.splite_tensor(value,self.n_head) #[5, 6, 16, 52] - [5, 6, 52, 16] key_splited elt.Rearrange(b h l d - b h d l)(key_splited) # 计算query与key之间的权重系数 [5, 6, 16, 52]*[5, 6, 52, 16] - [5, 6, 16, 16] attention_prob torch.matmul(query_splited, key_splited) # 使用softmax对权重系数进行归一化计算 mask[5,1,16,1] attention_prob [5, 6, 16, 16] # 这里 mask的第1维和最1维维都使用了数组的广播机制使得维度和attention_prob attention_prob mask * -1e5 # 在自注意力权重基础上加上掩模值 attention_prob torch.softmax(attention_prob, dim-1) #计算权重系数与value的值从而获取注意力值[5, 6, 16, 16] * [5, 6, 16, 52] [5, 6, 16, 52] attention_score torch.matmul(attention_prob, value_splited) #合并回来[5, 16, 312] attention_score elt.Rearrange(b h l d - b l (h d))(attention_score) return (attention_score) def splite_tensor(self,tensor,h_head): #[5, 16, 312] - [5, 16, 6*52] - [5, 16, 6,52] embedding elt.Rearrange(b l (h d) - b l h d,h h_head)(tensor) #[5, 16, 6,52] - [5, 6, 16,52] embedding elt.Rearrange(b l h d - b h l d, hh_head)(embedding) return embedding def create_padding_mark(seq): mask torch.not_equal(seq, 0).float() mask torch.unsqueeze(mask, dim-1) mask torch.unsqueeze(mask, dim1) return mask if __name__ __main__: embedding torch.rand(size(5,16,312)) mask torch.ones((5,1,16,1)) Attention()(embedding,mask)