Python AI в StarCraft II. Часть X: строим модель нейронной сети

Предыдущая статья — Python AI в StarCraft II. Часть IX: создаем набор данных для обучения.

Добро пожаловать в десятую часть серии статей про использование искусственного интеллекта в игре Starcraft II. В данной статье мы будем создавать модель нейронной сети.

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

Если у вас есть данные, то распакуйте их — и вы готовы к приключениям! Сначала нам нужно разработать структуру нашей сверточной нейронной сети. Мы будем использовать фреймворк Keras, который является фактически надстройкой над TensorFlow. Если у вас еще нет библиотеки TensorFlow, вы легко сможете установить ее через pip. Мы будем использовать Keras версии 2.1.2 и TensorFlow версии 1.8.0.

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

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

Мы установили, что правильным решением было задать очень маленький коэффициент скорости обучения. Наша модель стартовала с коэффициентом 1e-5 и завершила свою работу с 1e-6 (то есть от 0.00001 до 0.000001).

Обычно мы начинаем с 1e-3 и заканчиваем на 1e-4 (от 0.001 до 0.0001). Но здесь мы решили, что начинать с 1e-4 все же вполне достаточно.

Для данной части наш код начнется с импорта следующих библиотек:

import keras  # Keras 2.1.2 and TF-GPU 1.8.0
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.callbacks import TensorBoard
import numpy as np
import os
import random   

Очевидно, что мы импортируем Keras, но также для наглядности мы отдельно пропишем классы dense, dropout и flatten. Это различные слои нашей нейронной сети. В частности, слой flatten разворачивает наши данные в вектор перед последним выходным слоем.

И наконец, мы разворачиваем сверточную нейронную сеть, поэтому использование Conv2D и MaxPooling2D обязательно. Для визуализации моделей обучения мы будем использовать TensorBoard.

Наши данные сохранены в формате numpy, поэтому для работы с ними мы загрузим этот модуль. Модуль os мы будем использовать для работы с директориями, а модуль random — для случайного перемешивания данных.

Теперь давайте строить нашу модель:

model = Sequential()

Это означает, что у нас будет обычная модель, где данные будут передаваться от слоя к слою.

Теперь создадим скрытые сверточные слои:

model.add(Conv2D(32, (3, 3), padding='same',
                 input_shape=(176, 200, 3),
                 activation='relu'))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))

model.add(Conv2D(64, (3, 3), padding='same',
                 activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))

model.add(Conv2D(128, (3, 3), padding='same',
                 activation='relu'))
model.add(Conv2D(128, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))

Далее добавим полносвязанный слой для выпрямления наших данных:

model.add(Flatten())
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))

И, наконец, создадим выходной слой:

model.add(Dense(4, activation='softmax'))

Теперь надо задать основные параметры работы нашей нейронной сети:

learning_rate = 0.0001
opt = keras.optimizers.adam(lr=learning_rate, decay=1e-6)

model.compile(loss='categorical_crossentropy',
              optimizer=opt,
              metrics=['accuracy'])

Напоследок, для логирования данных мы будем использовать TensorBoard:

tensorboard = TensorBoard(log_dir="logs/stage1")

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

Следующая статья — Python AI в StarCraft II. Часть XI: обучение нейронной сети.