☰
从训练调参到部署加速:Model-Optimizer模型优化全指南
2026/9/30 10:00:36 网站建设 项目流程

干过深度学习落地的人大概都遇到过这种场景:模型在验证集上的指标漂漂亮亮,一上生产环境就原形毕露——要么单次推理慢到无法接受,要么显存被吃穿,要么换个batch size直接报shape错误。另一类更早的问题发生在训练阶段:loss高开高走,曲线抖得像心电图,怎么调都收敛不了。这两类看起来八竿子打不着的麻烦,往深了挖都落在同一个关键词上:Model-Optimizer。

Model-Optimizer在深度学习圈子里其实指两件经常被混为一谈的事。训练阶段说的优化器(optimizer),管的是模型能不能收敛、收敛得快不快;部署阶段说的模型优化,管的是模型跑得多快、占多少资源。前者让模型学会,后者让模型好用。这篇文章我想把两个方向串起来讲一遍,结合自己在CV分类、NLP小模型项目里踩过的坑,给出一套从训练调参到推理部署的优化思路。不管你是刚接触深度学习的学生,还是正在为上线发愁的算法工程师,里面应该都有可以直接抄作业的部分。

1. 先搞清楚Model-Optimizer这个词到底指什么

1.1 训练侧:优化器是一门关于梯度的平衡术

训练阶段的optimizer,本质上是干一件事:根据损失函数算出来的梯度,决定模型参数往哪个方向更新、更新多大幅度。神经网络参数动辄几百万甚至上亿,如果只是机械地沿着负梯度方向走,会遇到一堆实际问题:最陡的方向不一定通向全局最优、样本间梯度方向不一致导致来回震荡、某些参数天然更新过快或过慢。优化器的工作就是在“走得太快容易震荡、走得太慢浪费时间”之间找平衡。

我经常跟团队里的新人打比方:梯度下降就像下山,你只知道脚底下这一小片地方的坡度。SGD是老老实实每一步都按当前坡度走,步子迈多大由学习率决定;动量SGD就是给下山过程加了一个惯性,走得顺的时候越走越快,遇到小坑能靠冲劲滑过去;Adam则像是配了一个智能拐杖,它会为不同的参数自适应不同的步幅,还带一点“历史经验”修正方向。这几种方案没有绝对的好与坏,完全取决于你的地形——也就是模型结构、数据集和损失面长什么样。

1.2 部署侧:把大而全的模型变成快而省的模型

部署阶段的Model-Optimizer,目标完全不同。训练好的模型精度高、泛化能力强,但它学到的知识里有大量冗余:接近零的权重、不重要的通道、可以被合并的算子、可以用更低精度表示的数值范围。生产环境的硬件资源是有限的,CPU算力、GPU显存、内存带宽、电池功耗都是成本。部署优化就是在“尽量不损失精度”的约束下,把模型改造成适合目标硬件的形态。

这一侧的技术栈包括量化(把FP32换成FP16、INT8甚至是INT4)、剪枝(删掉冗余的权重或通道)、蒸馏(让大模型教会小模型)、以及算子融合和格式转换。很多推理框架都自带这类能力,比如ONNX Runtime的graph optimization、TensorRT的层融合、OpenVINO Model Optimizer对模型中间表示的转换等。这些工具的收益肉眼可见:INT8量化通常能把推理延迟压到原来的1/2到1/3,显存占用降到1/4左右,代价是精度损失多半在0.5%到2%之间。对于工业场景,这是一笔非常划算的买卖。

1.3 两者的关系:同名不同命,但目标一致

训练侧优化器和部署侧优化器经常被混用,因为英文都带optimizer。但它们解决的问题、出现的时机、评测指标完全不同。我整理了下面这个表格,方便直观对照:

维度训练侧优化器部署侧模型优化
出现阶段训练/微调过程训练完成后的推理部署
核心目标尽快收敛到好的极小值降低推理延迟和资源占用
主要手段SGD、动量、Adam、学习率调度量化、剪枝、蒸馏、算子融合
评测指标loss下降曲线、验证集精度单帧耗时、吞吐、模型体积
副作用选错会不收敛或过拟合过度优化会掉点、工程复杂

