大模型基础——从零实现一个Transformer(4)

大模型基础——从零实现一个Transformer(1)-CSDN博客

大模型基础——从零实现一个Transformer(2)-CSDN博客

大模型基础——从零实现一个Transformer(3)-CSDN博客


一、前言

上一篇文章已经把Encoder模块的单个EncodeBlock已经实现了
本文我们继续了解Transformer中剩下的其他组件.

二、编码器(Encoder)

按照图把相应的子模块堆叠起来就可以了

from torch import nn,Tensor


# 自己实现的EncoderBlock
from llm_base.block.encoder_block import EncoderBlock
from llm_base.layer_norm.normal_layernorm import LayerNorm


class Encoder(nn.Module):
    def __init__(self,
                 d_model: int,
                 n_layers: int,
                 n_heads: int,
                 d_ff: int,
                 dropout: float = 0.1,
                 norm_first: bool = False) -> None:
        '''

        :param d_model: dimension of embeddings
        :param n_layers: number of encoder blocks
        :param n_heads: number of heads
        :param d_ff: dimension of inner feed-forward network
        :param drop: dropout ratio. Defaults to 0.1.
        :param norm_first:
        '''
        super().__init__()

        # stack n_layers encoder blocks
        self.layers = nn.ModuleList(
            [
                EncoderBlock(d_model,n_heads,d_ff,dropout,norm_first) for _ in range(n_layers)
            ]
        )

        self.norm = LayerNorm(d_model)
        self.dropout = nn.Dropout(dropout)


    def forward(self,src: Tensor,src_mask: Tensor = None,keep_attentions:bool = False) -> Tensor:
        '''

        :param src: (batch_size, seq_length, d_model)
        :param src_mask: (batch_size, 1, seq_length)
        :param keep_attentions: whether keep attention weigths or not. Defaults to False.

        :return: (batch_size, seq_length, d_model)
        '''
        x = src
        
        # pass through each layer
        for layer in self.layers:
            x = layer(x,src_mask,keep_attentions)
        return self.norm(x)

三、解码器(Decoder)

解码器(Decoder)相比 编码器(Encoder):

  • 增加了个掩码多头注意力(Masked Multi Head Attention),这里的掩码是为了防止解码器看到目标序列中当前位置的下一个标记,强制模型仅使用现有的标记作为上下文来预测下一个标记。
  • 多头注意力,它将编码器(Encoder)的输出作为附加输入——即Key和Value,来自掩码多头注意力的输出作为Query

3.1 解码器块(Decoder Block)

from torch import nn,Tensor
from typing import *

