OPQ-INT4-Z-Image

0 downloads 0 likes on ModelScope updated

Model card

OPQ INT4 Z-Image: 最优幂次量化扩散模型推理

使用 OPQ (Optimal Power Quantization) 将 Z-Image 6.02B 参数扩散模型量化到 INT4,GPU 峰值显存从 20.7 GB 降至 9.3 GB,图像质量几乎无损。

项目地址: www.modelscope.cn/dfytensor/OPQ-INT4-Z-Image


一键使用

# 1. 克隆项目 (含量化权重)
git clone https://www.modelscope.cn/dfytensor/OPQ-INT4-Z-Image.git
cd OPQ-INT4-Z-Image

# 2. 安装依赖
pip install -r requirements.txt

# 3. 运行推理 (自动加载量化权重 + 生成图像)
python opq_infer.py --load-saved

# 4. 查看结果
# → opq_output.png (768x1024, peak GPU 9.3 GB, ~57s)

显存要求: 仅需 12 GB GPU + 12 GB 内存即可运行。 速度取决于机器配置。


效果展示

bf16 原始 vs OPQ INT4

bf16 vs OPQ INT4 对比

左:bf16 原始 (20.7 GB GPU) | 右:OPQ INT4 α=0.73 (9.3 GB GPU)

数值对比

指标 bf16 原始 OPQ INT4 差异
Peak GPU 20.7 GB 9.3 GB -55%
图像亮度 (Mean) 122 118 -3%
图像对比度 (Std) 86.5 86.3 -0.2%
空间相关性 (CorrH) 0.989 0.996 超越原始
低频结构 (LF) 24.5% 31.5% 超越原始
推理时间 25s 58s +33s

量化前后的权重质量

指标 标准INT4 OPQ INT4 提升
SNR 18.5 dB 25.6 dB +7.1 dB
KLD 0.1150 0.0002 691× 降低
权重保留率 7.7% 16.2% 2.1×
等效精度 INT4 ≈ INT5 免费 +1 bit

对比图见 opq_full_compare.png。


OPQ 原理

传统均匀量化:q = round(w / Δ) — 均匀间距,不适应权重分布

OPQ 幂次量化:

归一化:  u = |w| / max(|w|)           ∈ [0, 1]
幂次变换: v = u^α                      (α=0.73 放大小值)
量化:    q = round(v × 15)             (INT4, 16级)
反变换:  w' = sign(w) × (q/15)^(1/α) × max(|w|)

α=0.73 是 Z-Image 权重分布的最优值,比 GPT-2 的 α=0.45 更大(扩散模型权重更集中)。

核心优势:

  • SNR +7.2 dB(等效免费 +1 bit 精度)
  • KLD 降低 691 倍(权重分布几乎无损)
  • 零额外存储开销(同样 INT4 格式)

文件结构

OPQ_ZImage_INT4/
├── README.md                        ← 本文件
├── opq_quantize.py                  ← OPQ 量化模块 (OPQLinear + replace_with_opq)
├── opq_save.py                      ← 量化权重保存脚本
├── opq_infer.py                     ← 推理脚本 (量化 + 生成图像)
├── opq_full_compare.png             ← bf16 vs OPQ INT4 对比图
├── OPQ_Application_Report.md        ← 完整评估报告
├── requirements.txt                 ← 依赖列表
└── quantized_weights/               ← 已量化的权重文件 (可直接加载)
    ├── transformer_opq_int4.pt      ← Transformer 权重 (3.67 GB)
    ├── text_encoder_opq_int4.pt     ← T5 编码器权重 (2.17 GB)
    ├── vae_opq_int4.pt              ← VAE 权重 (~0 GB)
    └── config.pt                    ← 量化配置

环境要求

硬件(最低配置)

  • GPU: 12 GB 显存 (如 RTX 3060 12GB / RTX 4070 / RTX 3090 / RTX 4090 等)
  • 内存: 12 GB RAM
  • 存储: 10 GB (克隆本项目含量化权重 ~6 GB + 模型缓存 ~4 GB)

