还有人用asp做网站吗,管理咨询公司swot,wordpress做网站,所有网站域名都有简介
要想了解一个模型的效果#xff0c;对模型进行一些评测#xff0c;或去评估是否能解决业务问题时#xff0c;首要任务是如何将模型跑起来。目前有较多方式运行模型#xff0c;提供client或者http能力。
名词解释
浮点数表示法
一个浮点数通常由三部分组成#xf…简介
要想了解一个模型的效果对模型进行一些评测或去评估是否能解决业务问题时首要任务是如何将模型跑起来。目前有较多方式运行模型提供client或者http能力。
名词解释
浮点数表示法
一个浮点数通常由三部分组成符号位、指数部分和尾数部分也称为小数部分或 mantissa。
符号位决定了数的正负。在大多数浮点数格式中符号位通常占1位0表示正数1表示负数。指数部分Exponent表示数值的大小或缩放因子。在浮点数中指数部分采用偏移码bias encoding来表示以确保0的特殊处理和指数的正负表示。例如在IEEE 754标准的单精度float32中指数部分实际占8位但由于偏移码通常偏移127实际的指数范围是从-126到127。尾数部分Mantissa或Fraction代表小数部分它是一个小于1的正数用来精确表示数值的非整数部分。在标准的浮点数表示中尾数部分总是以1开头这个1是隐含的不占用实际的位然后是若干位来表示其余的数字。例如在float32中尾数部分实际有23位因为隐含了一个1这提供了很高的精度。
以一个具体的例子来说明假设我们有一个二进制浮点数格式为1位符号位8位指数部分23位尾数部分。一个浮点数的值计算方式大致为(-1)^符号位 × 1.尾数部分 × 2^(指数部分 - 偏移值)。
torch_dtype
在PyTorch中torch_dtype参数是一个用于指定张量tensor数据类型的选项通常可用以下取值
auto自动判断读取模型目录的config.json中配置的torch_dtype值如果是bfloat16且当前硬件支持bfloat16则优先使用这种判断是否支持float16不支持才使用float32。torch.bfloat161位符号位、8位指数部分、7位尾数此种类型牺牲了一些精度但保持了与单精度float32相同的指数范围这在处理大范围数值和保持动态范围方面非常有利。torch.float16标准的16位浮点数格式由1位符号位、5位指数部分、10位小数部分组成。与bfloat16相比它有更精细的尾数精度但在指数范围上较窄这意味着它在处理非常大或非常小的数值时可能不够稳定。torch.float32单精度浮点数由1位符号位、8位指数部分使用偏移编码偏移值为127和23位尾数部分组成。torch.float64由1位符号位、11位指数部分使用偏移编码偏移值为1023和52位尾数部分组成。其它torch.int8, unit8, int32, int64等类型。
chat template
基础模型只提供了completion能力在大模型发展的过程中很多公司都推出了针对聊天的chat模型这类模型将用户分为了system, user, assistant角色将不同角色的输入内容用特定的token分隔开使得模型能够更好的理解上下文给出更精确的答复。
此外模型在训练的时候就提供了一些数据集使得system中提供的消息优先级高于user多模型的安全性也有一定的帮助避免用户在user message中改变system message对于模型的一些设置
transformers框架已经原生支持了这一模式通过执行以下代码帮助拼接prompt
from transformers import AutoModelForCausalLM, AutoTokenizertokenizer AutoTokenizer.from_pretrained(Qwen/Qwen1.5-7B-Chat)
prompt Give me a short introduction to large language model.
messages [{role: system, content: You are a helpful assistant.},{role: user, content: prompt}
]
# 这样不进行tokenize测试下效果直接输出拼接后的string
# 如果想直接进行tokenize需要传递参数tokenizeTrue(默认就是), return_tensorspt
text tokenizer.apply_chat_template(messages,tokenizeFalse,add_generation_promptTrue
)以上代码会去加载模型目录的tokenizer_config.json文件读取需要的信息这里以qwen1.5模型为例需要读取json中的以下字段
{chat_template: {% for message in messages %}{% if loop.first and messages[0][role] ! system %}{{ |im_start|system\nYou are a helpful assistant.|im_end|\n }}{% endif %}{{|im_start| message[role] \n message[content] |im_end| \n}}{% endfor %}{% if add_generation_prompt %}{{ |im_start|assistant\n }}{% endif %},
}由于指定了add_generation_promptTrue生成的拼接后的字符串如下
|im_start|system
You are a helpful assistant.|im_end|
|im_start|user
Give me a short introduction to large language model.|im_end|
|im_start|assistantCUDA_VISIBLE_DEVICES
在 PyTorch 中你可以使用 CUDA_VISIBLE_DEVICES 环境变量来指定可见的 GPU 设备。这个环境变量的值是一个以逗号分隔的 GPU 设备索引列表可以是单个索引也可以是多个索引组成的列表。
export CUDA_VISIBLE_DEVICES0,1 # 只使用 GPU 0 和 GPU 1
export CUDA_VISIBLE_DEVICES0 # 只使用 GPU 0
# 不使用任何 GPU将模型运行在 CPU 上
export CUDA_VISIBLE_DEVICES
export CUDA_VISIBLE_DEVICES device_map
device_map 参数是 Hugging Face transformers 库中一种用于控制模型在多个设备上分配的参数。它可以让你明确指定模型的哪些部分应该分配到哪个设备上以优化模型的性能和内存使用。可以取以下值
auto自动选择合适的设备来分配模型根据系统的可用资源和模型的大小智能选择设备。目前auto和balanced效果一样但后续可能会修改。balanced均匀地将模型分配到所有可用设备上以平衡内存使用。balanced_low_0将模型均匀地分配到除第一个 GPU 外的所有 GPU 上并且只将不能放入其他 GPU 的部分放在 GPU 0 上。sequential将模型层按顺序分配到多个设备上模型的第一层分配给第一个设备第二层分配给第二个设备依此类推。当模型层数超过可用设备数量时会循环回到第一个设备再次分配模型层。自定义映射你还可以提供一个字典明确指定每个模型层应该分配到哪个设备上。
查看设备分配的情况
# 查看主设备
model AutoModelForCausalLM.from_pretrained(model_name, device_mapauto)
print(model.device)# 查看每一层所在的设备
model AutoModelForCausalLM.from_pretrained(model_name, device_mapauto)
for name, param in model.named_parameters():print(name, param.device)max_memory
当模型在多个设备上运行时max_memory 参数可以帮助你限制每个设备上模型的内存使用以防止内存溢出或超出系统资源限制。你可以提供一个字典将设备名称例如 cuda:0、cuda:1 或 cpu映射到相应的最大内存使用量例如 10GB、20GB 或 10240MB
max_memory {0:5GB, 1:13GB}
model AutoModelForCausalLM.from_pretrained(model_name, device_mapauto, max_memorymax_memory)查看每个卡的gpu使用情况和能分配的最大内存
# 这里的gpu_id是基于CUDA_VISIBLE_DEVICES可见设备不是实际的卡位置
num_gpus torch.cuda.device_count()
for gpu_id in range(num_gpus):torch.cuda.set_device(gpu_id)allocated_memory torch.cuda.memory_allocated(gpu_id)max_memory_allocated torch.cuda.max_memory_allocated(gpu_id)print(fGPU {gpu_id}: Allocated Memory: {allocated_memory / 1024**3:.2f} GB, Max Allocated Memory: {max_memory_allocated / 1024**3:.2f} GB)下载模型
驱动下载https://www.nvidia.com/Download/index.aspx?langen-us
可以通过以下网站搜索模型 https://huggingface.co (基于transformers架构模型的官方地址一般新模型这里第一时间商家可能需要翻墙) https://hf-mirror.com (huggingface的镜像站) https://www.modelscope.cn (阿里云推出的一个模型开放平台国内下载速度较快但是更新可能不是太及时)
设置pip镜像站export PIP_INDEX_URLhttps://pypi.tuna.tsinghua.edu.cn/simple
运行模型的时候如果模型不存在会自动去下载模型你也可以提前通过以下方式将模型下载好
通过hugging face下载
pip install huggingface_hub
# 设置镜像站
export HF_ENDPOINThttps://hf-mirror.com
# 修改模型下载的目录可选默认是~/.cache/huggingface/hub
export HF_HUB_CACHE/data/modelscope
# 需要授权的仓库需要登录可选https://huggingface.co/settings/tokens
huggingface-cli login --token your hugging face token
# 下载qwen1.5-7b-chat模型
huggingface-cli download --resume-download Qwen/Qwen1.5-7B-Chat通过modelscope下载
pip install modelscope
# 修改模型下载的目录可选默认是~/.modelscope
export MODELSCOPE_CACHE/data/modelscope# python3
from modelscope import snapshot_download
model_dir snapshot_download(qwen/Qwen1.5-7B-Chat)运行模型
为了支持模型的版本控制、快速下载和增量更新huggingface下载的模型结构blobs、refs和snapshot几个目录 blobs: 这个目录存储了模型的实际权重数据和其他二进制文件。这些文件通常很大包含了模型训练得到的参数。每个blob可以看作是一个独立的数据块这样设计有利于分块下载和缓存特别是在更新模型时如果只有少量更改用户只需下载变化的部分。 refs: 这部分涉及到版本控制。它存储了指向特定模型版本的引用包括提交哈希commit hashes或者其他版本标识符。这使得用户可以明确地指定使用模型的哪个版本同时也方便开发者维护模型的历史变更。 snapshot: 这个目录通常包含了一个模型版本的快照它是一个特定时间点模型的状态。快照通常包含了指向blobs中具体权重文件的指针确保了模型的完整下载和加载。以commit id作为文件夹。
modelscope下载下来的模型文件并没有按照这个规则它直接存储的是模型的检查点checkpoint包含权重文件、状态、配置等加载modelscope下载的模型需要导入modelscope相应的包如
# huggingface 风格
from transformers import AutoModelForCausalLM, AutoTokenizer# modelscope 风格
from modelscope import AutoModelForCausalLM, AutoTokenizer也可以直接将模型的目录作为checkpoint_path参数传入这样huggingface就会作为checkpoint去加载模型而不是去下载。
import os
from transformers import AutoModelForCausalLM, AutoTokenizer# modelscope下载模型的存储目录这里以qwen1.5-7b-chat作为示例
checkpoint_path os.getenv(MODELSCOPE_CACHE) /qwen/Qwen1___5-7B-Chat
model AutoModelForCausalLM.from_pretrained(checkpoint_path, torch_dtypeauto, device_mapauto).eval()
tokenizer AutoTokenizer.from_pretrained(checkpoint_path)阻塞运行模型
模型下载页面一般提供了运行模型的测试代码有些在github仓库中提供了运行示例。
from transformers import AutoModelForCausalLM, AutoTokenizer
device cuda # the device to load the model ontocheckpoint_path Qwen/Qwen1.5-7B-Chat
model AutoModelForCausalLM.from_pretrained(checkpoint_path,torch_dtypeauto,device_mapauto
).eval()
tokenizer AutoTokenizer.from_pretrained(checkpoint_path)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,tokenizeFalse,add_generation_promptTrue
)
model_inputs tokenizer([text], return_tensorspt).to(device)generated_ids model.generate(model_inputs.input_ids,max_new_tokens512
)
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_tokensTrue)[0]
print(response)
流式运行模型
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Thread
device cuda # the device to load the model ontocheckpoint_path Qwen/Qwen1.5-7B-Chat
model AutoModelForCausalLM.from_pretrained(checkpoint_path,torch_dtypeauto,device_mapauto
).eval()
tokenizer AutoTokenizer.from_pretrained(checkpoint_path)prompt Give me a short introduction to large language model.
messages [{role: system, content: You are a helpful assistant.},{role: user, content: prompt}
]
input_ids tokenizer.apply_chat_template(messages, add_generation_promptTrue, return_tensorspt).to(device)
streamer TextIteratorStreamer(tokenizertokenizer, skip_promptTrue, timeout60.0, skip_special_tokensTrue)generation_kwargs dict(input_idsinput_ids, streamerstreamer, max_new_tokens20)
thread Thread(targetmodel.generate, kwargsgeneration_kwargs)
thread.start()for new_text in streamer:print(new_text, end, flushTrue)
并行推理
通过并行计算来利用多GPU资源分为两种场景
torch.nn.DataParallel多个GPU上并行处理数据批次data batches来加速训练。它在单个节点上工作自动将输入数据分割成多个部分每个部分在不同的GPU上进行前向传播然后将结果合并。它通常通过模型的复制来实现并行计算每个GPU上都有一个模型副本。model.parallelize它不仅在数据层面并行还在模型层面并行利用了NCCL等库来协调多GPU间通信可以对模型的不同层进行并行计算。适用于大型模型的训练尤其是那些单个GPU内存无法容纳的模型或者需要在多节点多GPU环境下进行分布式训练的情况。
数据批次并行
import osimport torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Threaddevice cuda # the device to load the model onto
checkpoint_path os.getenv(MODELSCOPE_CACHE) /qwen/Qwen1___5-7B-Chat
model AutoModelForCausalLM.from_pretrained(checkpoint_path,torch_dtypeauto,device_mapauto
).eval()
if torch.cuda.is_available():num_gpus torch.cuda.device_count()if num_gpus 1:print(fFound {num_gpus} GPUs, model is now parallelized.)model torch.nn.DataParallel(model)tokenizer AutoTokenizer.from_pretrained(checkpoint_path)prompt Give me a short introduction to large language model.
messages [{role: system, content: You are a helpful assistant.},{role: user, content: prompt}
]
input_ids tokenizer.apply_chat_template(messages, add_generation_promptTrue, return_tensorspt).to(device)
streamer TextIteratorStreamer(tokenizertokenizer, skip_promptTrue, timeout60.0, skip_special_tokensTrue)generation_kwargs dict(input_idsinput_ids, streamerstreamer, max_new_tokens512)
thread Thread(targetmodel.generate, kwargsgeneration_kwargs)
thread.start()for new_text in streamer:print(new_text, end, flushTrue)
模型数据批次并行
并不是所有的模型都支持这种方式
import osimport torch
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
from threading import Threaddevice cuda # the device to load the model onto
checkpoint_path os.getenv(MODELSCOPE_CACHE) /qwen/Qwen1___5-7B-Chat
model AutoModelForCausalLM.from_pretrained(checkpoint_path,torch_dtypeauto,device_mapauto
).eval()
if torch.cuda.is_available():num_gpus torch.cuda.device_count()if num_gpus 1:print(fFound {num_gpus} GPUs, model is now parallelized.)model.parallelize()tokenizer AutoTokenizer.from_pretrained(checkpoint_path)prompt Give me a short introduction to large language model.
messages [{role: system, content: You are a helpful assistant.},{role: user, content: prompt}
]
input_ids tokenizer.apply_chat_template(messages, add_generation_promptTrue, return_tensorspt).to(device)
streamer TextIteratorStreamer(tokenizertokenizer, skip_promptTrue, timeout60.0, skip_special_tokensTrue)generation_kwargs dict(input_idsinput_ids, streamerstreamer, max_new_tokens512)
thread Thread(targetmodel.generate, kwargsgeneration_kwargs)
thread.start()for new_text in streamer:print(new_text, end, flushTrue)