【大模型推理】大模型前向推理过程详解

news2024/11/25 13:00:32

文章目录

  • 前期准备
    • 环境安装
    • 下载模型
    • Qwen2-7b模型架构
    • vscode配置launch.json文件
  • 前向推理debug深入分析
    • 预测第一个next_token
    • 预测第二个next_token

为了搞清楚,大模型前向推理的具体流程,本文以Qwen2-7B-Instruct为例,通过直接debug官方推理示例,来深入理解其过程。

前期准备

环境安装

特别注意的是transformers库的版本,本文的版本为 transformers== 4.44.2

下载模型

下载Qwen2-7B-Instruct:

# 安装huggingface-cli工具
pip install -U "huggingface_hub[cli]"

# 切换huggingface镜像
export HF_ENDPOINT=https://hf-mirror.com

# 下载Qwen2-7B-Instruct到本地指定目录:
huggingface-cli download  --resume-download Qwen/Qwen2-7B-Instruct --repo-type model --local-dir /data/models/Qwen/Qwen2-7B-Instruct

Qwen2-7b模型架构

加载模型后打印模型结构:

Qwen2Model(
  (embed_tokens): Embedding(152064, 3584)
  (layers): ModuleList(
    (0-27): 28 x Qwen2DecoderLayer(
      (self_attn): Qwen2SdpaAttention(
        (q_proj): Linear(in_features=3584, out_features=3584, bias=True)
        (k_proj): Linear(in_features=3584, out_features=512, bias=True)
        (v_proj): Linear(in_features=3584, out_features=512, bias=True)
        (o_proj): Linear(in_features=3584, out_features=3584, bias=False)
        (rotary_emb): Qwen2RotaryEmbedding()
      )
      (mlp): Qwen2MLP(
        (gate_proj): Linear(in_features=3584, out_features=18944, bias=False)
        (up_proj): Linear(in_features=3584, out_features=18944, bias=False)
        (down_proj): Linear(in_features=18944, out_features=3584, bias=False)
        (act_fn): SiLU()
      )
      (input_layernorm): Qwen2RMSNorm((3584,), eps=1e-06)
      (post_attention_layernorm): Qwen2RMSNorm((3584,), eps=1e-06)
    )
  )
  (norm): Qwen2RMSNorm((3584,), eps=1e-06)
)

Qwen2-7B-Instruct对应的config.json文件:

{
  "architectures": [
    "Qwen2ForCausalLM"
  ],
  "attention_dropout": 0.0,
  "bos_token_id": 151643,
  "eos_token_id": 151645,
  "hidden_act": "silu",
  "hidden_size": 3584,
  "initializer_range": 0.02,
  "intermediate_size": 18944,
  "max_position_embeddings": 32768,
  "max_window_layers": 28,
  "model_type": "qwen2",
  "num_attention_heads": 28,
  "num_hidden_layers": 28,
  "num_key_value_heads": 4,
  "rms_norm_eps": 1e-06,
  "rope_theta": 1000000.0,
  "sliding_window": 131072,
  "tie_word_embeddings": false,
  "torch_dtype": "bfloat16",
  "transformers_version": "4.41.2",
  "use_cache": true,
  "use_sliding_window": false,
  "vocab_size": 152064
}

可以看到以下几个关键信息:

  • 一共28层hidden_layers,每一层的K和V矩阵维度一共是512,num_attention_heads=28表示每一层应该有28个head,也就是28个K和V,但是因为num_key_value_heads=4,所以每7个head共享K和V参数,也就是有4组不同的K和V,每个K和V矩阵维度是512/4=128
  • 输入最大长度是32768
  • 词表大小是152064
  • 默认使用 KV_cache

ok,前期熟悉模型的工作到这里就差不多结束了,下面开始配置vscode:

vscode配置launch.json文件

这里借鉴yuanzhoulvpi大佬的工作,使用非常优雅的方式来debug代码,首先在vscode中,代码目录下,创建launch.json文件,直接copy以下内容:

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "sh_file_debug",
      "type": "debugpy",
      "request": "attach",
      "connect": {
        "host": "localhost",
        "port": 9501
      },
      "justMyCode": false
    }
  ]
}

