Представляем версию 0.3 библиотеки глубокого обучения KotlinDL! Вас ждет множество новых фич: новые модели в ModelHub (включая модели для обнаружения объектов и распознавания лиц), возможность дообучать модели распознавания изображений, экспортированные из Keras и PyTorch в ONNX, экспериментальный высокоуровневый API для распознавания изображений и множество новых слоев, добавленных контрибьюторами. Также KotlinDL теперь доступен в Maven Central. В этой статье мы коснемся самых главных изменений релиза 0.3. Полный список изменений доступен по ссылке. В течение последнего года пользователи библиотеки просили нас добавить возможность работать с моделями, сохраненными в формате ONNX. Open Neural Network Exchange (ONNX) — это формат для моделей AI с открытым исходным кодом. Он задает расширяемую модель графа вычислений, определения встроенных операторов и стандартных типов данных. Также этот формат поддерживает экспорт большинства моделей фреймворков TensorFlow и PyTorch. Мы используем ONNX Runtime Java API для того, чтобы загружать и исполнять модели, сохраненные в формате `.onnx`. О том, как использовать это низкоуровневое API напрямую, можно прочитать в документации. В KotlinDL есть модуль `onnx` — именно он отвечает за поддержку ONNX. Чтобы использовать ONNX в вашем проекте, добавьте соответствующую зависимость в список зависимостей. Есть два способа делать прогнозы на модели ONNX. Если вы, например, хотите использовать LeNet-5 (одну из моделей ModelHub), вы можете загрузить ее следующим образом: Чтобы загрузить модель в формате ONNX, создайте экземпляр OnnxInferenceModel:  Если у модели сложный выход, состоящий, из нескольких тензоров (например YOLOv4 или SSD), вы можете вызвать метод predictRaw : Таким образом вы получите доступ ко всему выходу модели и сможете проанализировать его вручную. Найти подходящую модель в ONNXModelHub довольно легко: начните поиск с объекта верхнего уровня ONNXModels, спускайтесь глубже в CV или ObjectDetection, а затем к конкретным моделям. В итоге у вас получится некоторая цепочка вложенных объектов — она и будет являться уникальным идентификатором для получения конкретной модели или ее препроцессинга. Например, EfficientNet — одна из лучших моделей для распознавания изображений по итогам 2020 года — имеет вот такой идентификатор: ONNXModels.CV.EfficientNet4Lite. Делать прогнозы на готовых моделях, конечно же, хорошо. Но как насчет того, чтобы настроить их под наши задачи? К сожалению, ONNX Java API не дает возможности обучать модели. Но во многих случаях нам нужно тренировать не всю модель целиком, а лишь некоторые ее параметры. Классический подход к решению задачи Transfer Learning для ResNet-подобных архитектур состоит в том, чтобы заморозить все слои, кроме нескольких последних, а затем обучить несколько верхних слоев (полносвязных слоев, формирующих выход модели) на новом наборе данных. Верхние слои можно рассматривать как небольшую нейронную сеть, входные данные которой являются выходными данными модели, состоящей из замороженных слоев. Замороженные слои можно рассматривать как финальную часть препроцессинга для новой модели, состоящей из нескольких полносвязных слоев. Мы реализовали этот подход в нашей библиотеке, используя модель ONNX в рамках предварительной обработки (препроцессинга) и добавляя к ней небольшую нейросеть, созданную при помощи Sequential или Functional API. Итак, предположим, что у вас есть огромная модель в Keras или PyTorch, которую вы хотите дообучить в KotlinDL. Вам необходимо отрезать от нее последние слои, экспортировать в формат ONNX, загрузить в KotlinDL в качестве дополнительного слоя препроцессинга через ONNXModelPreprocessor, описать недостающие слои с помощью API KotlinDL и обучить полученную нейросеть. Ниже показано, как мы загружаем модель ResNet50 из ONNXModelHub и дообучаем ее на встроенном наборе данных Dogs-vs-Cats, чтобы она могла классифицировать изображения кошек и собак: topModel — простейшая нейронная сеть, которую можно быстро обучить, так как у нее всего несколько параметров. Полный пример вы можете найти по ссылке. Поскольку API для отрезания слоев и выкорчевывания весов из модели, сохраненной в формате ONNX, отсутствует, вам необходимо выполнить эти операции самостоятельно перед экспортом в формат ONNX. Да, это придется делать на Python. Но сильно не переживайте: в следующем релизе мы планируем добавить в ModelHub много готовых моделей из PyTorch и Keras с уже отрезанными последними слоями. В KotlinDL 0.2 появилось хранилище моделей, которое позволяет загружать модели и кэшировать их на диске. Сначала мы назвали его ModelZoo, а потом переименовали в ModelHub. Сейчас ModelHub содержит коллекцию моделей глубокого обучения, которые предварительно обучены на больших наборах данных, таких как ImageNet и COCO В настоящее время есть два ModelHub, с которых можно скачать модели: базовый TFModelHub, доступный в модуле `api`, и дополнительный ONNXModelHub, доступный в модуле` onnx`. TFModelHub содержит модели: VGG’16 VGG’19 ResNet18 ResNet34 ResNet50 ResNet101 ResNet152 ResNet50v2 ResNet101v2 ResNet152v2 MobileNet MobileNetv2 Inception Xception DenseNet121 DenseNet169 DenseNet201 NASNetMobile NASNetLarge ONNXModelHub содержит модели: CV Lenet ResNet18 ResNet34 ResNet50 ResNet101 ResNet152 ResNet50v2 ResNet101v2 ResNet152v2 EfficientNet4Lite ObjectDetection SSD FaceAlignment Fan2d106 Все модели TFModelHub содержат специальный загрузчик конфигураций моделей и весов моделей, а также специальную функцию предварительной обработки данных (препроцессинга), которая применялась при обучении моделей на наборе данных ImageNet. Если забыть ее применить к входным данным модели, то выход вас неприятно удивит. К примеру, вы можете применить модель ResNet50 для прогнозирования следующим образом: Таким образом вы получите модель и веса модели. Далее вы сможете использовать их в KotlinDL. не забудьте выполнить препроцессинг новых данных. Для каждой модели ModelHub доступна своя функция препроцессинга preprocessInput: Полный пример использования нейросети ResNet’50 для прогнозирования и дообучения на новых данных можно найти в этом руководстве. при работе с моделями ONNX вам не обязательно отдельно загружать веса (см. раздел «Интеграция ONNX» выше). Прошлая версия ModelHub включала только модели для распознавания изображений (Image Recognition). Мы решили начать постепенно расширять возможности библиотеки по работе с изображениями. В этом релизе мы добавили модель Single Shot MultiBox Detector (SSD), которая способна находить объекты на изображениях (задача Object Detection). Задача Object Detection заключается в обнаружении экземпляров объектов определенного класса в изображении. Причем мы хотим определять не только сам факт наличия таких объектов, но еще и их границы (например прямоугольник, в который объект целиком вписан). Модель SSD обучается на наборе данных COCO, состоящем из 328 000 изображений. Для каждого экземпляра заданы ограничивающие рамки и маски сегментации, а также одна из 80 категорий объекта (например «человек», «машина», «светофор», «велосипед»). Такую модель можно использовать для обнаружения объектов и их границ при прогнозировании в реальном времени. Для решения этой задачи мы разработали простой API, скрывающий детали препроцессинга и постпроцессинга изображений от пользователя. Мы прогнали через наш детектор небольшое видео с камеры на уличном перекрестке, выделив красным людей, синим — велосипеды, зеленым — автомобили. Модель YOLOv4 также доступна в ONNXModelHub. Однако мы не добавили постобработку вывода YOLOv4, потому что в библиотеке Multik (аналог NumPy для Kotlin) нет некоторых операций. Если вам интересна эта задача (или другие похожие задачи), вы можете стать контрибьютором и участвовать в адаптации новых моделей или создании нового удобного API для использования широким кругом разработчиков на Kotlin (да и на Java тоже). ПРИМЕЧАНИЕ: вы также можете использовать стандартный API для загрузки ONNX-модели и метод predictRaw — для последующей ручной обработки результата, но это довольно непросто. Если вам это удастся, ваш пулреквест станет большим вкладом в KotlinDL. Чтобы решить задачу обнаружения объектов, мы использовали упрощенное API для предсказаний. Для решения задачи распознавания изображений мы тоже можем использовать API, который скроет от пользователя предварительную обработку изображений, компиляцию и инициализацию модели, а значит, значительно упростит процесс взаимодействия с моделями, загруженными из ModelHub. Чтобы увидеть, как это работает, давайте загрузим и сохраним на диске предварительно обученную модель типа ImageRecognitionModel. Модели этого типа не дообучаются — они только делают прогнозы. Но плюс в том, что с ними очень легко работать. Обратите внимание на этот милый синтаксис с квадратными скобочками — он используется для доступа к предобученным моделям. У класса ImageRecognitionModel есть методы, которые принимают файлы изображений в качестве входных данных и возвращают метки распознаваемых объектов в строковом формате. Это экспериментальный API — он для хардкорных бэкенд-инженеров. По сути, модель представляет собой черный ящик с входом и выходом. Обязательно попробуйте этот API и напишите нам о своих впечатлениях. Библиотека KotlinDL делает свои первые шаги в области работы со звуком. В этом релизе мы добавили несколько слоев, необходимых для построения модели, подобной SoundNet:  Conv1D, MaxPooling1D, Cropping1D, UpSampling1D и другие слои с суффиксом «1D» в названии. Давайте построим небольшую нейронную сеть на основе архитектуры модели SoundNet: По сути, это сверточная нейросеть, которая использует одномерные слои для сверток и максимального объединения входных звуковых данных. На тестовых данных датасета FSDD эта сеть достигла точности ~55% за 10 эпох и ~85% — за 100 эпох. Ниже приведен код SoundBlock. Это довольно простая композиция из двух слоев Conv1D и одного слоя MaxPool1D: Когда модель будет готова для тренировки, мы сможем загрузить набор данных Free Spoken Digits Dataset (FSDD) и обучить модель. FSDD — это простой набор аудио/речевых данных, состоящий из записей произнесенных цифр, в файлах .wav с частотой 8 кГц. После обучения модель сможет понимать цифры по аудиозаписям. Можно даже сделать тренажер, который поможет отработать произношение цифр на английском языке.  Полный пример работы с SoundNet можно найти тут. Множество контрибьюторов добавили в KotlinDL новые слои с весьма нетривиальной логикой. Эти слои дают больше возможностей для построения нейросетей, обрабатывающих фотографии, звук, видео или 3D-изображения: Softmax activation layer (D. Lowl) LeakyReLU activation layer Masoud Kazemi) PReLU activate layer (Masoud Kazemi) ELU activation layer (Maciej Procyk) ThresholdedReLU activation layer (Masoud Kazemi) Conv1D layer (Maciej Procyk) MaxPooling1D layer (Masoud Kazemi) AveragePooling1D layer (Masoud Kazemi) GlobalMaxPooling1D layer (Masoud Kazemi) GlobalAveragePooling1D layer (Ansh Tyagi) Conv3D layer (Maciej Procyk) MaxPooling3D layer (Ansh Tyagi) AveragePooling3D layer (Masoud Kazemi) GlobalAveragePooling3D layer (Ansh Tyagi) GlobalMaxPool2D layer (Masoud Kazemi) GlobalMaxPool3D layer (Masoud Kazemi) Cropping1D and Cropping3D layers (Masoud Kazemi) Permute layer (Ansh Tyagi) RepeatVector layer (Stan van der Bend) UpSampling1D, UpSampling2D, and UpSampling3D layers (Masoud Kazemi) Новые инициализаторы: Identity initializer (Hauke Brammer) Orthogonal initializer (Ansh Tyagi) Новые функции активации: Gelu activation function (Ansh Tyagi) HardShrink activation function (Ansh Tyagi) LiSHT activation function (Veniamin Viflyantsev) Mish activation function (Xa9aX ツ) Snake activation function (cagriyildirimR) TanhShrink activation function(Femi Alaka) Эти функции активации не входят в основной пакет TensorFlow. Мы решили добавить их в KotlinDL, поскольку они часто упоминаются в ряде новых научных статей о распознавании изображений. В следующих релизах мы планируем достичь паритета по слоям с фреймворком Keras и, возможно, пойти дальше, добавив несколько популярных слоев из последних реализаций SOTA-моделей. Мы будем рады вашим пулреквестам на добавление новых слоев, функций активации, обратных вызовов (callbacks) или инициализаторов из новых/популярных научных статей! Чтобы начать использовать KotlinDL в вашем проекте со всеми его возможностями (включая поддержку ONNX и визуализацию), просто добавьте следующие зависимости в файл build.gradle: Если вам не нужна поддержка ONNX и визуализация, достаточно одной зависимости: KotlinDL можно использовать в Java-проектах, даже если в них нет ни капли Kotlin. Здесь вы найдете пример построения и тренировки сверточной сети, полностью написанной на Java. Если вы хотели бы использовать в проектах Java API, напишите нам об этом или создайте PR. Мы надеемся, что вам понравилась наша статья и новые возможности KotlinDL.  Хотите узнать больше о проекте? Предлагаем ознакомиться с Readme или со страничкой проекта на GitHub. А этот туториал поможет вам создать вашу первую нейросеть на Kotlin. Если вам интересно, как устроен KotlinDL, как он появился и в каком направлении развивается, почему он так похож на Keras, и планируется ли поддержка PyTorch, посмотрите свежее видео от Алексея Зиновьева. Также мы ждем вас в Slack-канале #kotlindl (инвайт можно получить тут). В нем вы можете задавать вопросы, участвовать в дискуссиях и первыми получать информацию о превью-релизах и новых моделях в хабе моделей. Ваша обратная связь, ваши описания багов и краш-репорты, идеи и комментарии — все это очень важно для нас. Мы ждем новых пользователей и контрибьюторов, как начинающих, так и опытных исследователей — всех, кому интересны Deep Learning и Data Science на Kotlin, Java и Scala!