当前位置: 首页 > news >正文

【gpt预测与推理区别】

推理时不能并行计算所有位置的主要原因在于生成文本的过程是自回归的,也就是说,生成每个新的单词都依赖于之前已经生成的单词。这个过程需要一步一步地进行,因为每一步的输出会成为下一步的输入。下面是对这个过程的详细解释:

自回归模型的推理过程

自回归模型(如GPT-2)在推理时是基于已经生成的上下文来预测下一个单词的。具体来说:

  1. 初始化:从一个初始种子文本(例如 “and”)开始。
  2. 逐步生成:模型使用当前的输入序列来预测下一个单词。
  3. 更新输入:将新生成的单词追加到输入序列中。
  4. 重复:重复上述步骤,使用更新后的输入序列来生成下一个单词。

为什么不能并行计算所有位置

  1. 依赖关系:每个新生成的单词依赖于之前生成的所有单词。这意味着在生成下一个单词之前,必须先生成当前的单词。

    例如,如果输入是 “and” 并且模型生成了 “established”,那么在生成 “established” 之前不能生成 “himself”。

  2. 逐步更新:输入序列会在每一步更新,新生成的单词会追加到输入序列中作为下一步的输入。这种更新是顺序的,不能提前知道之后的单词。

  3. 非平行计算:因为每一步的输出依赖于前一步的结果,所以不能并行计算每一步的输出。每一步都必须等待前一步的结果,然后才能继续。

训练时的并行计算

在训练过程中,模型已经拥有整个目标序列,可以一次性计算所有位置的预测。这是因为训练数据包含了完整的输入和目标序列( 通过右移动一位,获得了多个训练样本),模型可以在一次前向传播中计算所有位置的预测结果,并与目标序列进行比较来计算损失。

示例:逐步生成 vs. 并行计算

逐步生成

以下是逐步生成文本的示例代码,每一步都依赖于前一步的结果:

import torch
from transformers import GPT2Tokenizer, GPT2LMHeadModel# 加载预训练模型和tokenizer
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')
model = GPT2LMHeadModel.from_pretrained('gpt2')# 初始种子文本
input_text = "and"
input_ids = tokenizer.encode(input_text, return_tensors='pt')# 逐步生成文本
for _ in range(5):  # 假设生成5个词outputs = model(input_ids)logits = outputs.logitsnext_token_id = torch.argmax(logits[:, -1, :], axis=-1)input_ids = torch.cat([input_ids, next_token_id.unsqueeze(-1)], axis=-1)next_token = tokenizer.decode(next_token_id)print(f"Current input: {tokenizer.decode(input_ids[0])}")print(f"New token: {next_token}\n")
并行计算(仅在训练时有效)

以下是训练时的一次性计算所有位置预测结果的示例代码:

import torch
import torch.nn as nn
from transformers import GPT2Tokenizer, GPT2Config, GPT2Modelclass GPT2LMHeadModel(nn.Module):def __init__(self, config):super(GPT2LMHeadModel, self).__init__()self.transformer = GPT2Model(config)self.lm_head = nn.Linear(config.n_embd, config.vocab_size, bias=False)def forward(self, input_ids, labels=None):transformer_outputs = self.transformer(input_ids)hidden_states = transformer_outputs.last_hidden_state# 通过语言模型头(线性层)生成logitslogits = self.lm_head(hidden_states)loss = Noneif labels is not None:# Shift logits and labels for loss computationshift_logits = logits[..., :-1, :].contiguous()shift_labels = labels[..., 1:].contiguous()# Compute the loss using CrossEntropyloss_fct = nn.CrossEntropyLoss()loss = loss_fct(shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1))return (loss, logits) if loss is not None else logits# 加载配置和模型
config = GPT2Config()
model = GPT2LMHeadModel(config)# 加载预训练的tokenizer
tokenizer = GPT2Tokenizer.from_pretrained('gpt2')# 准备输入
input_text = "and established himself in a manner that was both deliberate and efficient."
input_ids = tokenizer.encode(input_text, return_tensors='pt')# 模型前向传播
outputs = model(input_ids, labels=input_ids)# 提取损失和logits
loss, logits = outputsprint(f"Loss: {loss.item()}")
print(f"Logits shape: {logits.shape}")

并行计算:

在训练过程中,所有token的自注意力计算是同时进行的,这意味着每个token都能在一次计算中获取到所有其他预测的token的信息。
这使得模型能够一次性计算所有位置的预测结果。

总结

1、训练时候上下文是已知的可并行
2、训练时候是一次得到所有预测的token
3、推理时候一次只能得到一个token

这说明了训练时候用GPU的高效率,其实推理时候可以用CPU的,如果推理时候CPU里的并行计算矩阵也有,那么cpu成本更低。其次例如特有的LPU(语言处理器)为什么这么快了

在推理过程中,生成新单词必须依赖之前生成的单词,因此每一步都需要等待前一步的结果,这使得并行计算变得不可能。而在训练过程中,由于模型可以一次性获取整个输入和目标序列,所以可以并行计算所有位置的预测结果。这个区别是自回归模型固有的特性,确保模型在生成文本时能够逐步利用上下文信息。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Apache Kylin与BI工具集成:数据可视化实战
  • 树的存储结构
  • 2024最简七步完成 将本地项目提交到github仓库方法
  • IPV6公网暴露下的OPENWRT防火墙安全设置(只允许访问局域网中指定服务器指定端口其余拒绝)
  • virtualbox7安装centos7.9配置静态ip
  • Java 并发编程:Java 线程池的介绍与使用
  • C# 串口通信(通过serialPort控件发送及接收数据)
  • Android 实现屏幕录制
  • GCKontrol-GCAir工具链在飞机功能系统设计中的应用
  • 安装 electron 报错解决
  • 你有GitHub Models,我有CSGHub和StarShip
  • 谷粒商城实战笔记-105~107-全文检索-ElasticSearch-入门
  • Mac OS平台,利用 gifify 制作gif教程
  • RK3568笔记五十:SPI通信-回环测试
  • vue3表格组件formatter
  • @angular/forms 源码解析之双向绑定
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Angular 响应式表单之下拉框
  • HTTP那些事
  • IOS评论框不贴底(ios12新bug)
  • PHP 使用 Swoole - TaskWorker 实现异步操作 Mysql
  • php中curl和soap方式请求服务超时问题
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • swift基础之_对象 实例方法 对象方法。
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • vue自定义指令实现v-tap插件
  • 阿里云购买磁盘后挂载
  • - 概述 - 《设计模式(极简c++版)》
  • 记一次用 NodeJs 实现模拟登录的思路
  • 面试遇到的一些题
  • 那些年我们用过的显示性能指标
  • 浅谈web中前端模板引擎的使用
  • 如何进阶一名有竞争力的程序员?
  • 如何在 Tornado 中实现 Middleware
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 小程序01:wepy框架整合iview webapp UI
  • 一道面试题引发的“血案”
  • 最近的计划
  • 交换综合实验一
  • 新海诚画集[秒速5センチメートル:樱花抄·春]
  • ​ ​Redis(五)主从复制:主从模式介绍、配置、拓扑(一主一从结构、一主多从结构、树形主从结构)、原理(复制过程、​​​​​​​数据同步psync)、总结
  • ​字​节​一​面​
  • #if和#ifdef区别
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • $.proxy和$.extend
  • (6)STL算法之转换
  • (TOJ2804)Even? Odd?
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (七)c52学习之旅-中断
  • (三)mysql_MYSQL(三)
  • (三分钟)速览传统边缘检测算子
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (转)清华学霸演讲稿:永远不要说你已经尽力了