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

На входе сети два значения: 1 и x. b и w — это веса соответствующих связей. Как правило, нейрон обрабатывает суммарный сигнал, обозначаемый переменной net. net — это сумма произведений сигналов и соответствующих весов. В нашем случае
Выходной сигнал нейрона определяется функцией активности y(net). Пусть функцией активности будет тождественная функция:
Тогда такая нейросеть будет эквивалентна выражению
Расчет ошибки
Предположим, что на выходе, при данном значении x, нейрон должен выдавать результат t. В таком случае мы можем определить функцию расчета ошибки следующим образом:
Функция ошибки будет равна нулю, если нейрон выдаст предполагаемое значение, и больше нуля в противном случае.
Обучение
На данном этапе становится ясно, что «мозгом» сети являются переменные w и b. Возникает вопрос: как следует изменить значения этих переменных, чтобы уровень ошибки для определенной пары (x,y) уменьшился? Ответить на этот вопрос поможет градиент функции ошибки. Найдем частные производные функции E по переменным w и b.
Если уменьшить w и b на соответствующие значения градиента, сеть будет выдавать более близкий к предполагаемому результат.
Таким образом, процесс обучения сети можно описать с помощью следующего алгоритма:
- Сформировать набор пар «аргумент — значение».
- Инициализировать w и b случайными ненулевыми значениями в интервале (-1, 1).
- Для всех пар «аргумент — значение»:
- Задать аргумент.
- Попустить сигнал через нейросеть.
- Рассчитать градиент, соответствующий функции E.
- Уменьшить w и b на соответствующие значения градиента.
- Если уровень ошибки для набора пар выше необходимого, вернуться к пункту 3.
Практика
Следующий этап — реализация данного алгоритма на языке C++. Все необходимые данные и методы будут описаны в рамках отдельной структуры.
#include <iostream>
#include <math.h>
using namespace std;
struct Neuron {
double b, w, y, t, x, d;
Neuron(double w, double b) { // Инициализация весов нейрона
this->b = b;
this->w = w;
};
void forwrd() { // Прямой проход сигнала x
y = w*x + b;
};
void backwrd() { // Расчет производных и коррекция весов
d = y - t;
w -= d*x;
b -= d;
};
double calcEps() { // Ошибка - модуль разности результата и требуемого значения
return abs(y-t);
};
};
int main(int argc, char* argv[]) {
double x[] = {0.0, 1.0}; // аргументы и
double y[] = {0.0, 0.5}; // требуемые значения соответственно
double eps;
int size = sizeof(x)/sizeof(double); // количество аргументов
cout << "(x,y):";
for(int i=0; i<size; i++) // вывод точек, на которых обучается нейрон
cout << " (" << x[i] << "," << y[i] << ")";
cout << endl;
Neuron p(0.007, 0.005); // Инициализация нейрона p.
do {
eps = 0.0;
for(int i=0; i<size; i++) { // цикл по всем аргументам
p.x = x[i]; // установка аргумента
p.t = y[i];
// установка требуемого значенияp.forwrd();
// распространение сигнала в прямом направленииeps += p.calcEps();
// суммирование ошибокp.backwrd();
// расчет производных и коррекция весов};
cout << "Sum eps = " << eps << endl; // вывод суммарной ошибки
} while(eps > 0.05);
// тест нейрона для произвольного аргументаcout << "Test" << endl;
cout << "x = ";
cin >> p.x;
p.forwrd();
cout << "y = " << p.y << endl;
return 0;
};
Вывод программы:
(x,y): (0,0) (1,0.5)
Sum eps = 0.498
Sum eps = 0.493
Sum eps = 0
Test
x = 10
y = 5
В рассмотренном примере выбраны две точки для обучения. Так как через них можно провести единственную прямую, установка сколь угодно малого ограничения на eps не приведет к «зацикливанию». Ситуация поменяется, если таких точек будет больше и они не будут расположены на одной прямой. Тем не менее, смысл обучения от этого не теряется. В таком случае, обучая нейрон, мы найдем прямую, максимально близко расположенную к точкам обучения. Если, например, точки — это люди в очереди, то обученный нейрон — это прямая, вдоль которой все выстроились. Причем данная прямая будет обнаружена, несмотря на неточности в расположении людей.
Более сложный пример.
Добавить комментарий