Узнайте, как вы можете сделать то же самое

Имя AI-бота: Janken
Используемая технология: TensorFlow, Keras, Numpy, SqueezeNet и Open CV

TL;DR

Если вы хотите начать работу, вы можете перейти прямо к моему GitHub и клонировать.
https://github.com/DarrenBro/rock-paper-scissors-ai
Есть подробные инструкции, которым вы можете следовать в Readme.

В проект Github я включил примеры моделей, зависимости для проекта, модели SqueezeNet (будут упомянуты позже) и тестовые изображения.

Я постарался сделать его как можно более минимальным, чтобы начать работу, даже если вы никогда раньше не работали с ML или python.

Остальная часть этой статьи будет сосредоточена на 4 шагах, которые сделали Янкен;

  1. Сбор данных
    (что показалось подходящим)
  2. SqueezeNet и обучение нейронной сети
  3. Тестирование модели
  4. Играйте в игру!

Сбор данных - что показалось целесообразным

Мы хотим собрать 4 типа изображений (камень, бумага, ножницы и фон / шум) и сопоставить их как наши входные метки.
Нам просто нужно их проиндексировать.

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

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

На что нужно обратить внимание.

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

ValueError: Ошибка при проверке: ожидалось, что squeezenet_input будет иметь форму (None, 300, 300, 3), но получен массив с формой (1, 227, 227, 3).

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

Удалить смещение

Огромная область в машинном обучении - это модель, которая имеет хорошее обобщение.

Достаточно ли разнообразия данных для обучения? Сотни изображений только моей руки, скорее всего, не смогут идентифицировать кого-либо, кроме меня как игрока.

Моим временным решением было слишком использовать руку в перчатке, чтобы побудить CNN сосредоточиться на особенностях жеста.

Затем я расширил это, протянув руку и собрав изображения из модуля Quantum, и потренировался, чтобы еще больше снизить мою предвзятость.

Идея улучшения. Сохраняйте все обученные изображения черно-белыми и конвертируйте игровые изображения также в черно-белые.

И последнее, что нужно отметить; когда я наклоняю руку во время захвата изображения, некоторые из них получаются размытыми из-за движения. Было важно очистить их путем удаления, так как они только запутают модель, чтобы идентифицировать статические изображения, как это было бы во время игрового процесса.

Шумовое загрязнение / Освещение
«
шум», означающее фон или что-либо иное, кроме руки, играющей жест. Одна из проблем заключалась в том, что у меня была проблема с тем, чтобы Янкен не узнал, что еще ничего не сыграно, и он пропускал между прогнозами. Так что сохранение стабильного фона в обучении было не лучшим выбором, я мог бы смешать с данными больше контраста, затенения, плакатов, дверей, просто более естественных предметов дома и офиса.

SqueezeNet и обучение нейронной сети

Здесь можно многое сказать, я добавил много комментариев в код в моем GitHub (ссылки вверху и внизу), файл, на котором нужно сосредоточиться, называется «train_model.py».

Keras
В этом проекте все вращается вокруг keras, это Python API для глубокого обучения.

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

INPUT_LABELS = {
    "rock": 0,
    "paper": 1,
    "scissors": 2,
    "noise": 3
}

После этого я решил заняться «последовательной моделью».

Дизайн, который позволяет простое отображение 1–1, в терминах ML это позволяет слоям, которые принимают 1 входной тензор и создают 1 выходной тензор. Например, последовательный позволяет нейронной сети (NN) идентифицировать бумажное изображение как значение 1.

