Нейронные сети для чайников. Сеть Кохонена

в 16:32, , рубрики: .net, искусственный интеллект, нейронные сети, метки: ,

В статье Нейросети для чайников. Начало автор Paul_Smith доступно показал насколько просто создать нейронную сеть для распознования картинок. Но есть одно но — то что он описал нейронной сетью не является. Перед его следующей статьей хочу рассказать вам как решить ту же задачу, но с использованием нейронной сети Кохонена.

Итак, распознавать мы будем цифры, написанные белым по черному, такие как эти:
image image image image image image

Картинки 45 на 45 пикселей, а значит входов в нашу нейронную сеть будет 45 * 45.
Для простоты, распознаем только цифры от 0 до 5, поэтому нейронов у нас будет 6 — по одному на каждый ответ.

Cтруктура нашей нейросети:
image

Каждая связь входа сети с нейроном имеет свой вес. Импульс, проходя через связь, меняется: импульс = импульс * вес_связи.
Нейрон получает импульсы от всех входов и просто суммирует их. Нейрон набравший больший суммарный импульс побеждает. Все просто, реализуем!

Классы для представления элементов сети (C#):
// Вход
public class Input
{
     // Связи с нейронами
     public Link[] OutgoingLinks;
}

// Связь входа с нейроном
public class Link
{
     // Нейрон
     public Neuron Neuron;
     // Вес связи
     public double Weight;
}

public class Neuron
{
     //Все входы нейрона
     public Link[] IncomingLinks;
     // Накопленный нейроном заряд
     public double Power { get; set; }
}

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

Состояние класса KohonenNetwork это массив Input[] и массив Neuron[]:
public class KohonenNetwork
{
     private readonly Input[] _inputs;
     private readonly Neuron[] _neurons;
...
}

Предположим, что наша сеть уже обучена. Тогда, чтобы узнать что изображено на картинке мы вызовем метод Handle, там все перемножится, сложится и найдется максимум:
// Пропустить вектор через нейронную сеть
public int Handle(int[] input)
{
     for (var i = 0; i < _inputs.Length; i++)
     {
          var inputNeuron = _inputs[i];
          foreach (var outgoingLink in inputNeuron.OutgoingLinks)
          {
               outgoingLink.Neuron.Power += outgoingLink.Weight * input[i];
          }
     }
     var maxIndex = 0;
     for (var i = 1; i < _neurons.Length; i++)
     {
          if (_neurons[i].Power > _neurons[maxIndex].Power)
               maxIndex = i;
     }
     //снять импульс со всех нейронов:
     foreach (var outputNeuron in _neurons)
     {
          outputNeuron.Power = 0;
     }
     return maxIndex;
}

Но перед тем как спрашивать у сети что-либо, её надо обучить. Для обучения предъявляем картинки и указываем что на них нарисовано:
image
Обучение — это изменение весов связей:
public void Study(int[] input, int correctAnswer)
{
     var neuron = _neurons[correctAnswer];
     for (var i = 0; i < neuron.IncomingLinks.Length; i++)
     {
          var incomingLink = neuron.IncomingLinks[i];
          incomingLink.Weight = incomingLink.Weight + 0.5 * (input[i] - incomingLink.Weight);
     }
}

После обучения на двух шрифтах, нейронная сеть различает цифры и из других шрифтов. В том числе будет пройден контрольный тест на таких вот цифрах:
image image image image image image
Конечно, для расспознавания капчей такая поделка не годится — все перестает работать, стоит только сдвинуть, растянуть или повернуть изображение.
Однако всем становится понятно, что использовать нейронные сети не так уж и сложно, если начинать с простых примеров.
Исходник поделки

Автор: Kn4av


  1. Denis:

    Возобновите пожалуйста доступ к исходникам. Как не пытаюсь понять и реализовать описанное в статье – не получается. Исходники бы очень помогли. Заранее СПАСИБО!

  2. Дмитрий:

    Ссылка на исходник не работает, а посмотреть на эту сеть очень бы хотелось

  3. Vitalii:

    :( Присоединяюсь с просьбой исходника…

  4. Sophia:

    Скажите, а можно и мне исходник посмотреть?

  5. Нефрит:

    Ссылка на исходник не работает, исправьте пожалуйста, очень нужно.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js