要特别注意的是,需要设置justMyCode=false,这样debug时才可以进入环境安装时的库文件。

然后,在运行主代码的开头,添加如下代码:

import debugpy
try:
    # 5678 is the default attach port in the VS Code debug configurations. Unless a host and port are specified, host defaults to 127.0.0.1
    debugpy.listen(("localhost", 9501))
    print("Waiting for debugger attach")
    debugpy.wait_for_client()
except Exception as e:
    pass

完整代码如下,并命名为main.py文件:

from transformers import AutoModelForCausalLM, AutoTokenizer

# 代码地址:https://github.com/yuanzhoulvpi2017/vscode_debug_transformers
import debugpy
try:
    # 5678 is the default attach port in the VS Code debug configurations. Unless a host and port are specified, host defaults to 127.0.0.1
    debugpy.listen(("localhost", 9501))
    print("Waiting for debugger attach")
    debugpy.wait_for_client()
except Exception as e:
    pass


model_name = "/root/autodl-tmp/renruilong/models/Qwen/Qwen2-7B-Instruct"
device = "cuda" # the device to load the model onto

model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype="auto",
    device_map="auto"
)

tokenizer = AutoTokenizer.from_pretrained(model_name)

prompt = "Give me a short introduction to large language model."

messages = [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": prompt}
]

text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True
) 
# <|im_start|>system\nYou are a helpful assistant.<|im_end|>\n<|im_start|>user\nGive me a short introduction to large language model.<|im_end|>\n<|im_start|>assistant\n'

model_inputs = tokenizer([text], return_tensors="pt").to(device)
'''
{'input_ids': tensor([[151644,   8948,    198,   2610,    525,    264,  10950,  17847,     13,
         151645,    198, 151644,    872,    198,  35127,    752,    264,   2805,
          16800,    311,   3460,   4128,   1614,     13, 151645,    198, 151644,
          77091,    198]], device='cuda:0'), 
 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1]], device='cuda:0')}
'''
generated_ids = model.generate(
    **model_inputs,
    max_new_tokens=512
)

generated_ids = [
    output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
]

response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]

print(response)

前向推理debug深入分析

首先,我们需要打开三个文件:

  • 上面的运行文件main.py
  • 环境安装的transformer库中的~/transformers/models/qwen2/modeling_qwen2.py,主要关注位于1057行的def forward函数
  • 环境安装的transformer库中的~/transformers/generation/utils.py,主要关注位于2888行的def _sample函数

预测第一个next_token

首先,我们需要在utils.py文件中打个断点:

在这里插入图片描述

然后运行main.py文件,terminal出现Waiting for debugger attach,我们点击debug按钮,如下图所示:

在这里插入图片描述

等待模型加载,并且停在我们打的断点处:

在这里插入图片描述

然后,我们运行到 outputs = self(**model_inputs, return_dict=True)处,停下来先看一下即将传入到模型forward函数的参数长什么样子:

在这里插入图片描述
可以看到:

  • 输入token序列的维度为[1, 29]
  • 此时的KV cache均为空

接着我们跳转到modeling_qwen2.py文件的forward函数中,运行到loss = None处,停下来查看输出结果的情况:

在这里插入图片描述

可以看到:

  • 第一次前向,输出的维度是[1, 29, 3584]和输入维度[1, 29]一致,这里我们应该知道,这29个特征中最后一个是我们第一次前向,预测的next_token所表示的特征
  • 经过lm_head后,维度变为[1, 29, 152064],也就是转换为词表中所有index对应的logits

接着,返回utils.py文件,运行到if do_sample:处停下来查看此时的变量情况:

在这里插入图片描述

可以看到:

  • 我们取出模型输出的最后一个特征,作为next_token_logits
  • 此时的next_token_logits值还没有被处理(也就是没有被采样)

我们继续往下运行,logits_warper(input_ids, next_token_scores)会根据 temperature,top_p以及top_k参数,来筛选候选token,并且将其他token的logits值置为-inf(为了后续softmax置为0):

在这里插入图片描述

接着,对候选的token做softmax,然后选择其中一个作为最终的next_token,注意,这里选择是next_token_scores没有被置-inf的索引index,这里候选的token是两个 32, 34253,我们一开始的logits值是:tensor([35.8929, 34.4643], device='cuda:0'),softmax后的结果是 tensor(0.8067, device='cuda:0'), tensor(0.1933, device='cuda:0')