不过这两个方向也不是完全割裂。训练时用了什么优化器、正则技巧,会直接影响权重分布和冗余程度,继而影响部署时量化、剪枝的难度。比如一个用SGD训练到位的模型,权重分布往往比较规整,做INT8量化时精度损失通常比训练不充分的模型小得多。所以真正成熟的团队会从训练的第一天就开始考虑部署优化,而不是训完再补救,这也正是“Model-Optimizer”作为一个整体词的价值所在。

2. 训练阶段的优化器选型与关键参数

2.1 动量SGD为什么还没退出历史舞台

很多人刚接触深度学习的第一个直觉是:Adam这么先进,自动调学习率、自带动量,干嘛还要用SGD?但如果你去翻ImageNet竞赛、经典检测模型的论文,会发现大批SOTA模型用的还是动量SGD。我在CIFAR-10上复现ResNet时也做过对比:同样的epoch数,SGD+momentum训出来的最终精度经常比Adam高0.5到1个百分点,而且泛化更稳。

原因说起来其实不复杂。Adam为每个参数单独维护一阶矩和二阶矩估计,相当于自适应地放大了学习率,这让它在稀疏梯度和非平稳目标上很有效;但这种自适应机制本身也带来一种隐式的正则化破坏——参数空间里平坦而宽阔的最优区域,往往比尖锐的极小值泛化更好,Adam会在梯度方向上更快冲进尖锐区域,而SGD的“匀速慢跑”反而更利于找到平坦区域。换句话说,动量SGD天然更适合那些需要强泛化能力的CV任务。

动量SGD的关键参数就那几个:学习率、momentum、weight decay。以ResNet在ImageNet上的常见配置为例,lr从0.1起步,momentum=0.9,weight_decay=1e-4到5e-4,配合cosine退火或者step下降。momentum的作用是平滑梯度方向,前几步小幅震荡、后面逐渐加速。weight decay对SGD来说就是真正的L2正则,它把权重往原点方向拉,能有效抑制过拟合,别直接抄Adam那套0.01级别的数值。

2.2 Adam与AdamW的优势和适用场景

Adam真正发光发热的领域是NLP、Transformer架构、扩散模型这类任务。BERT、GPT系列、Stable Diffusion的训练,几乎清一色用AdamW。原因是这类模型规模大、结构复杂,梯度噪声大,手动调学习率的成本极高,而Adam的自适应步长让模型在初期就能稳定前进了。

AdamW和经典Adam表面上只差一个实现细节:weight decay的处理方式。经典Adam把L2正则梯度加进梯度后再做归一化,实际效果会被二阶矩估计“带偏”;AdamW则是把weight decay直接在参数更新阶段施加,和梯度归一化解耦。这个改动别看小,实证效果是Transformer训练更稳、收敛更好。我第一次用Transformer做文本分类时直接沿用Adam+lr=1e-3,结果loss高位震荡,换成AdamW并把weight_decay调到0.01,问题立刻缓解。

对大多数任务,我建议按这个口诀起手:

  • CV分类/检测:动量SGD + weight_decay=5e-4 + cosine退火,先从lr=0.1试。
  • NLP/Transformer类:AdamW + weight_decay=0.01到0.05 + warmup,lr从1e-4到3e-4区间试。
  • GAN、扩散模型等不稳定训练:AdamW + 梯度裁剪,lr尽量保守,2e-4附近起步。
  • 微调大模型:低学习率AdamW,可以是1e-5到5e-5,warmup比例加大。

2.3 我常用的几组优化器配置与调参心得

这里贴一段我在PyTorch里常用的配置,配合学习率调度,基本可以覆盖大部分中小规模任务:

import torch import torch.nn as nn from torch.optim import SGD, AdamW from torch.optim.lr_scheduler import CosineAnnealingLR model = nn.Sequential(...) # 随便一个模型 # 场景1:CV分类,ResNet风格 optimizer = SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4, nesterov=True) scheduler = CosineAnnealingLR(optimizer, T_max=100, eta_min=1e-5) # 场景2:Transformer/文本分类,推荐AdamW optimizer = AdamW(model.parameters(), lr=2e-4, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.01) scheduler = CosineAnnealingLR(optimizer, T_max=50, eta_min=1e-6)