# 引入自己实现的模块
from llm_base.attention.MultiHeadAttention1 import MultiHeadAttention
from llm_base.layer_norm.normal_layernorm import LayerNorm
from llm_base.ffn.PositionWiseFeedForward import PositonWiseFeedForward
class DecoderBlock(nn.Module):
    def __init__(self,
                 d_model: int,
                 n_heads: int,
                 d_ff: int,
                 dropout: float,
                 norm_first: bool = False) -> None:
        '''

        :param d_model: dimension of embeddings
        :param n_heads: number of heads
        :param d_ff: dimension of inner feed-forward network
        :param dropout: dropout ratio
        :param norm_first: if True, layer norm is done prior to attention and feedforward operations(Pre-Norm).
                Otherwise it's done after(Post-Norm). Default to False.
        '''
        super().__init__()
        self.norm_first = norm_first

        # masked multi-head attention 定义
        self.masked_attention = MultiHeadAttention(d_model,n_heads,dropout)
        self.norm1 =  LayerNorm(d_model)

        # cross multi-head attention 定义
        self.cross_attention = MultiHeadAttention(d_model,n_heads,dropout)
        self.norm2 = LayerNorm(d_model)

        # position-wise feed-forward network 定义
        self.ff = PositonWiseFeedForward(d_model,d_ff,dropout)
        self.norm3 = LayerNorm(d_model)

        self.dropout1 = nn.Dropout(dropout)
        self.dropout2 = nn.Dropout(dropout)
        self.dropout3 = nn.Dropout(dropout)


    # self attention sub layer
    def _self_attention_sub_layer(self,x: Tensor,attn_mask: Tensor,keep_attentions: bool) -> Tensor:
        x = self.masked_attention(x,x,x,attn_mask,keep_attentions)
        return  self.dropout1(x)

    # cross attention sub layer
    def _cross_attention_sub_layer(self,x: Tensor,encode_mem: Tensor,atten_mask:Tensor,keep_attentions:bool) -> Tensor:
        x = self.cross_attention(x,encode_mem,encode_mem,atten_mask,keep_attentions)
        return self.dropout2(x)

    def _feedforward_sub_layer(self,x: Tensor) -> Tensor:
        x = self.ff(x)
        return  self.dropout3(x)

    def forward(self,
                target_tensor: Tensor,
                encoder_mem: Tensor,
                target_mask: Tensor = None,
                memory_mask: Tensor = None,
                keep_attentions: bool = False)-> Tuple[Tensor,Tensor,Tensor]:
        '''

        :param target_tensor:   (batch_size, tgt_seq_length, d_model) the (target) sequence to the decoder block.
        :param encoder_mem: (batch_size, src_seq_length, d_model) the sequence from the last layer of the encoder.
        :param target_mask: (batch_size, 1, tgt_seq_length, tgt_seq_length) the mask for the tgt sequence.
        :param memory_mask: (batch_size, 1, 1, src_seq_length) the mask for the memory sequence.
        :param keep_attentions: whether keep attention weigths or not. Defaults to False.
        :return: (batch_size, tgt_seq_length, d_model) output of decoder block
        '''

        # pass througth masked multi-head attention
        # target_tensor (batch_size, tgt_seq_length, d_model)
        # masked_attn_score (batch_size, n_heads, tgt_seq_length, tgt_seq_length)
        
        x = target_tensor
        if self.norm_first:
            # Post Norm
            x = x + self._self_attention_sub_layer(self.norm1(x),target_mask,keep_attentions)
            x = x + self._cross_attention_sub_layer(self.norm2(x),encoder_mem,memory_mask,keep_attentions)
            x = x + self._feedforward_sub_layer(self.norm3(x))
        else:
            # Pre Norm
            x = self.norm1(x + self._self_attention_sub_layer(x,target_mask,keep_attentions))
            x = self.norm2(x + self._cross_attention_sub_layer(x,encoder_mem,memory_mask,keep_attentions))
            x = self.norm3(x + self._feedforward_sub_layer(x))
        
        return x

3.2 掩码多头注意力Mask

掩码多头注意力的时候,希望解码器只看到当前和之前的输入,而屏蔽未来的输入。

以:<bos>我很高兴认识你 为例

import torch
from torch import nn ,Tensor



def make_target_mask(target_tensor,pad_idx: int =0) -> Tensor:
    '''
    make mask tensor for target sequences
    :param target_tensor: (batch_size, seq_length)  raw sequences with padding
    :param pad_idx: (int, optional): pad index. Defaults to 0.
    :return: (batch_size, 1, seq_length, seq_length)
    '''

    seq_len = target_tensor.size()[-1]

    # padding mask
    # target_mask (batch_size,1,1,seq_length)
    # 中间两个维度为1,在后面操作的时候可以通过BroadCast机制自动补全大搜相应的维度
    target_mask = (target_tensor != pad_idx).unsqueeze(1).unsqueeze(2)

    # subsentence mask
    # subseq_mask (batch_size, 1, seq_length, seq_length)
    subseq_mask = torch.tril(torch.ones((seq_len,seq_len)).bool())

    target_mask = target_mask & subseq_mask

    return target_mask


if __name__ == '__main__':
    seq_len = 10
    batch_size = 1
    target_tensor = torch.randint(1,1000,(batch_size,seq_len))
    # 模拟padding
    target_tensor[:,int(seq_len/2):] = 0
    print(target_tensor)

    target_mask = make_target_mask(target_tensor)
    print(target_mask)
    print(target_mask.shape)

3.3 Decoder模块实现

from torch import nn,Tensor
from llm_base.block.decoder_block import DecoderBlock
from llm_base.layer_norm.normal_layernorm import LayerNorm


