Download validate.py from VioletXF/comic-region-clip-coreml: direct link, hf CLI and curl.
- Browser
- Download file 2.68 kB
-
https://huggingface.co/VioletXF/comic-region-clip-coreml/resolve/main/validate.py
- Command line
-
hf download hf://VioletXF/comic-region-clip-coreml/validate.py
-
curl -L -o validate.py https://huggingface.co/VioletXF/comic-region-clip-coreml/resolve/main/validate.py
2.68 kB
| #!/usr/bin/env python3 | |
| """Compare synthetic PyTorch and Core ML CPU/GPU classifier probabilities.""" | |
| import json | |
| from pathlib import Path | |
| import coremltools as ct | |
| import numpy as np | |
| import torch | |
| from transformers import CLIPVisionModelWithProjection | |
| from convert import Classifier, LABELS | |
| def main(): | |
| torch.set_num_threads(4) | |
| rng = np.random.default_rng(20260927) | |
| # RGB-like solid, gradient, and noise, after the CLIP image normalization. | |
| mean = np.array([0.48145466, 0.4578275, 0.40821073], np.float32)[None, :, None, None] | |
| std = np.array([0.26862954, 0.26130258, 0.27577711], np.float32)[None, :, None, None] | |
| rgb = [ | |
| np.full((1, 3, 224, 224), 0.5, np.float32), | |
| np.broadcast_to(np.linspace(0, 1, 224, dtype=np.float32)[None, None, None, :], (1, 3, 224, 224)).copy(), | |
| rng.random((1, 3, 224, 224), dtype=np.float32), | |
| ] | |
| samples = [(x - mean) / std for x in rgb] | |
| vision = CLIPVisionModelWithProjection.from_pretrained(".source", local_files_only=True).eval() | |
| proto = torch.from_numpy(np.load("text_prototypes.npy")) | |
| reference = Classifier(vision, proto).eval() | |
| with torch.inference_mode(): | |
| expected = [reference(torch.from_numpy(x)).numpy() for x in samples] | |
| del vision, reference, proto | |
| results = {"source_revision": "3d74acf9a28c67741b2f4f2ea7635f0aaf6f0268", "labels": [x[0] for x in LABELS], "cases": []} | |
| for unit_name, unit in [("cpu", ct.ComputeUnit.CPU_ONLY), ("cpu_gpu", ct.ComputeUnit.CPU_AND_GPU)]: | |
| core = ct.models.MLModel("RegionClassifier.mlpackage", compute_units=unit) | |
| for index, (sample, want) in enumerate(zip(samples, expected)): | |
| got = core.predict({"image": sample})["probabilities"] | |
| if got.shape != (1, 12) or got.dtype != np.float32: | |
| raise AssertionError((got.shape, got.dtype)) | |
| max_error = float(np.max(np.abs(got - want))) | |
| sum_error = float(abs(float(got.sum()) - 1.0)) | |
| same_label = int(got.argmax()) == int(want.argmax()) | |
| case = {"compute_unit": unit_name, "sample": index, "max_absolute_probability_error": max_error, | |
| "probability_sum_error": sum_error, "same_top_label": same_label, | |
| "pytorch_top_label": LABELS[int(want.argmax())][0], "coreml_top_label": LABELS[int(got.argmax())][0]} | |
| results["cases"].append(case) | |
| print(case, flush=True) | |
| if max_error > 0.03 or sum_error > 0.001 or not same_label: | |
| raise AssertionError(case) | |
| Path("validation.json").write_text(json.dumps(results, indent=2) + "\n") | |
| print("VALIDATED") | |
| if __name__ == "__main__": | |
| main() | |