调参的几个心得,都是拿训练时长换出来的: 先把batch size固定下来再动学习率。batch size翻倍,学习率通常也要相应放大,但不一定是严格的线性关系。 warmup不是摆设。大模型、大批量训练时,前几个step用很小的lr稳定下来,再进入正常学习率,能显著减少早期不收敛。我见过Transformer任务完全不设warmup直接跑,前500步loss波动大到直接nan。 如果loss曲线在一个平台期下不去,先试cosine退火而不是无脑加大lr。cosine退火能让lr在后期自然降得很低,帮助模型在极小值附近精细化收敛,这个技巧几乎零成本。 跑小规模模型时别忽视梯度裁剪。max_grad_norm设在1.0附近,可以防止单个batch带来梯度爆炸,至少不会让loss瞬间飞走。

3. 部署侧的模型优化技术拆解

3.1 结构化剪枝:把冗余通道真正删掉

剪枝的思路很直白:模型里大量参数的数值接近于0,它们对输出的贡献微乎其微,留着纯属浪费。不过剪枝也分两个层次,我强烈建议直接做结构化剪枝,而不是非结构化剪枝。非结构化剪枝是逐个权重地砍,砍完模型参数矩阵里全是稀疏的洞,除非底层硬件和库对稀疏矩阵有专门优化,否则速度不升反降。结构化剪枝是按输出通道或卷积核整组删除,比如一个卷积层有256个输出通道,评估后发现其中32个通道的贡献可以忽略,就直接把这32个通道连同其后层的对应输入索引一起移除。

通道重要度评估最常用的方法是统计每个输出通道对应的权重L1范数。L1范数越小,说明这个通道产生的影响越弱,对精度的潜在伤害也越小。实际执行时不会一次性剪掉太多,而是迭代式地“剪一点-微调-再评估”:先按L1范数对通道排序,剪掉占比10%到20%的通道,然后用训练数据做几个epoch的微调恢复精度,重复这个过程。我在一个轻量分类模型上做过实验,剪掉30%的通道配合微调,精度几乎不降,模型推理速度提升约20%。

剪枝的代价是要改网络结构定义,不像量化那样只要插一个转换函数就行。对PyTorch来说,可以用torch.nn.utils.prune做基础实验,但要真正把结构瘦身,得手动重建一个窄版模型再拷贝保留下来的权重。这条路的工程复杂度最高,但它能带来实质性的计算量下降,尤其适合端侧CPU和低算力设备。

3.2 量化:用INT8换速度,精度怎么守住

量化是部署优化里性价比最高、也最常用的一招。FP32的权重和激活是32位浮点,量化成INT8就是8位整数,理论上权重体积直接缩到1/4,推理延迟也能大幅下降,因为整数运算在CPU和GPU上都比浮点快得多。代价是数值精度下降,所以量化的核心问题是找一组好的缩放系数,把FP32的数值范围合理映射到[-128, 127]的整数区间。

量化分训练后量化和量化感知训练两种。训练后量化最简单,拿一批代表真实分布的输入数据在模型上跑前向推理,统计各层激活值的min/max或百分位数,据此算出缩放系数。这个过程中有两点最容易翻车。第一,校准数据必须贴近实际业务数据,我用训练集做过一次,图像风格跟线上用户上传的图片差异太大,量化后精度掉了快5个点,换成线下真实采样数据后立即恢复到只掉0.8%。第二,如果不做任何处理,某些层(特别是首层和靠近输出的层)对量化非常敏感,需要单独保留FP32精度。

推荐的做法是先用百分位校准而不是min/max。激活值偶尔出现几个异常大的离群点,会把缩放范围拉得特别宽,导致大多数正常值映射后精度被压扁。percentile=99.9或者基于KL散度的方法,能容忍离群点,量化效果明显更稳。量化感知训练则是在训练过程中加入伪量化节点,让模型自己适应数值误差,适合量化后精度掉得比较多的场景,代价是要多一轮训练流程。

3.3 蒸馏:让大模型带小模型

蒸馏的思路是让一个又大又准的模型当老师,指导一个较小的学生模型学习。学生模型不直接模仿老师的硬标签,而是模仿老师输出的软概率分布。直观理解是:硬标签只告诉你这是“猫”,老师的软概率分布还告诉你“它有些像狗、也有些像狐狸”——这种额外信息就是学生模型能在参数量少很多的情况下,仍逼近老师精度的关键。

