〇、媒介
近来在做大模型压缩这一块,我感觉从拿到一个模型,到选取一个对象选取一种压缩方法,最后查看压缩的结果,这应该算是一次完整的流程了。
一、模型的选择
Transformer、LLaMA、BERT、GPT 之间既有精密联系,也有显著区别。它们都是基于 Transformer 的架构,但在设计、使命、预练习方式和应用场景上有所不同。
1. Transformer
特点:
- 架构: Transformer 是谷歌在 2017 年提出的一种全新的神经网络架构,摒弃了传统的循环神经网络(RNN)和卷积神经网络(CNN),接纳了 自注意力机制(self-attention) 进行序列数据的处理。
- 编码器-解码器结构: Transformer 的原始架构包含一个编码器和一个解码器,最初用于机器翻译使命。编码器将输入序列转换为一组表现,解码器基于这些表现生成输出序列。
- 自注意力机制: 自注意力机制使 Transformer 可以或许并行处理数据,办理了 RNN 中序列依赖问题,且能更好地捕捉长间隔的依赖关系。
应用:
Transformer 是后续浩繁模型的基础架构,包括 BERT、GPT、T5 等。它的自注意力机制使得模型可以或许更有效地处理长文本序列,并在多个 NLP 使命中体现精彩。
2. BERT(Bidirectional Encoder Representations from Transformers)
特点:
- 双向编码器: BERT 是基于 Transformer 的编码器部分 构建的,但与原始 Transformer 的自回归生成不同,BERT 通过双向的方式进行文本建模。它会同时考虑一个词前后的上下文,这种 双向注意力 的机制使得 BERT 在文本明白使命中非常强大。
- 预练习使命: BERT 使用了两种主要的预练习使命:
- Masked Language Model (MLM):在练习时随机屏蔽部分词汇,让模型根据上下文预测这些词汇。这种方式让 BERT 可以或许明白上下文信息。
- Next Sentence Prediction (NSP):让模型预测两句话是否在语料库中精密相连,资助模型学习句子间的关系。
- 下游使命微调: BERT 是通过大量无监督预练习后,再在特定使命上进行有监督的微调,适应各种下游使命,如情感分析、问答、文天职类等。
应用:
BERT 被广泛用于各种 文本明白 使命,如分类、问答、命名实体辨认(NER)等。它并不擅永生成使命,因为它只使用了 Transformer 的编码器部分,无法生成新的文本。
联系:
- BERT 和 Transformer 精密相连,BERT 直接基于 Transformer 的编码器架构构建,主要用于明白使命。
3. GPT(Generative Pretrained Transformer)
特点:
- 自回归生成模型: GPT 是基于 Transformer 的解码器部分 构建的。与 BERT 不同,GPT 是一个 自回归模型,它通过生成下一个词来徐徐生成整个序列。在生成下一个词时,GPT 仅使用前面的上下文,而不依赖于将来的词,因此是 单向 的。
- 预练习使命: GPT 通过 语言模型预练习(Language Model Pretraining) 进行预练习,即给定一个序列,预测下一个词。这种自回归方式使 GPT 在生成使命上具有很强的能力。
- 模型版本:
- GPT-2:通过大规模练习,GPT-2 显现了强大的生成能力,能生成连贯的长文本。
- GPT-3:GPT-3 扩展了模型的规模,拥有 1750 亿参数,不仅在文本生成使命中体现良好,还能通过提示完成多种使命,险些无需微调。
应用:
GPT 系列模型尤其善于 文本生成使命,如对话生成、机器翻译、文本补全、编写文章等。GPT 也可以应用于部分文本明白使命,但其设计初志主要是为了生成使命。
联系:
- GPT 也是基于 Transformer 架构,但它只使用了 解码器部分,并通过自回归方式生成文本。与 BERT 的双向编码器不同,GPT 是单向解码器。
4. LLaMA(Large Language Model Meta AI)
特点:
- 轻量化大模型: LLaMA 是由 Meta(Facebook) 提出的 大语言模型,目标是提供一种参数目相对较小但能与更大型模型(如 GPT-3)相媲美的语言模型。它的设计强调在较小的规模下提供高效的性能体现,因此其练习本钱较低,但在使命上体现优秀。
- 多个参数规模: LLaMA 提供了从 7B 到 65B 不等的参数规模版本,便于研究人员和开发者在资源受限的情况下进行实验。
- 架构: LLaMA 基于 Transformer 架构,使用类似于 GPT 的自回归生成方式,主要用于生成使命。
应用:
LLaMA 主要用于 文本生成使命,类似于 GPT 系列的应用场景,但其目标是在较小的参数规模下提供与更大模型相似的性能。由于其较小的模型规模,LLaMA 更适合研究人员进行探索性研究。
联系:
- LLaMA 和 GPT 一样,也是基于 Transformer 架构的生成模型,但 Meta 针对其规模进行了优化,使其在较小的模型下也能显现强大的性能。
5. 总结:各个transfomer架构模型区别与联系表格整理
模型架构使命类型预练习方式主要应用Transformer编码器-解码器通用架构N/ANLP 和 CV 使命的基础架构BERT编码器文本明白(分类、问答等)Masked Language Model (MLM) 和 Next Sentence Prediction (NSP)文本明白使命,特别是分类和问答GPT解码器文本生成语言模型(LM)预练习文本生成使命,如对话生成、文章生成LLaMA解码器文本生成自回归语言模型文本生成,强调轻量化大模型 a.主要联系:架构基础相同+注意力机制
- 架构基础相同:全部这些模型都基于 Transformer 的架构,不同之处在于它们是否使用了 Transformer 的编码器、解码器部分,以及怎样进行预练习。
- 注意力机制的广泛应用:自注意力机制是它们共同的核心,使得它们可以或许有效处理序列数据,尤其是长间隔的依赖关系。
b.主要区别:仅编码、仅解码、编码和解码
- BERT 使用编码器进行 双向文本明白,适合分类和明白使命。
- GPT 和 LLaMA 使用解码器进行 单向文本生成,适合生成使命,如对话和文章生成。
- Transformer 是全部这些模型的基础,但其原始设计包含编码器和解码器结构,而 BERT 和 GPT 分别只使用了编码器和解码器部分。
二、压缩的对象
在深度学习模型的练习和推理阶段需要保存或使用的不同类型的对象。
1. 练习阶段:梯度、优化器
在练习时,模型通过盘算梯度和调解模型参数来学习和优化。
- 梯度(Gradients):
- 练习过程中,模型会盘算丧失函数(Loss),然后通过 反向传播算法(Backpropagation) 盘算丧失函数相对于每个参数的梯度。梯度是一个向量,指示了怎样改变模型参数以最小化丧失。
- 梯度表现了每个参数需要调解的方向和幅度,因此在每次参数更新时都需要存储和使用梯度。
- 这些梯度随着模型的更新而变化,只有在练习期间存在。
- 优化器(Optimizer):
- 优化器根据梯度信息来调解模型的权重,以最小化丧失函数。常见的优化器有 SGD(随机梯度降落)、Adam 等。
- 优化器的状态(如动量、学习率等)也会被保存,它们是辅助参数更新的关键。
- 优化器在每一轮练习时都会根据当前的梯度来更新权重,因此在练习过程中需要保存优化器的状态。
2.推理阶段:权重、激活、KV Cache
在推理时,模型的目标是基于给定输入生成输出,不再进行梯度盘算,而是使用预练习好的权重和缓存。
- 权重(Weights):
- 推理过程中,模型只需使用已经练习好的参数(也就是权重)来生成预测结果。权重是模型在练习期间学到的用于表现输入数据特征的数值。
- 在推理时,权重不会更新,它们是模型进行盘算的基础。
- 激活(Activations):
- 激活值是模型每一层的输出,是中心盘算结果。它们是输入数据通过神经网络各层的加权和非线性变更后产生的。
- 在推理阶段,激活值会用于每一层的盘算,特别是深度模型,激活值的缓存对于保持前后层的连贯性非常重要。
- 对于一些特定使命,如生成使命或序列生成,激活值可能会被缓存,以加速后续的推理。
- KV Cache(Key-Value Cache):
- KV Cache 主要用于 Transformer 解码器 模型(如 GPT 等)的推理过程中。
- 在自回归生成使命中(如对话生成),模型需要徐徐生成每个词。为了避免在每一步生成时重复盘算之前的结果,模型会缓存前几步的键和值(Key 和 Value)。这样,后续生成时可以直接复用之前的盘算结果,极大进步推理效率。
- Key 和 Value 是在注意力机制中盘算出的值,它们资助模型保持上下文信息,从而生成连贯的输出。
三、压缩的方法
PTQ(Post-Training Quantization) 和 QAT(Quantization-Aware Training) 是两种常见的量化(Quantization)方法,它们的目标是通过淘汰模型的数值精度来压缩模型大小、加快推理速率,并淘汰盘算资源的消耗,尤其在移动装备或嵌入式装备上。它们的主要区别在于 量化发生的机遇 和 如那边理量化偏差。
1. PTQ(Post-Training Quantization)
后练习量化 是指在模型练习完成之后对模型进行量化。它不需要在练习期间考虑量化问题,只在练习后进行处理。
特点:
- 量化机遇:在模型练习完成后,直接对预练习的浮点模型进行量化。
- 简朴且快速:因为不需要重新练习模型,只需要对已经练习好的模型参数进行量化,PTQ 的实现相对简朴,所需盘算量小。
- 量化偏差较大:由于没有在练习过程中考虑量化带来的偏差,因此模型可能在量化后精度丧失较大,尤其是对浮点模型非常敏感的使命。
- 典型用法:通常将 32 位浮点数(FP32)模型转换为 8 位整数(INT8)模型,以低落存储和盘算本钱。
工作流程:
- 练习浮点模型:首先,在高精度(如 FP32)下完成模型的正常练习。
- 模型量化:在练习完成后,将模型参数(如权重、激活值等)直接从浮点精度转换为低精度格式(通常是 INT8)。
- 校准数据(可选):偶尔会用一个较小的数据集进行量化校准,以淘汰量化偏差并进步模型性能。
优势:
- 不需要重新练习:只需对现有模型进行量化,节流了盘算资源和时间。
- 实现简朴:只需额外的量化步调,不需要改变练习过程。
劣势:
- 精度丧失较大:由于模型在练习时没有考虑到量化,因此在量化过程中引入的偏差会导致性能降落,尤其是对于对精度要求高的使命。
2. QAT(Quantization-Aware Training)
量化感知练习 是指在模型练习的过程中模拟量化过程,使得模型可以或许感知量化的影响,并调解参数以适应量化后的推理。
特点:
- 量化机遇:量化过程是在练习期间进行的,模型在练习时就已经意识到量化的存在,并通过梯度更新来适应量化偏差。
- 精度丧失小:由于在练习期间已经考虑到了量化,模型会调解自身参数以最小化量化带来的偏差,从而在推理时保持更高的精度。
- 练习复杂度增加:需要在练习过程中模拟量化操作,这会增加练习的复杂性和盘算本钱。
工作流程:
- 量化模拟:在练习过程中,模型的权重和激活会定期被模拟量化(通常是从 FP32 到 INT8),以使模型学习到量化偏差并调解参数。
- 梯度更新:练习过程中,模型会通过梯度降落法更新参数,适应低精度的盘算,淘汰量化偏差。
- 量化模型:练习完成后,模型已经适应了量化操作,推理时直接使用低精度模型(如 INT8)进行推理。
优势:
- 精度丧失小:由于模型在练习时已经考虑到量化的影响,因此量化后的精度保持得较好,尤其适合对精度要求较高的使命。
- 量化偏差可控:通过模拟量化过程,模型可以在练习中适应量化带来的偏差,并进行自我调解。
劣势:
- 练习本钱高:与传统的浮点模型练习相比,QAT 的练习复杂度更高,练习时间更长,因为需要模拟低精度盘算。
- 实现复杂:需要修改练习流程来引入量化模拟。
3.PTQ 和 QAT 的对比表格整理
特性PTQ(Post-Training Quantization)QAT(Quantization-Aware Training)量化机遇在模型练习完成后进行量化在练习过程中模拟量化实现难度简朴,练习后直接量化较复杂,需在练习中进行量化模拟练习本钱无需重新练习,练习本钱低需要重新练习,练习本钱高精度丧失可能较大,尤其是复杂使命精度丧失较小,模型适应量化偏差适用场景对精度要求不高的场景对精度要求较高的场景模型类型预练习的浮点模型量化感知模型 4.选择哪种量化方法?
- PTQ 适用于以了局景:
- 资源有限的装备中需要快速部署模型。
- 对精度要求不是特别高的使命(如简朴的分类使命或边缘装备的推理)。
- 练习后不盼望再耗费大量时间进行重新练习。
- QAT 适用于以了局景:
- 对精度要求很高的使命(如复杂的自然语言处理、图像辨认等使命)。
- 可以接受较长的练习时间和更高的练习本钱,来确保量化后的精度。
四、压缩的结果
大模型压缩的结果评估涉及多个维度,不仅需要考虑模型压缩后在存储和盘算资源上的节流,还要衡量模型在推理性能、速率和准确性上的体现。常见的大模型压缩结果评估指标可以分为以下几类:
1. 模型性能指标
模型压缩后最重要的是确保其性能不会大幅降落,因此常用的模型性能评估指标包括:
- 准确率(Accuracy):
- 对于分类使命,模型压缩后仍然需要评估其分类准确率。
- 比方,图像分类使命的 Top-1 和 Top-5 准确率。
- F1 值(F1 Score):
- 对于不均衡的数据集,F1 值 是一种更好的评估尺度,结合了模型的精准率(Precision)和召回率(Recall)。
- F1 值用于评估分类型使命的模型压缩结果
- BLEU、ROUGE 分数:
- 在机器翻译、文本择要等使命中,常用 BLEU 和 ROUGE 分数来评估压缩后的生成质量。
- 均方偏差(MSE):
- 对于回归使命或者一些特定的预测使命,可以通过 均方偏差 来衡量模型在数值预测上的偏差。
- 感知丧失(Perceptual Loss):
- 在图像或语音生成使命中,可能需要用感知丧失来衡量生成数据的质量是否接近原始数据。
2. 模型尺寸和存储效率
压缩模型的一个主要目标是淘汰其存储空间。以下指标可以用于评估模型压缩带来的存储优化结果:
- 模型大小(Model Size):
- 压缩后的模型权重文件的大小,通常以 MB 或 GB 为单位。这个指标可以直接反映出模型压缩结果。
- 比方,将模型从原来的 1 GB 压缩到 100 MB,表现模型的存储需求淘汰了 90%。
- 参数目(Number of Parameters):
- 模型中可练习参数的数目。压缩后参数目通常会大幅淘汰,如从数十亿个参数淘汰到几亿甚至几百万个参数。
- 比方,模型压缩后从 175B 参数淘汰到 7B。
- 浮点数运算量(FLOPs):
- FLOPs 表现模型在推理时需要进行的浮点运算次数。FLOPs 越少,意味着盘算复杂度越低,推理速率也越快。
- 压缩后可以通过比较压缩前后模型的 FLOPs 来衡量压缩结果。
3. 推理速率
压缩后的模型是否能显著加速推理过程,是评估其结果的一个重要指标,特别是在资源受限的装备上。
- 延迟(Latency):
- 模型从接收到输入到输出结果所需的时间。延迟通常以 毫秒(ms) 为单位,尤其是在及时推理系统中(如自动驾驶、语音助手),延迟是至关重要的指标。
- 延迟可以分为 单样本延迟 和 批处理延迟。
- 吞吐量(Throughput):
- 吞吐量指的是模型在固定时间内处理的样本数目,通常以 样本/秒 为单位(如 1000 样本/秒)。在压缩后,模型的吞吐量应该显著进步。
- 对于需要高效处理大量数据的系统,如推荐系统、搜刮引擎等,吞吐量是关键指标。
4. 能耗和资源使用效率
在现实部署中,特别是移动装备或嵌入式装备中,评估压缩后的模型资源使用效率至关重要。
- 功耗(Power Consumption):
- 运行压缩模型所消耗的能量,尤其是对电池供电装备(如智能手机或 IoT 装备)非常重要。功耗越低,意味着压缩后的模型更节能。
- 内存占用(Memory Usage):
- 模型在推理时所占用的 RAM 大小。压缩后的模型应该显著淘汰推理过程中对内存的需求,特别是在装备资源有限的场景中。
- 硬件使用率(Hardware Utilization):
- 压缩后的模型可否更好地使用硬件资源,比如 GPU 或 TPU 的使用率。通过更有效的硬件使用,模型推理的效率和速率都能得到提拔。
5. 压缩比例
这个指标用来直接量化压缩的结果,通常包括以下几类:
- 参数压缩率(Parameter Compression Ratio):
- 表现压缩后模型的参数数目相对于原始模型的淘汰程度。可以表现为:
[
\text{参数压缩率} = \frac{\text{压缩后模型的参数数目}}{\text{压缩前模型的参数数目}}
]
- 比方,假如原模型有 1 亿个参数,压缩后变为 1000 万个参数,压缩率为 10%。
- 模型大小压缩率(Model Size Compression Ratio):
- 表现压缩后模型的存储大小相对于原始模型的淘汰程度。可以表现为:
[
\text{模型大小压缩率} = \frac{\text{压缩后模型大小}}{\text{压缩前模型大小}}
]
- 比方,将模型从 500MB 压缩到 50MB,压缩率为 1/10。
6. 压缩对比实验
为了评估压缩结果,通常需要进行对比实验,包括以下方式:
- 压缩前后性能对比:
- 比较压缩前后的模型性能(如准确率、推理速率等),用量化数据来直接反映压缩的结果。
- 与其他压缩方法的对比:
- 在同样的压缩场景下,与其他压缩技术(如剪枝、知识蒸馏、权重量化等)进行对比,评估哪种方法结果更好。
7.感知质量(Perceptual Quality)
对于涉及图像、视频、语音等生成使命的模型,感知质量是重要的评估指标,主要通过人类的主观感知或基于模型的感知丧失函数来衡量。
- 人类评估(Human Evaluation):
- 在图像生成或文本生成使命中,经过压缩的模型输出质量每每需要通过人类进行主观评分(如图像的清楚度、文本的流通度等)。
- 自动评估:
- 使用感知丧失、SSIM(结构相似性指数)等指标来衡量生成结果与原始数据的相似度。
五、示例:以Llama-7B的中文版本为例
1.原理:
LLM.int8(): Int8 矩阵乘法来处理 Transformer 模型中的前馈层(Feed Forward)和注意力投影层(Multi-HeadAttention),从而将推理所需的内存减半,同时保持完整精度的性能。
2.使用源码
- import torch
- import torch.nn as nn
- import os
- import time
- from modelscope import AutoTokenizer
- from transformers import LlamaForCausalLM
- import bitsandbytes as bnb
- import random
- import numpy as np
- random.seed(42)
- np.random.seed(42)
- torch.manual_seed(42)
- def redirect_output_to_file(file_path):
- import sys
- sys.stdout = open(file_path, 'w')
- output_file = os.path.join(os.getcwd(), 'LLMint8_try_output.txt')
- redirect_output_to_file(output_file)
- model_dir = '/home/mshw/model/Llama2-Chinese-7b-Chat-ms'
- print(model_dir)
- if not torch.cuda.is_available():
- raise RuntimeError("CUDA 不可用,请检查 GPU 配置")
- n_gpus = torch.cuda.device_count()
- print(f"Number of GPUs detected: {n_gpus}")
- if n_gpus == 0:
- raise RuntimeError("没有检测到可用的 GPU")
- max_memory = {}
- for i in range(n_gpus):
- free_mem, total_mem = torch.cuda.mem_get_info(i)
- max_mem_gb = max(0, int(free_mem / 1024**3) - 1)
- max_memory[i] = f"{max_mem_gb}GB"
- print(f"GPU {i}: {max_mem_gb}GB free memory allocated for usage.")
- cache_dir = os.getcwd()
- offload_folder = os.path.join(cache_dir, 'offload')
- os.makedirs(offload_folder, exist_ok=True)
- # 加载模型
- model = LlamaForCausalLM.from_pretrained(model_dir, torch_dtype=torch.float16, device_map='auto')
- # 确保模型权重绑定
- model.tie_weights()
- tokenizer = AutoTokenizer.from_pretrained(model_dir, cache_dir=cache_dir)
- def get_sparsity(tensor: torch.Tensor) -> float:
- tensor_cpu = tensor.to('cpu')
- return 1 - float(tensor_cpu.count_nonzero()) / tensor_cpu.numel()
- def get_num_parameters(model: nn.Module, count_nonzero_only=False) -> int:
- num_counted_elements = 0
- for param in model.parameters():
- if count_nonzero_only:
- param_cpu = param.detach().to('cpu')
- num_counted_elements += param_cpu.count_nonzero()
- else:
- num_counted_elements += param.numel()
- return num_counted_elements
- def get_model_size_in_gb(model: nn.Module, data_width=8, count_nonzero_only=False) -> float:
- data_width_bytes = data_width // 8
- model_size_bytes = get_num_parameters(model, count_nonzero_only) * data_width_bytes
- model_size_gb = model_size_bytes / (1024**3)
- return model_size_gb
- def calculate_memory_access(tensor: torch.Tensor) -> int:
- return tensor.numel() * tensor.element_size()
- def get_model_memory_access(model: nn.Module) -> int:
- total_access = 0
- for param in model.parameters():
- total_access += calculate_memory_access(param)
- return total_access
- # 使用8位宽度进行模型大小计算
- model_size_gb = get_model_size_in_gb(model, data_width=8)
- inputs = "咖啡的作用是什么?"
- MiB = 1024 * 1024
- torch.cuda.reset_peak_memory_stats()
- start_time = time.time()
- # 使用适当的方法进行推理
- inputs_encoded = tokenizer(inputs, return_tensors='pt').to('cuda')
- inputs_encoded.pop("token_type_ids", None) # 移除不需要的键
- outputs = model.generate(**inputs_encoded)
- result = tokenizer.decode(outputs[0], skip_special_tokens=True)
- end_time = time.time()
- for i in range(n_gpus):
- peak_mem = torch.cuda.max_memory_reserved(device=i) / MiB
- print(f"GPU {i} 峰值内存: {peak_mem:.2f} MiB")
- print(result)
- print(f"推理时间: {end_time - start_time:.2f} 秒")
- # 恢复标准输出
- import sys
- sys.stdout.close()
- sys.stdout = sys.__stdout__
复制代码
3.思考
怎么区分权重的异常特征和正常特征?
均值和尺度差:盘算每层权重的均值和尺度差,辨认那些偏离较大的权重
设定合理阈值:界说上下限,找出超出范围的权重。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |