Код для вычислений на графическом процессоре в модели Apple Core ML, преобразованный из Keras

Фоны

Я использую машину Windows с мощным графическим процессором nVidia для обучения моей модели Keras с огромным набором данных. Это означает, что я должен преобразовать обученную модель Keras в формат Apple Core ML, когда я использую модель для прогнозирования на iPhone, iPad и Mac.

Кроме того, моя модель Keras имеет пользовательские слои, мои оригинальные слои, для лучшей производительности.

После долгого и извилистого пути я успешно импортировал свои пользовательские слои Keras в свое приложение Core ML. Я хотел бы поделиться своим опытом с программистами, потому что мало информации, показывающей путь от начала до конца.

Мои среды кодирования:

  • Windows 10 для обучения: Python 3.7.9, Keras 2.2.4 и TensorFlow 1.15.0 в миниконде
  • macOS BigSur для преобразования и прогнозирования: Python 3.7.9 и coremltools 3.4 в miniconda и Xcode 12

Условие:

  • Понимание кодирования Keras и Python, а также программирования macOS на языке C в Xcode.

Пожалуйста, обратитесь к документам, учебникам или веб-сайтам, чтобы узнать, что такое настраиваемый слой в Keras, как его кодировать, а также подробности о Core ML и Metal в программировании macOS.

Пользовательский слой Keras

Прежде всего, я хотел бы использовать следующий пользовательский слой Keras, myCustomLayer, в качестве образца. Этот слой вычисляет простое линейное преобразование входных данных x с использованием обучаемых переменных класса self.weight и self.bias. Таким образом, метод класса call() возвращает self.weight * x + self.bias в качестве результат.

Обученная модель Кераса

Нам нужна обученная модель Keras, которая использует в себе указанный выше пользовательский слой. Я пропускаю этот шаг, потому что полагаю, что читатели могут самостоятельно пройти обучение модели.

Преобразователь Keras в CoreML

Затем нам нужен преобразователь для создания модели Core ML (файл .mlmodel) из обученной модели Keras (файл .h5), которая содержит пользовательские слои. Необходимо передать пользовательские объекты (здесь = пользовательский слой) и соответствующую функцию преобразования в преобразователь в coremltools, чтобы он знал, как реализовать пользовательский слой в модели Core ML.

Я использую coremltools 3.4 от Apple. Это предыдущая версия, но методология будет аналогична и в последней версии.

Внедрение пользовательского слоя в Core ML

В Core ML есть базовый класс MLCustomLayer для создания пользовательского пользовательского слоя. Я переписал его, чтобы создать класс myCustomLayer, и заполнил содержимое для реализации пользовательского слоя Keras.

Заголовочный файл:

Здесь evaluateOnCPUWithInputs: outputs: error:определяет код, который будет выполняться на ЦП. Официальный комментарий Apple гласит:

Для заданных входных данных заполните выходную память предоставления. Это будет вызываться для каждой оценки, выполняемой на ЦП. Входные и выходные данные будут иметь форму самого последнего вызова outputShapesForInputShapes. Память для входных и выходных массивов выделена заранее, и ее нельзя копировать или перемещать. Реализация не должна изменять входные данные. Должен возвращать «ДА» в случае успеха или «НЕТ» и устанавливать ошибку в случае неудачи.

Кроме того, encodeToCommandBuffer: inputs: outputs: error: определяет код, который должен выполняться на графическом процессоре. В официальном комментарии говорится:

Необязательный селектор для кодирования шейдера, реализующего пользовательский слой, в буфер команд. Выполнение буфера будет происходить внутри Core ML. Предоставление этой функции не гарантирует оценку GPU для каждого прогноза. Если не указано, выполнение этого уровня всегда будет на ЦП. Должен возвращать «ДА» при успешном кодировании или «НЕТ» и устанавливать ошибку, если кодирование не удалось.

Объективный код C:

Metal Code для слоя Core ML

Наконец, для быстрого выполнения в графическом процессоре требуется код Metal.

Как видите, вычисление вес * x + смещение определено в приведенном выше evaluateOnCPUWithInputs (с использованием ускорения vDSP). потому что расчет должен быть завершен к концу метода в режиме ЦП.

Но в encodeToCommandBuffer, режиме графического процессора, определяются только конвейер и буферы, поскольку фактическая процедура расчета определяется в коде Metal отдельно (файл .metal). Следующий код Metal вычисляет линейное преобразование.

Выводы

Я очень рад, если мой пример кода будет полезен для вашего программирования Core ML. Пожалуйста, проверьте следующие ссылки для получения дополнительной информации. Спасибо!

использованная литература

  1. Core ML — Интегрируйте модели машинного обучения в свое приложение (Apple)
  2. Core ML — Создание пользовательского слоя (Apple)
  3. Core ML — coremltools версии 3.4 (Apple)
  4. Metal — Ускорение графики и многое другое (Apple)
  5. Metal — Спецификация языка шейдинга (Apple)
  6. Пользовательские слои в Core ML (Мэттейс Холлеманс)
  7. Преобразование модели Keras в Core ML с пользовательским слоем — функция преобразования игнорируется (переполнение стека)
  8. Дополнительные советы по Core ML (Джеймсон Тул)