Инструкции по выполнению шага
За предыдущие шаги мы сделали хорошую игру, в которую можно поиграть самому. Чего-то не хватает? Наверное, "интеллекта"? Давайте этим и займемся!
"Искусственный интеллект" мы создадим на основе нейронной сети. Приведем одно (из многочисленных) определений:
Нейронная сеть — математическая модель, а также её программное или аппаратное воплощение, построенная по принципу организации и функционирования биологических нейронных сетей — сетей нервных клеток живого организма.
Важным словом, которое выделено, является модель нейронной сети. Без модели наш искусственный интеллект на основе нейронной сети не заведется.
Модель нейронной сети описывает её архитектуру и конфигурацию, а также используемые алгоритмы обучения.
- Архитектура нейронной се ти определяет общие принципы её построения (плоскослоистая, полносвязная, слабосвязная, прямого распространения, рекуррентная и т.д.).
- Конфигурация конкретизирует структуру сети в рамках заданной архитектуры: число нейронов, число входов и выходов сети, используемые активационные функции.
Более того, нам нужно каким-то образом запускать модель нейронной сети запускать... И желательно в браузере. Для этого мы воспользуемся ONNX.js.
ONNX.js - это библиотека JavaScript для запуска моделей ONNX в браузерах и на Node.js.
Почему модели ONNX? ONNX (формат обмена открытыми нейронными сетями) является открытым стандартом для представления моделей машинного обучения. Самым большим преимуществом ONNX является то, что он обеспечивает совместимость между различными фреймворками искусственного интеллекта с открытым исходным кодом, что само по себе обеспечивает большую гибкость при внедрении фреймворков искусственного интеллекта.
При этом ONNX.js позволит запускать нам интерактивно модели нейронных сетей без установ ки и независимо от устройства, задержки связи между сервером и клиентом.
Давайте внедрять ONNX.js в нашу замечательную игру!
Сначала, мы добавим onnx.min.js
, взятый из публичного репозитория, в папку js
.
Далее мы добавим кнопку, которая позволит нам загружать модели нейронных сетей в формате ONNX в браузерное окружение.
Кнопку сделаем из двух ассетов: upload1.svg
и upload2.svg
.
Две картинки мы будем использовать для анимации. Когда модель будет успешно загружена в браузерное окружение, кнопка будет менять картинку через равные промежутки времени.
Добавим upload1.svg
и upload2.svg
в папку наших assets
.
Далее нам необходимо добавить нашу кнопку в игру. Для этого внесём следующие изменения в наш главный файл index.html
сразу после элемента h1
(информация про способности игрока):
<!-- Начало места, которое мы изменя ем -->
</h1>
<p class='upload'>
<label for="file_input">
<img src="assets/upload1.svg" width="50px"></img>
<img src="assets/upload2.svg" width="50px" hidden></img>
ONNX file
</label>
<input type="file" id='file_input' class="modelFile" accept=".onnx" />
</p>
<script src="js/render.js"></script>
<!-- Конец редактирования -->
Теперь опишем механизмы, которые будут реализовывать искусственный интеллект. Для этого создадим в папке js
новый скрипт ai.js
. Не забудем подгрузить его в index.html
перед скриптом engine.js
. За ним добавим onnx.min.js
:
<!-- Начало места, которое мы изменяем -->
<script src="js/download.js"></script>
<script src="js/onnx.min.js"></script>
<script src="js/ai.js"></script>
<script src="js/engine.js"></script>
</body>
</html>
<!-- Конец редактирования -->
Вот так будет выглядеть наша папка проекта после создания файла ai.js
:
ping-pong
├── index.html
├── assets
│ ├── ball.png
│ ├── paddle.png
│ ├── background.jpg
│ ├── style.css
│ ├── download.svg
│ ├── upload1.svg
│ └── upload2.svg
└── js
├── render.js
├── engine.js
├── controls.js
├── pause.js
├── scores.js
├── logging.js
├── download.js
├── onnx.min.js
└── ai.js
Положение только что созданного элемента необходимо зафиксировать, поэтому внесём в файл style.css
следующие настройки:
Следующая часть добавляется в конец файла style.css
.
.upload {
color: white;
position: fixed;
right: 100px;
top: 35px;
}
.upload input {
display: none;
}
.upload label:hover {
cursor: pointer;
}
Таким образом, мы привязали нашу кнопку к конкретному месту на экране с помощью CSS селектора.
Остается добавить логику для загрузки модели и реализовать анимацию в случае успешной загрузки модели. Приступим!
В файле ai.js
напишем следующий код:
const botImages = Array.from(
document.getElementsByClassName("upload")[0].getElementsByTagName("img")
);
var onnxSess;
var use_bot = {
state: false,
busy: false,
intervalId: 0
};
// https://stackoverflow.com/questions/52184291/async-await-with-setinterval
async function waitUntil(condition) {
let frame = 0;
return await new Promise((resolve) => {
condition.intervalId = setInterval(() => {
if (!condition.state) {
resolve("a");
} else {
if (!condition.busy && !isPaused) {
if (frame === 0) {
botImages[0].style.display = "block";
botImages[1].style.display = "none";
const tmp = botImages[0];
botImages[0] = botImages[1];
botImages[1] = tmp;
}
frame = (frame + 1) % 10;
}
}
}, 50);
});
}
document.getElementsByClassName("modelFile")[0].onchange = async function (
event
) {
var fileList = this.files;
use_bot.state = false;
if (use_bot.intervalId) {
clearInterval(use_bot.intervalId);
}
if (!fileList.length) {
return;
}
// breakLoop = true;
let file = fileList[0];
let reader = new FileReader();
reader.onloadend = async function () {
onnxSess = new onnx.InferenceSession();
await onnxSess.loadModel(reader.result);
use_bot.state = true;
waitUntil(use_bot);
};
reader.readAsDataURL(file);
console.log(fileList[0]);
};
Давайте обсудим то, что делает написанные код:
- В начале мы на странице обнаружили нашу кнопку и получаем ее картинку в переменную
botImages
. - Далее мы создали именованный массив
use_bot
, куда будем сохранять признак загрузки модели, занятости и информацию для реализации интервальной анимации. - Метод
waitUntil
позволят организовать интервальную анимацию кнопки и кое-какую другую тактовую деятельность, о которой пойдет речь на следующем шаге. - Когда мы нажимаем на кнопку, появляется окно загрузки файла с локального диска. Мы в
index.html
указали, что ждем файлы с расширением.onnx
. Когда мы выбрали модель или закрыли окно, мы приостанавливаем анимацию кнопки, если она была запущена. Далее мы проверяем, был ли передан файл в ожидаемом формате. Если да, то осуществим чтением модели из файла и запустим анимацию кнопки.
Итоговый результат выполнения шага можно скачать тут.