锋哥原创的Transformer 大语言模型(LLM)基石视频教程:
https://www.bilibili.com/video/BV1X92pBqEhV
课程介绍
本课程主要讲解Transformer简介,Transformer架构介绍,Transformer架构详解,包括输入层,位置编码,多头注意力机制,前馈神经网络,编码器层,解码器层,输出层,以及Transformer Pytorch2内置实现,Transformer基于PyTorch2手写实现等知识。
Transformer 大语言模型(LLM)基石 - Transformer架构详解 - 自注意力机制(Self-Attention)算法实现
自注意力机制的目标是计算输入序列中每个词语与其他词语的关系。通过这种机制,模型能够自适应地选择与每个词语相关的信息,以构建其上下文表示。
核心组件:
Q(Query):查询向量,表示当前关注的点
K(Key):键向量,表示被查询的点
V(Value):值向量,包含实际的信息
注意力分数:Q和K的相似度
计算注意力权重
接着,通过计算 Query 和 Key 的相似度来确定每个词语对其他词语的关注程度。这个相似度通常通过计算点积来实现,并对结果进行缩放以避免数值过大。具体地,计算方式为:
其中,dk是 Key 向量的维度。通过 softmax 操作,得到的矩阵表示了每个词语对于其他词语的注意力权重。
除以开根号dk,主要目的是防止梯度消失和q,k的统计变量满足正太分布,实现归一化。
输出
最后,将这些注意力权重与对应的 Value 向量进行加权平均,得到每个词语的上下文表示。
自注意力机制(Self-Attention)算法实现
def create_sequence_mask(seq_len): """ 创建序列掩码(下三角矩阵) """ mask = np.triu(np.ones((3, seq_len, seq_len), dtype=np.uint8), k=1) return torch.from_numpy(1 - mask) # 实现自注意力机制层 def self_attention(query, key, value, mask=None, dropout=None): """ 自注意力机制层 参数: query: 查询张量 [batch_size, seq_len, d_model] key: 关键张量 [batch_size, seq_len, d_model] value: 值张量 [batch_size, seq_len, d_model] mask: 掩码张量 [batch_size, seq_len, seq_len] dropout: Dropout概率 防止模型过拟合,从而提升其泛化能力 返回: 注意力输出和注意力权重 """ # 获取词嵌入维度 512 dk = query.size(-1) print("dk:", dk) # 计算注意力分数 [batch_size, seq_len, seq_len] attention_scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(dk) # 将掩码位置的注意力分数设置为负无穷 if mask is not None: attention_scores = attention_scores.masked_fill(mask == 0, -1e9) # softmax 函数,将注意力分数进行归一化 attention_weights = F.softmax(attention_scores, dim=-1) # 对权重进行dropout,随时失活 if dropout is not None: attention_weights = dropout(attention_weights) return torch.matmul(attention_weights, value), attention_weights if __name__ == '__main__': vocab_size = 2000 # 词表大小 embedding_dim = 512 # 词嵌入维度的大小 embeddings = Embeddings(vocab_size, embedding_dim) embed_result = embeddings(torch.tensor([[1999, 2, 99, 4, 5], [66, 2, 3, 22, 5], [66, 2, 3, 4, 5]])) print("embed_result.shape:", embed_result.shape) print("embed_result", embed_result) positional_encoding = PositionalEncoding(embedding_dim) result = positional_encoding(embed_result) print("result:", result) print("result.shape:", result.shape) # 测试自注意力机制 query = key = value = result mask = create_sequence_mask(5) dropout = nn.Dropout(0.1) attention_output, attention_weights = self_attention(query, key, value, mask, dropout) print("attention_output.shape:", attention_output.shape) # [3, 5, 512] print("attention_weights.shape:", attention_weights.shape) # [3, 5, 5]