大模型应用曙光 - 10X压缩技术

news/2024/9/25 9:05:33/文章来源:https://www.cnblogs.com/xfuture/p/18430520

关注TechLead,复旦AI博士,分享AI领域全维度知识与研究。拥有10+年AI领域研究经验、复旦机器人智能实验室成员,国家级大学生赛事评审专家,发表多篇SCI核心期刊学术论文,上亿营收AI产品研发负责人。

file

如何在不牺牲性能的情况下将大型语言模型缩小十倍

虽然LLM的巨大规模赋予了它们在各种用例中的出色性能,但这也在其应用于现实世界问题时带来了挑战。在本文中,我将讨论如何通过压缩LLM来克服这些挑战。我将从概述关键概念开始,接着通过Python代码展示一个具体的示例。

2023年AI领域的口号是"越大越好",提升语言模型的公式非常简单:更多的数据 + 更多的参数 + 更多的计算资源 = 更好的性能

虽然这仍然是目前的趋势,但处理1000亿以上参数的模型显然存在挑战。例如,一个具有1000亿参数的模型仅在FP16格式下存储就需要200GB的空间!

不用说,大多数消费设备(如手机、平板电脑、笔记本电脑)无法处理如此庞大的模型。但……如果我们可以让模型变小呢?

模型压缩

模型压缩旨在在不牺牲性能的前提下减少机器学习模型的大小。对于(大型)神经网络,这可行,因为它们通常是过参数化的(即由冗余的计算单元组成)。

模型压缩的主要好处是降低推理成本。这意味着功能强大的ML模型可以更广泛地被使用(例如在本地笔记本电脑上运行LLM),并且能够以更低的成本将AI集成到消费产品中,还支持设备上的推理,从而保护用户隐私和安全。

三种压缩模型的方法

模型压缩有多种技术。这里我将重点介绍三种广泛使用的类别。

  • 量化——使用更低精度的数据类型表示模型
  • 剪枝——从模型中删除不必要的组件
  • 知识蒸馏——通过较大的模型训练较小的模型

注意:这些方法是相互独立的。因此,可以组合来自多个类别的技术,以实现最大的压缩效果!

量化

file

虽然"量化"听起来像是一个复杂的术语,但它实际上是一个简单的概念。它包括降低模型参数的精度。你可以把它想象成将高分辨率图像转换为低分辨率图像,同时保持图片的核心属性。

两类常见的量化技术是后训练量化(PTQ)量化感知训练(QAT)

后训练量化(PTQ)

对于一个神经网络,后训练量化(PTQ)通过将参数替换为低精度的数据类型(例如从FP16转换为INT-8)来压缩模型。这是减少模型计算需求最快且最简单的方法之一,因为它不需要额外的训练或数据标注

虽然这是降低模型成本的相对简单的方法,但以这种方式过度量化(例如从FP16到INT4)通常会导致性能下降,这限制了PTQ的潜在收益。

量化感知训练(QAT)

对于需要更高压缩的情况,可以通过从零开始用低精度数据类型训练模型来克服PTQ的局限性。这就是量化感知训练(QAT)的思想。

虽然这种方法在技术上更具挑战性,但它可以生成一个显著更小且表现良好的模型。例如,BitNet架构使用了一种三进制数据类型(即1.58位),匹配了原始Llama模型的性能!

当然,PTQ和从零开始的QAT之间存在较大的技术鸿沟。一种介于两者之间的方法是量化感知微调,它包括在量化后对预训练模型进行额外的训练。

剪枝

file

剪枝的目的是删除对模型性能影响较小的组件。这很有效,因为ML模型(尤其是大型模型)往往会学习到冗余和噪声结构。

一个比喻是修剪树木中的枯枝。去除它们可以减少树的大小而不会伤害树。

剪枝方法可以分为两类:非结构化剪枝结构化剪枝

非结构化剪枝

