crivo-web / scripts /conversion /quantize.py
dizyann's picture
feat: support the full Crivo model family
6986878
Raw History Blame Contribute Delete
1.78 kB
"""Portable INT8 weight storage with FP32 arithmetic (no dynamic activation quantization)."""
import numpy as np
import onnx
from onnx import numpy_helper, helper, TensorProto
def quantize_weights(source, destination):
model = onnx.load(str(source))
initializers = []
dequantizers = []
gather_weights = {node.input[0] for node in model.graph.node if node.op_type == 'Gather'}
for tensor in model.graph.initializer:
if tensor.data_type != TensorProto.FLOAT or len(tensor.dims) != 2:
initializers.append(tensor)
continue
array = numpy_helper.to_array(tensor)
axis = 0 if tensor.name in gather_weights else 1
scale = np.maximum(np.max(np.abs(array), axis=1-axis) / 127, np.finfo(np.float32).tiny)
expanded = scale[:, None] if axis == 0 else scale[None, :]
quantized = np.clip(np.rint(array / expanded), -127, 127).astype(np.int8)
weight, factor, zero = [tensor.name + suffix for suffix in ('_int8', '_scale', '_zero')]
initializers.extend([numpy_helper.from_array(quantized, weight),
numpy_helper.from_array(scale, factor),
numpy_helper.from_array(np.zeros_like(scale, dtype=np.int8), zero)])
dequantizers.append(helper.make_node('DequantizeLinear', [weight, factor, zero],
[tensor.name], axis=axis, name=tensor.name+'_dequantize'))
del model.graph.initializer[:]
model.graph.initializer.extend(initializers)
nodes = list(model.graph.node)
del model.graph.node[:]
model.graph.node.extend(dequantizers + nodes)
onnx.save_model(model, str(destination))
if __name__ == '__main__':
import sys
quantize_weights(sys.argv[1], sys.argv[2])