蒸馏的实现很简单,在损失函数里同时加入学生模型在真实标签上的交叉熵,以及学生和老师输出概率之间的KL散度。温度参数T负责调节软概率的平滑程度:T越高,概率分布越平滑,中间类别的相近概率信息被保留得更多。我在一个文本意图识别模型上做过蒸馏实验:老师模型是BERT-base,学生模型是一个6层的MiniBERT,参数量只有老师的1/3,蒸馏后学生模型在测试集上比直接训练同等结构高出近3个百分点,推理延迟也明显低于老师。

蒸馏最适合的场景有三个:模型体积和延迟有硬性要求、大模型已经训好不想重训、任务数据量不多但老师精度足够高。它最大的好处是不改变推理结构,不需要处理稀疏矩阵或低精度数值,只需在训练阶段多跑一个模型的前向推理。

3.4 推理引擎的编译与格式转换

训练好的模型无论用什么框架写的,最后都要落到目标推理引擎上。这一环节的Model-Optimizer主要负责格式转换、计算图优化和算子融合。以PyTorch模型为例,常规路线是先导出成ONNX,再由ONNX Runtime或TensorRT消费。ONNX Runtime会做算子融合,比如把Conv+BN+ReLU合并成单个算子,减少内存读写的次数;TensorRT则对NVIDIA GPU做更激进的层融合和kernel自动调优。

格式转换看起来是琐碎工作,实则暗坑不断。最典型的是动态shape问题:训练时模型接受固定尺寸输入,但业务上图片长短不一。导出ONNX时需要显式声明动态维度,否则推理引擎会全程按固定shape分配内存,换一个输入尺寸直接报错。另外,ONNX导出时opset版本也要留意,太老的版本不支持某些新算子,太新的版本在旧设备上可能没有对应实现。

OpenVINO的Model Optimizer是这类工具的典型代表,它把不同框架训练好的模型转换成统一的中间表示IR,再做图优化和精度分析。类似这样的“模型优化器”工具还有很多,选型逻辑很整齐:目标硬件是什么就用配套最成熟的工具,别指望一套工具吃遍所有芯片。

4. 一个完整的Model-Optimizer落地流程:从PyTorch训练到推理部署

4.1 场景设定与基线

为了把上面这些概念串成一条实际可跑的链路,我拿一个图像分类项目举例:模型是ResNet-18,训练数据是自采的工业零件缺陷图片,类别有6类,一共约5万张图。业务要求是部署在办公室的一台普通Intel CPU服务器上,单张图片推理耗时毛利率目标是不超过10毫秒,内存占用不能超过300MB,精度尽量接近线上原模型的94%左右。

先说基线。一个标准的ResNet-18在PyTorch里以FP32跑CPU推理,单张224x224图片耗时大约15到20毫秒,模型文件45MB左右,精度94.2%。直接上线虽然能用,但每秒只能处理50到60张图,遇到峰值流量会排队;模型体积倒不是大问题,延迟才是痛点。所以我需要做的是:训练阶段选择合适的优化器把模型训稳,再用推理引擎和量化工具把延迟压下去。

4.2 训练侧优化器配置

这个任务数据量不算太大、类别也不复杂,CV模型用动量SGD是稳妥选择。训练配置上我用了SGD+momentum=0.9+weight_decay=5e-4,初始学习率0.1,batch size=128,总共训练100个epoch,学习率在第30、60、90个epoch时各除以10。训练过程很顺,最终测试精度94.2%。

有人会问为什么不用AdamW一步到位?我在一副本上两种优化器都跑了:AdamW以lr=1e-3训练到100个epoch后精度93.4%,明显低于SGD。原因就是前面说的泛化差距。而且训练尾声我用cosine退火又微调了20个epoch,精度还能再涨0.3个点左右。这一步的价值不仅是精度,更重要的是:一个收敛充分的模型,权重分布更集中、冗余更少,后续量化时高精度区间被破坏的程度更小。把训练优化和部署优化当成一整个流程看待,收益是乘法而不是加法。

4.3 导出ONNX与形状处理

训练完成后,先把PyTorch模型导出成ONNX。这一步代码不多,但细节决定成败:

import torch model = torch.load("best_model.pth") # 训练好的模型 model.eval() dummy_input = torch.randn(1, 3, 224, 224) torch.onnx.export( model, dummy_input, "resnet18.onnx", opset_version=17, input_names=["input"], output_names=["output"], dynamic_axes={ "input": {0: "batch_size"}, "output": {0: "batch_size"} } )