非结构化剪枝从神经网络中移除不重要的权重(即将它们设置为零)。例如,早期的工作如Optimal Brain Damage和Optimal Brain Surgeon通过估计每个参数对损失函数的影响来计算其重要性分数。

最近,基于幅值的方法(即移除绝对值最小的权重)变得更受欢迎,因为它们简单且易于扩展。

虽然非结构化剪枝可以显著减少参数数量,但这些收益需要特殊硬件才能实现。非结构化剪枝会导致稀疏矩阵操作(即乘以大量零的矩阵),而标准硬件无法比非稀疏操作更有效地执行这些操作。

结构化剪枝

相对而言,结构化剪枝从神经网络中删除整个结构(例如注意力头、神经元和层)。这样可以避免稀疏矩阵操作的问题,因为整个矩阵可以从模型中删除,而不是个别参数。

虽然有多种方法可以确定要剪枝的结构,但原则上,它们都试图删除对性能影响最小的结构。

知识蒸馏

知识蒸馏是将知识从一个(较大的)教师模型传递到一个(较小的)学生模型。一种方法是通过教师模型生成预测,并使用这些预测来训练学生模型。通过学习教师模型的输出logits(即所有可能的下一个标记的概率),学生模型获得了比原始训练数据更丰富的信息,从而提高了性能。

最近的蒸馏应用完全摒弃了logits的需求,而是通过教师模型生成的合成数据进行学习。一个著名的例子是斯坦福的Alpaca模型,它使用来自OpenAI的text-davinci-003(即原始ChatGPT模型)的合成数据微调了LLaMa 7B(基础)模型,使其能够遵循用户指令。

示例代码:通过知识蒸馏和量化压缩文本分类器

在基本了解了各种压缩技术后,让我们看一个如何在Python中进行压缩的实际示例。这里,我们将压缩一个有1亿参数的模型,该模型用于分类URL是否安全(即钓鱼网站)。

我们首先使用知识蒸馏将1亿参数的模型压缩到5000万参数。然后,使用4位量化进一步将内存占用减少3倍,得到的最终模型比原始模型小7倍

示例代码可以在 https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/model-compression 上找到。教师模型 https://huggingface.co/shawhin/bert-phishing-classifier_teacher 、学生模型https://huggingface.co/shawhin/bert-phishing-classifier_student、 4位学生模型 https://huggingface.co/shawhin/bert-phishing-classifier_student_4bit 、数据集https://huggingface.co/datasets/shawhin/phishing-site-classification 可以在Hugging Face Hub上免费获取。

首先,我们导入一些有用的库。

from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForSequenceClassification
from transformers import DistilBertForSequenceClassification, DistilBertConfig
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from sklearn.metrics import accuracy_score, precision_recall_fscore_support

然后,我们从Hugging Face Hub加载数据集。包括训练集(2100行)、测试集(450行)和验证集(450行)。

data = load_dataset("shawhin/phishing-site-classification")

接下来,我们加载教师模型。为了加速训练,我将模型加载到Google Colab上提供的免费T4 GPU上。

device = torch.device('cuda')model_path = "shawhin/bert-phishing-classifier_teacher"tokenizer = AutoTokenizer.from_pretrained(model_path)
teacher_model = AutoModelForSequenceClassification.from_pretrained(model_path).to(device)

教师模型是Google的 bert-base-uncased https://huggingface.co/google-bert/bert-base-uncased 的微调版本,执行对钓鱼网站URL的二分类。训练教师模型的代码可在 GitHub https://github.com/ShawhinT/YouTube-Blog/tree/main/LLMs/model-compression 上找到。

对于学生模型,我们从 distilbert-base-uncased https://huggingface.co/distilbert/distilbert-base-uncased 初始化一个新模型。我们通过移除两层和剩余层的四个注意力头修改了架构。

