Datawhale------Tiny-universe学习笔记——Qwen

news2024/12/23 14:14:11

1. Qwen整体介绍

        对于一个完全没接触过大模型的小白来说,猛一听这个名字首先会一懵:Qwen是啥。这里首先解答一下这个问题。下面是官网给出介绍:Qwen是阿里巴巴集团Qwen团队研发的大语言模型和大型多模态模型系列。其实随着大模型领域的发展,这类产品已经有很多了例如:由百度开发的ERNIE,由清华大学开发的Zhuiyi等等。

        目前,Qwen已升级至Qwen2版本。无论是语言模型还是多模态模型,均在大规模多语言和多模态数据上进行预训练,并通过高质量数据进行后期微调以贴近人类偏好。Qwen具备自然语言理解、文本生成、视觉理解、音频理解、工具使用、角色扮演、作为AI Agent进行互动等多种能力。

       

        废话不多说,我们可以先看一下Qwen的整体架构。Qwen的整体架构与Llama2类似,如下图所示:742783c260624227847cc91f252ad49e.jpeg

 

        接下来我们顺着整体架构图学习,对于输入问题Text,首先会经过Tokenizer。在这里,对于没有了解过NLP的友友们又开始疑惑了:Tokenizer是啥?其实Tokenizer就是一个分词器,在这里的作用就是将问题中句子分成各个词,每一个词都对应着词表的索引,每个索引对应着一个词向量。

        接着之后生成一个input_ids,由此输入Qwen2的主干部分。

 

1.1 模型初始化

        第一部首先进行模型初始化:

class Qwen2Model(Qwen2PreTrainedModel):
    def __init__(self, config: Qwen2Config):
        super().__init__(config)
        self.padding_idx = config.pad_token_id
        self.vocab_size = config.vocab_size

        self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
        self.layers = nn.ModuleList(
            [Qwen2DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
        )
        self.norm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)

        self.gradient_checkpointing = False
        # Initialize weights and apply final processing
        self.post_init()

        下面我们来解释一下这段代码:

     1.def __init__(self, config: Qwen2Config):
        super().__init__(config)

        Qwen2Model继承自Qwen2PreTrainedModelQwen2PreTrainedModel继承自PreTrainedModel。PretrainedConfig是transformers框架中所有配置类的基类。

        Qwen2PreTrainedModel是已经预训练好的模型,具体代码如下:

引自:transformers/src/transformers/models/qwen2/modeling_qwen2.py at main · huggingface/transformers · GitHub

