Upload quantize.py with huggingface_hub
Browse files- quantize.py +58 -0
quantize.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Quantize the exported fp32 ONNX graphs, matching onnx-community/convert-to-onnx recipes.
|
| 3 |
+
|
| 4 |
+
q4 : MatMulNBitsQuantizer(bits=4, block_size=32, is_symmetric=True)
|
| 5 |
+
q4f16 : float16(keep_io_types=True) applied to the q4 graph
|
| 6 |
+
fp16 : float16(keep_io_types=True) applied to the fp32 graph
|
| 7 |
+
|
| 8 |
+
Run: python quantize.py q4 # or: fp16 q4f16
|
| 9 |
+
Large graphs (encoder) are saved with external data.
|
| 10 |
+
"""
|
| 11 |
+
import sys
|
| 12 |
+
from pathlib import Path
|
| 13 |
+
|
| 14 |
+
import onnx
|
| 15 |
+
from onnxconverter_common import float16 as onnx_float16
|
| 16 |
+
from onnxruntime.quantization.matmul_nbits_quantizer import MatMulNBitsQuantizer
|
| 17 |
+
|
| 18 |
+
OUT = Path("onnx")
|
| 19 |
+
STEMS = ["encoder_model", "decoder_model_merged"]
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def _save(model, path: Path):
|
| 23 |
+
onnx.save(model, str(path), save_as_external_data=True, all_tensors_to_one_file=True,
|
| 24 |
+
location=path.name + "_data", convert_attribute=True)
|
| 25 |
+
print(f" wrote {path.name} ({(path.stat().st_size)/1e6:.1f} MB graph + external data)")
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def make_q4(stem: str):
|
| 29 |
+
m = onnx.load(str(OUT / f"{stem}.onnx"), load_external_data=True)
|
| 30 |
+
q = MatMulNBitsQuantizer(m, bits=4, block_size=32, is_symmetric=True)
|
| 31 |
+
q.process()
|
| 32 |
+
_save(q.model.model, OUT / f"{stem}_q4.onnx")
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def make_fp16(stem: str):
|
| 36 |
+
m = onnx.load(str(OUT / f"{stem}.onnx"), load_external_data=True)
|
| 37 |
+
# disable_shape_infer: the >2GB encoder overflows the single-proto serialize in infer_shapes.
|
| 38 |
+
fp16 = onnx_float16.convert_float_to_float16(m, keep_io_types=True, disable_shape_infer=True)
|
| 39 |
+
_save(fp16, OUT / f"{stem}_fp16.onnx")
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def make_q4f16(stem: str):
|
| 43 |
+
m = onnx.load(str(OUT / f"{stem}_q4.onnx"), load_external_data=True)
|
| 44 |
+
fp16 = onnx_float16.convert_float_to_float16(m, keep_io_types=True, disable_shape_infer=True)
|
| 45 |
+
_save(fp16, OUT / f"{stem}_q4f16.onnx")
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def main():
|
| 49 |
+
targets = sys.argv[1:] or ["q4"]
|
| 50 |
+
for stem in STEMS:
|
| 51 |
+
for t in targets:
|
| 52 |
+
print(f"[{t}] {stem}")
|
| 53 |
+
{"q4": make_q4, "fp16": make_fp16, "q4f16": make_q4f16}[t](stem)
|
| 54 |
+
print("Done.")
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
if __name__ == "__main__":
|
| 58 |
+
main()
|