Кружок Программирования

Архитектура нейронной сети для Гомоку

Эта нейронная сеть предназначена для игры в Гомоку, где нужно ставить фишки на поле 15x15. Она умеет:

  • Предлагать лучший ход (policy)
  • Оценивать позицию (value)

Как сеть "видит" поле

На вход подаётся поле 15x15 с двумя каналами:

  • Первый канал — позиции текущего игрока
  • Второй канал — позиции противника

Свёрточные слои (извлечение признаков)

📋
conv1 = register_module("conv1",
    torch::nn::Conv2d(torch::nn::Conv2dOptions(2, 64, 3).padding(1)));
conv2 = register_module("conv2",
    torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 64, 3).padding(1)));
conv3 = register_module("conv3",
    torch::nn::Conv2d(torch::nn::Conv2dOptions(64, 128, 3).padding(1)));

Эти слои анализируют поле. Каждый слой ищет всё более сложные паттерны:

  • conv1 — простые формы (линии, соседние клетки)
  • conv2 — комбинации (угрозы, пары)
  • conv3 — сложные структуры (почти выигрышные позиции)

В Conv2dOptions первые два параметра - это количество входных и выходных каналов. Третий параметр определяет размер сканирующего ядра (3 на 3). Padding=1 позволяет сохранять размер поля 15x15. Первому слою приходят на вход два канала - это позиции игрока, который должен походить следующим (первый канал, ноль либо еденица для каждой из 225 клеток) и во втором канале точно также передаются позиции игрока который ходил только что. Первый слой имеет 64 выхода, которые поступают на второй слой, и т.д. (см. схему).

Policy head (выбор хода)

📋
policy_conv = register_module("policy_conv",
    torch::nn::Conv2d(torch::nn::Conv2dOptions(128, 2, 1)));
policy_fc = register_module("policy_fc",
    torch::nn::Linear(2 * 15 * 15, 225));

Этот блок отвечает за выбор хода:

  • Сжимает информацию
  • Преобразует её в 225 значений (по одному на каждую клетку)

 

Value head (оценка позиции)

📋
value_conv = register_module("value_conv",
    torch::nn::Conv2d(torch::nn::Conv2dOptions(128, 1, 1)));
value_fc1 = register_module("value_fc1",
    torch::nn::Linear(15 * 15, 64));
value_fc2 = register_module("value_fc2",
    torch::nn::Linear(64, 1));

Этот блок оценивает позицию:

  • -1 — проигрыш
  • 0 — равная позиция
  • +1 — выигрыш

Прямой проход (forward)

📋
std::pair<torch::Tensor, torch::Tensor> forward(torch::Tensor x) {
    x = torch::relu(conv1->forward(x));
    x = torch::relu(conv2->forward(x));
    x = torch::relu(conv3->forward(x));

    auto p = policy_conv->forward(x);
    p = p.view({p.size(0), -1});
    p = policy_fc->forward(p);

    auto v = torch::relu(value_conv->forward(x));
    v = v.view({v.size(0), -1});
    v = torch::relu(value_fc1->forward(v));

    if (this->is_training()) {
        v = torch::dropout(v, 0.15, true);
    }

    v = torch::tanh(value_fc2-> forward(v));

    return {p, v};
}

Что происходит:

  1. Сеть анализирует поле
  2. Policy предлагает ходы
  3. Value оценивает позицию
  4. Dropout уменьшает переобучение

Итог

Сеть одновременно думает "куда ходить" и "насколько всё хорошо". Это делает её гораздо сильнее простых алгоритмов.

Схема обучения

Self-play (игра) Forward Pass (Model) Candidate Selection adaptiveK, spread, dominance, strongWinner Policy Loss Value Loss Total Loss Backprop (update weights)

Описание функций и шагов обучения:
🔹 Self-play: партия нейронки против легаси или самой себя, собираем статистику ходов.
🔹 Forward Pass: сеть выдаёт вероятность каждого хода (policy logits) и оценку позиции (value).
🔹 Candidate Selection (TREE TRAIN): выбираются ходы по totalDirectChilds и фильтрам, вычисляется spread, dominance и определяется strongWinner. AdaptiveK выбирается на основе числа прямых дочерних узлов.
🔹 Policy Loss: сравнивает предсказанные вероятности с целевыми (из дерева/рейтинга ходов) и добавляет энтропийное сглаживание.
🔹 Value Loss: MSE между предсказанной оценкой позиции и целевой (nodeRating или результат партии).
🔹 Total Loss: комбинированный loss с коэффициентом beta и L2-регуляризацией весов. Корректируется для X/O ходов.
🔹 Backprop: градиентный спуск по Total Loss обновляет веса нейросети.
🔹 🔁 Процесс повторяется для каждой позиции партии и каждой self-play игры.

🔹 Важно: Warning "not existed node" появляется из-за exploration: нейронка выбирает редкий ход, которого нет в дереве легаси. Это нормально и не критично для обучения.
🔹 strongWinner обычно коррелирует с totalDirectChilds, показывая явного лидера среди кандидатов.

Страница создана 08.04.2026
Изменена 09.04.2026
М.О.