Перейти к основному содержимому

Введение в Нейроф

· 6 мин. чтения

1. Введение

В этой статье рассматривается Neuroph — библиотека с открытым исходным кодом для создания нейронных сетей и использования машинного обучения.

В статье мы рассмотрим основные концепции и несколько примеров того, как все это собрать вместе.

2. Нейрофил

Мы можем взаимодействовать с Neuroph, используя:

  • инструмент на основе графического интерфейса
  • библиотека Java

Оба подхода основаны на базовой иерархии классов, которая строит искусственные нейронные сети из слоев нейронов .

Мы сосредоточимся на программной стороне, но обратимся к нескольким общим классам из подхода Neuroph на основе графического интерфейса, чтобы прояснить, что мы делаем.

Чтобы узнать больше о подходе на основе графического интерфейса, загляните в документацию Neuroph .

2.1. Зависимости

Если вы хотите использовать Neuroph, нам нужно добавить следующую запись Maven:

<dependency>
<groupId>org.beykery</groupId>
<artifactId>neuroph</artifactId>
<version>2.92</version>
</dependency>

Самую последнюю версию можно найти на Maven Central .

3. Ключевые классы и понятия

Все используемые основные концептуальные строительные блоки имеют соответствующие классы Java.

Нейроны связаны со слоями , которые затем группируются в нейронные сети . Впоследствии нейронные сети обучаются с использованием LearningRules и DataSets .

3.1. Нейрон

Класс Neuron имеет четыре основных атрибута:

  1. inputConnection: взвешенные соединения между нейронами
  2. inputFunction: определяет веса и векторные суммы , применяемые к входящим данным соединения .
  3. TransferFunction: определяет веса и векторные суммы , применяемые к исходящим данным . ``
  4. output: выходное значение, полученное в результате применения transferFunctions и inputFunctions к inputConnection

Вместе эти четыре основных атрибута определяют поведение:

output = transferFunction(inputFunction(inputConnections));

3.2. Слой

Слои представляют собой группы нейронов , так что каждый нейрон в слое (обычно) связан только с нейронами в предыдущем и последующем слоях .

Таким образом, слои передают информацию между собой через взвешенные функции, существующие на их нейронах .

Нейроны можно добавлять в слои: ``

Layer layer = new Layer(); 
layer.addNeuron(n);

3.3. Нейронная сеть

Надкласс верхнего уровня NeuralNetwork подразделяется на несколько знакомых видов искусственных нейронных сетей, включая сверточные нейронные сети (подкласс ConvolutionalNetwork ), нейронные сети Хопфилда (подкласс Hopfield ) и многослойные нейронные сети персептрона (подкласс MultilayerPerceptron ).

Все нейронные сети состоят из слоев , которые обычно организованы в виде трихотомии:

  1. входные слои
  2. скрытые слои
  3. выходные слои

Если мы используем конструктор подкласса NeuralNetwork (например, Perceptron ), мы можем передать Layer s, количество Neuron для каждого Layer и их индекс, используя этот простой метод:

NeuralNetwork ann = new Perceptron(2, 4, 1);

Иногда мы хотим сделать это вручную (и хорошо видеть, что происходит под капотом). Основная операция по добавлению слоя в нейронную сеть выполняется следующим образом:

NeuralNetwork ann = new NeuralNetwork();   
Layer layer = new Layer();
ann.addLayer(0, layer);
ann.setInputNeurons(layer.getNeurons());

Первый аргумент указывает индекс слоя в нейронной сети ; второй аргумент определяет сам слой . Слои , добавленные вручную, должны быть подключены с помощью класса ConnectionFactory :

ann.addLayer(0, inputLayer);    
ann.addLayer(1, hiddenLayerOne);
ConnectionFactory.fullConnect(ann.getLayerAt(0), ann.getLayerAt(1));

Первый и последний слой также должны быть связаны:

ConnectionFactory.fullConnect(ann.getLayerAt(0), 
ann.getLayerAt(ann.getLayersCount() - 1), false);
ann.setOutputNeurons(ann.getLayerAt(
ann.getLayersCount() - 1).getNeurons());

Помните, что сила и мощность нейронной сети во многом зависят от:

  1. количество слоев в нейронной сети
  2. количество нейронов в каждом слоевзвешенные функции между ними), и
  3. эффективность алгоритмов обучения/точность набора данных

3.4. Обучение нашей нейронной сети

Нейронные сети обучаются с использованием классов DataSet и LearningRule .

DataSet используется для представления и предоставления информации, которую нужно изучить или использовать для обучения NeuralNetwork . Наборы данных характеризуются своим входным размером, выходным размером и строками (DataSetRow).

int inputSize = 2; 
int outputSize = 1;
DataSet ds = new DataSet(inputSize, outputSize);

