coremltools 权重 Palettization API 完整指南:Core ML 与 PyTorch 模型压缩实战

发布时间:2026/10/13 7:03:35
coremltools 权重 Palettization API 完整指南:Core ML 与 PyTorch 模型压缩实战
AI 应用机器学习模型优化【免费下载链接】coremltoolsCore ML tools contain supporting tools for Core ML model conversion, editing, and validation.项目地址https://gitcode.com/gh_mirrors/co/coremltools点击查看免费下载本篇技术指南系统讲解 coremltools 中用于**模型权重 Palettization调色板化/查表压缩**的全部公开 API。你将掌握一条通用且一致的工作流先定义压缩配置对象Config再调用压缩方法将模型权重量化为 n-bit 查表表示。文中覆盖 Core ML 模型cto.coreml.palettize_weights与 PyTorch 模型PostTrainingPalettizer、SKMPalettizer、DKMPalettizer两条压缩路线并深入参数语义、定制粒度与底层实现读完即可在你的模型上完成从压缩到 Core ML 转换的完整实操。一、Palettization 与 API 总览Palettization 是权重压缩技术把连续浮点权重离散化为一组有限的“调色板”值Lookup TableLUT权重只存储指向 LUT 的索引。一个n-bitLUT 最多有2^n个条目相比原始 fp16/fp32 权重可显著降低存储占用。运行时由 LUT 与索引重建浮点权重后再参与浮点运算因此不改变计算精度与中间张量精度只改变存储形式见 palettize_weights 源码。虽然核心mltools 提供了多条 Palettization API因输入模型格式——Core ML 还是 PyTorch——以及优化工作流的不同而各异但所有 API 都遵循相同的两步流程定义配置对象Config指定算法参数如位数n_bits、粒度granularity等。配置既可在全局层面定义应用到模型中所有 op/module也可按op 类型op-type或op 名称op-name做细粒度定制。配置对象既可在代码中以字典初始化也可通过 YAML 文件从磁盘加载from_dict/from_yaml。调用压缩方法传入配置与模型执行压缩。二、Palettizing a Core ML 模型cto.coreml路线这条路线针对已经转换为 Core MLmlprogram 类型的模型做训练后压缩Post-Training Palettization。压缩对模型内所有受支持权重矩阵执行 K-Means 聚类生成 LUT 并改写权重存储。2.1 最简示例全局 6-bit Palettization以下示例对所有参数个数超过 512 的 op应用6-bitPalettization通过weight_threshold512控制import coremltools as ct import coremltools.optimize as cto # load model mlmodel ct.models.MLModel(uncompressed_model_path) # define op config op_config cto.coreml.OpPalettizerConfig(nbits6, weight_threshold512) # define optimization config by applying the op config globally to all ops config cto.coreml.OptimizationConfig(global_configop_config) # palettize weights compressed_mlmodel cto.coreml.palettize_weights(mlmodel, config)2.2OpPalettizerConfig核心参数配置类 OpPalettizerConfig 是描述算法参数的载体其字段与默认值在源码中有完整定义关键参数如下参数说明默认值 / 取值nbits控制聚类数量即 LUT 条目数为2^nbits合法值{1, 2, 3, 4, 6, 8}kmeans/uniform模式必填unique/custom模式禁止填写weight_threshold元素总数小于该阈值的权重张量不被 palettize2048源码_check_weight_threshold校验为非负整数mode决定 LUT 的构造方式kmeans默认、unique、uniform、customgranularityPalettization 粒度per_tensor默认或per_grouped_channelgroup_size一个分组内的通道数仅per_grouped_channel时生效32channel_axis形成通道分组的轴仅per_grouped_channel时生效None为None时按 op 类型自动选择cluster_dim每个 LUT 质心的维度1为标量 palettization1为向量 palettization沿通道轴每cluster_dim长度的权重向量共享同一个 2-D 质心1enable_per_channel_scale为True时palettize 前按输出通道使用逐通道 scale 对权重归一化Falsenum_kmeans_workers执行 k-means 的 worker 进程数多 CPU 时建议大于 1 以并行聚类1关于mode的底层细节来自 OpPalettizerConfig 源码kmeans默认通过 k-means 聚类生成 LUT需提供nbits。uniform基于线性直方图生成 LUT取值形如[v_min, v_min scale, ..., v_max]其中scale (v_max - v_min) / (1 nbits - 1)。源码注释示例nbits4、weight[0.11, 0.19, 0.3, 0.08, 0.0, 0.02]时数据范围[0.0, 0.3]被线性切成 4 份得到 LUT[0.0, 0.1, 0.2, 0.3]权重被舍入为索引[01b, 10b, 11b, 01b, 00b, 00b]。unique直接从权重中的唯一值构造 LUT适用于离散网格但以浮点存储的权重。此时不能传nbits框架自动在{1, 2, 4, 6, 8}中选取能容纳唯一值数量的最小位数若唯一值超过 256 个则跳过压缩。例如权重{0.1, 0.2, 0.3, 0.4}会被转换为{00b, 01b, 10b, 11b}并生成 LUT[0.1, 0.2, 0.3, 0.4]。custom使用自定义函数lut_function(weight)计算 LUT 与索引此时须提供lut_function且nbits由函数内部自定义。注意OpPalettizerConfig._from_dict不支持lut_function的字典/ YAML 序列化需在代码中直接构造对象源码 L774-L777 有明确约束。2.3OptimizationConfig按 op 类型与 op 名称精细定制除全局配置外OptimizationConfig提供三级配置优先级op name最高→op type→global源码 OptimizationConfig 的_get_op_config/_get_const_op_config实现层级越具体覆盖越广。示例对全部 op 应用6-bit但所有linearop 用8-bit并跳过名为conv1、conv3的两个卷积 opimport coremltools as ct import coremltools.optimize as cto mlmodel ct.models.MLModel(uncompressed_model_path) global_config cto.coreml.OpPalettizerConfig(nbits6) linear_config cto.coreml.OpPalettizerConfig(nbits8) config cto.coreml.OptimizationConfig( global_configglobal_config, op_type_configs{linear: linear_config}, op_name_configs{conv1: None, conv3: None}, # None 表示跳过该 op ) compressed_mlmodel cto.coreml.palettize_weights(mlmodel, config)要点说明op_type_configs的键是 op 类型字符串如conv、linear值为对应的 config值为None表示该类型 op 不压缩。op_name_configs的键是具体常量或 op 实例的名称值为None表示跳过该实例。若某个常量被多个 op 消费且各 op 配置冲突框架会抛出compression config conflict detected错误见_get_const_op_config。也可用config.set_global(...)、config.set_op_type(...)、config.set_op_name(...)方法等价地设置各层级注意若使用旧的ct.compression_utils兼容路径set_op_type/set_op_name会被禁用。配置对象支持OptimizationConfig.from_dict(...)与OptimizationConfig.from_yaml(...)源码 L1031-L1182可从嵌套字典或 YAML 文件构造YAML 中通过config_type: OpPalettizerConfig指定配置类。2.4 获取 op 名称get_weights_metadata()要定制op_name_configs必须先知道模型里各权重/op 的名字。使用cto.coreml.get_weights_metadata(mlmodel, weight_threshold...)工具见 mlmodel-utilities.md它返回一个保序字典键为权重名称值为CoreMLWeightMetaData包含val权重数据、sparsity稀疏率、unique_values唯一值数量、child_ops该权重馈入的 op 元信息。weight_threshold用于过滤元素总数不大于该阈值的权重不会出现在结果中源码 get_weights_metadata。典型用法——找到最后一个权重并跳过其压缩最后一层往往对精度更敏感import coremltools.optimize as cto from coremltools.models import MLModel from coremltools.optimize.coreml import get_weights_metadata mlmodel MLModel(SegmentationModel_with_metadata.mlpackage) weight_metadata_dict get_weights_metadata(mlmodel, weight_threshold2048) # 遍历权重按名称筛选要定制/跳过的 op op_name_configs {name: None for name in weight_metadata_dict.keys() if 需要跳过} config cto.coreml.OptimizationConfig(global_config..., op_name_configsop_name_configs)2.5 底层原理从const到constexpr_lut_to_dense从 palettize_weights 源码 可以看清内部机制函数遍历mlprogram中所有权重按mode指定的算法离散化并构造 LUT随后把存储权重的constop 替换为constexpr_lut_to_denseop。运行时由 LUT 与 n-bit 索引重建浮点权重再参与浮点计算。该函数本质上是对PASS_REGISTRY[compression::palettize_weights]图变换graph pass的封装通过PassOption(config, ...)把配置注入 pass它还支持joint_compressionTrue做联合压缩如“剪枝 palettize”lut(sparse) - constexpr_lut_to_sparse - weight(sparse) - constexpr_sparse_to_dense - weight(dense)。三、Palettizing 一个 Torch 模型ct.optimize.torch.palettization路线与 Core ML 路线逻辑一致但直接作用于 PyTorch 模型在转换前压缩提供三种算法训练后 PalettizationPT、Sensitive K-MeansSKM与可微 K-MeansDKM。公共 API 在 palettization/init.py 中统一导出。3.1 训练后 PalettizationPostTrainingPalettizer与 Core ML 路线相同的 k-means 思想只不过对象是 Torch 模型。示例为所有 op应用4-bitgranularity为per_grouped_channelgroup_size4每 4 个通道共享一个 LUTfrom model_utilities import get_torch_model from coremltools.optimize.torch.palettization import PostTrainingPalettizer, \ PostTrainingPalettizerConfig # load model torch_model get_torch_model() palettization_config_dict { global_config: {n_bits: 4, granularity: per_grouped_channel, group_size: 4}, } palettization_config PostTrainingPalettizerConfig.from_dict(palettization_config_dict) palettizer PostTrainingPalettizer(torch_model, palettization_config) palettized_torch_model palettizer.compress()关键参数定义于 ModulePostTrainingPalettizerConfig参数说明默认值n_bits聚类数量控制位LUT 条目数为2^n_bits4lut_dtypeLUT 元素的存储 dtype为None时不对 LUT 量化None支持torch.int8、torch.uint8granularityper_tensor整个张量共享一个 LUT或per_grouped_channelper_tensorgroup_size一个分组内的通道数仅per_grouped_channel时必填且需 0per_tensor时须为None源码有校验Nonechannel_axis形成通道分组的轴仅per_grouped_channel生效当前支持输入或输出通道轴0cluster_dim每个 LUT 质心的维度1表示 2-D 聚类LUT 中每个条目长度为cluster_dimNoneenable_per_channel_scale为True时按输出通道逐通道 scale 归一化权重后再 palettize与cluster_dim 1不兼容源码有断言校验Falseenable_fast_kmeans_mode开启时若数据在 fp16 范围内先舍入再聚类fp32 会先转 fp16加速 k-meansTruerounding_precisionenable_fast_kmeans_mode开启时的舍入小数位数越小越快但近似更粗糙4compress()方法支持num_kmeans_workers与inplace参数当 worker 数 1 时走_ParallelKMeans.cluster_weights并行聚类推荐多 CPU 场景开启否则走_SequentialKMeans.cluster_weights见 PostTrainingPalettizer.compress 源码。压缩后还可调用report()获得压缩前后对比报告。3.2 Sensitive K-MeansSKMPalettizer需校准数据SKM 实现基于敏感度的加权 k-means对应算法介绍见 opt-palettization-algos.md。与普通 k-means 的差异在于它利用 Fisher 信息矩阵Hessian 的近似计算每个权重元素对模型损失的敏感度加权 k-means 会把聚类中心向更敏感的值靠拢从而在同等位数下获得更小的精度损失。该算法需校准数据与损失函数来计算敏感度。配置同样可用 YAML 文件描述以下palettization_config.yaml实现全部 op4-bit、所有Linear模块6-bit、跳过conv1/conv3global_config: n_bits: 4 module_type_configs: Linear: n_bits: 6 module_name_configs: conv1: null conv3: null calibration_nsamples: 64Python 脚本加载该 YAML 并执行 SKM Palettizationfrom model_utilities import get_torch_model from data_utils import get_calibration_data from coremltools.optimize.torch.palettization import (SKMPalettizer, SKMPalettizerConfig) import torch.nn.functional as F torch_model get_torch_model() palettization_config SKMPalettizerConfig.from_yaml(palettization_config.yaml) # create the loss function loss_fn lambda mod, dat: F.nll_loss(mod(dat[0]), dat[1]) calibration_data get_calibration_data() palettizer SKMPalettizer(torch_model, palettization_config) palettized_torch_model palettizer.compress(dataloadercalibration_data, loss_fnloss_fn)要点配置参数与训练后 Palettization 相同n_bits、lut_dtype、granularity、group_size、channel_axis、cluster_dim、enable_per_channel_scale定义于 ModuleSKMPalettizerConfig另加顶层calibration_nsamples默认128见 SKMPalettizerConfig。compress()相比 PT 路线多两个必传参数dataloader可迭代对象每个元素是模型的输入用于计算权重的梯度源码中通过loss.backward()累计梯度平方得到敏感度。loss_fn可调用对象接收模型与数据执行前向并计算训练损失。从源码看SKM 支持单进程与多进程两种敏感度计算_compute_sensitivity_impl_single_worker/_compute_sensitivity_impl_multiple_workers多进程模式用FullyShardedDataParallel分片模型适合单卡放不下的大模型。3.3 Differentiable K-MeansDKMPalettizer训练时压缩DKM 是**训练时training-time**的 Palettization 算法基于注意力机制的可微 k-means直接嵌入训练流水线通常需要更多数据。核心思路见 palettizer.py 源码用可微 k-means 对权重聚类使 LUT 与索引可以通过 SGD 等梯度优化方法联合学习。训练时 Palettization 的关键步骤定义DKMPalettizerConfig配置 Palettization 参数用DKMPalettizer初始化 palettizer 对象调用prepare(inplaceTrue)向模型插入FakePalettize模块通过给模块挂qconfig实现见_attach_qconfig源码运行常规训练循环并额外调用palettizer.step()模型收敛后调用finalize()将 LUT 与索引折叠回权重得到可直接转换 Core ML 的模型。以下示例对全部 op 应用2-bitDKM配置字典中n_bits: 4仅为示意默认值并指定milestone10即第 10 次调用palettizer.step()时才真正开始 Palettizationfrom model_utilities import get_torch_model from training_utilities import train_step from data_utils import get_dataloader from coremltools.optimize.torch.palettization import (DKMPalettizer, DKMPalettizerConfig) import torch.nn as nn torch_model get_torch_model() dataloader get_dataloader() num_palettization_epochs 2 palettization_config_dict { global_config: {n_bits: 4, milestone: 10}, } palettization_config DKMPalettizerConfig.from_dict(palettization_config_dict) palettizer DKMPalettizer(torch_model, palettization_config) # Call the prepare API to insert palettization friendly modules into the model palettizer.prepare(inplaceTrue) torch_model.train() for epoch in range(num_palettization_epochs): for batch_idx, (data, target) in enumerate(dataloader): train_step(data, target, torch_model) palettizer.step() palettized_torch_model palettizer.finalize()ModuleDKMPalettizerConfig关键参数定义于 palettization_config.py参数说明默认值n_bits聚类数量控制位聚类数为2^n_bitsLinear 默认4其余层默认2见DEFAULT_PALETTIZATION_SCHEME按模块类型weight_threshold权重元素数不超过该值的模块不 palettize对MultiheadAttention等含多个权重的模块须所有权重都超过阈值才压缩2048granularity/group_size/channel_axis同前述per_grouped_channel时group_size必填DKM 目前仅支持输出通道轴分组per_tensor/None/0enable_per_channel_scale为True时沿通道维度使用逐通道 scaleFalsemilestone开始 Palettization 前需调用palettizer.step()的次数若每步调用一次则为训练步序号若每 epoch 调用一次则为 epoch 序号0表示训练一开始即启用0cluster_dim每个聚类LUT 条目的维度按模块类型quantize_activations为True时同时对激活量化Falsequant_min/quant_max权重聚类被量化时每个元素的最小/最大值-128/127dtype激活量化使用的 dtype仅quantize_activationsTrue时生效torch.qint8支持 qint8/quint8/fp32lut_dtypeLUT 元素的量化 dtypef32表示不量化聚类f32可选 i8/u8/f16/bf16/f32此外还有大量高级选项DEFAULT_PALETTIZATION_ADVANCED_OPTIONS源码 L40-L66如kmeans_max_iter可微 k-means 最大迭代默认 3、kmeans_initauto/opt1d/cpu.kmeans/kmeans、palett_modegsm/dkm/hard、palett_tauDKM softmax 温度默认 0.0001、enforce_zero强制将最接近原点的质心固定为 0、palett_unique/palett_shard/palett_batch_mode面向大模型 LLM 的 eDKM 高效/分布式选项、percentage_palett_enable、kmeans_n_init等。源码注释明确说明大多数情况下无需修改这些高级参数使用默认值即可仅在将 DKM 与激活量化联用时才需要调整quant_min/quant_max/dtype/quantize_activations。另外旧参数partition_size、cluster_dtype已被标记弃用请改用group_size、lut_dtype。四、将 Palettized 的 PyTorch 模型转换为 Core ML对使用ct.optimize.torch.*API 完成 Palettization 的 PyTorch 模型coremltools 8 可以直接转换无需额外参数。若使用了需要较新系统能力的新特性如per_grouped_channel粒度对应 iOS18/macOS15则须通过minimum_deployment_target指定部署目标import torch import coremltools as ct palettized_torch_model.eval() traced_model torch.jit.trace(palettized_torch_model, example_input) palettized_coreml_model ct.convert(traced_model, inputs...) # or if iOS18 features were used in palettization palettized_coreml_model ct.convert(traced_model, inputs.., minimum_deployment_targetct.target.iOS18)如果你是用其他非 coremltools 的 API 对 Torch 模型做了 Palettization或使用的是 coremltools 8 之前的版本则需要走另一条转换流程来保证 Core ML 模型内包含正确的 palettized op详见 opt-conversion.md。五、如何选择 Palettization 算法三条 Torch 路线对应三种工作流Core ML 路线则是已转换模型的后处理手段PostTrainingPalettizer训练后直接压缩无需重新训练适合对精度要求不苛刻、追求快速压缩的场景SKMPalettizer训练后压缩但需要少量校准数据与损失函数计算敏感度能显著降低大模型压缩后的精度损失参考 SqueezeLLM 思想适合对精度敏感、可提供校准集的场景DKMPalettizer训练时压缩LUT 与索引随训练联合优化效果通常最好但数据与算力要求更高适合从零训练或继续微调fine-tune的场景。无论选择哪条路线通用的最佳实践是先用weight_threshold跳过小权重张量、用get_weights_metadata()识别对精度敏感的关键层如最后一层并通过op_name_configs跳过再配合modekmeans/uniform/unique/custom与granularityper_tensor或per_grouped_channel在压缩率与精度之间做权衡。赞分享AI 应用机器学习模型优化【免费下载链接】coremltoolsCore ML tools contain supporting tools for Core ML model conversion, editing, and validation.项目地址https://gitcode.com/gh_mirrors/co/coremltools点击查看免费下载相关推荐coremltools 压缩模型转换实战从 PyTorch 压缩权重到 Core ML 压缩 MIL 算子coremltools 压缩模型转换实战从 PyTorch 压缩权重到 Core ML 压缩 MIL 算子 压缩pruning、palettization、AI 应用机器学习模型优化coremltools ML Program 权重压缩工具指南量化、Palettization 与稀疏化coremltools ML Program 权重压缩工具指南量化、Palettization 与稀疏化 导读 Core ML Tools 为 mlprogrAI 应用机器学习模型优化coremltools 的 PyTorch 权重 Palettization 完全指南DKM 训练时压缩、敏感度加权 SKM 与训练后 Palettizationcoremltools 的 PyTorch 权重 Palettization 完全指南DKM 训练时压缩、敏感度加权 SKM 与训练后 PalettizatiAI 应用机器学习模型优化上一篇解决ESP32-C5开发痛点噪声层测量异常深度排查与优化方案下一篇ESP-IDF中esp_reset_reason()函数在日志级别为NONE时的异常行为深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考