训练一个机器学习模型,或许在基准数据集上达到最高的准确率是一回事。但部署该模型,使其服务数百万用户、处理 TB 级数据并全天候可靠运行,则是一个截然不同的挑战。
从一开始,训练和部署机器学习模型的每个部分、每个阶段都需要仔细的规划和正确的工具。
从早期开发到全面部署,构建和运行人工智能系统是……
强大的软件开发技能变得重要,这是许多人工智能工程师所缺乏的
在本篇博文中,我们将探讨构建一个能够创建 LLM、多模态模型以及各种其他 AI 产品的大规模 AI 系统所需的各个开发阶段。每个开发阶段之间的相互关系以及各自的职责。
我们的目录按阶段排列。您可以自由探索每个阶段。
【AI代码助手、代码静态分析工具、软件成分分析与同源漏洞检测、渗透测试工具、模糊测试、恶意代码检测平台、软件漏洞挖掘平台、软件供应链安全平台。试用及合作请后台私信工程师13381155803(微信同步)】
第一阶段:人工智能系统和硬件
·人工智能计算硬件
·人工智能的分布式系统
·优化网络
·人工智能存储解决方案
第二阶段:高级模型训练技术
·优化神经网络训练的策略
·大规模训练的框架和工具
·使用 TensorFlow 和 PyTorch 进行扩展
·模型缩放和高效处理
第三阶段:高级模型推理技术
·大规模高效推理
·大规模高效推理
·管理实时应用程序的延迟和吞吐量
·边缘人工智能和移动部署
第四阶段:性能分析与优化
·诊断系统瓶颈
·操作化人工智能模型
·调试人工智能系统:工具和方法
·机器学习的 CI/CD 管道
·结论
第一阶段:人工智能系统和硬件
构建大规模人工智能系统的第一步是选择合适的硬件。它会影响模型的运行速度、投资成本以及整体能耗。
在本节中,我们将讨论可用的不同硬件系统,以及如何提高它们的成本和能源效率。
人工智能计算硬件
广泛用于训练或其他 AI 任务的三种最常见的硬件类型是:
AI 硬件可用性
·CPU(中央处理单元)它们擅长执行许多不同的任务,但它们没有很多核心,因此对于需要大量并行处理的深度学习或大型 AI 作业来说,它们的速度可能会比较慢。CPU(中央处理器) 它们擅长执行许多不同的任务,但它们没有太多的核心,因此对于需要大量并行处理的深度学习或大型 AI 任务来说,它们可能会较慢。
·GPU(图形处理单元)最初是为处理视频和图形而设计的,但现在它们已成为人工智能的宠儿。因为它们比 CPU 拥有更多核心,这意味着它们可以同时处理大量任务,非常适合训练和运行人工智能模型。
·TPU(张量处理单元)是谷歌专为深度学习打造的芯片。它们速度极快、效率极高,而且能耗更低。这使得它们非常适合处理大型复杂的人工智能任务。
但最近,由于对人工智能的需求不断增长,一些新型硬件也被推出。
·一个很好的例子是FPGA(现场可编程门阵列)。这些芯片的特殊之处在于它们可以重新编程以适应不同的 AI 任务。它们让你能够根据模型需求灵活地微调性能,这在快速变化的 AI 项目中非常有用。
·还有ASIC(专用集成电路)。它们不像CPU或FPGA那样通用。相反,它们的设计只有一个目的:尽可能快速高效地运行AI模型。由于它们是为特定任务(例如为神经网络供电)而设计的,因此它们节能且运行速度非常快。
在选择硬件时,直接跳到 GPU 并不总是正确的方法,因为我们通常认为它们会自动提高性能,无论是数据预处理、微调还是 LLM 推理。
然而,性能很大程度上取决于……
模型架构+基础设施选择
1.对于 AI 架构而言,一种有用的技术是模型量化,许多现代开源模型 API 提供商(例如Together AI或Nebius AI)已经在使用这种方法。这意味着减少 AI 模型在计算时使用的细节,例如使用较小的数字(例如,使用 8 位而不是 32 位)。
2.在基础设施方面,云服务和虚拟化通常是最佳解决方案。您无需购买昂贵的硬件,而是可以从 AWS、Google Cloud 或 Azure 等提供商处租用功能强大的机器。这使您可以根据项目灵活地扩展或缩减规模,从而节省资金并避免浪费。
看一下 Google 的比较图,其中显示了不同模型架构在各种 GPU 上的表现。
Google 在 MLPerf 3.1 基准上对此进行了测试(主要用于测试系统处理输入的速度)。
·A3 VM使用强大的H100 GPU ,在处理棘手的 AI 任务时,速度比旧款A2 VM快1.7 到 3.9 倍。
·如果您希望节省资金同时获得稳定的 AI 性能,那么使用L4 GPU的G2 VM是一个不错的选择。
·测试表明,与同类云服务相比,L4 GPU 每一美元的投入可以提供高达 1.8 倍的性能提升。
Bending Spoons等公司已经在使用G2 VM来高效地为用户带来新的 AI 功能。
人工智能的分布式系统
一旦您根据您的要求选择了优化的硬件和模型架构,我们将进入下一阶段,其中涉及如何规划 AI 的分布式系统。
分布式系统的主要原理是……
将大任务分成几个较小的部分,并让多台计算机同时处理它们。
在人工智能中,这通过共享工作负载来加快数据处理和模型训练。
因此,要创建分布式系统,我们需要牢记一些重要因素。让我们先将其可视化,然后再了解其流程。
分布式人工智能系统
在将分布逻辑应用到我们的AI系统中时,我们需要牢记各种因素。让我们看看流程是怎样的:
1.首先,我们需要了解规模。我们要处理的数据点是数百、数千还是数百万?尽早了解这些有助于我们规划系统,确保其平稳发展。
2.接下来,我们选择合适的工具。根据项目的规模和类型,我们需要合理的处理能力、内存和通信方式组合。云平台让这一切管理变得更加轻松。
3.然后,我们确保所有组件协同工作。系统的不同部分可能需要并行运行,或者在不同的机器上运行。我们的目标是避免速度变慢,确保系统平稳运行。
4.之后,我们保持灵活性。我们不再手动调整资源,而是采用自动化方式。像Kubernetes这样的工具可以帮助系统根据负载变化自动调整。
5.我们还需要监控性能。密切关注系统有助于我们及早发现问题,无论是数据分布不均还是网络瓶颈。
6.最后,我们确保一切保持同步。随着系统规模的扩大,数据和模型在所有部分保持一致至关重要。
优化网络
一旦决定了 AI 系统的分布部分,您需要确保所有组件都正确连接。
他们必须能够顺畅地沟通,没有任何障碍
如果分布式组件无法有效通信,则可能会破坏您的训练或生产代码。
让我们看看如何让对话流畅而不中断:
分布式系统网络优化
让我们分解一下:
1.首先,我们会寻找潜在的速度下降。延迟、容量受限或数据丢失都会严重影响性能,因此尽早识别这些风险至关重要。
2.然后,我们减少延迟。为了加快速度,我们使用更快的连接,将机器紧密放置,甚至将部分处理转移到边缘。
3.接下来,我们会增加带宽。网络路径狭窄会导致流量堵塞。我们通过压缩数据、优先处理重要信息或升级网络来解决这个问题。
4.之后,我们选择合适的通信方法。有些协议比其他协议更能有效地处理大负载。选择合适的协议可以确保您的系统快速高效地运行。
5.我们也为未来的发展做好了规划。随着系统规模的扩大,网络也必须随之扩展。采用灵活的、可按需扩展的设置至关重要。
6.最后,我们会监控网络。定期检查有助于我们及早发现问题。监控工具可以在问题导致网络速度变慢之前发出警报。
人工智能存储解决方案
因此,在您决定了用于训练或推理的硬件及其背后的分布逻辑之后,接下来需要的是存储来保存您训练的模型以及用户与您的 AI 模型对话的数据。
我们存储数据的方式必须适合今天,并为明天的更多数据做好准备
AI存储需求不断增长
数据存储选项
·对象存储最适合大数据。您可以不断添加文件,而无需担心数据结构。当您的数据来自多个来源,并且需要稍后汇总时,对象存储是理想的选择。
·文件系统更适合规模较小、组织有序的环境。它们就像电脑上的文件夹一样。它们有助于保持文件整洁,尤其适合数据量有限且结构良好的情况。
第三种类型是数据库,当你的数据具有结构时很有用。以下是如何选择正确的类型:
1.SQL 数据库非常适合组织有序、相互关联的数据。当您的数据(例如用户、订单和产品)之间存在清晰的关系时,请使用 SQL 数据库。它们非常适合那些对准确性和一致性至关重要的复杂任务。
2.NoSQL 数据库非常适合处理灵活多变的数据。如果您的数据无法整齐地存储在表中,或者数据增长迅速,MongoDB或Cassandra等 NoSQL 数据库能够提供您所需的自由度和扩展性。
虽然工具不是唯一重要的东西,但如何使用它们也很重要:
·数据湖以原始形式保存所有内容。它是一个巨大的容器,用于存储各种数据,您可以稍后对其进行排序和处理。
·数据仓库存储干净、随时可用的数据。它就像一个井然有序的图书馆,您可以快速找到所需的信息。
·数据版本控制可以跟踪变更。这在更新模型或处理随时间变化的数据时非常重要。它有助于保持条理清晰,避免错误。
·混合存储兼具速度与成本优势。您可以使用快速存储存储常用数据,而使用价格更低的存储存储其他数据。这样,您既能节省成本,又能在必要时快速访问数据。
快速数据访问是人工智能性能的关键。
使用 Redis 等内存存储进行快速检索,并应用数据分片来分配负载并防止速度变慢。
在某些时候,您需要决定哪种存储设置效果最佳:云、本地或两者的混合。
云与本地
1.混合存储为您提供灵活性。您可以将敏感数据保存在自己的服务器上,同时将其他所有数据都存储在云端。这有助于平衡安全性和可扩展性。
2.多云策略提供更多选择。通过使用多家云提供商,您可以避免被单一云提供商所束缚。这就像拥有不同的菜单,可以根据您的需求进行选择。
第二阶段:高级模型训练技术
到目前为止,我们已经介绍了硬件、存储以及如何充分利用它们。现在是时候看看训练技术的工作原理以及如何优化它们了。
优化神经网络训练的策略
人工智能模型通常建立在神经网络之上,虽然许多模型都是从基本的梯度下降开始的,但还有一些更高级的选项可以在现实场景中表现得更好。
Adam 优化是一个明智的选择。它结合了 AdaGrad 和 RMSprop 的优势。它能够很好地处理噪声数据和稀疏梯度,因此成为一种流行的默认选择。
优化器 = optim.Adam(model.parameters(), lr=0.001)0.001)
RMSprop 有助于提高学习的稳定性。它根据近期梯度行为调整学习率,并且非常适合非平稳问题。
优化器 = optim.RMSprop(模型.参数(), lr=0.001, alpha=0.99)0.001,α= 0.99)
Adagrad 会根据你的数据进行调整。它会改变每个参数的学习率,这对于稀疏数据非常有用,但可能会导致学习率随着时间的推移而过度收缩。
优化器 = optim.Adagrad(model.parameters(), lr=0.01)0.01)
让我们有一个简单的表格,它将为我们提供有关我们拥有的优化器以及它们如何组合在一起的概述。
Optimizer |
优势 |
非常适合场景 |
Adam |
将 AdaGrad 和 RMSProp 的优势与智能学习率相结合 |
在大多数情况下都能很好地工作,特别是对于大型复杂数据 |
RMSprop |
修复了 AdaGrad 学习率下降的问题 |
适合在线学习和更改数据 |
Adagrad |
改变每个参数的学习率,适用于稀疏数据 |
在数据稀疏或要素变化很大时非常有用 |
Nadam |
为亚当增加 Nesterov 动量,以加快学习速度 |
当你想要比亚当更快的训练时 |
Adadelta |
通过保持学习率不会变得太小来改进 Adagrad |
非常适合调整模型和稳定的训练 |
L-BFGS |
精确优化方法的内存友好版本 |
最适合需要精细控制的中小型问题 |
Conjugate Gradient |
使用线搜索查找智能步长,很好地处理稀疏性 |
适用于计算量大的大型问题 |
因此,这种比较可以帮助机器学习工程师决定选择哪种优化器。
我们可以放心地从 Adam 开始。虽然优化器之间存在差异,但重要的是从实际出发,获得一些初步的见解。
大规模训练的框架和工具
接下来是正则化技术,它对于防止过拟合和确保模型能够很好地泛化到新数据至关重要。以下是一些常见的方法,可以帮助你的模型很好地泛化到新数据。
具有权重衰减的 L2 正则化有助于抑制过大的权重,从而使模型更简单。
优化器 = optim.Adam(model.parameters(), lr= 0.001 , weight_decay= 1e-5 )
模型中的 Dropout 层会在训练过程中随机删除神经元,从而降低模型过度拟合的可能性。
根据验证损失提前停止训练。如果验证损失不再改善,则进一步训练就没有意义了。
best_loss = float ( 'inf' ) # 将最佳损失初始化为无穷大waiting = 10 # 如果没有改进,则停止前等待的时期数waiting = 0 #计算范围内(max_epochs)时期没有改进的时期 数: val_loss = verify(model, val_loader) # 在验证集上进行评估if val_loss < best_loss: best_loss = val_loss # 更新最佳损失 waiting = 0 # 如果有改进,则重置计数器else : waiting += 1 # 没有改进,增加计数器if timer >= waiting: print ( 'Early stops' ) # 如果“patience”时期没有改进,则停止训练break
处理超大型模型会带来新的挑战。以下是一些简化处理的方法。
模型并行将模型拆分到不同的 GPU 上。模型的不同部分在不同的设备上进行处理。
数据并行将数据分布在各个 GPU 上。PyTorch自动管理此DataParallel
过程。
模型 = DataParallel(MyModel()) model.to( 'cuda' )
梯度累积允许更大的批次。当内存受限时,通过在更新之前累积梯度,这种方法很有帮助。
联邦学习将数据保存在本地设备上。模型在单独的设备上进行训练,并且仅共享更新。
为了使大型模型更高效,同时又不损失太多性能,知识提炼是一种很好的方法。
使用大型教师模型训练小型学生模型。这有助于在保持良好准确率的同时缩小模型规模。
def knowledge_distillation_loss ( outputs, label, teacher_outputs, temp= 2.0 , alpha= 0.5 ): # 硬损失:学生预测和真实标签之间的标准交叉熵hard_loss = F.cross_entropy(outputs, label) # 软损失:软化的学生和教师预测之间的 KL 散度# 温度用于软化概率分布soft_loss = F.kl_div( F.log_softmax(outputs / temp, dim= 1 ), # 学生对数(软化)F.softmax(teacher_outputs / temp, dim= 1 ), # 教师对数(软化)reduction= 'batchmean' # 批次平均值) # 最终损失:硬损失和软损失的加权和# 按照原始 KD 论文中的建议,将软损失乘以 temp^2 return alpha * hard_loss + ( 1 - alpha) * soft_loss * (temp ** 2 )
通过结合正确的优化器、正则化方法和训练策略,我们可以构建强大而高效的模型,甚至规模化。
让我们有一个比较表来获得更清晰的理解。
技术 |
描述 |
优势 |
缺点 |
最适合场景 |
模型并行性 |
跨不同设备拆分模型层 |
允许您在多个 GPU 上训练非常大的模型 |
由于设备之间的通信而变慢 |
当模型对于一个设备的内存来说太大时 |
数据并行性 |
向不同设备发送不同的数据批次 |
易于使用,可通过 PyTorch 等工具进行良好扩展 |
同步渐变可能导致网络速度减慢 |
可轻松拆分数据的大型模型 |
梯度累积 |
在更新之前合并较小批次的渐变 |
帮助在小内存上训练大批量 |
由于更新速度较慢,需要更长的训练时间 |
当 GPU 内存紧张但需要大批量处理时 |
联邦学习 |
在本地设备上进行培训并集中组合结果 |
改善隐私并使用来自不同来源的数据 |
更难建立和管理通信 |
当隐私问题和数据跨设备传播时 |
知识蒸馏 |
使用大型模型的知识训练小型模型 |
创建具有相似性能的较小模型 |
需要一个好的大模型和仔细的调整 |
需要一个好的大模型和仔细的调整 |
管道并行性 |
将模型分解为在管道中运行的阶段 |
通过重叠工作使设备更繁忙 |
拆分和管理模型阶段更加复杂 |
对于其他方法不足以解决的大型模型, |
使用 TensorFlow 和 PyTorch 进行扩展
在大规模使用 AI 时,框架也发挥着重要作用。以下是一些常用的框架:
1.TensorFlow提供 TensorFlow 分布式策略,帮助在 GPU 和 TPU 之间有效地扩展训练。
2.PyTorch以 PyTorch Distributed 而闻名,支持跨多个 GPU 和多台机器进行扩展。
3.Horovod与 TensorFlow、PyTorch 和 Keras 协同工作,以提高 GPU 和 CPU 的可扩展性。
4.Kubernetes有助于在大规模运行时顺利部署和管理 AI 工作负载。
5.CUDA和cuDNN加速GPU计算和深度学习性能。
6.NeMo专注于构建语音和自然语言处理模型。
模型缩放和高效处理
扩展模型是处理大数据集和复杂任务的关键。让我们探索一些简单的方法,实现模型和数据的并行化、智能地处理批次数据,并应对训练挑战。
模型并行,当模型规模过大,单 GPU 无法处理时,我们可以将其拆分到多个设备。您可以按层(垂直)或部分层(水平)进行拆分。这样做的目的是减少设备之间的数据传输。
我们可以使用像 NCCL 这样的快速通信库来减少移动数据时的延迟并torch.cuda.synchronize()
确保设备按顺序完成任务。
数据并行,我们可以在多个设备的不同数据块上运行同一个模型。当模型适合单个GPU,但我们希望并行处理更多数据时,这非常有用。
在反向传递之后,DDP 会在设备之间同步梯度,因此模型权重保持不变。
我们还可以通过梯度压缩来减少通信负载。这是一个使用 8 位量化的简单版本:
高效的批处理,我们可以通过调整批次处理的方式来提高速度和内存使用率。
·混合精度训练使用半精度(float16)来实现更快的计算:
scaler = GradScaler() # 处理缩放以防止 float16 梯度下溢, dataloader中的目标: optimizer.zero_grad() #使用autocast() 清除先前的梯度: # 启用混合精度 - 在安全的情况下使用 float16,否则使用 float32 output = model(data) # 前向传递(float16 中的一些操作) loss = loss_fn(output, target) # 计算损失(仍然在 float32 中) scaler.scale(loss).backward() # 缩放损失以避免梯度下溢,然后反向传播 scaler.step(optimizer) # 取消缩放梯度,如果没有溢出,则调用optimizer.step() scaler.update() # 调整下一次迭代的比例
·如果你的 GPU 无法处理大批量,梯度累积会有所帮助:
让我们了解同步和异步训练之间的基本区别:
同步训练,所有工作线程在更新权重之前等待交换梯度。确保模型一致,但最慢的工作线程会拖慢所有工作线程的速度。
·梯度平均
·自适应批次大小
·预测等待时间调度
异步训练工作器无需等待即可更新权重。虽然速度加快,但梯度可能会失效。
·使用过时的梯度校正
·动态调整学习率
·维护模型版本以跟踪更新
那么,到目前为止我们所学到的知识,让我们将其总结在一个表格中:
第三阶段:高级模型推理技术
当我们部署机器学习模型并且数百万人使用它们时,肯定需要一种有效的推理方法,以便所有用户都能轻松访问它。
我们经常会遇到资源不如预期那么容易获得的情况。在本节中,我们将探讨各种可以帮助我们更优化、更有效地进行推理的技术和策略。
大规模高效推理
模型量化 (Model Quantization)可以通过降低数字的精度(例如从 32 位浮点数转换为 8 位整数)来缩小模型体积并加快推理速度。这意味着模型更小、计算速度更快,但需要注意准确率的下降。
主要有两种类型:
·静态量化:在运行模型之前将权重转换为低精度。
·动态量化:在推理过程中动态转换权重和激活,平衡速度和灵活性。
以下是使用 PyTorch 在 ResNet18 模型上进行动态量化的方法:
# 使用 ResNet18 的动态模型量化示例import torch from torchvision.models import resnet18 # 加载预训练的 ResNet18 模型model = resnet18(pretrained= True ) model.eval ( ) # 设置为推理的评估模式# 在线性层上应用动态量化,以实现更快的推理和更小的模型尺寸quantumized_model = torch.quantization.quantize_dynamic( model, {torch.nn.Linear, torch.nn.Conv2d}, dtype=torch.qint8 ) # 打印量化模型架构print (quantized_model)
有两种最常用的训练技术在节省磁盘空间、内存以及最重要的成本方面发挥着重要作用。
·训练后量化:在训练后对模型进行量化。这种方法速度很快,但可能会导致更大的准确率损失,因为模型在训练时并不知道它会使用较低的精度。
·量化感知训练 (QAT):模型在训练期间考虑量化进行学习,因此它能够适应量化后的情况,并且通常能够保持更好的准确性。
以下是使用 PyTorch 在 ResNet18 模型上执行 QAT 的方法:
从torchvision.models导入resnet18导入torch.quantization model = resnet18(pretrained= True ) model.train() #融合 Conv、BatchNorm 和 ReLU 层以实现更好的量化model = torch.quantization.fuse_modules(model, [[ 'conv1' , 'bn1' , 'relu' ]]) # 设置 QAT 配置model.qconfig = torch.quantization.get_default_qat_qconfig( 'fbgemm' ) # 为 QAT 准备模型 (就地) torch.quantization.prepare_qat(model, inplace= True ) # ... 在此处添加训练循环以微调模型 ... # 训练后转换为量化版本torch.quantization.convert(model, inplace= True ) print (model)
模型修剪通过删除不太重要的部分来帮助缩小模型——要么将单个权重清零,要么切除整个神经元或通道。
·非结构化剪枝:将单个权重(模型中大量的微小“洞”)归零。它可以使模型变得稀疏,但通常需要特殊的硬件/软件才能获得速度优势。
·结构化修剪:删除整个通道或过滤器,这在常规硬件上更容易加速,但通常需要一些重新训练。
您还可以在训练期间动态修剪。
让我们看一个非结构化和结构化修剪的例子。
大规模高效推理
在手机、物联网设备或云服务器等不同平台上部署 ML 模型时,您需要针对每个环境采取不同的方法:
·模型简化:删除那些对准确率提升不大但耗费资源的层或操作。这有助于使模型更精简、更快速,尤其是在有限的设备上。
·硬件感知优化:使您的模型适应可用的硬件功能,例如使用 GPU 优化或利用某些智能手机上的 NPU(神经处理单元)。
·软件框架和工具:使用专为您的平台设计的部署工具。示例:TensorFlow Lite:非常适合移动设备和边缘设备。ONNX Runtime:可跨多个平台运行,确保性能稳定。
专用硬件可以大大提高速度:
·GPU:非常适合深度学习中常见的矩阵乘法等并行任务。
·TPU:谷歌针对张量数学优化的定制芯片,对于训练和推理都非常高效。
·FPGA:灵活的硬件,可针对特定工作负载进行编程,提供出色的性能和能源效率。
假设优化 ML 系统进行推理的时间表为一年,则时间表可能如下所示:
我们来看一个LLM推理优化的例子:
从transforms导入torch导入AutoModelForCausalLM、AutoTokenizer、BitsAndBytesConfig 导入时间 def setup_model ( optimized= True ): # 为“facebook/opt-350m”模型加载标记器 tokenizer= AutoTokenizer.from_pretrained( “facebook/opt-350m” ) if optimal: # 设置量化配置,使用 float16 计算精度进行 4 位加载quantumization_config = BitsAndBytesConfig( load_in_4bit= True, bnb_4bit_compute_dtype=torch.float16 ) # 加载启用 4 位量化的模型model = AutoModelForCausalLM.from_pretrained( “facebook/opt-350m”, quantization_config=quantization_config ) # 将模型转换为 BetterTransformer 后端以实现更快的推理model = model.to_bettertransformer() else : # 加载标准全精度模型(不进行优化)model = AutoModelForCausalLM.from_pretrained( "facebook/opt-350m" ) # 将模型移至 GPU 以加快计算速度return tokenizer, model.to( "cuda" ) def generate_text ( model, tokenizer, input_text, use_flash_attention= False ): # 对输入文本进行标记并将张量移至 GPUinput = tokenizer(input_text, return_tensors= "pt" ).to( "cuda" ) if use_flash_attention: # 启用 FlashAttention 内核,以便在支持的 GPU 上进行高效的注意力计算with torch.backends.cuda.sdp_kernel(enable_flash= True , enable_math= False , enable_mem_efficient= False ): output = model.generate(**inputs) else : # 常规生成,不使用 FlashAttention 优化output = model.generate(**inputs) # 将生成的标记 ID 解码为字符串,跳过特殊标记return tokenizer.decode(outputs[ 0 ], skip_special_tokens= True ) def measure_performance ( input_text, optimal= True , use_flash_attention= False ): # 设置模型和标记器(优化或标准)tokenizer, model = setup_model(optimized) # 记录生成的开始时间start_time = time.time() # 使用给定的模型和 tokenizer 生成文本 result_text = generate_text(model, tokenizer, input_text, use_flash_attention) # 记录结束时间并计算耗时end_time = time.time() print ( f"生成的文本:{result_text} " ) print ( f"花费时间:{end_time - start_time: .2 f}秒" ) # 示例输入提示input_text = "Hello my dog is cute and" # 启用优化运行(4 位量化 + BetterTransformer + FlashAttention)print ( "Running optimal version:" ) measure_performance(input_text, optimal= True , use_flash_attention= True ) # 使用标准模型且不使用 FlashAttention 运行print ( "nRunning unoptimized version:" ) measure_performance(input_text, optimal= False , use_flash_attention= False )
当你的模型训练完毕并准备就绪后,下一个重要步骤就是确保它在现实世界中运行良好。
管理实时应用程序的延迟和吞吐量
这意味着它应该能够处理大量请求、快速响应,并且无论发生什么情况都保持可靠。让我们来看看如何在生产环境中高效地扩展模型推理。
在生产环境中,请求可能飞速涌入。您需要将这些请求均匀地分布到您的服务器,以免任何服务器过载。这就是负载平衡的作用,它能确保一切平稳运行。但如果处理不当,您的系统仍然可能出现问题。
·自适应负载平衡:这意味着根据服务器当时的繁忙程度向服务器发送请求,就像交通管制员指挥汽车行驶在最不拥挤的道路上一样。
·资源分配:合理使用硬件至关重要。GPU 处理繁重任务时性能强劲,但处理简单请求时可能略显吃力。根据请求的强度将任务分配给 GPU 或 CPU,有助于节省资源并加快处理速度。
当您的机器学习模型上线时,特别是在实时应用程序中,您需要处理两件大事:延迟和吞吐量。
·延迟是指您获得答复的速度。
·吞吐量是指在给定时间内您可以处理的答案数量。
两者都很重要,但有时改进其中一项可能会拖慢另一项的进度。让我们来分析一下如何在没有技术术语的情况下同时管理两者。
在实时应用中,用户或系统不想等待太久。你希望模型能够快速给出答案。
·修剪您的模型:使用量化和修剪等技术(前面介绍过)来缩小您的模型并使其更快,而不会降低准确性。
·更智能地服务:模型的服务方式至关重要!需要额外处理能力时使用 GPU,或者使用 TorchServe 等工具来高效管理请求,可以带来巨大的改变。
吞吐量是指您的模型可以同时处理多少个请求,这在流量高峰期间非常重要。
·批量处理:将多个传入请求合并并一次性处理,就像乘坐一辆满载乘客的公交车,而不是为每位乘客单独安排一辆车一样。整体速度更快,但批量处理需要一些时间才能完成。
·异步处理:让您的系统在处理先前请求的同时处理新请求,就像您在烹饪时接收新订单一样。这确保一切顺利进行。
平衡延迟和吞吐量意味着有时您需要根据实时发生的情况更改一次处理的请求数和批量大小。
以下是使用 PyTorch 实现此目的的简单方法:
两者都很重要,但有时改进其中一项可能会拖慢另一项的进度。让我们来分析一下如何在没有技术术语的情况下同时管理两者。
在实时应用中,用户或系统不想等待太久。你希望模型能够快速给出答案。
·修剪您的模型:使用量化和修剪等技术(前面介绍过)来缩小您的模型并使其更快,而不会降低准确性。
·更智能地服务:模型的服务方式至关重要!需要额外处理能力时使用 GPU,或者使用 TorchServe 等工具来高效管理请求,可以带来巨大的改变。
吞吐量是指您的模型可以同时处理多少个请求,这在流量高峰期间非常重要。
·批量处理:将多个传入请求合并并一次性处理,就像乘坐一辆满载乘客的公交车,而不是为每位乘客单独安排一辆车一样。整体速度更快,但批量处理需要一些时间才能完成。
·异步处理:让您的系统在处理先前请求的同时处理新请求,就像您在烹饪时接收新订单一样。这确保一切顺利进行。
平衡延迟和吞吐量意味着有时您需要根据实时发生的情况更改一次处理的请求数和批量大小。
以下是使用 PyTorch 实现此目的的简单方法:
从队列导入torch从线程导入队列#定义一个简单的线性模型用于推理模型= torch.nn.Linear( 10 , 2 )模型。eval () # 将模型设置为评估模式def inference_worker ( input_queue ): while True : # 等待来自队列的一批输入 batch = input_queue.get() if batch is None : # 检查退出信号break with torch.no_grad(): # 禁用推理的梯度计算 output = model(batch) # 对输入批次运行推理# (可选)根据需要在此处处理输出 input_queue.task_done() # 将任务标记为完成# 创建一个最大大小为 10 的队列来保存输入批次input_queue = Queue(maxsize= 10 ) # 启动一个工作线程来处理来自队列的输入批次worker = Thread(target=inference_worker, args=(input_queue,)) worker.start() # 动态地将批次送入队列for _ in range ( 100 ): input_batch = torch.randn( 5 , 10 ) # 创建一个包含 5 个样本的批次,每个样本包含 10 个特征 input_queue.put(input_batch) # 将批次添加到队列进行处理input_queue.put( None ) # 向工作线程发送退出信号worker.join() # 等待工作线程完成
到目前为止,我们已经了解了……
这不仅仅关乎速度或容量,还关乎平衡快速响应和平稳处理重负载,以让用户满意
边缘人工智能和移动部署
在智能手机和物联网设备等边缘设备上部署人工智能模型意味着在数据创建的地方运行人工智能。
这种设置可以减少延迟、节省网络带宽,并且由于数据不必离开设备,因此可以使您的数据更加私密。
为了使 AI 在这些有限的设备上良好运行,您需要关注几个智能策略:
·模型优化:使用量化、剪枝和知识提炼等技术来缩小模型规模。较小的模型运行速度更快,并且在性能较弱的硬件上也能更好地适应。
·边缘友好型框架: TensorFlow Lite 和 PyTorch Mobile 等工具专为此而构建。它们有助于转换和优化您的模型,使其在边缘设备上高效运行。
import tensorflow as tf # 将 TensorFlow 模型转换为 TensorFlow Lite 格式以用于边缘部署converter = tf.lite.TFLiteConverter.from_keras_model(model) tflite_model = converter.convert() with open ( 'model.tflite' , 'wb' ) as f: f.write(tflite_model)
边缘设备通常对处理能力、内存和电池寿命有严格的限制。因此,您的 AI 模型需要精简高效:
·模型压缩:使用修剪或量化缩小模型以节省空间并加快推理速度。
·节能算法:选择或设计不会耗尽电池或使处理器过载的算法。
·边缘优化架构:使用 MobileNet 或 EfficientNet 等网络,这些网络专门构建为快速、轻便且准确的网络。
第四阶段:性能分析与优化
在优化人工智能系统时,关键是要找出造成瓶颈的地方,以便修复它们并提高性能。
诊断系统瓶颈
这里有两个主要帮助工具:分析和基准测试。
分析旨在深入挖掘系统如何使用 CPU、GPU 和内存等资源,以及代码不同部分的运行时间。它就像一张性能地图,突出显示了您想要改进的缓慢或繁重之处。
·Python 的 cProfile:一个方便的内置工具,用于测量 Python 代码花费大部分时间的地方。
·NVIDIA Nsight 系统:如果您使用 NVIDIA GPU,此工具可以跟踪 GPU 性能并帮助查找 CUDA 代码中的瓶颈。
基准测试着眼于全局:与标准或以往版本相比,您的整个系统的速度和效率如何。它设定了一个基准,让您了解起点,并衡量您的改进措施带来的成效。
·建立基线:在改变任何东西之前,对当前系统进行基准测试。
·比较:检查您的系统与其他系统或行业基准相比如何。
·衡量影响:优化后,再次进行基准测试,看看您的改进是否真的产生了影响。
瓶颈有不同的形式,如计算、内存或网络,每种形式都需要不同的修复。
当您的处理器(CPU/GPU)无法跟上工作时,就会出现计算瓶颈。
修复:
·使用并行计算:将工作分散到多个核心或 GPU 上以加快速度。
·优化算法:简化计算或切换到更有效的方法来减轻负担。
当您的系统无法足够快地移动数据或内存不足时,就会出现内存瓶颈。
修复:
·缓存经常使用的数据以避免内存读取速度缓慢。
·使用修剪、量化或更轻的数据结构来减少内存占用。
·示例:如果您的模型对于 GPU 内存来说太大,您可能需要这些技巧,因为您不能仅仅添加更多 RAM。
网络瓶颈出现在数据需要在机器之间传输的分布式系统中。
修复:
·使用更好的数据序列化来缩小发送数据的大小。
·切换到更高效的通信协议,以降低延迟并加快数据传输。
操作化人工智能模型
密切关注系统健康状况和 AI 模型性能对于平稳可靠的运行至关重要。良好的监控有助于及早发现问题,防止其恶化成更大的问题。以下是建立有效监控策略的简单方法:
您可以使用的工具:
·Prometheus:一款开源工具,用于收集和存储 CPU 使用率、内存消耗、磁盘 I/O 和网络流量等指标。它非常适合追踪 AI 基础架构的整体运行状况。
·Grafana:一款强大的可视化工具,可与 Prometheus 完美配合,创建直观的仪表板。它可以帮助您轻松发现系统数据中的异常和趋势。
模型性能监控热门选项包括:
·TensorBoard: TensorBoard 专为 TensorFlow 和 PyTorch 构建,可让您可视化训练和评估指标,例如损失、准确率、权重分布,甚至模型架构。定期检查这些指标有助于您了解模型的学习和性能。
·自定义日志记录:有时您需要跟踪 TensorBoard 未涵盖的应用程序特定指标或事件。实现您自己的日志记录系统可以捕获预测、错误或任何自定义 KPI,以便进行更深入的分析。
因此,一些最好的监控技术是:
·设置有意义的警报:收集数据固然重要,但定义关键指标的阈值也至关重要,这样当出现问题时,您就能立即收到通知。警报可以帮助您在问题影响用户之前迅速采取行动。
·监控数据质量:模型的优劣取决于其获取的数据。请注意数据漂移(输入数据随时间的变化)以及可能降低性能的异常情况。例如,记录样本图像或数据批次可以帮助您及早发现数据漂移。
·持续评估:定期使用新数据评估您的模型,以发现性能下降。当准确率或其他指标低于设定的阈值时,自动发出警报或触发重新训练,确保您的模型持续有效。
·指标异常检测:使用基于 ML 的异常检测技术自动标记模型性能中的异常模式,这样您无需人工检查即可始终掌握潜在问题。
·检测数据和概念漂移:定期检查数据或问题本身的性质是否发生变化。专用的漂移检测工具可以提醒您这些变化,从而提示您更新模型或进行重新训练。
·自动重新训练管道:构建能够在新数据到达或性能下降时自动重新训练和部署模型的工作流。但务必设定严格的标准,避免将资源浪费在实际应用中无关紧要的细微改进上。
调试人工智能系统:工具和方法
由于数据流和模型复杂,调试 AI 非常棘手。请使用以下工具和方法:
·PyTorch Autograd Profiler:检查 PyTorch 模型中的时间和内存使用情况。
·TensorFlow 调试器 (tfdbg):检查张量值以发现 NaN 或错误形状等错误。
·交互式调试:使用 Jupyter 笔记本进行实时数据和模型检查。
·高级分析: NVIDIA Nsight 和 PyTorch Profiler 等工具可以分析 GPU 的使用情况和硬件瓶颈,以优化性能。
机器学习的 CI/CD 管道
快速、可靠的模型更新是 AI 项目的关键。CI/CD 可自动执行测试、集成和部署,以最少的手动工作确保模型平稳运行。
能够快速测试和改进机器学习模型是构建成功的人工智能系统的关键。通过使用 CI/CD(持续集成和持续部署),我们可以以最少的手动工作量实现测试、模型更新和部署的自动化。这确保一切运行顺畅可靠。
机器学习中的持续集成 (CI)
CI 指的是自动检查代码更改,以便及早发现问题。在机器学习中,它还包括检查数据、训练脚本以及模型本身。
·自动化测试:设置测试来检查数据质量、模型训练和预测。单元测试用于小部件,集成测试用于整个流程。自动化测试 :设置测试以检查数据质量、模型训练和预测。对小部件使用单元测试,对完整管道使用集成测试。
·版本控制:使用DVC等工具跟踪数据和模型的变更,就像代码一样。这有助于保持所有内容的一致性,并在需要时轻松回滚。
机器学习中的持续部署 (CD)
CD 意味着自动将新模型投入生产,以便用户快速获得最新的改进。
·模型服务:TensorFlow Serving或TorchServe等工具有助于高效地提供模型并管理版本。
·Docker:使用Docker将模型与其所有依赖项捆绑在一起。这使得在任何地方运行模型都变得很容易。
·Jenkins + Kubernetes:使用Jenkins自动执行测试和部署模型等任务。与Kubernetes结合使用,可在生产环境中扩展和管理模型。
额外的工具使其更好地工作
·实验跟踪:MLflow或Weights & Biases等工具有助于跟踪实验、模型指标和结果。
·环境管理:使用Conda或Pipenv等工具来管理 Python 包,并与 Docker 配对以在开发和生产过程中保持一致性。
·模型验证:设置自动检查,以确保每个模型在部署之前符合性能标准(例如准确性或精确度)。
原文始发于微信公众号(StaticCodeAnalysis):如何设计大规模人工智能系统(您需要了解的每一个组件)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论