DataSetRow rOne
= new DataSetRow(new double[] {0, 0}, new double[] {0});
ds.addRow(rOne);
DataSetRow rTwo
= new DataSetRow(new double[] {1, 1}, new double[] {0});
ds.addRow(rTwo);

LearningRule определяет способ, которым DataSet обучается или обучается NeuralNetwork . Подклассы LearningRule включают BackPropagation и SupervisedLearning .

NeuralNetwork ann = new NeuralNetwork();
//...
BackPropagation backPropagation = new BackPropagation();
backPropagation.setMaxIterations(1000);
ann.learn(ds, backPropagation);

4. Собираем все вместе

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

4.1. Слои

Мы соберем нашу нейронную сеть , объединив четыре слоя. Наша цель — построить (2, 4, 4, 1) нейронную сеть.

Давайте сначала определим наш входной слой:

Layer inputLayer = new Layer();
inputLayer.addNeuron(new Neuron());
inputLayer.addNeuron(new Neuron());

Затем мы реализуем скрытый слой один:

Layer hiddenLayerOne = new Layer();
hiddenLayerOne.addNeuron(new Neuron());
hiddenLayerOne.addNeuron(new Neuron());
hiddenLayerOne.addNeuron(new Neuron());
hiddenLayerOne.addNeuron(new Neuron());

И второй скрытый слой:

Layer hiddenLayerTwo = new Layer(); 
hiddenLayerTwo.addNeuron(new Neuron());
hiddenLayerTwo.addNeuron(new Neuron());
hiddenLayerTwo.addNeuron(new Neuron());
hiddenLayerTwo.addNeuron(new Neuron());

Наконец, мы определяем наш выходной слой:

Layer outputLayer = new Layer();
outputLayer.addNeuron(new Neuron());

4.2. Нейронная сеть

Затем мы можем объединить их в нейронную сеть :

NeuralNetwork ann = new NeuralNetwork();
ann.addLayer(0, inputLayer);
ann.addLayer(1, hiddenLayerOne);
ConnectionFactory.fullConnect(ann.getLayerAt(0), ann.getLayerAt(1));
ann.addLayer(2, hiddenLayerTwo);
ConnectionFactory.fullConnect(ann.getLayerAt(1), ann.getLayerAt(2));
ann.addLayer(3, outputLayer);
ConnectionFactory.fullConnect(ann.getLayerAt(2), ann.getLayerAt(3));
ConnectionFactory.fullConnect(ann.getLayerAt(0),
ann.getLayerAt(ann.getLayersCount()-1), false);
ann.setInputNeurons(inputLayer.getNeurons());
ann.setOutputNeurons(outputLayer.getNeurons());

4.3. Подготовка

В целях обучения давайте соберем DataSet , указав размер как входного, так и результирующего выходного вектора:

int inputSize = 2;
int outputSize = 1;
DataSet ds = new DataSet(inputSize, outputSize);

Мы добавляем элементарную строку в наш DataSet , придерживаясь входных и выходных ограничений, определенных выше — наша цель в этом примере — научить нашу сеть выполнять основные операции XOR (исключающее или):

DataSetRow rOne
= new DataSetRow(new double[] {0, 1}, new double[] {1});
ds.addRow(rOne);
DataSetRow rTwo
= new DataSetRow(new double[] {1, 1}, new double[] {0});
ds.addRow(rTwo);
DataSetRow rThree
= new DataSetRow(new double[] {0, 0}, new double[] {0});
ds.addRow(rThree);
DataSetRow rFour
= new DataSetRow(new double[] {1, 0}, new double[] {1});
ds.addRow(rFour);

Далее давайте обучим нашу нейронную сеть с помощью встроенного BackPropogation LearningRule :

BackPropagation backPropagation = new BackPropagation();
backPropagation.setMaxIterations(1000);
ann.learn(ds, backPropagation);

4.4. Тестирование

Теперь, когда наша нейронная сеть обучена, давайте проверим ее. Для каждой пары логических значений, переданных в наш DataSet как DataSetRow , мы запускаем следующий тип теста:

ann.setInput(0, 1);
ann.calculate();
double[] networkOutputOne = ann.getOutput();

Важно помнить, что NeuralNetworks выводит значение только на инклюзивном интервале 0 и 1 . Чтобы вывести какое-то другое значение, мы должны нормализовать и денормализовать наши данные.

В этом случае для логических операций идеально подходят 0 и 1. Вывод будет:

Testing: 1, 0 Expected: 1.0 Result: 1.0
Testing: 0, 1 Expected: 1.0 Result: 1.0
Testing: 1, 1 Expected: 0.0 Result: 0.0
Testing: 0, 0 Expected: 0.0 Result: 0.0

Мы видим, что наша нейронная сеть успешно предсказывает правильный ответ!

5. Вывод

Мы только что рассмотрели основные концепции и классы, используемые Neuroph.

Дополнительную информацию об этой библиотеке можно найти здесь , а примеры кода, использованные в этой статье, можно найти на GitHub .