对 Qwen3.5-4B(BF16, 8.07GB)进行逐层混合动态量化,在保持模型质量(PPL)的前提下,将模型压缩到4~5bit平均位宽。
核心思想:最简单的方案。所有层统一 bit(uniform),或按固定比例分上/下层(Q4-8-mix 上层8bit下层4bit)。不需要校准数据,不需要搜索算法。
| 配置 | 策略 | 平均bit | PPL | 模型大小 |
|---|---|---|---|---|
| FP16 基线 | 不量化 | 16 | 10.40 | 8.07GB |
| uniform_8bit | 全部8bit | 8 | 10.39 | 4.14GB |
| Q4-8-mix | 上层8bit+下层4bit | ~5.5 | 10.69 | 2.63GB |
| uniform_4bit | 全部4bit | 4 | 11.26 | 2.19GB |
核心思想:346个线性层,每层独立选 bit 位宽。用贝叶斯优化(高斯过程 + UCB acquisition)搜索最优分配,避免固定比例的"一刀切"问题。
| 版本 | 改进点 | bit池 | 平均bit | PPL | 备注 |
|---|---|---|---|---|---|
| v1 bayes | 基础GP+UCB | {3,4,8} | 4.00 | 11.35 | 首次跑通 |
| v2 bayes | 扩展bit池 | {2,3,4,5,6,8} | 5.06 | 14.63 | 2bit引入后变差 |
| v3 bayes | +低bit惩罚(3.0) | {2,3,4,5,6,8} | 5.06 | 10.88 | 惩罚2/3bit |
| v4 bayes ★ | +imatrix感知 | {2,3,4,5,6,8} | 5.05 | 10.49 | 项目最优 |
核心思想:参考 llama.cpp Q4_K_M。用 imatrix 对权重列排序,每 group_size 个元素一块,块内用 hi/lo 两种 bit 混合量化。不同于贝叶斯逐层选bit,K-quant是在层内做混合。
| 配置 | hi bit | lo bit | group_size | 平均bit | PPL |
|---|---|---|---|---|---|
| h5l3 ★ | 5 | 3 | 32 | 4.0 | 10.77 |
| h4l3 | 4 | 3 | 32 | 3.5 | 10.89 |
| h4l2 | 4 | 2 | 32 | ~3.0 | 13.44 |
核心思想:扫描不同平均 bit 下限(2.5~4.8),观察 PPL 随压缩率的变化曲线,找到质量-大小的拐点。
| 配置 | 平均bit | PPL | 模型大小 | 状态 |
|---|---|---|---|---|
| mixed_avg2.5 | 2.5 | 26813.65 | 0.34GB | 崩溃 |
| mixed_avg3.0 | 3.0 | 14.96 | 0.69GB | 可用但差 |
| mixed_avg3.5 | 3.5 | 14.22 | 1.03GB | 可用但差 |
| mixed_avg4.0 | 4.0 | 11.08 | 2.84GB | 接近uniform_4bit |
| mixed_avg4.8 | 4.8 | 11.04 | 3.10GB | 最优混合比例 |
结论:avg < 3.5 时质量急剧下降,avg 4.0~4.8 区间收益递减。
| 代码文件 | 方案 | 关键函数/类 | 说明 |
|---|---|---|---|
| dynquant/pipeline.py | A 固定D sweep | apply_quantization(), compute_sensitivity(), save_quantized(), load_quantized() | 通用流水线:灵敏度计算+量化替换+存储 |
| scripts/export_gguf.py | A 固定 | build_multisource(), tok_blocks() | 生成固定比例量化模型(uniform/mixed) |
| scripts/run_quant_vram.py | A 固定 | sampler(), stage() | 量化+VRAM监控 |
| dynquant/bayes_alloc.py | B 贝叶斯 | allocate_bits_bayesian(), greedy_restricted(), simulated_annealing(), load_layer_importance() | v1~v4核心:GP+UCB搜索+imatrix+lowbit惩罚 |
| scripts/run_p2_v4_imatrix.py | B 贝叶斯 | 主入口 | v4: imatrix+lowbit_penalty+bayesian |
| scripts/compute_imatrix.py | BC | imatrix计算 | per-column L2激活能量 |
| dynquant/quant.py | C K-quantA 均匀 | QuantLinear, KQuantLinear, KMeansQuantLinear, kquant_quantize_weight() | 量化内核:均匀4/8bit+K-quant+K-means |
| scripts/run_p2_v5_kquant.py | C K-quant | 单次评测 | KQuantLinear.from_linear()替换 |
| scripts/run_p2_v5b_kquant_sweep.py | C K-quant | hi/lo配置遍历 | 扫描不同hi/lo组合 |
| scripts/bench_our_models.py | AD | 批量compute_ppl评测 | 批量评测所有固定比例+sweep配置 |
| scripts/bench_all_unsloth_v6.py | 竞品评测 | llama-perplexity批量调用 | unsloth GGUF全量评测 |
| 发现 | 证据 | 结论 |
|---|---|---|
| 贪心分配必崩溃 | v1/v3/v4 greedy 均 PPL>8000 | 必须用贝叶斯/启发式搜索 |
| 2bit引入有害 | v1→v2: PPL 11.35→14.63 | 需 lowbit_penalty 抑制 |
| lowbit_penalty 有效 | v2→v3: PPL 14.63→10.88 | penalty=3.0 是合理值 |
| imatrix 显著提升 | v3→v4: PPL 10.88→10.49 | 感知量化比盲搜好 |
| K-quant hi=5/lo=3 最优 | v5b sweep: 10.77 vs 10.89 vs 13.44 | hi/lo差距不宜超过2bit |
| avg<3.5 质量崩塌 | sweep: avg3.0→PPL=14.96, avg2.5→崩溃 | 4bit是下限 |
| 备份目录 | 时间 | 内容 |
|---|---|---|
| p2_alloc_bak_20260929 | 2026-08-29 18:01 | v1原始分配结果 |
| p2_unsloth_20260830_195114 | 2026-08-30 19:51 | unsloth竞品评测结果 |
| p2_v2_extended_20260830_203957 | 2026-08-30 20:39 | v2扩展bit池结果 |
| p2_v3_lowbit_20260830_221126 | 2026-08-30 22:11 | v3低bit惩罚结果 |
| p2_v4_imatrix_20260830_224448 | 2026-08-30 22:45 | v4 imatrix结果 |
| p2_v5_kquant_20260831_011231 | 2026-08-31 01:17 | v5 K-quant单次结果 |
| p2_v5b_sweep_20260831_011710 | 2026-08-31 01:17 | v5b K-quant sweep结果 |
| 对比量化方式 | 模型归属 | 校准数据 | 评测数据 | 评测数据规模 | 评测数据来源 | PPL(越低越好) | 模型文件大小 |
|---|---|---|---|---|---|---|---|
| FP16 基线 | 我们的 | 无 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.40 | 8.07GB |
| uniform_8bit | 我们的 | 无 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.39 | 4.14GB |
| uniform_4bit | 我们的 | 无 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 11.26 | 2.19GB |
| Q4-8-mix (上层8bit+下层4bit) | 我们的 | 无 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.69 | 2.63GB |
| mixed_avg4.8 (贝叶斯4.8bit) | 我们的 | 4源混合5万token | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 11.04 | 3.10GB |
| mixed_avg4.0 (贝叶斯4.0bit) | 我们的 | 4源混合5万token | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 11.08 | 2.84GB |
| mixed_avg3.5 (贝叶斯3.5bit) | 我们的 | 4源混合5万token | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 14.22 | 1.03GB |
| mixed_avg3.0 (贝叶斯3.0bit) | 我们的 | 4源混合5万token | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 14.96 | 0.69GB |
| mixed_avg2.5 (贝叶斯2.5bit) | 我们的 | 4源混合5万token | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 26813.65 (崩溃) | 0.34GB |
| v3 bayes (低bit惩罚, avg=5.06) | 我们的 | 4源混合5万token | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.88 | — |
| v4 bayes imatrix+lowbit (avg=5.05) ★ | 我们的 | 4源混合5万token+imatrix | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.49 | — |
| v5 K-quant h5l3 (hi=5,lo=3,avg=4.0) | 我们的 | imatrix排序 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.77 | — |
| v5b K-quant h4l3 (hi=4,lo=3,avg=3.5) | 我们的 | imatrix排序 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 10.89 | — |
| v5 K-quant h4l2 (hi=4,lo=2) | 我们的 | imatrix排序 | wikitext-2 parquet test | 80k tokens | 本地测试 compute_ppl | 13.44 | — |
| 对比量化方式 | 模型归属 | 校准数据 | 评测数据 | 评测数据规模 | 评测数据来源 | PPL(越低越好) | 模型文件大小 |
|---|---|---|---|---|---|---|---|
| BF16 | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.06 | 8.07GB |
| Q3_K_S | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.52 | 2.03GB |
| Q3_K_M | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.06 | 2.37GB |
| Q4_0 | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.11 | 2.49GB |
| Q4_1 | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 9.98 | 2.68GB |
| Q4_K_S | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.04 | 2.50GB |
| Q4_K_M ★ | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 9.98 | 2.83GB |
| Q5_K_S | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.15 | 2.91GB |
| Q5_K_M | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.17 | 3.21GB |
| Q6_K | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.06 | 3.39GB |
| Q8_0 | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.04 | 4.61GB |
| IQ4_NL | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.65 | 2.54GB |
| IQ4_XS | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.58 | 2.46GB |
| UD-IQ2_M | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 11.48 | 1.81GB |
| UD-IQ3_XXS | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.55 | 1.96GB |
| UD-Q2_K_XL | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 11.32 | 1.98GB |
| UD-Q3_K_XL | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.19 | 2.36GB |
| UD-Q4_K_XL | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.19 | 2.99GB |
| UD-Q6_K_XL | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.02 | 3.97GB |
| UD-Q8_K_XL | unsloth | 无 | wikitext-2-test-short.txt | ~12.5k tokens | llama-perplexity (llama.cpp b10679) | 10.02 | 6.07GB |
v4 imatrix+lowbit
PPL = 10.49 | avg=5.05bit
框架: compute_ppl (transformers)
评测数据: wikitext-2 parquet test
数据规模: 80k tokens
unsloth Q4_K_M
PPL = 9.98 | 2.83GB
框架: llama-perplexity (llama.cpp)
评测数据: wikitext-2-test-short.txt
数据规模: ~12.5k tokens
差距 0.51 PPL,但框架不同(transformers vs llama.cpp)且数据规模不同(80k vs 12.5k tokens),PPL 不完全可直接对比。下一步需将项目模型转为 GGUF 后用同一框架、同一数据规模公平评测。
Qwen3.5-4B 逐层混合动态量化项目 | 2026-08-31