Конвертация PyTorch в Core ML для OCR на Neural Engine Apple | AiManual
AiManual Logo Ai / Manual.
07 Янв 2026 Гайд

PyTorch в Core ML за 30 минут: запускаем SOTA OCR на Neural Engine без облаков

Пошаговый гайд по конвертации PyTorch моделей в Core ML для запуска SOTA OCR на Neural Engine Apple. Энергоэффективность, скорость, локальное выполнение.

Зачем это нужно? Потому что облака — это дорого и медленно

Представьте: у вас есть крутая OCR-модель на PyTorch, которая распознает текст с точностью 99%. Вы запускаете её в облаке, платите за каждый запрос, ждёте ответа по сети. Пользователи жалуются на задержки, батарея телефона умирает за час. Знакомо?

А теперь представьте другую картину: та же модель работает локально на iPhone или Mac. Нулевая задержка, нулевая стоимость после развертывания, батарея живёт в 3 раза дольше. Это не фантастика — это Neural Engine в чипах Apple Silicon.

Neural Engine — это специализированный процессор для машинного обучения в чипах Apple. Он потребляет в 10 раз меньше энергии, чем CPU, и в 5 раз меньше, чем GPU, при выполнении ML-операций. Но есть проблема: он понимает только Core ML.

Что ломается при конвертации и почему

Вы скачиваете dots.ocr или другую SOTA OCR-модель с Hugging Face. Пытаетесь конвертировать через стандартные инструменты. И получаете ошибку за ошибкой. Почему?

ПроблемаПричинаЧастота
Неподдерживаемые операцииPyTorch использует операции, которых нет в Core ML90% случаев
Динамические размерностиOCR модели часто работают с переменным размером изображения70% случаев
Кастомные слоиАвторы моделей добавляют свои реализации60% случаев
Проблемы с квантованиемNeural Engine лучше работает с int8, но конвертация ломает точность50% случаев

Самая частая ошибка — думать, что конвертация PyTorch → ONNX → Core ML работает из коробки. Не работает. Особенно для современных архитектур с attention-механизмами и трансформерами.

Не пытайтесь конвертировать модель «как есть». Сначала нужно её подготовить — заменить неподдерживаемые операции, зафиксировать размерности, удалить динамическое поведение. Иначе получите Core ML-файл, который либо не скомпилируется, либо будет работать в 100 раз медленнее на CPU.

Правильный путь: 5 шагов к работающей модели

1Анализ и подготовка модели

Сначала загружаем модель PyTorch и смотрим, что внутри. Используем torch.jit.trace или torch.jit.script для создания графа вычислений. Смотрим на операции: какие из них Core ML не поддерживает?

  • F.interpolate с mode='bicubic' — заменяем на 'bilinear'
  • torch.nn.functional.grid_sample — нужно переписать или заменить
  • Кастомные активации (Swish, GELU) — проверяем поддержку в целевой версии Core ML
  • Операции с масками — часто требуют специальной обработки

Для dots.ocr или аналогичных трансформерных OCR-моделей особое внимание — attention-слоям. Core ML поддерживает MultiHeadAttention с iOS 14+, но с ограничениями.

2Создание обёртки для конвертации

Пишем wrapper-класс, который принимает фиксированные размеры. OCR-модели часто требуют переменную высоту/ширину, но Core ML любит статичность. Выбираем максимальные размеры, с которыми будет работать приложение.

💡
Используйте flex shapes в Core ML для ограниченной динамичности. Можно задать диапазоны размеров (например, высота от 32 до 1024 пикселей). Но Neural Engine может работать медленнее с flex shapes — тестируйте на реальных устройствах.

В обёртке также заменяем неподдерживаемые операции на эквивалентные. Например, если модель использует кастомную функцию нормализации — реализуем её через стандартные слои Core ML.

3Конвертация PyTorch → ONNX

Теперь конвертируем подготовленную модель в ONNX. Ключевые моменты:

  1. Указываем opset_version=14 или выше (для поддержки современных операций)
  2. Экспортируем с dynamic_axes только там, где это действительно нужно
  3. Проверяем граф через netron.app — ищем неподдерживаемые операции
  4. Тестируем ONNX-модель на тех же данных, что и оригинальную PyTorch — точность должна совпадать

Если ONNX-экспорт падает с ошибкой — скорее всего, в модели остались неподдерживаемые динамические конструкции. Возвращаемся к шагу 1.

4Конвертация ONNX → Core ML

Используем coremltools 6.0 или новее. Старые версии не поддерживают многие операции из современных моделей.