我在导出时固定用opset 17,既能支持常见的ResNet算子,又能覆盖Conv、BatchNorm、ReLU融合的优化逻辑;dynamic_axes一定要加,因为线上推理的batch size很可能会变化,1、4、8几个不同的batch size都会出现。导出后再用onnxsim简化计算图,把一些重复的reshape、transpose清掉,ONNX Runtime读取时会更高效。这一步做完,先别急着量化,先把FP32的ONNX模型在ONNX Runtime里跑一遍,基线的单张延迟降到了大约12到14毫秒——光是格式转换和算子融合就带来了约25%的加速。

4.4 量化校准与精度验证

接下来做INT8量化。我用的方案是训练后量化,校准数据集从线上真实图片中抽了500张,覆盖全部6个类别。先把ONNX模型转成INT8动态量化版本,再用这500张图片统计各层激活值范围。第一次我偷懒只用了100张训练集图片,结果量化后精度掉到90.8%,足足3个多点,排查下来是校准集数据分布和线上偏差太大。换回500张近线真实采样后,精度恢复到93.6%,损失控制在0.6个百分点。

动态量化和静态量化也有区别:动态量化只量化权重,激活值在推理时才临时计算缩放,实现简单但对延迟提升有限;静态量化把权重和激活的缩放全部提前算好,推理时不计算动态缩放,速度更快,代价是需要校准过程。在这个项目里,静态量化的收益更明显:单张推理延迟从14毫秒降到了6毫秒左右,内存占用从45MB降到约12MB,基本满足业务要求。

4.5 部署结果对比

最终版本用ONNX Runtime加载INT8静态量化模型,CPU多线程设为8,单张224x224图片平均耗时5.8毫秒,内存占用约80MB,精度93.6%。相比原始的PyTorch FP32模型,延迟快了近3倍,体积降到1/4,精度只掉了0.6个百分点。整个优化过程中,模型结构和训练代码没有发生任何改动,投入的工时大约两个下午,大部分时间花在校准集抽样和精度验证上。

我把各阶段的指标整理成了表格,方便直观对比:

版本精度单张延迟模型体积
PyTorch FP3294.2%约16 ms45 MB
ONNX FP3293.9%约13 ms43 MB
ONNX INT8动态量化93.4%约9 ms12 MB
ONNX INT8静态量化93.6%约5.8 ms12 MB

5. 常见问题与排查技巧实录

5.1 训练不收敛,先别急着换模型

训练阶段的“不收敛”分好几种:loss完全不动、loss震荡、loss冲到NaN、验证集指标纹丝不动但训练loss很低。我的排查顺序是固定的:先看数据,再调优化器,最后才怀疑模型结构。

数据层面最容易被忽略的是输入归一化。很多人换用ImageNet预训练权重后,忘记把自己的图片也做相同的mean/std归一化,模型输出直接一片乱。其次看loss曲线形态:如果从一开始就不降,多半是学习率太小或者数据归一化错了;如果初始几步小幅下降后彻底停滞,可以试试把学习率调大10倍;如果loss直接NaN,优先检查是否有大规模梯度爆炸,权重初始化值是否过大,或者数据里混进了异常值。

优化器层面的调法也讲究优先级。不要同时把lr、momentum、weight decay、batch size全改一遍,这样根本无法定位原因。我习惯一次只动一个变量:先调学习率,再看weight decay,最后才动betas或momentum。一次调参记录一次实验,跑小规模的mini-set验证而不是整个数据集。

5.2 量化后精度崩了,问题可能不在量化本身

量化后精度大幅下降,大多数人第一反应是换更复杂的量化算法,但实际上问题往往更基础。先确认校准集是不是从真实业务分布里采的,这是我踩过最深的一个坑:训练集上漂亮的量化精度,到了线上就崩,本质上是分布漂移而不是量化算法不好。校准集不需要很大,但必须能代表真实数据的多样性,500张覆盖所有常见模式的图片已经够用。

其次检查有没有未融合的BatchNorm层。量化前必须把BatchNorm融合进卷积层,否则激活分布统计会被BN的缩放和偏移搅乱。ONNX Runtime和TensorRT通常会自动处理,但如果自己写转换流程,这一步很容易漏。最后再考虑哪些层需要跳过量化:第一层卷积接收原始图像输入,对量化极其敏感;输出层附近的逻辑层同理。对这些层保留FP32精度,通常能让精度回来一大截。