my_config = DistilBertConfig(n_heads=8, n_layers=4)student_model = DistilBertForSequenceClassification.from_pretrained("distilbert-base-uncased", config=my_config).to(device)

在训练学生模型之前,我们需要对数据集进行标记。这是必要的,因为模型期望输入文本以特定的方式表示。

在这里,我根据每个批次的最长示例填充样本。这使批次能够表示为PyTorch张量。

def preprocess_function(examples):return tokenizer(examples["text"], padding='max_length', truncation=True)tokenized_data = data.map(preprocess_function, batched=True)
tokenized_data.set_format(type='torch', columns=['input_ids', 'attention_mask', 'labels'])

训练前的另一个重要步骤是定义一个评估策略,用于在训练期间评估我们的模型。在下面,我定义了一个函数,该函数在给定模型和数据集的情况下计算准确率、精确率、召回率和F1得分

def evaluate_model(model, dataloader, device):model.eval()all_preds = []all_labels = []with torch.no_grad():for batch in dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)outputs = model(input_ids, attention_mask=attention_mask)logits = outputs.logitspreds = torch.argmax(logits, dim=1).cpu().numpy()all_preds.extend(preds)all_labels.extend(labels.cpu().numpy())accuracy = accuracy_score(all_labels, all_preds)precision, recall, f1, _ = precision_recall_fscore_support(all_labels, all_preds, average='binary')return accuracy, precision, recall, f1

现在我们可以开始训练了。为了让学生模型同时学习训练集中的真实标签(即硬目标)和教师模型的logits(即软目标),我们需要构建一个特殊的损失函数,该函数考虑到两种目标。

这可以通过结合学生和教师输出概率分布的KL散度与学生logits与真实标签的交叉熵损失来实现。

def distillation_loss(student_logits, teacher_logits, true_labels, temperature, alpha):soft_targets = nn.functional.softmax(teacher_logits / temperature, dim=1)student_soft = nn.functional.log_softmax(student_logits / temperature, dim=1)distill_loss = nn.functional.kl_div(student_soft, soft_targets, reduction='batchmean') * (temperature ** 2)hard_loss = nn.CrossEntropyLoss()(student_logits, true_labels)loss = alpha * distill_loss + (1.0 - alpha) * hard_lossreturn loss

接下来,我们定义超参数、优化器和训练/测试数据集。

batch_size = 32
lr = 1e-4
num_epochs = 5
temperature = 2.0
alpha = 0.5optimizer = optim.Adam(student_model.parameters(), lr=lr)dataloader = DataLoader(tokenized_data['train'], batch_size=batch_size)
test_dataloader = DataLoader(tokenized_data['test'], batch_size=batch_size)

最后,我们使用PyTorch训练学生模型。

student_model.train()for epoch in range(num_epochs):for batch in dataloader:input_ids = batch['input_ids'].to(device)attention_mask = batch['attention_mask'].to(device)labels = batch['labels'].to(device)with torch.no_grad():teacher_outputs = teacher_model(input_ids, attention_mask=attention_mask)teacher_logits = teacher_outputs.logitsstudent_outputs = student_model(input_ids, attention_mask=attention_mask)student_logits = student_outputs.logitsloss = distillation_loss(student_logits, teacher_logits, labels, temperature, alpha)optimizer.zero_grad()loss.backward()optimizer.step()print(f"Epoch {epoch + 1} completed with loss: {loss.item()}")teacher_accuracy, teacher_precision, teacher_recall, teacher_f1 = evaluate_model(teacher_model, test_dataloader, device)print(f"Teacher (test) - Accuracy: {teacher_accuracy:.4f}, Precision: {teacher_precision:.4f}, Recall: {teacher_recall:.4f}, F1 Score: {teacher_f1:.4f}")student_accuracy, student_precision, student_recall, student_f1 = evaluate_model(student_model, test_dataloader, device)print(f"Student (test) - Accuracy: {student_accuracy:.4f}, Precision: {student_precision:.4f}, Recall: {student_recall:.4f}, F1 Score: {student_f1:.4f}")print("\n")student_model.train()