在这里插入图片描述

继续运行,程序主要做的操作:

  • 更新input_ids序列
  • 更新model_kwargs字典,尤其是past_key_valuescache_position两个变量,直接关系到第二次前向推理,以及之后所有的前向推理过程。

在这里插入图片描述

预测第二个next_token

接着运行第二次前向推理,此时模型的输入序列情况:
在这里插入图片描述

运行模型的forward函数,此时的模型输出结果:

在这里插入图片描述
可以看到,可以第一次明显不同“

  • 输入维度为[1, 1],也就是第一次输出的next_token值
  • 输出维度为[1, 1, 3584],也就是第二次输出的next_token对应的特征值

模型在第二次前向以及之后的前向推理时,会直接读取已经缓存的KV cache,根据当前输入token的Q进行attention的计算,最后输出next_token对应的特征

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

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

相关文章

战外网配置——光猫桥接+路由器PPPoE拨号+防火墙外网链路健康检查+外网流量负载均衡

一、适用场景&#xff1a; 1、企业规模较大时&#xff0c;1条公网带宽流量可能不足&#xff0c;需要用到多条公网出口时。 2、企业有业务需要静态ip映射&#xff0c;但是因静态ip专线价格较高&#xff0c;所以需要拨号光纤承载较多的下行流量。 3、当公网出口有多条链路&#…

最大矩阵和

题目描述 给定一个二维整数矩阵&#xff0c;要在这个矩阵中选出一个子矩阵. 使得这个子矩阵内所有的数字和尽量大&#xff0c;我们把这个子矩阵称为和最大子矩阵 子矩阵的选取原则是原矩阵中一块相互连续的矩形区域。 输入描述 输入的第一行包含2个整数n,m(1< n,m< 10…

C++设计模式——Interpreter解释器模式

一&#xff0c;解释器模式的定义 解释器模式是一种行为型设计模式&#xff0c;它用于定义一个语言的文法并解析语言中的表达式&#xff0c;使开发者可以实现自定义语言&#xff0c;并通过解释器对语言中的表达式进行解析和执行。 解释器模式主要用于解决对特定表达式的解析与…

python-游戏自动化(三)(实战-豆腐女孩)

前提准备 特别注意&#xff1a; 本节教程所演示的模拟器分辨率设置为 720x1080&#xff08;手机版&#xff09;&#xff0c;电脑分辨率设置大720x1080并且没有设置放大。 今天的课程开始之前我们来回顾一下昨天所学的知识内容&#xff0c;因为今天要学的内容和昨天内容…

CogView-3-Plus:深度解锁智谱AI的图像生成新力量

一、引言&#xff1a;AI助力创意与效率的全面提升 在如今这个瞬息万变的科技时代&#xff0c;AI大模型早就不是实验室里的“神秘武器”&#xff0c;它们已经实实在在地融入到我们的日常工作中了&#xff0c;尤其是在图像生成和内容创作这块儿&#xff0c;简直是效率神器。只要几…

Leetcode3270. 求出数字答案

Every day a Leetcode 题目来源&#xff1a;3270. 求出数字答案 解法1&#xff1a;模拟 按题意模拟。 代码&#xff1a; /** lc appleetcode.cn id3270 langcpp** [3270] 求出数字答案*/// lc codestart class Solution { public:int generateKey(int num1, int num2, int…

基于python+django+vue鲜花商城系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的线…

反射(java)

一、junit单元测试框架 1、单元测试 就是针对最小的功能单元&#xff08;方法&#xff09;&#xff0c;编写测试代码对其进行正确性测试。 之前的是如何进行单元测试的&#xff1f; 有啥问题&#xff1f; 1、只能在ma方法编写测试代码&#xff0c;去调用其他方法进行测试。…

CCS811二氧化碳传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理介绍 三、程序设计 main.c文件 ccs811.h文件 ccs811.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 CCS811模块是一种气体传感器&#xff0c;可以测量环境中TVOC(总挥发性有机物质)浓度和eCO2…

