Пользовательские модели Firebase ML Kit для разработчиков iOS. Часть 2. Реализация крестиков-ноликов

В Части 1 мы создаем модель для добавления 3 чисел с плавающей запятой, чтобы понять, как модель TensorFlow Lite работает с набором Firebase ML.

Эта модель никогда не будет использоваться в реальном приложении, поэтому давайте рассмотрим более реалистичный пример. Допустим, вы создаете приложение для игры в крестики-нолики (также известное как крестики-нолики или OXO), и ваше приложение должно предлагать подсказки игроку или реализовывать ИИ.

Давайте создадим модель TensorFlow Lite, которая находит лучшие ходы для определенного состояния доски, и используем ее в нашем приложении для iOS, чтобы подсчитывать все возможные следующие ходы, которые может сделать игрок.

Шаг 1. Осмотрите модель

Модель Tic Tac Toe принимает состояние доски (сетка ячеек 3x3) и выводит следующий ход для каждой ячейки (поэтому вывод также 3x3). Это простая сеть с двумя скрытыми слоями, обученная на миллионе игр, в которые играют два случайных игрока. Обратите внимание, что модель не является идеальным игроком! (Я оставляю читателям ML переобучить модель, чтобы она стала лучшим игроком — пришлите мне свои результаты, пожалуйста)

Вы можете самостоятельно воссоздать набор данных и переобучить модель в его Tic Tac Toe Colab. Или вы можете сделать, как я, и сразу перейти к загрузке файла tictactoe.tflite.

Снова откройте модель в Netron. Вы увидите интересующие нас слои и входы и выходы:

  • Тип ввода: float32[3,3]
  • Тип выхода: float32[3,3]

Как мы вводим X и O как числа с плавающей запятой? Модель была построена таким образом, что если текущий игрок O, то ячейки с O будут закодированы как 1.0, а X оппонента будут закодированы как -1.0. Если текущий игрок X, то это происходит в обратном порядке (Xs равны 1,0, а Os равны -1,0). Пустые ячейки всегда кодируются как 0.0.​

Например, на доске написано:

X|O|
-+-+-
X|O|O
-+-+-
 | |X

Если текущий игрок O, входные данные для модели будут такими:

[[-1., 1., 0.],
 [-1., 1., 1.],
 [0., 0., -1.]]

Результатом модели является та же форма, где значение каждой ячейки показывает, насколько хорош ход для текущего игрока. Ясно, что лучший ход для O — это нижняя средняя ячейка, поэтому можно надеяться, что модель выведет что-то похожее на:

[[0., 0., 0.],
 [0., 0., 0.],
 [0., 1., 0.]]

Изучив модель и поняв ее входные и выходные данные, мы теперь знаем, что нам нужно делать в коде Swift:

  1. Преобразуйте состояние доски в двумерный массив (3x3), где текущие ячейки игрока равны 1,0, ячейки противника равны -1,0, а пустые ячейки равны 0,0 в качестве входных данных для модели.
  2. Интерпретируйте выходные данные модели как 0,0 для плохого хода и 1,0 для лучшего хода.

Давайте начнем!

Шаг 2. Интегрируйте модель в свой проект iOS.

Пользовательский интерфейс приложения представляет собой доску Tic Tac Toe, которая позволяет пользователю настроить любое состояние доски и кнопку для переключения текущего игрока («Следующий ход»). Фон пустых ячеек на доске затенен в соответствии с выходными данными модели — темно-серый имеет более высокое значение и лучший ход, чем светло-серый.

1. Добавьте модель локально и в облаке. Мы уже сделали это для локальной модели в предыдущем примере. В этом примере давайте также добавим модель на сервер, чтобы мы могли обновлять нашу модель в будущем (без необходимости обновления приложения пользователями). Мы можем сделать это, разместив файл модели TensorFlow Lite в проекте Xcode для локального использования, а также загрузив файл модели TensorFlow Lite в консоль Firebase в разделе «Пользовательские модели ML Kit», чтобы сделать его доступным в облаке.

2. Подготовьте переводчика. Как и раньше, загрузите модель, настроив источники модели и создав объект ModelInterpreter из одного из них.

Как видите, шаги по настройке локальной модели такие же. Однако есть некоторые дополнительные шаги по настройке для удаленных (в облаке) моделей. Во-первых, создайте объект CustomRemoteModel, указав имя модели, которое вы присвоили при публикации через Firebase Console. Еще одна часть, которая нам нужна перед созданием ModelInterpreter, — это запуск задачи загрузки модели путем передачи CustomRemoteModel с условиями загрузки.

Затем мы можем создать ModelInterpreter из одной из моделей, локальной или удаленной, проверив, загружена ли уже удаленная модель перед ее использованием.

3. Укажите входные и выходные данные модели. Модель Крестики-нолики имеет [3,3] в качестве входной и выходной формы. Входные данные — это текущее состояние доски, представляющее собой двумерные массивы, включающие -1 (ячейка противника), 0 (пустая ячейка), 1 (ячейка текущего игрока). Выходные данные также представляют собой двумерные массивы, которые представляют собой оценки всех ходов, как описано на шаге проверки выше.

4. Выполните вывод по входным данным. А вот и самое интересное! Каждый раз, когда состояние доски или игрок меняются в пользовательском интерфейсе, мы вызываем функцию запуска интерпретатора, чтобы получить лучшие ходы для текущего игрока.

В функции запуска довольно много проверок, чтобы убедиться, что размер ввода и вывода правильный. Если все в порядке, выходные данные будут отправлены обратно, чтобы показать результаты в контроллере представления.

Я надеюсь, что вместе эти Часть 1 и Часть 2 помогут вам начать работу с пользовательскими моделями в Firebase ML Kit и в будущем вы сможете добавлять более сложные модели в свои приложения для iOS.

Firebase ML Kit все еще находится в стадии бета-тестирования и, следовательно, может измениться — следите за официальной документацией по пользовательским моделям на iOS для получения последних примеров.

Получите полный код проекта для этих примеров на github.com/naluinui.