5.3 推理速度没提升,瓶颈在IO

模型量化完、延迟还是很糟,这时候先别急着继续压模型,看看瓶颈到底在哪个环节。最常见的坑是数据加载和预处理成了主要耗时:读取图片、解码、缩放、归一化、HWC转CHW,这一整套操作挂在CPU上,可能比模型推理本身还慢。我在一次优化中把模型延迟从20毫秒降到7毫秒,但端到端没改善多少,一查发现图片解码占了15毫秒。解决办法是预处理线程负责异步流水线,让推理线程只拿处理好的张量。

另一个高频问题是没有充分利用硬件特性。ONNX Runtime默认的线程数可能不是最优,CPU上可以显式设置线程数并开启intra-op并行;GPU上则要注意NCHW/NHWC布局和TensorCore的使用,一个数据布局不对,卷积算子的效率差好几倍。最后值得检查的是batch size,但小模型上频繁提交小batch的调度开销会抵消并行收益,这时候可能反而batch=1配合流水线更优。养成用profiler看算子级耗时的习惯,别靠猜。

5.4 避坑速查表

现象常见原因优先排查/解法
loss不下降学习率过低或输入未归一化调大lr验证、检查mean/std
loss震荡lr过大、batch过小降低lr、增大batch
loss为NaN梯度爆炸、异常样本梯度裁剪、检查数据
量化后精度大跌校准集分布不对、BN未融合换真实采样、融合BN
量化后个别层失准敏感层被量化首尾层跳过量化
推理延迟无改善预处理IO瓶颈profiler定位耗时、异步流水线
动态shape报错导出时未声明dynamic axes导出配置加dynamic_axes
算子不支持opset版本过老或过新调整opset版本

6. 工具链选型与我的几条经验建议

6.1 按团队条件选优化路线

Model-Optimizer不是一套固定的工具,而是一套解决问题的思路。选具体什么工具,取决于你的目标硬件、团队工程能力和上线紧迫度。

如果只是原型验证或者团队没有专职部署工程师,最省力的路线是PyTorch训练 + ONNX导出 + ONNX Runtime + 训练后INT8量化。这条链路几乎不用改代码,文档多、社区大,遇到问题基本能搜到答案,ROI最高。如果目标是NVIDIA GPU高性能推理,TensorRT是绕不开的选项,它能把图优化和算子自动调优做到极致,但格式转换、动态shape、精度校准的坑也最多,至少要预留一周的调试时间。如果目标设备是Intel CPU或集成显卡,OpenVINO的工具链配合得最好。端侧移动端则优先考虑NCNN、MNN这类专门为ARM优化过的推理引擎。

选型还有一个容易被忽略的维度:团队里谁负责后续维护。我见过有团队选了最激进的FP16+INT8混合精度方案,性能确实很顶,但半年后换一个人维护,对着配置完全无从下手。工程上稳定可用比极端性能更重要,尤其是长期运行的项目。

6.2 最后分享几点个人心得

我做模型优化这些年,最大的体会是:永远把精度下降当成一个预算问题来管理。训练阶段的优化器调参,省下的收敛时间;部署阶段的量化剪枝蒸馏,换来的推理速度,这些都是收益,但每一项都多多少少带着精度或复杂度的成本。成熟的优化过程不是一锤子买卖,而是反复的训练-评估-微调循环。

我自己的习惯是给每次优化建立一份简单的实验记录表,把精度、延迟、体积、校准集来源都写下来。很多时候一个方案失败,不是方案本身不行,而是之前的实验条件没对齐,换个校准集或者改个学习率,结论就完全不一样。另外,不管用什么优化手段,保留一个可复现的训练配置和完整的日志,比任何离线分析工具都重要。

最后再分享一个小技巧:量化、剪枝这类优化不要在整个模型上一次性开大火力,先拿一个子网络或者单层做小范围实验,确认精度和收益均衡合理,再全量推广。这个习惯帮我避开过好几次“全模型量化完了才发现某类算子不支持”的返工。模型优化的本质就是用最小代价换最大收益,而所有的代价和收益,都应该先用实验量化出来,再下结论。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询