[Из песочницы] Введение в нейронные сети на Golang

habr.png

Привет читателям Habrahabr! В этой статье я продемонстрирую вам пример простой нейронной сети на языке Golang с использованием готовой библиотеки.

Немного предисловия


Начав изучать язык программирования Golang, мне стало интересно, что может этот язык в сфере машинного обучения. Тогда я начал искать примеры кода какой-либо НС на этом языке. К сожалению, ничего толкового найти не получилось. И вот тогда я решил переписать НС из этой статьи под GO.

Нейросеть


Задача нейронной сети — решить, что делать персонажу, исходя из 3х параметров:

  • Количество здоровья (от 1 до 100)
  • Наличие оружия
  • Количество врагов


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

  • Атаковать
  • Красться
  • Убегать
  • Ничего не делать


Примеры:

Здоровье Оружие Враги Решение
50 1 1 Атаковать
90 1 2 Атаковать
80 0 1 Атаковать
30 1 1 Красться
60 1 2 Красться
40 0 1 Красться
90 1 7 Убегать
60 1 4 Убегать
10 0 1 Убегать
60 1 0 Ничего не делать
100 0 0 Ничего не делать


Подготовка


Мы будем использовать библиотеку GoNN.

Установка:

go get github.com/fxsjy/gonn/gonn


Приступим!


Для начала зададим импорт:

import (
     "fmt"
     "github.com/fxsjy/gonn/gonn"
)


Теперь приступим к созданию нейронной сети:


func CreateNN() {
    // Создаём НС с 3 входными нейроннами (столько же входных параметров),
    // 16 скрытыми нейронами и
    // 4 выходными нейронами (столько же вариантов ответа)
    nn := gonn.DefaultNetwork(3, 16, 4, false)
     
    // Создаём массив входящих параметров:
    // 1 параметр - количество здоровья (0.1 - 1.0)
    // 2 параметр - наличие оружия (0 - нет, 1 - есть)
    // 3 параметр - количество врагов
    input := [][]float64 {
             []float64{0.5, 1, 1}, []float64{0.9, 1, 2}, []float64{0.8, 0, 1}, 
             []float64{0.3, 1, 1}, []float64{0.6, 1, 2}, []float64{0.4, 0, 1},
             []float64{0.9, 1, 7}, []float64{0.6, 1, 4}, []float64{0.1, 0, 1}, 
             []float64{0.6, 1, 0}, []float64{1, 0, 0} }
    
    // Теперь создаём "цели" - те результаты, которые нужно получить
    target := [][]float64 {
             []float64{1, 0, 0, 0}, []float64{1, 0, 0, 0}, []float64{1, 0, 0, 0},
             []float64{0, 1, 0, 0}, []float64{0, 1, 0, 0}, []float64{0, 1, 0, 0},
             []float64{0, 0, 1, 0}, []float64{0, 0, 1, 0}, []float64{0, 0, 1, 0},
             []float64{0, 0, 0, 1}, []float64{0, 0, 0, 1} }

    // Начинаем обучать нашу НС.
    // Количество итераций - 100000
    nn.Train(input, target, 100000)

    // Сохраняем готовую НС в файл.
    gonn.DumpNN("gonn", nn)
}


Теперь нам нужно написать функцию, которая выберет ответ нейрона с самым большим весом.


func GetResult(output []float64) string {
    max := -99999
    pos := -1
    // Ищем позицию нейрона с самым большим весом.
    for i, value := range output {
        if (value > max) {
            max = value
            pos = i
        }
    }

    // Теперь, в зависимости от позиции, возвращаем решение.
    switch pos {
    case 0: return "Атаковать"
    case 1: return "Красться"
    case 2: return "Убегать"
    case 3: return "Ничего не делать"
    }
}


И теперь пишем функцию main.


func main() {
    CreateNN()
    // Загружем НС из файла.
    nn := gonn.LoadNN("gonn")

    // Записываем значения в переменные:
    // hp - здоровье (0.1 - 1.0)
    // weapon - наличие оружия (0 - нет, 1 - есть)
    // enemyCount - количество врагов
    hp := 0.7
    weapon := 1
    enemyCount := 1

    // Получаем ответ от НС (массив весов)
    out := nn.Forward([]float64{ hp, weapon, enemyCount })
    // Печатаем ответ на экран.
    fmt.Println(GetResult(out))
}


В данном случае ответ — «Атаковать»

Заключение


Как видим, процесс работы с нейронными сетями на Golang такой же, как и с другими языками программирования. Эксперементируйте с этой сетью и создавайте свои!

© Habrahabr.ru