[Из песочницы] Введение в нейронные сети на Golang
Привет читателям 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 такой же, как и с другими языками программирования. Эксперементируйте с этой сетью и создавайте свои!