训练结果如下图所示。令人惊讶的是,训练结束时,学生模型在所有评估指标上都超过了教师模型

file

接下来,我们可以在独立的验证集上评估模型,即未用于训练模型参数或调整超参数的数据。

validation_dataloader = DataLoader(tokenized_data['validation'], batch_size=8)teacher_accuracy, teacher_precision, teacher_recall, teacher_f1 = evaluate_model(teacher_model, validation_dataloader, device)
print(f"Teacher (validation) - Accuracy: {teacher_accuracy:.4f}, Precision: {teacher_precision:.4f}, Recall: {teacher_recall:.4f}, F1 Score: {teacher_f1:.4f}")student_accuracy, student_precision, student_recall, student_f1 = evaluate_model(student_model, validation_dataloader, device)
print(f"Student (validation) - Accuracy: {student_accuracy:.4f}, Precision: {student_precision:.4f}, Recall: {student_recall:.4f}, F1 Score: {student_f1:.4f}")

在这里,我们再次看到学生模型优于教师模型。

到目前为止,我们已经将模型从1.09亿参数(438 MB)缩小到5280万参数(211 MB)。然而,我们可以更进一步,对学生模型进行量化。

首先,我们将模型推送到 Hugging Face Hub https://huggingface.co/shawhin/bert-phishing-classifier_student 。

student_model.push_to_hub("shawhin/bert-phishing-classifier_student")

然后,我们可以使用4位量化加载模型。为此,我们可以使用transformers库中的BitsAndBytes集成。

我们设置配置以使用 QLoRA https://medium.com/towards-data-science/qlora-how-to-fine-tune-an-llm-on-a-single-gpu-4e44d6b5be32 论文中描述的4位NormalFloat数据类型存储模型参数,并使用bfloat16进行计算

from transformers import BitsAndBytesConfignf4_config = BitsAndBytesConfig(load_in_4bit=True,bnb_4bit_quant_type="nf4",bnb_4bit_compute_dtype=torch.bfloat16,bnb_4bit_use_double_quant=True
)model_nf4 = AutoModelForSequenceClassification.from_pretrained(model_id, device_map=device, quantization_config=nf4_config)

接下来,我们可以在验证集上评估量化模型。

quantized_accuracy, quantized_precision, quantized_recall, quantized_f1 = evaluate_model(model_nf4, validation_dataloader, device)
print("Post-quantization Performance")
print(f"Accuracy: {quantized_accuracy:.4f}, Precision: {quantized_precision:.4f}, Recall: {quantized_recall:.4f}, F1 Score: {quantized_f1:.4f}")

我们再次看到压缩后的性能略有提升(缩小到62.7MB)。一个直观的解释是奥卡姆剃刀原理,即越简单的模型越好

在这种情况下,模型可能对于这个二分类任务来说过度参数化了。因此,简化模型带来了更好的性能。

原文链接:https://medium.com/towards-data-science/compressing-large-language-models-llms-9f406eea5b5e
本文由博客一文多发平台 OpenWrite 发布!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

绝缘手套穿戴智能识别系统

绝缘手套穿戴智能识别系统通过opencv深度学习技术赋能现场摄像头,绝缘手套穿戴智能识别系统对现场电力作业人员在带电设备上作业施工时有没有按厂区要求佩戴绝缘手套进行识别检测,当绝缘手套穿戴智能识别系统检测到现场电力作业人员违规行为即未佩戴绝缘手套时立刻抓拍告警,…

智慧工地安全帽智能识别系统

智慧工地安全帽智能识别系统通过opencv深度学习技术,智慧工地安全帽智能识别系统可自动检测识别作业现场人员有没有戴安全帽,当智慧工地安全帽智能识别系统检测出现场施工作业人员没有按照要求戴安全帽时,立即抓拍存档并同步回传违规数据到后台监控大数据平台,并提醒后台人…