推理速度参考

GPU 显存 推理时间 (30步) 说明
RTX 4090 24 GB ~57s 测试基准
RTX 3090 24 GB ~60s 同代, 略慢
RTX 4070 12 GB ~90s 显存刚好够用
RTX 3060 12 GB ~120s 最经济方案

注意: 即使显存只有 12 GB, OPQ INT4 的 peak 仅 9.3 GB, 有足够余量。

软件

# 创建虚拟环境
python -m venv .venv

# Windows
.venv\Scripts\activate
# Linux
source .venv/bin/activate

# 安装依赖
pip install -r requirements.txt

requirements.txt 内容:

torch>=2.4.0
diffusers>=0.30.0
transformers>=4.45.0
accelerate>=0.34.0
Pillow>=9.0.0
numpy>=1.24.0
safetensors>=0.4.0

模型下载

Z-Image 原始模型需提前下载(推理脚本需要先加载原始模型结构,再覆盖为量化权重):

# 方式1: modelscope
pip install modelscope
modelscope download --model Tongyi-MAI/Z-Image --local_dir /path/to/zimage

# 方式2: huggingface
huggingface-cli download Tongyi-MAI/Z-Image --local-dir /path/to/zimage

下载后修改 opq_infer.py 中的 MODEL_PATH:

MODEL_PATH = "/path/to/zimage"  # 改成你的路径

本项目已含量化权重 (quantized_weights/, ~6 GB), 无需单独下载量化模型。 原始模型仅用于加载模型结构, 推理时使用量化权重。


快速开始

方式 A:从量化权重加载(推荐,最快)

quantized_weights/ 已包含预计算的 OPQ INT4 权重,无需重新量化:

cd OPQ_ZImage_INT4
python opq_infer.py --load-saved

输出:

[1] Loading Z-Image...
      Original GPU: 20.7 GB
[2] Loading saved quantized weights...
      transformer: 276 layers, 0 missing buffers
      text_encoder: 252 layers, 0 missing buffers
      vae: 8 layers, 0 missing buffers
      Total: 20.7 -> 7.3 GB (saved 13.4 GB)
[3] Generating image...
  Result:
    Image:       opq_output.png
    Size:        768x1024
    Mean:        118
    Std:         86.3
    CorrH:       0.9956
    Peak GPU:    9.3 GB
    Time:        57s

方式 B:在线量化(用于换模型或调参数)

# 1. 量化原始权重并保存(首次运行,约 10 秒)
python opq_save.py

# 2. 之后用 --load-saved 直接加载
python opq_infer.py --load-saved

输出:

  Quantizing transformer...
    276 layers quantized (2s), saving...
    Saved: quantized_weights/transformer_opq_int4.pt (3.94 GB, 5s)
  Quantizing text_encoder...
    252 layers quantized (1s), saving...
    Saved: quantized_weights/text_encoder_opq_int4.pt (2.33 GB, 2s)
  Quantizing vae...
    8 layers quantized (0s), saving...
    Saved: quantized_weights/vae_opq_int4.pt (0.00 GB, 0s)
  Done! Files in quantized_weights/

方式 C:在线量化 + 推理(一步到位,不保存)

python opq_infer.py

推理参数配置

编辑 opq_infer.py 顶部的参数:

# 模型路径(必须修改为你的本地路径)
MODEL_PATH = r"F:\zimage_cache\models\Tongyi-MAI--Z-Image\snapshots\master"

# 量化参数
OPQ_BITS = 4       # 量化位数: 3, 4, 5, 6
OPQ_ALPHA = 0.73   # 幂次参数: 0.3-1.0 (0.73=最优)
OPQ_GS = 128       # 分组大小: 32, 64, 128, 256

# 生成参数
PROMPT = "你的提示词"
NEGATIVE = "负面提示词"
HEIGHT = 1024
WIDTH = 768
STEPS = 30
SEED = 42

