🐛 Describe the bug
This is a crosspost to huggingface huggingface/optimum#776
Expected behavior
I would expect a similar accuracy for both models:
Accuracy onnx: 17 %
Accuracy torch: 70 %
on test data with 3800 samples.
I would like to know what went wrong, how I can fix it, or who can help me. I'm clueless at the moment.
I trained a small Longformer language model from scratch and fine-tuned it with custom data on a Sequence classification head. I used fp16 for training. The training run on a GPU.
Reproduction
This model is trained on client data and I'm not allowed to share the data or the weights, which makes any reproduction of this issue much harder. Please let me know when you need more information.
Here is the code snippet for the onnx conversion:
I follow this tutorial, but I also tried your tutorial.
conversion:
import numpy as np
from onnxruntime import InferenceSession
from tqdm.auto import tqdm
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
tokenizer = AutoTokenizer.from_pretrained("deployment/best_model/")
model = AutoModelForSequenceClassification.from_pretrained("deployment/best_model/")
model.to("cpu")
model.eval()
example_input = tokenizer(
dataset["test"]["text"][0], max_length=512, truncation=True, return_tensors="pt"
)
_ = model(**example_input)
torch.onnx.export(
model,
tuple(example_input.values()),
f="model.onnx",
input_names=["input_ids", "attention_mask"],
output_names=["logits"],
dynamic_axes={
"input_ids": {0: "batch_size", 1: "sequence"},
"attention_mask": {0: "batch_size", 1: "sequence"},
"logits": {0: "batch_size", 1: "sequence"},
},
do_constant_folding=True,
opset_version=16,
)
Calculating the accuracy:
session = InferenceSession("deployment/model.onnx", providers=["CPUExecutionProvider"])
y_hat_torch = []
y_hat_onnx = []
for text in dataset["test"]["text"]:
tok_text = tokenizer(
text, padding="max_length", max_length=512, truncation=True, return_tensors="np"
)
pred = session.run(None, input_feed=dict(tok_text))
pred = np.argsort(pred[0][0])[::-1][0]
y_hat_onnx.append(int(pred))
tok_text = tokenizer(
text, padding="max_length", max_length=512, truncation=True, return_tensors="pt"
)
pred = model(**tok_text)
pred = torch.argsort(pred[0][0], descending=True)[0].numpy()
y_hat_torch.append(int(pred))
print(
f"Accuracy onnx:{sum([int(i)== int(j) for I, j in zip(y_hat_onnx, dataset['test']['label'])]) / len(y_hat_onnx):.2f}"
)
print(
f"Accuracy torch:{sum([int(i)== int(j) for I, j in zip(y_hat_torch, dataset['test']['label'])]) / len(y_hat_torch):.2f}"
)
I also looked into the models' weights and the weights for the attention layer differ between torch and onnx. Here is an example:
import torch
import onnx
from onnx import numpy_helper
import numpy as np
from numpy.testing import assert_almost_equal
from transformers import AutoTokenizer, AutoModelForSequenceClassification
model = AutoModelForSequenceClassification.from_pretrained("deployment/best_model/")
onnx_model = onnx.load("deployment/model.onnx")
graph = onnx_model.graph
initalizers = dict()
for init in graph.initializer:
initalizers[init.name] = numpy_helper.to_array(init).astype(np.float16)
model_init = dict()
for name, p in model.named_parameters():
model_init[name] = p.detach().numpy().astype(np.float16)
assert len(initalizers) == len(model_init.keys()) # 53 layers
assert_almost_equal(initalizers['longformer.embeddings.word_embeddings.weight'],
model_init['longformer.embeddings.word_embeddings.weight'], decimal=5)
assert_almost_equal(initalizers['classifier.dense.weight'],
model_init['classifier.dense.weight'], decimal=5)
For the layer longformer.encoder.layer.0.output.dense.weight, which aligns with onnx::MatMul_6692 in shape and position:
assert_almost_equal(initalizers['onnx::MatMul_6692'],
model_init['longformer.encoder.layer.0.output.dense.weight'], decimal=4)
I get:
AssertionError:
Arrays are not almost equal to 4 decimals
Mismatched elements: 2356293 / 2359296 (99.9%)
Max absolute difference: 1.776
Max relative difference: inf
x: array([[ 0.0106, 0.1076, 0.0801, ..., 0.0425, 0.1548, 0.0123],
[-0.0399, -0.1415, 0.0916, ..., 0.0181, -0.1277, -0.1335],
[-0.0961, 0.0013, 0.0558, ..., -0.1354, -0.0965, 0.0447],...
y: array([[-0.0699, 0.0743, 0.0339, ..., 0.0564, -0.087 , 0.0649],
[-0.1315, -0.0967, -0.045 , ..., -0.0492, 0.0775, 0.0284],
[-0.1094, 0.0364, 0.1263, ..., -0.0308, -0.0118, 0.1523],...
Versions
Python version: 3.9.12
PyTorch version (GPU?): 1.13.0 (False)
onnx: 1.13.0
onnxruntime: 1.13.1
transformers version: 4.26.1
Platform: macOS-10.16-x86_64-i386-64bit
🐛 Describe the bug
This is a crosspost to huggingface huggingface/optimum#776
Expected behavior
I would expect a similar accuracy for both models:
Accuracy onnx: 17 %
Accuracy torch: 70 %
on test data with 3800 samples.
I would like to know what went wrong, how I can fix it, or who can help me. I'm clueless at the moment.
I trained a small Longformer language model from scratch and fine-tuned it with custom data on a Sequence classification head. I used fp16 for training. The training run on a GPU.
Reproduction
This model is trained on client data and I'm not allowed to share the data or the weights, which makes any reproduction of this issue much harder. Please let me know when you need more information.
Here is the code snippet for the onnx conversion:
I follow this tutorial, but I also tried your tutorial.
conversion:
Calculating the accuracy:
I also looked into the models' weights and the weights for the attention layer differ between torch and onnx. Here is an example:
For the layer longformer.encoder.layer.0.output.dense.weight, which aligns with onnx::MatMul_6692 in shape and position:
I get:
Versions
Python version: 3.9.12
PyTorch version (GPU?): 1.13.0 (False)
onnx: 1.13.0
onnxruntime: 1.13.1
transformers version: 4.26.1
Platform: macOS-10.16-x86_64-i386-64bit