model = Sequential([
    SqueezeNet(input_shape=(300, 300, 3), include_top=False),
    Dropout(0.2),
    Convolution2D(LABELS_COUNT, (1, 1), padding='valid'),
    Activation('relu'),
    GlobalAveragePooling2D(),
    Activation('softmax')

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

Я скоро расскажу о «SqueezeNet». Все остальное ниже считается слоем (keras.layers), все они важны, поэтому давайте потратим минуту, чтобы объяснить каждый.

Исключение добавлено для уменьшения переобучения, 0,2 = 20%, поэтому на протяжении всего процесса обучения отбрасывайте 1/5 полученного результата, чтобы модель продолжала изучать новые подходы и не устаревала. Это не редкость, когда эта цифра достигает 50%.

Convolution2D управляет размером слоя с помощью первого аргумента LABELS_COUNT, который в сумме будет равен 4 (3 жеста + шум) метка. Он добавляется к уже определенной нейронной сети SqueezeNet.

Активация (ReLU) Выпрямленное линейное устройство превращает отрицательные значения в 0 и выводит положительные значения.
Почему? Функция активации отвечает за ввод входных данных и присвоение весов выходным узлам, модель не может хорошо координировать себя с отрицательными значениями, она становится неоднородной в том смысле, как мы ожидаем от модели.

𝑓 (𝑥) = max {0, 𝑥} = ›Выход блока ReLU неотрицателен. Возвращая x, если меньше нуля, то max возвращает 0.

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

Это еще не все, это может вызвать проблему под названием «умирающий ReLU». Если вы возвращаете слишком много негативов, вы не хотите, чтобы они все превращались в 0, а возвращались в отрицательной линейной форме. Выполните поиск по запросу Leaky ReLU, если хотите узнать больше.

GlobalAveragePooling2D выполняет классификацию и вычисляет средний результат для каждой карты функций на предыдущем слое.
т.е. слой сокращения данных, подготавливает модель для активации (softmax).

Активация (softmax) дает вероятность каждого знака руки.
У нас есть 4 класса изображений (проблема), softmax обрабатывает мультиклассы, все, что больше 2.

SqueezeNet

Это предварительно созданная нейронная сеть для классификации изображений, что означает, что мы можем сосредоточиться на ее расширении для нашей цели по созданию Janken, что само по себе является достаточной работой, чем дополнительные усилия по созданию нейронной сети с нуля. Одно только тренировочное время для этого может составлять дни.

Бонусы от SqueezeNet;

  1. Меньшие сверточные нейронные сети (CNN) требуют меньше связи между серверами во время распределенного обучения.
  2. Меньше пропускной способности для экспорта новой модели.
  3. Меньшие CNN более удобны для развертывания и используют меньше памяти.

Чтобы повторно посетить строку кода из обучающего скрипта.

SqueezeNet(input_shape=(300, 300, 3), include_top=False)

# input_shape - это изображение размером 300 x 300 пикселей. 3 - для цветового диапазона RGB.

# include_top позволяет вам выбрать, хотите ли вы получить окончательный плотный слой или нет.

# Плотные слои могут интерпретировать найденные шаблоны для классификации изображений.
например это изображение содержит камень.

# Установите значение False, поскольку мы уже обозначили, как выглядят данные горных пород.

Сверточные слои работают как экстракторы функций. Они идентифицируют серию узоров на изображении, и каждый слой может идентифицировать более сложные узоры, просматривая узоры узоров.

Обратите внимание на вес:

  • Веса в сверточном слое имеют фиксированный размер. Сверточный слой не заботится о размере входного изображения.
    Он просто выполняет обучение и представляет результирующее изображение на основе того же размера входного изображения.
  • Веса в плотном слое полностью зависят от размера ввода. Это один вес для каждого элемента ввода. Поэтому для этого необходимо, чтобы вводимые данные всегда были одного и того же размера, иначе у вас не будет должных выученных весов.

Из-за этого установка для последнего плотного слоя значения false позволяет вам определить размер ввода (300 x 300). (И размер вывода соответственно увеличится / уменьшится).

Тестирование модели

В скрипте «test_model» вы можете увидеть прогнозы модели на изображениях, которые вы уже обработали, или на новых изображениях, которые модель никогда раньше не видела.

Скрипт обрабатывает любое новое изображение, которое вы хотите предоставить, поскольку оно будет преобразовано в формат 300x300 с использованием открытого CV.

Играйте в игру!

Прогнозы результатов игры Янкена
Я представил, что прогноз, который сделает Янкен, будет сильно «мерцать», поскольку движущееся изображение камеры всегда будет предоставлять различные исходные данные для анализа и запуска модели.

Освещение будет играть большую роль, поэтому я попытался разделить свой набор данных и собирать изображения в разное время дня.

Статический фон или элементы управления для фиксации изображения помогут сделать более стабильные прогнозы жестов.

Как все прошло?

Janken не создавался с учетом ограничений, поэтому было разработано «элегантное»… решение, позволяющее воспроизводить других через веб-камеру Mac на общем экране с другим игроком на мониторе.

Однако Янкен мог только постоянно побеждать меня, он смог выиграть 50% жестов от других игроков через монитор, но я подозревал, что природа изображений и обработки камеры затрудняет для Янкена, вероятно, разобрать все жесты.

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

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

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

Мир!

Ресурсы

Ссылка на GitHub с полным кодом



Keras API



Информация о SqueezeNet





О’Рейли (TensorFlow и Keras)