class Qwen2PreTrainedModel(PreTrainedModel):
    config_class = Qwen2Config
    base_model_prefix = "model"
    supports_gradient_checkpointing = True
    _no_split_modules = ["Qwen2DecoderLayer"]
    _skip_keys_device_placement = "past_key_values"
    _supports_flash_attn_2 = True
    _supports_sdpa = True
    _supports_cache_class = True
    _supports_quantized_cache = True
    _supports_static_cache = True

    def _init_weights(self, module):
        std = self.config.initializer_range
        if isinstance(module, nn.Linear):
            module.weight.data.normal_(mean=0.0, std=std)
            if module.bias is not None:
                module.bias.data.zero_()
        elif isinstance(module, nn.Embedding):
            module.weight.data.normal_(mean=0.0, std=std)
            if module.padding_idx is not None:
                module.weight.data[module.padding_idx].zero_()

 

   2.  self.padding_idx = config.pad_token_id
        self.vocab_size = config.vocab_size

        这里设置了模型的两个属性:padding_idx(用于指定填充标记的索引),vocab_size(词汇表的大小,即模型能够处理的不同token的数量)。

   

    3.  self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)

         self.layers = nn.ModuleList([Qwen2DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)])
        self.norm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)

        初始化模型的嵌入层、解码器层、归一化层:

  • 嵌入层(nn.Embedding):模型使用嵌入层将输入的标记映射成密集的向量表示。config.vocab_size是词汇表的大小,config.hidden_size是嵌入向量的维度,self.padding_idx是padding token的索引。
  • 解码器层(nn.ModuleList()):模型包含多个解码器层,这些层都是由 `Qwen2DecoderLayer`` 定义。每个解码器层都是根据配置对象中的参数构建的,并且有一个索引layer_idx,它表示层在模型中的位置。
  • 归一化层 Qwen2RMSNorm:归一化层使用的是 Root Mean Square Layer Normalization

 

    4. self.gradient_checkpointing = False

        设置了是否使用 gradient_checkpoint 主要是用来节省显存。它用于控制是否使用梯度检查点技术。这是一种节省内存的技术,通过在正向传播中丢弃一些中间梯度来实现。

 

    5. self.post_init()

        调用 post_init() 完成一些初始化和准备检查的代码。post_init()代码。

 

def post_init(self):
    """
    A method executed at the end of each Transformer model initialization, to execute code that needs the model's
    modules properly initialized (such as weight initialization).
    """
    self.init_weights()
    self._backward_compatibility_gradient_checkpointing()

 

1.2 forward方法

        第二步实现Qwen2Model的forward方法。在实现 Qwen2Model 的 forward 方法时,我们需要分成三个主要部分:Embedding、Hidden States 和 Decoder Layers。这一过程展示了模型的前向传播行为,即在接收输入数据后,如何计算输出结果。

        1. Embedding

        首先,对于输入的 input_ids,我们将使用 torch.nn.Embedding 进行嵌入处理。这一步负责将每个输入标识符映射到一个高维向量空间中,以便后续的处理。

        2. Hidden States

        接下来,经过嵌入处理后的向量将转化为 Hidden States。这些状态代表了输入数据的内部表示,将作为输入提供给模型的 Decoder Layers。

        3. Decoder Layers

        最后,经过前两步处理的 Hidden States 会传递到多层的 Decoder Layers 进行进一步的处理。Decoder Layers 是模型的核心部分,它们通过自注意力机制和前馈神经网络对输入进行深入处理,以生成最终的输出。

        代码如下:

引自:transformers/src/transformers/models/qwen2/modeling_qwen2.py at main · huggingface/transformers · GitHub

    @add_start_docstrings_to_model_forward(QWEN2_INPUTS_DOCSTRING)
    def forward(
        self,
        input_ids: torch.LongTensor = None,
        attention_mask: Optional[torch.Tensor] = None,
        position_ids: Optional[torch.LongTensor] = None,
        past_key_values: Optional[List[torch.FloatTensor]] = None,
        inputs_embeds: Optional[torch.FloatTensor] = None,
        use_cache: Optional[bool] = None,
        output_attentions: Optional[bool] = None,
        output_hidden_states: Optional[bool] = None,
        return_dict: Optional[bool] = None,
        cache_position: Optional[torch.LongTensor] = None,
    ) -> Union[Tuple, BaseModelOutputWithPast]:
        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions
        output_hidden_states = (
            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
        )
        use_cache = use_cache if use_cache is not None else self.config.use_cache

        return_dict = return_dict if return_dict is not None else self.config.use_return_dict

        if (input_ids is None) ^ (inputs_embeds is not None):
            raise ValueError(
                "You cannot specify both input_ids and inputs_embeds at the same time, and must specify either one"
            )

        if self.gradient_checkpointing and self.training:
            if use_cache:
                logger.warning_once(
                    "`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`..."
                )
                use_cache = False

        use_legacy_cache = False
        if use_cache and not isinstance(past_key_values, Cache) and not self.training:
            use_legacy_cache = True
            past_key_values = DynamicCache.from_legacy_cache(past_key_values)
            logger.warning_once(
                "We detected that you are passing `past_key_values` as a tuple and this is deprecated and will be removed in v4.46. "
                "Please use an appropriate `Cache` class (https://huggingface.co/docs/transformers/internal/generation_utils#transformers.Cache)"
            )

        if inputs_embeds is None:
            inputs_embeds = self.embed_tokens(input_ids)

        if cache_position is None:
            past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
            cache_position = torch.arange(
                past_seen_tokens, past_seen_tokens + inputs_embeds.shape[1], device=inputs_embeds.device
            )
        if position_ids is None:
            position_ids = cache_position.unsqueeze(0)

        causal_mask = self._update_causal_mask(
            attention_mask, inputs_embeds, cache_position, past_key_values, output_attentions
        )

        hidden_states = inputs_embeds

        # create position embeddings to be shared across the decoder layers
        position_embeddings = self.rotary_emb(hidden_states, position_ids)

        # decoder layers
        all_hidden_states = () if output_hidden_states else None
        all_self_attns = () if output_attentions else None
        next_decoder_cache = None

        for decoder_layer in self.layers:
            if output_hidden_states:
                all_hidden_states += (hidden_states,)

            if self.gradient_checkpointing and self.training:
                layer_outputs = self._gradient_checkpointing_func(
                    decoder_layer.__call__,
                    hidden_states,
                    causal_mask,
                    position_ids,
                    past_key_values,
                    output_attentions,
                    use_cache,
                    cache_position,
                    position_embeddings,
                )
            else:
                layer_outputs = decoder_layer(
                    hidden_states,
                    attention_mask=causal_mask,
                    position_ids=position_ids,
                    past_key_value=past_key_values,
                    output_attentions=output_attentions,
                    use_cache=use_cache,
                    cache_position=cache_position,
                    position_embeddings=position_embeddings,
                )

            hidden_states = layer_outputs[0]

            if use_cache:
                next_decoder_cache = layer_outputs[2 if output_attentions else 1]

            if output_attentions:
                all_self_attns += (layer_outputs[1],)

        hidden_states = self.norm(hidden_states)

        # add hidden states from the last decoder layer
        if output_hidden_states:
            all_hidden_states += (hidden_states,)

        next_cache = None
        if use_cache:
            next_cache = next_decoder_cache.to_legacy_cache() if use_legacy_cache else next_decoder_cache

        if not return_dict:
            return tuple(v for v in [hidden_states, next_cache, all_hidden_states, all_self_attns] if v is not None)
        return BaseModelOutputWithPast(
            last_hidden_state=hidden_states,
            past_key_values=next_cache,
            hidden_states=all_hidden_states,
            attentions=all_self_attns,
        )

    # Copied from transformers.models.llama.modeling_llama.LlamaModel._update_causal_mask

        这里内容有点多,我们看核心:

inputs_embeds = self.embed_tokens(input_ids)
# embed positions
hidden_states = inputs_embeds

for idx, decoder_layer in enumerate(self.layers):
    # 将所有的hidden_states保存成tuple
    if output_hidden_states:
        all_hidden_states += (hidden_states,)
    # 将hs送入每一层decoder_layer
    layer_outputs = decoder_layer(
        hidden_states,
        attention_mask=attention_mask,
        position_ids=position_ids,
        past_key_value=past_key_value,
        output_attentions=output_attentions,
        use_cache=use_cache,
    )
    # 取出上一层decoder_输出的hs,再传入下一个layer
    # 只要第一个,第二个是cache的一个类,然后进入下一个layer
    hidden_states = layer_outputs[0]
    
# 将最后layers输出后的hidden_states进行标准化  
hidden_states = self.norm(hidden_states)
    
# 加上最后一层的hidden_states
if output_hidden_states:
    all_hidden_states += (hidden_states,)
  • 如果保存output_hidden_states的话,就是第一个为input_ids进行emb,然后保存到n-1层的decoder_layer的输出hs,再加上最后一层layer的输出hs进行过norm后的hs.
  • 最后是以BaseModelOutputWithPast的形式输出。

 

 

1.3 RMSNorm

        计算公式:

9040e8c3b3494235915b2a4352c13934.jpeg

        

其中:

  • x是层的输入的hidden_state
  • eq?w_%7Bi%7D表示的是hidden_state的最后一个维度的值
  • n 表示上面输入的最后一个维度的数量。
  • ϵ 表示是很小的数,防止除0。
class Qwen2RMSNorm(nn.Module):  # 标准化层
    def __init__(self, hidden_size, eps=1e-6):
        """
        Qwen2RMSNorm is equivalent to T5LayerNorm
        """
        super().__init__()
        self.weight = nn.Parameter(torch.ones(hidden_size))
        self.variance_epsilon = eps

    def forward(self, hidden_states):
        input_dtype = hidden_states.dtype
        hidden_states = hidden_states.to(torch.float32)
        variance = hidden_states.pow(2).mean(-1, keepdim=True)
        hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
        return self.weight * hidden_states.to(input_dtype)
  • torch.rsqrt表示输入的东西开根的导数。
  • .pow(2).mean(-1, keepdim=True)表示对最后一个维度平方并取均值。

 

2. Qwen2Attention 

        cf16aefd8f2f42f6a101bb5294182fb0.png

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

卡尔曼滤波中Q和R与噪声的关系

卡尔曼滤波 一种用于估计系统状态的递归滤波器,通过融合传感器测量和系统模型,提供系统状态的最优估计。 Q和R是什么 在卡尔曼滤波中,Q和R分别表示过程噪声和测量噪声的协方差矩阵。 Q Q Q矩阵(过程噪声协方差矩阵)…

电子连接器温升仿真教程 一

电子连接器温升是指电子连接器的所有端子在施加额定电载荷的情况下,经过一段时间后,达成热平衡,连接器局部温度不再继续升高,此时规定测试点的温度与测试环境温度的差值。连接器的温升规格值因其应用环境不同,而不同。工业应用,且不与人体接触的电子连接器一般允许温升会…

日系编曲:电吉他音色制作 拾音器选择 电吉他音色制作逻辑 音箱分类 效果器单块分类

拾音器选择 拾音器:获取琴弦震动产生电信号经过线材传输到音箱(amp)使听众听到 一般的电吉他分为三块和两块拾音器,挡位分为三档或五档 Bridge(琴桥拾音器):声音更加清晰,音色更突…

[JAVA]介绍怎样在Java中通过字节字符流实现文件读取与写入

一,初识File类及其常用方法 File类是java.io包下代表与平台无关的文件和目录,程序中操作文件和目录,都可以通过File类来完成。 通过这个File对象,可以进行一系列与文件相关的操作,比如判断文件是否存在,获…

第3步VM的虚拟机无法用网络安装直接改用CDROM镜像包安装软件

精简版的CentOS只有ip add可用 ping命令可用其它软件版本太低都不能用,改用光盘镜像来安装软件。 步骤:1、修改Vm的设置,将光盘映像改为ISO文件。 步骤:2、在centos挂载cdrom 步骤:3、挂载成功后直接安装软件 发现软件…

认知杂谈68《燃爆!兄弟萌不可错过的人生开挂宝典》

内容摘要​: 生活如舞台,我们要做自己人生的导演兼主演。实现自我成长需打牢基础,如读《认知觉醒》等书并制定成长计划。 要向上生长,定短期和长期目标,学新技能、提升沟通能力,可借助在线平台和社群。用番…

面试经典150题——多数元素

目录 题目链接:169. 多数元素 - 力扣(LeetCode) 题目描述 示例 提示: 解法一:哈希表 Java写法: C写法: 解法二:它就在那里 Java写法: C写法: 解法…

求n至少为多大时,n个1组成的整数能被2013整除

题目&#xff1a;编写程序&#xff0c;求n至少为多大时&#xff0c;n个1组成的整数能被2013整除 #include<iostream> using namespace std; int main(){int n1;int m1;while(m%2013!0){m(m%2013)*101;n;}cout<<n<<endl;return 0; } 思路&#xff1a;直接用n…

2024年上海小学生古诗文大会倒计时一个月:做几道2024官方模拟题

2024年上海市小学生古诗文大会自由报名活动的初赛日期于10月19日开始&#xff0c;距离今天只有33天了。 那么如何准备2024年的小学生古诗文大会的自由报名初选呢&#xff1f;吃透&#xff08;记熟&#xff09;2024年小学生古诗文阅读专辑上的题目、知识点和往年真题及知识点。…

Linux memcg lru lock提升锁性能

内核关于per memcg lru lock的重要提交&#xff1a; f9b1038ebccad354256cf84749cbc321b5347497 6168d0da2b479ce25a4647de194045de1bdd1f1d 计算虚拟地址转换基本机制 为了处理多应用程序的地址冲突&#xff0c; linux 系统在应用中使用了虚拟地址&#xff0c;得益于硬件的…

【C++题目】1.日期差值

日期差值 题目&#xff1a; 链接&#x1f517;&#xff1a;日期差值 代码&#xff1a; #include <iostream> using namespace std; /* *思路&#xff1a; * 1. 分别求出每一个日期与0000年0月1日距离的天数 * 2. 两个距离天数相减即可得到两个日期相差的天数 *///平年…

AIGC图片相关知识和实战经验(Flux.1,ComfyUI等等)

最近看了网上的一些新闻&#xff0c;flux.1火出圈了&#xff0c;因此自己也尝试跑了一下&#xff0c;作图的质量还是蛮高的&#xff0c;在这里做个知识总结回顾。 flux.1是什么&#xff1f; 根据介绍&#xff0c;flux.1是由stable diffusion 一作&#xff0c;Stability AI的核…

基于ssm的个性化影片推荐系统设计与实现

需要项目源码请联系我&#xff0c;目前有各类成品 毕设 javaweb ssh ssm springboot等等项目框架&#xff0c;源码丰富。 专业团队&#xff0c;咨询就送开题报告&#xff0c;活动限时免费&#xff0c;有需要的朋友可以来咨询。 一、摘要 随着科学技术的飞速发展&#xff0c;社…

matlab DFT的点数与周期

只需要0——N-1个点就可以算得另一个域全部的信号 周期 时域信号的全部长度时一个周期&#xff0c;所以时域的周期化没有混叠 频域的周期与采样率有关&#xff0c;会混叠。 取一个周期进行傅里叶变换都是对于周期化后的信号取得&#xff0c;由于时域周期化不混叠&#xff0c;所…

全方位解读信息架构:从挑战到解决方案,推动企业数字化转型的全面指南

在数字经济迅猛发展的今天&#xff0c;信息架构 已经成为企业实现数字化转型、提高运营效率和优化 IT 投资的关键手段。无论是初创企业还是成熟企业&#xff0c;构建和实施有效的信息架构不仅能支持业务增长&#xff0c;还能确保数据安全和合规性。《信息架构&#xff1a;商业智…

node.js 中的进程和线程工作原理

本文所有的代码均基于 node.js 14 LTS 版本分析 概念 进程是对正在运行中的程序的一个抽象&#xff0c;是系统进行资源分配和调度的基本单位&#xff0c;操作系统的其他所有内容都是围绕着进程展开的 线程是操作系统能够进行运算调度的最小单位&#xff0c;其是进程中的一个执…

Zookeeper学习

文章目录 学习第 1 章 Zookeeper 入门1.1 概述Zookeeper工作机制 1.2 特点1.3 数据结构1.4 应用场景统一命名服务统一配置管理统一集群管理服务器动态上下线软负载均衡 1.5 下载zookeeper 第 2 章 Zookeeper 本地安装2.1 本地模式安装安装前准备配置修改操作 Zookeeper本地安装…

【三方演化博弈】模型构建与模型求解

一、背景介绍二、收益矩阵计算2.1 博弈主体策略2.2 概率2.3 具体公式2.4 计算过程&#xff08;1&#xff09;企业&#xff08;2&#xff09;政府&#xff08;3&#xff09;环境NGO 三、期望与复制动态方程3.1 企业平均期望3.2 政府平均期望3.3 环境NGO平均期望3.4 三方演化博弈…

旋转链表问题(python3)

旋转链表 问题描述解题思路代码实现 问题描述 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3] 链表中节点的数目在范围 [0, 500] 内-100 < Node.va…

robomimic基础教程(一)——基本概念

robosuite和robomimic都是由ARISE Initiative开发的开源工具&#xff0c;旨在推进机器人学习和机器人操作领域的研究。 一、基本概念 robomimic是一个用于机器人示范学习的框架。它提供了在机器人操作领域收集的大量示范数据集&#xff0c;以及用于从这些数据集中学习的离线学…