首页 > 其他分享 >Datawhale------Tiny-universe学习笔记——Qwen

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

时间:2024-09-16 22:50:25浏览次数:11  
标签:None universe self cache Tiny states Qwen hidden config

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:None,universe,self,cache,Tiny,states,Qwen,hidden,config
From: https://blog.csdn.net/m0_74922316/article/details/142302307

相关文章

  • 开源模型应用落地-qwen2-7b-instruct-LoRA微调-unsloth(让微调起飞)-单机单卡-V100(十七)
    一、前言  本篇文章将在v100单卡服务器上,使用unsloth去高效微调QWen2系列模型,通过阅读本文,您将能够更好地掌握这些关键技术,理解其中的关键技术要点,并应用于自己的项目中。  使用unsloth能够使模型的微调速度提高2-5倍。在处理大规模数据或对时间要求较高的场景下......
  • thinkphp5数据库迁移工具 migration(longtext/tinyint等)
    我用tp5创建文件phpthinkmigrate:createUser在User文件里面写publicfunctionup(){$this->table('a3')->addColumn('a','integer',['limit'=>'10','default'=>0,'signed'=&......
  • 实战千问2大模型第三天——Qwen2-VL-7B(多模态)视频检测和批处理代码测试
    画面描述:这个视频中,一位穿着蓝色西装的女性站在室内,背景中可以看到一些装饰品和植物。她双手交叉放在身前,面带微笑,似乎在进行一场演讲或主持活动。她的服装整洁,显得非常专业和自信。一、简介阿里通义千问开源新一代视觉语言模型Qwen2-VL。其中,Qwen2-VL-72B在大部分指标上都......
  • 实战千问2大模型第二天——Qwen2-VL-7B(多模态)的部署和测试
    图片描述:这张图片展示了一辆蓝色的电动公交车停在街道上。公交车上有一个标志,写着“ceroemisiones”,意思是“零排放”。公交车的侧面还有一句标语,写着“Unminibús100%eléctricosiesplan”,意思是“如果计划的话,这是一辆100%电动的迷你巴士”。公交车的前方有一个标志,写......
  • 构建基于Qwen API 的AgentScope 聊天机器人
    环境搭建与库安装首先,我们需要创建一个Python3.10环境。你可以使用conda来创建一个新的虚拟环境,并激活它:condacreate-npy310python==3.10condaactivatepy310接着,安装所需的库agentscope,由于它可能处于预发布阶段,因此我们需要指定--pre标志:pipinstallagentscope--pre获取......
  • 万字解析qinguoyi / TinyWebServer项目的源码
    前言项目地址项目详细介绍本文章适合刚学习完C++基础知识并尝试实现一个网络编程项目的同学,其中包含了该项目的代码逐行注释和解析以及许多刚学习网络编程中会遇到的疑问。项目简介:Linux下C++轻量级Web服务器,助力初学者快速实践网络编程,搭建属于自己的服务器.使用线......
  • llama factory LoRA微调qwen大模型 | 新手炼丹记录(1)
            之前用本地机器微调qwen大模型,结果由于显存不够或者其他配置问题,总是无法正常训练,莫名其妙报错。只能去尝试一些参数很小的模型,qwen2:0.5b、gemma:2b之类的,实在不够看。    今天尝试使用了算力平台AutoDL算力云租赁计算资源来跑微调以及量化,尝试了qwe......
  • 推荐一款开源、高效、灵活的Redis桌面管理工具:Tiny RDM!支持调试与分析功能!
    1、引言在大数据和云计算快速发展的今天,Redis作为一款高性能的内存键值存储系统,在数据缓存、实时计算、消息队列等领域发挥着重要作用。然而,随着Redis集群规模的扩大和复杂度的增加,如何高效地管理和运维Redis数据库成为了许多开发者和运维人员面临的挑战。TinyRDM(TinyRedisDes......
  • 基于Mindformers+mindspore框架在升腾910上进行qwen-7b-chat的lora微调
    基于Mindformers+mindspore框架在昇腾910上进行qwen-7b-chat的8卡lora微调主要参考文档:https://gitee.com/mindspore/mindformers/tree/r1.0/research/qwenSTEP1:环境准备我使用mindformers官方提供的docker镜像进行微调,下载指令:dockerpullswr.cn-central-221.ovaijisuan.......
  • 阿里重磅开源Qwen2-VL:超越人类的视觉理解能力,从医学影像到手写识别,这款开源多模态大模
    阿里重磅开源Qwen2-VL:超越人类的视觉理解能力,从医学影像到手写识别,这款开源多模态大模型究竟有多强?(附本地化部署教程)模型介绍最近呢,阿里巴巴开源了Qwen2-VL,在多模态大模型展现了在实际应用中的巨大潜力,尤其是在处理跨模态数据方面表现出众。以下是该模型的几大应用亮点:智......