Нет, ну а в самом деле! Сидеть, сложа руки, читать теорию и заглядываться на чужие нейронные сети? Нет, я так не могу. Сегодня я разберу, как пишется нейросеть на Python для чайников. Как написать нейронную сеть на python, как обучить нейросеть на Python, как её заставить работать. И всё это за какие-то 5-10 минут. А всё потому, что ничего сложного в этом нет. Давайте разбираться вместе.
Нейросеть на Python для чайников: что нам потребуется?
Прежде всего, среда разработки (IDE) для самого Python, я рекомендую использовать одну из последних версий. Откуда взять эту среду, какую версию редактора использовать… на эту тему можно говорить много, если не вечно. Но если вы уже программировали на Python (хотя бы выводили на экран пресловутое «Hello, world»), то вы уже в курсе, что нужно делать. Если же питон для вас не более, чем змея, то для вас я напишу отдельную статью — подготовка к программированию нейронных сетей на Python.
Нам понадобится библиотека NumPy, которая обеспечивает достаточно мощный математический аппарат. Она прекрасно подгружается из командной строки при помощи команды «pip3». Ну и, конечно же, здравый смысл со базовыми знаниями математики. И желание! Давайте я сведу всё в один список: что потребуется, чтобы написать нейросеть на Python?
- среда разработки Python;
- библиотека NumPy;
- базовое понимание основ линейной алгебры и математического анализа.
К слову, если вам больше по душе академический подход — вы ищете нейросети для чайников на python (учебник) — загляните в подборку лучших книг по нейронным сетям. Там есть отличный экземпляр!
Создание нейросети на Python для чайников: постановка задачи
Ну, приступим! Какую же задачу будет решать наша нейронная сеть на Python? Начнём с чего-нибудь простого. Например, дадим ей ряд значений (разумеется, либо «0», либо «1») и попросим её продолжить этот ряд. Естественно, не без подсказки (ведь наша нейронка на Python ещё маленькая и неопытная). Давайте я поясню наглядно:
Данные на входе | Данные на выходе | |||
Ситуация 1 | 0 | 0 | 1 | 0 |
Ситуация 2 | 1 | 1 | 1 | 1 |
Ситуация 3 | 1 | 0 | 1 | 1 |
Ситуация 4 | 0 | 1 | 1 | 0 |
Загадка | 1 | 0 | 0 | ? |
Как мы видим, для каждой из ситуаций (1-4) у нас есть ряд значений. Значение на выходе — своеобразная «подсказка» для нейросети на питоне. Взглянув на всю матрицу целиком, вы сразу обнаружите, что «ключ» к отгадке прост — это первое значение в каждом ряду. Отлично! Но это видим мы с вами, а нейросеть ещё нужно будет этому научить. Научить и проверить, как она справится с загадкой (последняя строка).
Как будет работать наш пример нейросети на Python для чайников?
Наша простая нейронная сеть на Python будет работать следующим образом. Мы случайным (ну, почти случайным, чуть позже поясню) образом сгенерируем веса, которые будут связывать входные и выходные данные. А затем…
- «взвесим» при помощи них входные данные, чтобы получить выходные и «прогоним» через так называемую сигмоиду (математическую функцию), чтобы нормализовать их;
- сравним полученные данные с тренировочными, чтобы посмотреть, насколько ошибается наша нейросеть на пайтон;
- откалибруем веса, чтобы снизить ошибку и, в итоге, добиться успеха;
- ах да, чуть не забыл — повторим этот цикл несколько десятков тысяч раз. Ну так, для большей уверенности.
А теперь всё спокойно и по порядку. Разбираем.
1. Взвешивание и нормализация
В нашей нейросети на Python есть два слоя — вход и выход. Мы просто обязаны добавить ещё один — скрытый. Этим слоем как раз и будет выступать матрица весов. Поскольку по условию задачи у нас 3 «входа», а «выход» всего один, то и размер матрицы будет — 3×1. Для примера предположим, что программа чудным образом сгенерировала нам абсолютно нейтральные веса — 0,5 каждый.
Входные данные | Веса | Взвешенная сумма | ||||
X | W |
\[ \sum X \times W \] |
||||
\[ \begin{bmatrix} 0& 0& 1\\0& 1& 0\\1& 0& 1\\1& 1& 0\end{bmatrix} \] |
× |
\[ \begin{bmatrix} 0,5\\0,5\\0,5\end{bmatrix} \] |
= |
\[ \begin{bmatrix} 0,5\\0,5\\1\\1\end{bmatrix} \] |
Далее нам нужно нормализовать данные, то есть привести их к одному, общему виду. Для этого воспользуемся математической функцией, сигмоидой.
\[ \begin{bmatrix} 0,5\\0,5\\1\\1\end{bmatrix} \] |
\[ \frac{1}{1+e^{-(0,5)}} \] \[ \frac{1}{1+e^{-(0,5)}} \] \[ \frac{1}{1+e^{-(1)}} \] \[ \frac{1}{1+e^{-(1)}} \] |
\[ \begin{bmatrix} 0,62\\0,62\\0,73\\0,73\end{bmatrix} \] |
Таким образом, нейросеть на питоне посчитала: с такими весами должны получаться вот такие выходные данные. Немного неточно, не находите? Ещё бы, ведь должно было получиться [0, 1, 1, 0]. А не вот эти дробные числа. Нейронная сеть Python срочно нуждается в обучении!
2. Расчёт ошибки нейронной сети
В этой части, как оказывается, всё достаточно просто. Полученный значения вычитаются из тренировочных (помните, та самая подсказка в четвёртом столбце?).
Значения на выходе | Полученные сетью значения | Ошибка нейронной сети | ||
\[ \begin{bmatrix} 0\\0\\1\\1\end{bmatrix} \] |
– |
\[ \begin{bmatrix} 0,62\\0,62\\0,73\\0,73\end{bmatrix} \] |
= |
\[ \begin{bmatrix} -0,62\\-0,62\\0,27\\0,27\end{bmatrix} \] |
3. Калибровка весов и обучение нейросети Python
И вот теперь — самый сок. Формула, по которой обучается наша нейронная сеть на питоне, я представлю в виде последовательного хода вычислений. Сейчас мы рассчитаем ту саму «дельту», на которую нейросеть на Python для чайников будет корректировать веса. Много-много раз. Но очень быстро. Итак, последовательность действий следующая:
- рассчитываем производную сигмоидной функции в значениях, полученных на выходе (dS);
- умножаем полученные значения производной на рассчитанные ошибки нейронной сети, получаем так называемую «дельту» (dS×Er);
- умножаем полученную дельту на транспонированную матрицу значений на входе (dS×Er×X(T));
- полученные значения добавляем к первоначальным весам (dS×Er×X(T)+W).
Умножение на производную сигмоидной функции здесь имеет большое значение. Ведь от того, какой окажется производная в определённой точке, зависит то, насколько нейронная сеть уверенна в своём результате.
Веса | Калибровка | Новые веса | ||
\[ \begin{bmatrix} 0,5\\0,5\\0,5\end{bmatrix} \] |
+ |
\[ \begin{bmatrix} 0,106\\-0,092\\-0,092\end{bmatrix} \] |
= |
\[ \begin{bmatrix} 0,60\\0,40\\0,40\end{bmatrix} \] |
И теперь это надо повторить несколько десятков тысяч раз. Не пугайтесь, программа осилит. Нейросеть на python для чайников может быть представлена, например, таким кодом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
from numpy import exp, array, random, dot class NeuralNetwork(): def __init__(self): random.seed(1) self.synaptic_weights = 2 * random.random((3, 1)) - 1 def __sigmoid(self, x): return 1 / (1 + exp(-x)) def __sigmoid_derivative(self, x): return x * (1 - x) def train(self, training_set_inputs, training_set_outputs, number_of_training_iterations): for iteration in range(number_of_training_iterations): output = self.think(training_set_inputs) error = training_set_outputs - output adjustment = dot(training_set_inputs.T, error * self.__sigmoid_derivative(output)) self.synaptic_weights += adjustment def think(self, inputs): return self.__sigmoid(dot(inputs, self.synaptic_weights)) if __name__ == "__main__": neural_network = NeuralNetwork() print ("Случайные начальные синаптические веса: ") print (neural_network.synaptic_weights) training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]]) training_set_outputs = array([[0, 1, 1, 0]]).T neural_network.train(training_set_inputs, training_set_outputs, 10000) print ("Синаптические веса нейронной сети после обучения") print (neural_network.synaptic_weights) print ("Как продолжить ряд [1, 0, 0] -> ?: ") print (neural_network.think(array([1, 0, 0]))) |
Можно ли описать свертку, которая была здесь использована?
Обучение нейросети на Python — довольно выгодная затея. Простой и понятный в использовании язык, а количество подключаемых библиотек… Ух!