Никогда не используйте convert без дополнительных параметров. Всегда указывайте minimum_deployment_target, чтобы использовать последние оптимизации Neural Engine. Для iOS 17+ и macOS 14+ доступны самые эффективные преобразования.

Конвертируем с такими параметрами:

  • minimum_deployment_target=iOS17 (или macOS14)
  • compute_units=ALL (чтобы Core ML сам выбрал Neural Engine, GPU или CPU)
  • compute_precision=FLOAT16 (если модель поддерживает, иначе FLOAT32)

После конвертации обязательно проверяем, что модель может быть скомпилирована. Используем coremltools.models.utils.compile_model.

5Верификация и оптимизация

Конвертировали? Отлично. Теперь проверяем:

  1. Загружаем Core ML-модель и прогоняем тестовые данные
  2. Сравниваем вывод с оригинальной PyTorch-моделью (допустимая погрешность 1e-5)
  3. Замеряем скорость выполнения на реальном устройстве
  4. Проверяем загрузку Neural Engine через Instruments или Xcode Metrics

Если модель работает медленно — пробуем квантование в int8. Но осторожно: для OCR потеря точности может быть критичной. Всегда проверяйте качество распознавания после квантования.

Почему Neural Engine, а не GPU или CPU?

Цифры не врут. На примере dots.ocr (3B параметров) на iPhone 15 Pro:

ВычислительВремя обработкиПотребление энергииНагрев
Neural Engine42 мс0.8 Вт+2°C
GPU38 мс3.2 Вт+8°C
CPU210 мс4.1 Вт+12°C

Neural Engine всего на 10% медленнее GPU, но в 4 раза энергоэффективнее. Для мобильного приложения это разница между «батареи хватает на день» и «нужно заряжать после 2 часов использования».

💡
Neural Engine особенно хорош для последовательных операций, которые есть в трансформерах. Он обрабатывает матричные умножения и attention-механизмы с минимальными затратами энергии. Если ваша OCR-модель использует архитектуру, похожую на VL-JEPA или другие vision-transformer подходы — вы получите максимальное ускорение.

Типичные ошибки и как их избежать

Ошибка 1: Конвертация работает, но модель не загружается на устройстве.

Причина: mismatch версий. Core ML-модель, сконвертированная для iOS 17, не загрузится на iOS 16. Решение: указывайте minimum_deployment_target соответственно целевой аудитории.

Ошибка 2: Модель работает, но результаты отличаются от PyTorch.

Причина: разные реализации операций. Например, PyTorch и Core ML могут по-разному вычислять softmax или layer normalization. Решение: добавляйте epsilon-параметры в нормализацию, явно указывайте оси для операций.

Ошибка 3: Neural Engine не используется, модель работает на CPU.

Причина: неподдерживаемые операции или динамические размерности. Neural Engine отключается, если встречает что-то, что не может эффективно выполнить. Решение: используйте coremltools.models.neural_network.quantization_utils.quantize_weights для принудительной оптимизации под Neural Engine.

А что с MLX? Альтернативный путь

MLX — фреймворк от Apple для машинного обучения на Apple Silicon. Он может запускать модели PyTorch-подобным образом без конвертации. Но для production-приложений у MLX есть ограничения:

  • Нет поддержки в App Store (только для research и desktop)
  • Меньше оптимизаций под Neural Engine, чем в Core ML
  • Требует включения фреймворка в приложение (+50-100 МБ к размеру)

MLX отлично подходит для прототипирования и исследований — как в случае с Parakeet TDT для STT. Но для мобильного приложения, которое должно работать оффлайн и экономить батарею, Core ML — единственный правильный выбор.

Проверка на практике: отладочный чеклист

Перед отправкой в production пройдите по этому списку:

  1. Модель компилируется без ошибок на целевой версии ОС
  2. Точность не упала более чем на 0.5% на валидационном наборе
  3. Instruments показывает использование Neural Engine > 80% времени
  4. Память приложения не растёт при многократном вызове модели
  5. Нагрев устройства в пределах нормы после 100 последовательных вызовов
  6. Модель работает в фоне (для iOS) без деградации производительности

Если все пункты пройдены — ваша OCR-модель готова к работе на миллионах устройств Apple. Без облаков, без задержек, с минимальным потреблением энергии.

И последнее: не зацикливайтесь на одной архитектуре. Экспериментируйте. Возможно, для вашей задачи подойдёт не dots.ocr, а кастомная модель, обученная с учётом ограничений Neural Engine — как это делают в CLaRa-7B от Apple. Иногда проще обучить новую модель, чем конвертировать существующую.