class Decoder(nn.Module):
    def __init__(self,
                 d_model: int,
                 n_layers: int,
                 n_heads: int,
                 d_ff: int,
                 dropout: float = 0.1,
                 norm_first: bool = False) -> None:
        '''

        :param d_model: dimension of embeddings
        :param n_layers: number of encoder blocks
        :param n_heads: number of heads
        :param d_ff: dimension of inner feed-forward network
        :param dropout:  dropout ratio. Defaults to 0.1.
        :param norm_first:
        '''

        super().__init__()

        # 开始堆叠n_layers个 decoder blocks
        self.layers = nn.ModuleList(
            [ DecoderBlock(d_model,n_heads,d_ff,dropout,norm_first) for _ in range(n_layers)]
        )

        self.norm = LayerNorm(d_model)
        self.dropout = nn.Dropout(dropout)

    def forward(self,
                target_tensor: Tensor,
                encoder_memory: Tensor,
                target_mask: Tensor = None,
                memory_mask: Tensor = None,
                keep_attentions: bool = False) -> Tensor:
        '''

        :param target_tensor:  (batch_size, tgt_seq_length, d_model) the (target) sequence to the decoder.
        :param encoder_memory:  (batch_size, src_seq_length, d_model) the  sequence from the last layer of the encoder.
        :param target_mask: (batch_size, 1, tgt_seq_length, tgt_seq_length) the mask for the tgt sequence.
        :param memory_mask: (batch_size, 1, 1, src_seq_length) the mask for the memory sequence.
        :param keep_attentions: whether keep attention weigths or not. Defaults to False.
        :return:  (batch_size, tgt_seq_length, d_model) model output (logits)
        '''
        
        x  = target_tensor
        
        # pass through each layer
        for layer in self.layers:
            x = layer(x,encoder_memory,target_mask,memory_mask,keep_attentions)
        
        x = self.norm(x)
        return x

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/729307.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flutter【组件】富文本组件

简介 flutter 富文本组件。 github地址&#xff1a; https://github.com/ThinkerJack/jac_uikit 使用方式 运行 flutter pub add jac_uikit组件文档 使用方式&#xff1a; HighlightedTextWidget.builder(text: "全部文案包含高亮文案测试用",highlights: [Hig…

1. zookeeper分布式协调者

zookeeper分布协调者 一、zookeeper介绍1、软件设计架构1.1 单体架构1.2 SOA架构/分布式1.3 微服务架构 二、zookeeper角色1、角色2、选举机制3、znode类型 三、zookeeper集群部署1、环境规划2、安装jdk3、安装配置zookeeper3.1 安装zookeeper3.2 编辑配置文件3.3 创建myid文件…

聊聊最近比较火的AI产品做互联网算法备案

今年AI&#x1f525;了&#xff0c;而且是大火&#xff0c;导致监管部门相继出台相关政策&#xff0c;需要管控下&#xff0c;所以互联网算法备案就自然而然重新被提出来。其实这个互联网算法备案去年就已经开始实施了&#xff0c;去年只有几个大厂比如BAT等互联网巨头等会去弄…

Lazada API接口——一键获取商品买家评论数据信息

一、引言 在电商领域&#xff0c;买家评论是商品销售中不可忽视的重要因素。它们不仅影响着潜在消费者的购买决策&#xff0c;还为商家提供了宝贵的客户反馈。为了满足商家和数据分析师对买家评论数据的需求&#xff0c;我们特别开发了一款针对Lazada平台的接口&#xff0c;其…

Talk|北京大学张嘉曌:NaVid - 视觉语言导航大模型

本期为TechBeat人工智能社区第602期线上Talk。 北京时间6月20日(周四)20:00&#xff0c;北京大学博士生—张嘉曌的Talk已经准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “NaVid - 视觉语言导航大模型”&#xff0c;NaVid是首个专为视觉语言导航&#xf…

Cancer Discovery | 非小细胞肺癌的空间蛋白组学研究再添新篇章

非小细胞肺癌&#xff08;NSCLC&#xff09;作为最常见的肺癌亚型&#xff0c;其治疗和预后的改善一直是医学研究的重点。由肿瘤细胞、免疫细胞、成纤维细胞等多种细胞类型组成的肿瘤微环境&#xff08;TME&#xff09;已被证实在肺癌的进展、转移和治疗响应中扮演着重要的角色…

MySQL——索引(概述和结构介绍)

