ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

端侧模型放得下吗?从体量计算到量化压缩实战

端侧模型放得下吗?从体量计算到量化压缩实战 1. 先把体量账算清楚端侧设备的容量天花板在哪1.1 参数量、精度和文件大小的换算关系标题里问“端侧本地模型放得下吗”这问题没法用一句“能”或者“不能”回答因为“模型规模”和“能不能放下”之间隔着好几层换算。很多人看到“XX亿参数”就紧张其实先要搞懂一个最小单元一个参数在内存里占多少个字节。同一个模型用不同精度存储大小差得很远。FP32单精度浮点每个参数占 4 字节FP16半精度浮点每个参数占 2 字节INT88比特整数每个参数占 1 字节常见的 4bit 量化每个参数约 0.5 字节所以一个 10 亿参数1B的模型原始 FP32 权重是 4GB转成 FP16 是 2GB量化到 INT8 是 1GB再激进一点压到 4bit 只剩约 500MB。这个换算关系是整个话题的地基后面所有讨论都建立在它上面。很多人只盯“文件大小”但真正决定能不能跑起来的是“运行时峰值内存”。权重文件能塞进存储不代表推理时能塞进内存。手机 App 拿到一个 1GB 的模型文件加载时权重、激活值、KV Cache自回归模型里的缓存、中间特征图是同时在内存里的实际占用往往是文件大小的 1.5 到 2 倍。1.2 端侧设备的“三堵墙”存储墙、内存墙、算力墙判断一个模型能不能本地跑要同时看三堵墙。第一堵墙是存储。普通手机现在 128GB 起步空间看起来不缺但系统、照片、App 把空间瓜分完之后留给单个应用离线模型包的往往只有几个 GB。嵌入式设备更紧张很多工业边缘盒子存储就是 8GB 或 16GB还要分一部分给日志和系统能放模型的区域非常有限。第二堵墙是内存。这是最常被低估的。手机内存看着有 12GB、16GB但操作系统、当前 App、后台进程都在抢。一个 App 能稳定申请到的内存很多时候只有 2GB 到 4GB。模型推理是内存密集型操作峰值一冲上去轻则掉帧重则直接被系统杀掉。第三堵墙是算力。端侧 NPU/DSP 现在跑 CNN 这类结构很擅长但 Transformer 里的注意力矩阵、Softmax、Gelu 这类算子在不同芯片上的表现方差非常大。有些 NPU 对动态形状支持很差词表检索、beam search 这类操作可能根本加速不了。算力不够模型就算装得下推理速度也会让人无法接受。1.3 端侧模型常见的量级区间结合我实际做过和见过的设备大致有这么几个舒适区模型量级FP16 大小INT8 大小4bit 量化后端侧可行性100M0.1B200MB100MB50MB非常轻松任何设备都能跑300M0.3B600MB300MB150MB主流手机无压力嵌入式需评估1B2GB1GB500MB手机上的上限区需配合优化3B6GB3GB1.5GB高端机勉强普通设备吃力7B14GB7GB3.5GB基本告别普通端侧除非特殊硬件所以“端侧能不能放下”不是一个绝对概念。200M 级别的模型几乎放哪都能跑1B 级别开始要精打细算再往上就属于硬件专项定制范畴。有了这张尺子我们再回头量“万物识物”和“多语言翻译”这两个具体需求。2. “万物识物”的本质为什么模型规模会失控2.1 从固定 1000 类到开放词表任务定义改变了模型结构传统图像分类模型比如大家熟悉的 ResNet、MobileNet 那套思路逻辑很简单图片输入网络提取特征最后接一个全连接分类头输出神经元个数等于类别数。你训练一个 1000 类模型分类头就是 1000 个神经元想识别 1 万类就把分类头改成 1 万维。模型主体不动动的只是一个线性层。但“万物识物”的诉求完全不是这样。现实里的物体远远超出固定列表今天加一个品类、明天加一个品牌分类头方案永远追不上。于是业界走向了开放词表Open Vocabulary路线代表性的做法就是类 CLIP 的对比学习架构一个图像编码器一个文本编码器把图片和文字映射到同一个向量空间通过计算图像特征和文本特征之间的相似度来判断“图片里是什么”。这个架构带来的第一个变化是模型不再是一个网络而是两个网络。图像编码器负责把像素变成向量文本编码器负责把候选标签变成向量。两个网络的参数量加在一起规模立刻比单纯分类模型大了一圈。2.2 类CLIP架构的端侧版本视觉和文本两条链路各占多少很多人以为 CLIP 类模型“只有”几百兆这个印象来自那些被裁剪过、只做推理用的版本。实际上完整训练态模型的体量视觉编码器加文本编码器动辄 1B 以上。不过刚才那张尺子告诉我们端侧更关心的是“能不能压缩后运行”所以我们要拆开看两条链路的压缩空间。视觉编码器通常是 CNN 或 ViTCNN 类结构对端侧非常友好卷积算子在各家 NPU 上都有深度优化压缩到 INT8 甚至 4bit 后精度损失相对可控。文本编码器是 Transformer算子和显式/隐式的注意力机制相关端侧支持度取决于芯片但 300M 到 600M 的文本编码器压到 150MB 左右并不夸张。更隐蔽的开销在“万物”这个词本身。你真正部署的时候不能把整本词典都当作候选标签一次丢进去算相似度。假设一次识别要比较 100 个候选类别的文本特征那至少要把 100 个文本向量全部加载到内存如果候选词表有 10 万个词把全部文本特征算一遍时间和内存都会失控。所以实际工程里要做候选挖掘Candidate Mining先用一个轻量模型粗筛再对候选子集精细比较。2.3 “万物”还需要词表兜底候选标签本身也要占内存这里还要补一个很多人忽略的点文本编码器不是吃进去一个词而是吃进去一段经过 tokenizer 切分的 token 序列。多语言场景下词表里每种语言都要有对应的子词单元标签文本越长编码器计算量越大。我遇到过最头疼的情况是“万物”清单里放了大量长尾名词比如一条商品的完整标题“2024 新款户外防水登山鞋男防滑耐磨徒步鞋”tokenizer 切完可能是一长串 token。识别时每一帧都要把这一长串文本编码一遍计算量不是线性的是隐性地暴涨。所以“万物识物”放在端侧真正决定成败的不是那个视觉编码器而是文本编码器和词表带来的附加内存与延迟。如果把视觉端压到 200M文本端却因为词表膨胀到 300M总账依然不好看。3. 多语言翻译的真正瓶颈词表膨胀比模型深度更麻烦3.1 BPE和子词为什么多语言词表按“语言数”放大多语言翻译模型和单语翻译模型的差异和“模型深度”关系不大最核心的差异在词表Vocabulary。单语词表通常 3 万到 5 万个子词就够用了。多语言场景下每种语言都有自己独特的字符体系中文的汉字、日文的假名、韩文的谚文、阿拉伯文的连写字母、各种拉丁字母变体……这些字符无法直接共享词表只能跟着语言数量往上膨胀。现在的做法主流是 BPE / SentencePiece 这类子词切分算法好处是把常见词拆成更小片段让不同语言之间可以共享一部分子词。比如“telephone”和“téléphone”可以共享一部分 token。但跨语系的共享非常有限中文汉字和英文子词之间几乎无法共享所以词表膨胀是硬约束。一个典型的多语言词表规模覆盖欧洲十余种语言时词表大约 100k 到 150k覆盖亚欧非数十种语言时词表往往冲到 250k 到 500k。这里每个 token 不是一个简单的整型它还对应一个向量。3.2 词表与隐藏维度决定的 Embedding 权重账Embedding 矩阵的体量很好算词表大小 × 隐藏维度 × 参数精度假设词表 300k、隐藏维度 1024、用 FP16300000 × 1024 × 2B 614MB这只是一个 Embedding 矩阵。Transformer 模型通常输入和输出层各有一次 Embedding 操作很多实现是共享权重的也就是输入层和输出层用同一个矩阵这时还好如果不共享上面这个 614MB 就要乘以 2变成 1.2GB。更麻烦的是Embedding 矩阵在推理时不像普通权重层那样可以连续计算它涉及查表操作内存访问模式对端侧缓存很不友好。翻译模型解码的时候每一步都要在输出层做一次“词表规模 × 隐藏维度”的矩阵乘法。词表越大这一步越慢。还有一个小细节多语言模型通常还要给每种语言加一个语言 ID 嵌入Language Embedding虽然体量不大但同样会占用维度空间。所以在多语言模型里几百兆的参数可能不是核心网络而是词表嵌入矩阵。3.3 多语言翻译模型的整体体量实测区间结合开源社区做过的一系列多语言翻译模型大致落在这些区间模型配置词表规模总参数量FP16 文件INT8 文件小型6层d_model 51260k200M-300M400-600MB200-300MB中型12层d_model 768150k800M-1.2B1.6-2.4GB0.8-1.2GB大型24层d_model 1024300k3B-5B6-10GB3-5GB结论很明确用中等规模的量化版本多语言翻译模型是可以放进端侧的尤其是词表控制在 150k 以内、参数量在 1B 左右、量化到 INT8 或 4bit 时总占用能压到 1GB 上下。对一部主流手机这是可行的对 8GB 存储的嵌入式盒子就要斟酌了。4. 端侧放不下时的实战压缩手段量化、蒸馏、分片的取舍4.1 量化从FP16到4bit的真实收益与精度回退既然原始模型放不下第一个想到的就是量化。量化不是新鲜概念但很多人把“量化”当成一键压缩忽略了精度回退问题的分布不均。对翻译模型来说量化掉的经验是Embedding 层对量化非常敏感因为词向量直接决定语义空间的位置从 FP16 强行砍到 4bit近义词之间的距离会发生漂移翻译出来的词经常“差一口气”。而 Transformer 里的注意力层和前馈层对量化相对宽容。实操上建议混合精度Embedding 层保留 INT8 甚至 FP16计算密集的线性层用 4bit注意力矩阵用 8bit。这样既保住了语义质量又把整体占用压下来。每次量化之后都要在真实数据上跑一遍双语 BLEU 或者 chrF 指标不要只看困惑度。4.2 蒸馏与结构化裁剪让端侧模型“本来就不大”量化是在“已训练好的大模型”上做减法蒸馏则是从源头上训练一个小的。做法是用一个千亿或者几十亿参数的大模型当老师让几百 M 的小模型去拟合老师模型的输出分布。蒸馏出来的小模型在指定语言对上的效果往往比直接拿小模型在数据上硬训要好很多。我特别推荐在多语言场景里做“分组蒸馏”不是让一个小模型同时学 100 种语言而是按语系分组蒸馏出一组小模型每个小组负责若干种相近语言。翻译时先判断语言类型再路由到对应的小模型。这样每个模型词表更小精度更高加载和切换也灵活。结构化裁剪剪枝在端侧的实际收益没有想象中大。Transformer 里过度剪枝容易导致整体性能崩塌而且剪枝后的稀疏矩阵在很多 NPU 上不能直接用还要再转回稠密折腾一圈还不如直接蒸馏一个小模型来得干净。4.3 模型分片与词表动态加载运行时再抠内存如果模型总量还是超了可以考虑“并不全部加载进内存”的思路。翻译模型里最常见的做法是“分片加载”把模型拆成 Embedding 层、若干 Transformer 层、输出层几个部分按需从存储映射进内存。端侧跑在第一个 token 之前只加载前几层解码到中途再加载后面的层。配合操作系统的内存映射mmap机制可以让系统按页读取权重而不是一次性把整个文件读进来。对词表特别大的模型可以做“词表裁剪快照”模型包里放一个完整词表用于离线检索但推理时只加载当前语言对相关的那部分 token 向量。比如一个 300k 词表的模型如果用户只切换中英、中日翻译只把中文和英文相关的 60k token 的子词向量加载进来Embedding 内存直接少一大块。4.4 分层卸载不是丢人方案端侧云端的混合架构纯端侧方案一旦要覆盖几十种语言和“万物识别”成本会非常难看。我见过不少团队最后选择了混合架构端侧放一个轻量级模型应对离线需求和常见场景云端放完整大模型兜底。联网时自动走云端断网时降级到端侧模型。很多人觉得“端侧云端”是妥协不“纯粹”。但在实际产品里用户在乎的是“能不能离线用”“快不快”“准不准”而不是“模型是否真的全部装在本地”。一个合理的降级链路往往比“死磕端侧”更能照顾体验。关键是降级策略要做到用户无感端侧模型负责大概率常见的识别和翻译当置信度低或遇到陌生语言对时自动切换到云端。这个置信度阈值需要反复调调太高则离线模式频繁失败调太低则云端流量和延迟白白增加。5. 务实决策框架什么必须放端侧什么应该留在云端5.1 判定标准延迟、隐私、带宽、离线到底哪些能力要放端侧哪些可以交给云端我习惯用四个维度打分。延迟敏感度实时翻译、实时识别用户等不起一次 800ms 的网络往返这类优先放端侧。隐私敏感度医疗影像、身份证件、聊天内容等数据不出设备是硬需求必须本地处理。带宽成本视频流、大批量图片识别在弱网环境下传不动端侧可以先兜底。离线可用性明确要求飞行模式、野外环境也能用的场景比如巡检、户外导航端侧是唯一选择。四项里只要中了两项就应该考虑端侧方案。如果一项都不占那上云端是更经济的选择没必要把模型塞进设备折磨自己。5.2 参考架构一个双级缓存系统我自己比较偏好的参考架构是“双级缓存”第一级端侧常驻一个覆盖高频需求的轻量模型比如 200M 的识别模型加一个 500M 左右、覆盖头部十几种语言的翻译模型。系统启动时就加载保证基础功能离线可用。第二级按需下载的语言包或品类包。用户第一次使用某种冷门语言或识别某个垂直品类时提示下载一个几十 MB 的增量模块。下载后替换或补充到第一级模型旁边。这个方案的好处是不是一开始就让用户下载一个 3GB 的“全家桶”而是让用户只为他需要的部分付费存储和流量。增量模块之间通过版本号管理服务端可以随时发布新的语言包而不需要用户升级整个 App。5.3 低资源场景下的降级方案词典、检索、模板翻译如果连 500M 的小模型都不想放或者设备太陈旧还有一条更轻的路线用检索式方案代替生成式模型。物体识别可以退化为“特征向量 本地检索库”每张图像抽一个向量提前给每个候选类别抽好向量部署时只放一个“类别向量库”几十 MB 搞定。翻译可以退化为“短语词典 模板匹配”离线词典命中高频短语模板负责句子结构替换。这种方案效果当然不如大模型但作为应急降级、特定垂直领域比如工业设备铭牌识别、餐厅菜单翻译完全够用。这里我特别想强调一个工程心态端侧方案不是“替代”云端方案而是“分层兜底”。很多时候低资源方案解决的是“有和没有”的问题不是“好和更好”的问题。5.4 给三类团队的选型建议团队资源不同策略完全不同。个人开发者别轻易碰多语言全家桶。选一个 300M 以下的单一语言翻译模型加一个轻量识别模型只支持中英等两三个核心语言对先把闭环跑通。中小团队采用“按需下载 双级缓存”架构主推 5 到 10 种高频语言冷门语言走云端 API云端失败再提示离线不可用。大团队有硬件和算法资源可以考虑自研蒸馏管线针对自家设备做混合精度量化把模型压到极限后常驻端侧。6. 我踩过的坑和给你的实操建议6.1 词表统一设计能一石二鸟我参与过的项目里有一个关键决策把“万物识物”的文本编码器词表和多语言翻译的词表统一起来。好处很明显同一个 tokenizer、同一套子词视觉语言和翻译模型共享 Embedding 矩阵整体包体直接小一截。但代价是词表设计阶段很痛苦。视觉标签用词偏名词翻译用词偏句式表达两者对子词切分的偏好不完全一致。你需要在大规模语料上做好词频统计平衡视觉和翻译两个域的子词覆盖。一旦定下来后续再做任何语言扩展都要小心翼翼因为改词表等于改模型输入空间。6.2 多语言质量退化加语言要雨露均沾多语言模型的经典坑是语言越加越多每种语言的质量都在掉尤其是资源稀缺的小语种会被高资源语言“挤占”。原因不难理解模型总容量有限词表、层参数要分给更多语言。我的建议是加语言不能“只加词表、不训练”要把新语言的语料和已有语言的语料按比例混合重新做一轮全语言微调。每次加语言之后都要在已有的主要语言上重新跑一遍回归测试。否则容易出现“新增中文翻译很好但英文翻译突然变差”的尴尬情况。6.3 别只看文件大小要看峰值内存和首Token延迟模型放进设备之后判断能不能用不要只看安装包大小。要实测两件事峰值内存用内存分析工具跑一段连续翻译任务看加载模型 推理时的峰值 RSSResident Set Size。如果超过 App 可用内存上限的一半大概率会在低内存设备上被杀。首 Token 延迟多语言翻译是自回归生成用户从输入文字到屏幕上出现第一个译文 token 的等待时间直接影响体验。这个数字受算力、量化方案、词表大小影响很大实测比理论估算可靠。我自己吃过亏一个 INT8 模型文件挺小但在某款 NPU 上因为嵌入查表和反量化算子不支持硬件加速首 token 延迟冲到 1.5 秒只能重做算子融合。6.4 热更新设计词表不能随便加模型版本要兼容端侧模型很方便做热更新但词表版本不兼容是个暗坑。云端如果发布了新词表旧模型不认识新 token新模型不认识旧缓存结果就是翻译质量暴跌或者直接索引越界。建议在模型包里带上 tokenizer 的版本号服务端下发增量包时校验词表版本一致性。模型文件命名务必带 hash不要用“model_v2_final_really”这种诡异命名发布流程会乱到你怀疑人生。多语言翻译和万物识别同时上端侧没有银弹但也不是天方夜谭。核心策略就一句话能剪的剪、能量化的量化、能拆的拆、能降级的降级把用户最常用的那部分留在本地把长尾需求交给云端。端侧模型这个方向上我会持续跟下去下次再分享更多实测数据和踩坑记录。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表