从量化权重加载的流程说明

--load-saved 模式的工作原理:

1. 加载原始 Z-Image bf16 模型到 GPU        (20.7 GB)
2. 对每个组件:
   a. 运行 replace_with_opq() 创建 OPQLinear 结构
   b. 用 quantized_weights/*.pt 覆盖 packed/sign_packed/mx buffers
3. 释放原始权重,仅保留量化数据             (7.3 GB)
4. 正常推理生成图像                         (peak 9.3 GB)

注意:即使使用 --load-saved,仍需下载原始 Z-Image 模型。因为 diffusers 需要先加载模型结构,然后用量化权重覆盖。

不同位宽的效果

配置 BPW SNR Peak GPU 图像质量 命令
bf16 16 ∞ 20.7 GB 基准 (无量化)
OPQ INT4 α=0.73 4.25 25.6 dB 9.3 GB 推荐 python opq_infer.py --load-saved
OPQ INT5 α=0.73 5.25 32.0 dB ~10 GB 更高质量 改 OPQ_BITS=5 后重新量化
OPQ INT6 α=0.73 6.25 38.1 dB ~12 GB 最高质量 改 OPQ_BITS=6 后重新量化

权重文件说明

quantized_weights/ 目录包含预计算好的 OPQ INT4 量化权重:

文件 大小 说明
transformer_opq_int4.pt 3.67 GB Flux Transformer (6.15B → INT4)
text_encoder_opq_int4.pt 2.17 GB T5 Encoder (4.02B → INT4)
vae_opq_int4.pt <0.01 GB VAE (0.08B → INT4)
config.pt <0.01 GB 量化参数配置

合计 5.84 GB(原始 bf16 20.5 GB,压缩 3.5×)


量化哪些组件

Z-Image pipeline 包含三个模型组件:

组件 参数量 bf16 OPQ INT4 是否量化
Transformer (Flux) 6.15B 12.3 GB 5.0 GB ✅
Text Encoder (T5) 4.02B 8.0 GB 2.0 GB ✅
VAE 0.08B 0.2 GB 0.1 GB ✅

默认量化全部组件。如需只量化 Transformer(保留 T5/VAE 为 bf16),修改 opq_infer.py:

# 只量化 transformer
components = ['transformer']

在你自己的代码中使用

from opq_quantize import replace_with_opq

# 加载任意 diffusers 模型
pipe = DiffusionPipeline.from_pretrained("your-model", torch_dtype=torch.bfloat16)
pipe.to("cuda")

# OPQ 量化 (一行搞定)
replace_with_opq(pipe.transformer, bits=4, alpha=0.73)
replace_with_opq(pipe.text_encoder, bits=4, alpha=0.73)

# 正常推理
image = pipe(prompt="hello").images[0]

技术细节

存储格式

每个权重存储 3 部分:

  1. Magnitude (4-bit): round((|w|/max)^0.73 × 15) → 8 个打包进 1 个 uint32
  2. Sign (1-bit): 正/负 → 32 个打包进 1 个 uint32
  3. Group max (float16): 每 128 个权重共享一个

有效 BPW = (4 + 0.125 + 0.125) = 4.25 BPW

推理解码

# 从存储格式重建权重:
qn = q / 15                    # [0, 1]
inv = qn ** (1.0 / 0.73)       # 逆幂次
w = sign * inv * group_max     # 正负号 × 幅度 × 组最大值

为什么 α=0.73?

  • Z-Image 权重 per-group 归一化后分布较集中(σ/μ ≈ 0.39)
  • 比均匀分布需要更弱的非线性(α 接近 1.0)
  • GPT-2 的 α=0.45 更小因为 LLM 权重分布尾部更长
  • α=0.73 是 Z-Image 上的平坦最优区 [0.65, 0.80] 的中心

引用

@misc{opq2026,
  title={Optimal Power Quantization for Diffusion Model Weight Compression},
  year={2026},
}

License

仅供学术研究使用。