OPPO 全家桶:Find X8/Pro、Pad3 Pro与Enco X3即将10月登场

随着科技的不断发展&#xff0c;智能手机、平板电脑和耳机等电子产品已经成为我们日常生活中不可或缺的一部分。 作为全球知名的科技企业&#xff0c;OPPO一直致力于为消费者提供优质的产品和服务。 近日&#xff0c;有关OPPO全家桶将在10月份“凑齐”的消息引起了广泛关注。…

Elemnt-UI + 递归组件实现后台管理系统左侧菜单

Elemnt-UI 递归组件实现后台管理系统左侧菜单 在 Vue.js 中&#xff0c;允许你编写一个组件来表示一个节点&#xff0c;而这个节点可以包含多个子节点&#xff0c;每个子节点又可以是同样的组件。这种方式使得组件能够处理无限层级的嵌套结构。 应用场景 递归组件非常适合处…

2013年

B D B C D 分支结点是非叶结点 B 47 C A C C D D C A C

2010-2022年各省乡村振兴新质生产力相关变量数据(40+指标)

2010-2022年各省乡村振兴新质生产力相关变量数据&#xff08;40指标&#xff09; 1、时间&#xff1a;2010-2022年 2、来源&#xff1a;统计年鉴、能源统计年鉴、农村统计年鉴、人口和就业统计年鉴、城乡建设统计年鉴以及各省份统计年鉴 3、指标&#xff1a;省份、年份、分地…

信号量(二值信号量和计数信号量)和互斥量

信号量 信号量&#xff08;Semaphore&#xff09; 是一种实现任务间通信的机制&#xff0c; 可以实现任务之间同步或临界资源的互斥访问&#xff0c; 常用于协助一组相互竞争的任务来访问临界资源。 在多任务系统中&#xff0c; 各任务之间需要同步或互斥实现临界资源的保护&a…

图神经网络介绍3

1. 图同构网络&#xff1a;Weisfeiler-Lehman 测试与图神经网络的表达力 本节介绍一个关于图神经网络表达力的经典工作&#xff0c;以及随之产生的另一个重要的模型——图同构网络。图同构问题指的是验证两个图在拓扑结构上是否相同。Weisfeiler-Lehman 测试是一种有效的检验两…

第二期: 第二节 , 逻辑编程 , gpio

1 首先就是 看原理图&#xff1a; 这里有两个 &#xff2c;&#xff25;&#xff24; 核心板的原理图。 可以看到 是这个脚。 &#xff12; 然后就是 查看数据手册。 从 数据手册可以看出 &#xff0c;一共有这么多的 gpio 组&#xff0c; 但是这些 组 是有复用的&#xf…

多文件编程实现链表创建,插入,输出(上)

linklist.c #include "linklist.h" //创建空的链表&#xff0c;为头结点在堆区分配空间 linklist_t *creat_empty_linklist() {linklist_t *head NULL;head (linklist_t *) malloc(sizeof(linknode_t));if(NULL head){printf("malloc is fail!\n");ret…

网格参数的应用和数学基础

引言 对于任意两个拓扑结构相似的表面&#xff0c;可以计算它们之间的一一对应映射。如果其中一个表面由三角形网格表示&#xff0c;那么计算这种映射的问题被称为网格参数化。映射到的表面通常被称为参数域。表面网格与各种域之间的参数化在计算机图形学和几何处理中有广泛的应…

移动WEB开发(第二天)_flex布局

移动WEB开发&#xff08;第二天&#xff09;_flex布局 移动web开发——flex布局1.0传统布局和flex布局对比1.1传统布局1.2 flex布局1.3 建议 2.0 flex布局原理3.0 父项常见属性3.1 flex-direction设置主轴的方向3.2 justify-content 设置主轴上的子元素排列方式3.3 flex-wrap设…

9月美联储决策前哨战——美国CPI数据来袭

随着本周关键CPI数据的即将发布&#xff0c;市场正翘首以待&#xff0c;这将是美联储在9月17日至18日议息会议前获取的最后一块重要经济拼图。鉴于美联储官员已进入传统的政策静默期&#xff0c;8月份的CPI报告无疑将成为交易员们评估未来货币政策走向的重要标尺。 欧洲央行降…