煤矿人员工服着装智能识别监测系统

煤矿人员工服着装智能识别监测系统在摄像头监控画面中自动检测作业人员是否正确着装,煤矿人员工服着装智能识别监测系统若发现有现场作业人员没有按要求正确佩戴安全帽、穿着工服,煤矿人员工服着装智能识别监测系统会立即抓拍存档回传后台大数据监控管理平台,现场同时进行语…

Ai检测人员穿衣规范系统

Ai检测人员穿衣规范系统可以通过yolo深度学习技术对现场画面中人员穿衣自动检测,Ai检测人员穿衣规范系统发现现场作业人员未正确按要求穿衣服如穿戴安全带、手套、安全帽、胶鞋、反光衣,Ai检测人员穿衣规范系统会进行语音播报提醒,并将违规行为截图回传给后台大数据平台进行…

车辆逆行识别检测系统

车辆逆行识别检测系统通过yolo网络深度学习技术,车辆逆行识别检测系统对监控画面中车辆逆向行驶行为进行检测,若车辆逆行识别检测系统检测到道路上有车辆逆向行驶时,车辆逆行识别检测系统则抓拍预警。车辆逆行识别预警系统提升传统监控的事后被动查询,真正做到事前主动抓拍…

工厂安全着装识别检测系统

工厂安全着装识别检测系统通过python+opencv技术,工厂安全着装识别检测系统对前端摄像机监控画面中的工厂人员着装穿戴进行实时分析检测,如果工厂安全着装识别检测系统识别出现场人员未按工厂要求正确着装,工厂安全着装识别检测系统会自动抓拍存档告警,同步回传给后台大数据…

Cisco ASA 9.22.1 发布下载,新增功能概览

Cisco ASA 9.22.1 发布下载,新增功能概览Cisco ASA 9.22.1 - 思科自适应安全设备 (ASA) 软件 Cisco Adaptive Security Appliance (ASA) 请访问原文链接:https://sysin.org/blog/cisco-asa/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org新增功能 重要说明AS…

人员超员识别系统

人员超员识别系统通过yolo深度学习网络模型对工厂车间生产区域进行实时监测,当人员超员识别系统监测到监控画面中区域人数超过规定人数时,人员超员识别系统立即抓拍存档预警并回传到后台监控平台提醒后台人员及时处理避免发生更大的危险情况。人员超员识别系统保障了危化品业…

广州C++信奥老师解一本通题 1346:【例4-7】亲戚(relation)

​ 【题目描述】或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。…

智源大会-2024-十一-

智源大会 2024(十一) 2024北京智源大会-视觉大模型 - P6:圆桌论坛:视觉重回第一赛道?-主持人:颜水成-嘉宾:鲍 凡-申琛惠-李俊男-程明明 - 智源社区 - BV13x4y1t7sb 今天的话虽然是我们是这个视觉的,这个呃大模型,但是我们也有这个AMP,也有多模态的那个俊男在这个地方…

智源大会-2024-十-

智源大会 2024(十) 2024北京智源大会-生成模型 - P4:视觉生成中的若干问题;古纾旸 - 智源社区 - BV1DS411w7hz 这个怎么控,好可以好,行那就这样吧,嗯好,大家好,我是谷舜阳,今天这个标题的title写的有点大,我一直在想我要不要起这个title,最后还是起了这个title,主…

智源大会-2024-二-

智源大会 2024(二) 2024北京智源大会-人工智能+数据新基建 - P2:大模型需要大数据流转模式创新-黄铁军 - 智源社区 - BV1qx4y14735 尊敬的上部长夏局长啊,各位领导啊,各位专家呃,特别感谢啊,大家来这个出席今天这个志愿大会,我们嗯围绕人工智能,特别是数据呃的一一些这…