Висновок GRU на пристроях Apple
Ну, ви можете сказати, що якщо ви хочете запустити модель NN на пристрої iOS, то CoreML є найкращим рішенням. Так, це правильно, коли ви готові до використання .mlmodel. Основна перевага CoreML полягає в тому, що в деяких випадках він використовує Neural Engine. Це надзвичайно швидко, але дуже обмежено. Neural Engine використовується не для багатьох шарів, і це не дуже корисно для періодичних мереж. У моєму випадку це потенційно може пришвидшити лише рівень Conv1d, що не матиме великої різниці. Крім того, CoreML може використовувати графічний процесор і резервний для CPU. Але перш ніж ви зможете використовувати свою модель в CoreML, вам потрібно експортувати його з чогось. І тут починається біль.

Я використовував tensorflow 2 для навчання своєї моделі, і я думав, що було б досить просто експортувати модель до CoreML, але це не так. Перш за все, я спробував основний пакет python coremltools від Apple. Хм ... Вибачте, але він ще не підтримує tf 2! Я використовував tf2 Keras API і думав, що можу використовувати Kerasand tf 1, і все повинно бути добре, оскільки coremltools підтримує Keras. Але цього не сталося. Я якось експортував свою модель; однак це було абсолютно непридатним для використання.
Потім я спробував знайти щось для експорту моделі tf2, але кожен скрипт, який я знайшов, не працював нормально. Потім я дізнався, що TFLite мав делегат CoreML, що означало, що він міг використовувати CoreML якось під капотом. Тоді я вирішив пропустити CoreML і перейдіть до TFLite.
Експорт моделі в TFLite набагато простіше, але у нього також є деякі проблеми.
Дозвольте мені показати вам усі підводні камені, які я знайшов під час експорту своєї моделі в TFLite та умовивід на пристрої iOS:
- Щоб експортувати модель, яка створить інтерпретатор на пристрої без помилок, потрібно використовувати експериментальний новий перетворювач.
Коли я використовував перетворювач за замовчуванням, він створив ще один порожній підграф, і Interpreter на iOS не вдалося створити.
2. Я насправді не знаю, чому, але з моєю моделлю, яку я мав, я не міг запустити її із звичайним стручком ObjC. Він завжди повертав нуль при отриманні вхідних/вихідних тензорів. Я успішно запустив свою мережу, лише використовуючи API TensorFlowLiteC 0.0.1 щоночі. Я не тестував версію Swift, оскільки використовував ObjC у поточному проекті.
Гаразд, моя мережа працювала успішно, але вона оброблялася повільно. Як я вже згадував раніше, TFLite має CoreML Delegate і GPU Delegate, і я подумав, що можу зробити висновок швидше. Що ж, я зібрав свою мережу за допомогою CoreML Delegate, що було використано на GPU Delegate із пристроєм TFLite модель не була супер крутою, я вирішив зібрати свою мережу за допомогою Metal. Можливо, графічний процесор повинен запустити його швидше.
За збірку мого НН з металом, Я писав не всі шейдери з нуля, оскільки Apple створила багато NN-шарів у рамках Metal Performance Shaders. У мене був шейдер Spectrogram, тому це звучало як хороший план. Я виправив свій код шару спектрограми, тому він був суміщений з MPS, а також написав шар Conv1d. Я забув, що можу моделювати Conv1d за допомогою Conv2d. Але навіть після того, як я це згадав, вирішив зберегти. До речі, ось репо з цими шейдерами.
techpro-studio/MetalAudioShaders
Щоб запустити приклад проекту, клонуйте репо та запустіть спочатку установку pod з каталогу Example. MetalAudioShaders - це ...
github.com
Всі шейдери, що залишились, були реалізовані Apple. Я був дуже радий, коли дізнався, що рівень GRU розроблений Apple. Пізніше я був розчарований, але перш за все. Ну, я зібрав свою мережу шар за шаром, подивився результати та порівняв їх із моделлю Кераса. MPS дуже дратує, оскільки орієнтована на зображення. Наприклад, шейдер для BatchNorm приймає лише MPSImage, але мої шейдери (Spectro, Conv1d, використані матриці) і рівень GRU працюють краще з матрицями (щодо документації Apple), тому мені потрібно було скопіювати матрицю на зображення і навпаки. У будь-якому випадку, все працювало добре, поки я не застряг у шарі GRU.
Я не розумів, чому, але це щоразу повертало недійсні результати. Чесно кажучи, я навіть не розумів, як правильно надсилати дані на цей шар, оскільки не було прикладу правильного їх використання. Крім того, це зовсім не проблема, яку можна шукати, оскільки навіть на офіційному веб-сайті розробника Apple ви не знайдете жодних документів про періодичні шари в MPS. Усі документи лише в коді. Пізніше я знайшов один невеликий приклад у сесії WWDC, коли вони використовували рівень LSTM, і я зафіксував вхідні дані в GRU, але він все одно повернув неправильні результати. Я вирішив застосувати рівень GRU на ЦП для кращого розуміння. Це повинно допомогти мені знайти рішення про те, як правильно налаштувати рівень GRU у MPS.