一、索引概述 1、索引(index&#xff09;是帮助 MySQL 高效获取数据的数据结构(是一种有序的数据结构)。 2、在数据之外&#xff0c;数据库系统还维护着满足特定查找算法的数据结构。这些数据结构以某种方式引用&#xff08;指向&#xff09;数据&#xff0c;这样就可以在这些…

概率论与数理统计期末复习

概率论常考知识点汇总 总括 1. 基础概率论 概率定义&#xff1a;理解概率是事件发生的可能性度量&#xff0c;范围从0&#xff08;不可能&#xff09;到1&#xff08;必然发生&#xff09;。概率公理&#xff1a;掌握概率的三大公理&#xff0c;即非负性、规范性和可加性。条…

使用 cx_Oracle 在 Oracle 中等待记录并执行操作

问题背景&#xff1a; 在第一个 Python 项目中&#xff0c;需要等待记录被插入 Oracle 表中&#xff0c;一旦记录存在&#xff0c;就调用 Python 函数。目前使用 cx_Oracle 库&#xff0c;采用一种无限循环的方式来查询表。如果记录存在&#xff0c;就调用函数&#xff0c;然后…

分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别

分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别 目录 分类预测 | ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融合注意力机制的故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.ZOA-PCNN-AT-SVM斑马优化并行卷积-支持向量机融…

Linux【实操篇-文件目录类命令】

05【实操篇-文件目录类命令】 1.pwd 显示当前工作目录的绝对路径 pwd:print working directory 打印工作目录 到现在为止&#xff0c;我们还不知道自己在系统的什么地方。在浏览器上&#xff0c;我们能够通过导航栏上的url&#xff0c;了解到自己在互联网上的具体坐标。相似的…

金蝶云星空与MES系统深度集成对接案例全公开

项目背景 深圳市某自动化设备有限公司&#xff0c;自2006年成立以来&#xff0c;一直专注于高端精密自动化设备的研发、生产与销售。作为一家高科技企业&#xff0c;公司依托深圳这一经济特区的地理优势&#xff0c;构建了覆盖全国的服务网络&#xff0c;并拥有两个先进的生产…

椭圆的矩阵表示法

椭圆的矩阵表示法 flyfish 1. 标准几何表示法 标准几何表示法是通过椭圆的几何定义来表示的&#xff1a; x 2 a 2 y 2 b 2 1 \frac{x^2}{a^2} \frac{y^2}{b^2} 1 a2x2​b2y2​1其中&#xff0c; a a a 是椭圆的长半轴长度&#xff0c; b b b 是椭圆的短半轴长度。 2.…

LogicFlow 学习笔记——9. LogicFlow 进阶 节点

LogicFlow 进阶 节点&#xff08;Node&#xff09; 连线规则 在某些时候&#xff0c;我们可能需要控制边的连接方式&#xff0c;比如开始节点不能被其他节点连接、结束节点不能连接其他节点、用户节点后面必须是判断节点等&#xff0c;想要达到这种效果&#xff0c;我们需要为…

iOS开发工具-网络封包分析工具Charles

一、Charles简介 Charles 是在 Mac 下常用的网络封包截取工具&#xff0c;在做 移动开发时&#xff0c;我们为了调试与服务器端的网络通讯协议&#xff0c;常常需要截取网络封包来分析。 Charles 通过将自己设置成系统的网络访问代理服务器&#xff0c;使得所有的网络访问请求…

云手机群控功能讲解

接触云手机之前&#xff0c;很多企业或者个人卖家都对群控有浓厚的兴趣&#xff0c;云手机群控具体是什么呢&#xff1f;云手机群控&#xff0c;顾名思义&#xff0c;是指能够同时对多台云手机进行集中控制和管理的功能。打破了传统单台手机操作的限制&#xff0c;实现了规模化…

ffmpeg音视频开发从入门到精通——ffmpeg下载编译与安装

音视频领域学习ffmpeg的重要性 音视频领域中ffmpeg的广泛应用&#xff0c;包括直播、短视频、网络视频、实时互动和视频监控等领域。掌握FM和音视频技术可以获得更好的薪酬。 学习建议音视频学习建议与实战应用 音视频处理机制的学习&#xff0c;需要勤加练习&#xff0c;带…

nginx出现504 Gateway Time-out错误的原因分析及解决

nginx出现504 Gateway Time-out错误的原因分析及解决 1、查看公网带宽是否被打满 2、查看网络是否有波动(可以在nginx上ping后端服务&#xff0c;看是否有丢包情况) 3、查看服务器资源使用情况(cpu、内存、磁盘、网络等) 4、查看nginx日志&#xff0c;具体到哪个服务的哪个…

浙江保融科技2025实习生校招校招笔试分享

笔试算法题一共是有4道&#xff0c;第一道是手搓模拟实现一个ArrayList&#xff0c;第二道是判断字符串是否回文&#xff0c;第三道是用代码实现1到2种设计模式。 目录 一.模拟实现ArrayList 二.判断字符串是否回文 ▐ 解法一 ▐ 解法二 ▐ 解法三 三.代码实现设计模式 一…

189.二叉树:把二叉搜索树转换为累加树(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* Tre…