Конвертація ML-моделі в Core ML для iOS

Проблеми конвертації в Core ML Отримати .mlpackage з PyTorch або TensorFlow — задача з конкретними кроками, де кожен може зламатися з неочевидної причини. [coremltools](https://github.com/apple/coremltools) не підтримує всі операції — наприклад, einsum, згортки з динамічними розмірами або розгалу

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Конвертація ML-моделі в Core ML для iOS
Середній
від 1 дня до 3 днів

Наші компетенції:

Часті запитання

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    896
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    1003
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    597

Проблеми конвертації в Core ML

Отримати .mlpackage з PyTorch або TensorFlow — задача з конкретними кроками, де кожен може зламатися з неочевидної причини. coremltools не підтримує всі операції — наприклад, einsum, згортки з динамічними розмірами або розгалуження в графі. Пряма конвертація часто видає помилку або призводить до падіння точності на 5–10 %. Ми накопичили досвід вирішення таких кейсів: за 5+ років роботи ми конвертували понад 50 моделей для фінансового сектора, рітейлу та AR-додатків. У середньому інференс на iPhone пришвидшується на 30–50 % після оптимізації під Apple Neural Engine. Замовте конвертацію — отримайте готовий .mlpackage з верифікацією точності.

Чому конвертація в Core ML потребує знань?

coremltools не підтримує всі операції PyTorch/TensorFlow, а для інших потрібне правильне налаштування параметрів. Пряма конвертація часто призводить до помилок або погіршення точності. Ми вирішуємо ці проблеми, підбираючи оптимальні параметри та при необхідності використовуючи кастомні шари.

Підготовка моделі до конвертації

Перед конвертацією модель має бути в eval-режимі з фіксованими вагами. torch.jit.trace вимагає прикладу вхідних даних — він записує граф для конкретного shape. Apple Core ML Tools рекомендують використовувати TorchScript для експорту:

import torch import torchvision import coremltools as ct model = MyModel() model.load_state_dict(torch.load("weights.pth", map_location="cpu")) model.eval() # trace — фіксує граф для конкретного shape example_input = torch.zeros(1, 3, 224, 224) traced_model = torch.jit.trace(model, example_input) # Для розгалужень (if/else) використовуйте torch.jit.script: # scripted_model = torch.jit.script(model) # Конвертація в mlprogram mlmodel = ct.convert( traced_model, inputs=[ct.ImageType( name="input", shape=ct.Shape(shape=(1, 3, 224, 224)), color_layout=ct.colorlayout.RGB, bias=[-0.485/0.229, -0.456/0.224, -0.406/0.225], scale=1/(255.0 * 0.229) )], outputs=[ct.TensorType(name="logits")], compute_precision=ct.precision.FLOAT16, minimum_deployment_target=ct.target.iOS16, convert_to="mlprogram" ) mlmodel.short_description = "Image classifier" mlmodel.input_description["input"] = "RGB image 224x224" mlmodel.output_description["logits"] = "Class probabilities" mlmodel.save("MyModel.mlpackage") 

Якщо пряма конвертація не працює, використовуйте ONNX як проміжний крок: torch.onnx.export(model, example_input, "model.onnx", opset_version=17), потім ct.converters.onnx.convert.

Перевірка коректності конвертації

Порівняйте виходи оригінальної моделі та Core ML на тестовому зображенні:

import numpy as np import PIL.Image img = PIL.Image.open("test.jpg").resize((224, 224)) transform = torchvision.transforms.Compose([ torchvision.transforms.ToTensor(), torchvision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) tensor = transform(img).unsqueeze(0) with torch.no_grad(): pytorch_out = model(tensor).numpy() coreml_out = mlmodel.predict({"input": img})["logits"] max_diff = np.max(np.abs(pytorch_out - coreml_out)) print(f"Max difference: {max_diff}") 

Норма для FP16 — менше 0.01. Якщо різниця більша за 0.05 — перевірте нормалізацію в ct.ImageType.

Налаштування змінних розмірів входу

Код для гнучких розмірів
# Діапазон розмірів flexible_shape = ct.Shape( shape=(1, 3, ct.RangeDim(min_val=64, max_val=1024), ct.RangeDim(min_val=64, max_val=1024)) ) # Набір конкретних розмірів enumerated_shapes = ct.EnumeratedShapes( shapes=[ ct.Shape(shape=(1, 3, 224, 224)), ct.Shape(shape=(1, 3, 384, 384)), ct.Shape(shape=(1, 3, 512, 512)), ] ) mlmodel = ct.convert(traced_model, inputs=[ct.TensorType(name="input", shape=enumerated_shapes)]) 

Кастомні операції

Якщо модель містить операцію, яку coremltools не знає, додайте кастомний шар на Swift. На Python реєструємо операцію:

@ct.converters.mil.register_torch_op() def my_custom_op(context, node): x = context[node.inputs[0]] result = mb.custom(params={"...": "..."}, inputs={"x": x}, ...) context.add(result) 
import CoreML @objc(MyCustomLayer) class MyCustomLayer: NSObject, MLCustomLayer { required init(parameters: [String: Any]) throws { } func setWeightData(_ weights: [Data]) throws { } func outputShapes(forInputShapes inputShapes: [[NSNumber]]) throws -> [[NSNumber]] { ... } func evaluate(inputs: [MLMultiArray], outputs: [MLMultiArray]) throws { } } 

Кастомний шар виконується на CPU — для продуктивності краще використовувати стандартні операції.

Порівняння продуктивності на пристроях

Apple Neural Engine пришвидшує інференс у 10–20 разів порівняно з CPU, що значно краще за GPU. Наприклад, для ResNet-50 mlprogram працює в 2 рази швидше за neuralnetwork на ANE. Результати для моделі ResNet-50 (224x224):

Пристрій CPU (ms) GPU (ms) ANE (ms)
iPhone 14 Pro 45 30 12
iPhone 13 60 40 18
iPhone SE (3rd gen) 90 65 30

Порівняння форматів Core ML

Параметр mlprogram neuralnetwork
iOS версія 15+ 12+
ANE підтримка Так Ні
FP16 Так Тільки FP32
Розмір Менше Більше
Продуктивність Вища Нижча

Що входить у роботу з конвертації?

  • Аудит моделі — аналіз графа, виявлення несумісних операцій, рекомендації щодо рефакторингу. Перевірка на підтримку ANE.
  • Конвертація — підбір точності (FP16/INT8), розміру входу, вирішення помилок coremltools. За потреби — кастомні шари.
  • Верифікація точності — порівняння на 100+ тестових прикладах, звіт з max diff та метриками (accuracy, mAP).
  • Оптимізація під ANE — заміна Reshape/Permute на ANE-сумісні, усунення вузьких місць, квантування.
  • Документація — опис параметрів моделі, інтеграції в Xcode, приклад використання.

Чек-лист конвертації

  • [ ] Модель в eval-режимі, ваги заморожені
  • [ ] Приклад вхідних даних підготовлений
  • [ ] Обраний format mlprogram (якщо iOS >= 15)
  • [ ] Перевірена підтримка операцій через PYTORCH_OPS_REGISTRY
  • [ ] Виконана числова верифікація (max diff < 0.01)
  • [ ] Протестовано на цільових пристроях (CPU/GPU/ANE)
  • [ ] Результати порівняння часу інференсу задокументовані

Квантування: INT8 vs FP16

Окрім конвертації в mlprogram, квантування дозволяє додатково зменшити розмір моделі та прискорити інференс. FP16 (float16) скорочує обсяг ваг удвічі без помітної втрати точності — це наш стандарт за замовчуванням. INT8 зменшує модель ще в 2 рази, але потребує калібрувального датасету для оцінки похибки квантування. На Apple Neural Engine INT8 працює особливо швидко: приріст швидкості становить 1,5–2× порівняно з FP16. Для задач класифікації та детекції об'єктів втрата точності при INT8 зазвичай не перевищує 1–2%. Для задач з текстом або генерацією — FP16 переважніший.

# Квантування в INT8 через coremltools mlmodel_int8 = ct.compression_utils.affine_quantize_weights(mlmodel, mode="linear_symmetric") mlmodel_int8.save("MyModel_INT8.mlpackage") 

Наша команда проводить порівняльне тестування обох форматів на вашому конкретному пристрої та обирає оптимальний варіант. Вартість квантування включена у вартість конвертації — загальна ціна починається від 500$.

Отримайте консультацію інженера по вашій моделі — оцінимо складність конвертації та підберемо оптимальні параметри. Ми гарантуємо якість та сертифікований досвід. Звертайтесь до нас для аудиту та конвертації.