По этой же книге я и хочу пройтись пошагово, а именно по практической части — написанию кода простой нейронной сети.
Эта статья для тех, кто хочет заниматься нейронными сетями и машинным обучением, но пока с трудом понимает эту удивительную область науки. Ниже будет описан самый простой скелет кода нейронной сети, чтобы многие поняли простейший принцип построения и взаимодействия всего того, из чего состоит эта нейронная сеть.
Теории по машинному обучению и нейронным сетям на хабре и так достаточно. Но если кому-то это необходимо, некоторые ссылки я оставлю в конце статьи. А сейчас, приступаем непосредственно к написанию кода, причем писать мы будем на python, будет лучше, если при написании кода вы будете использовать jupyter-notebook
Шаг 1. Инициализация сети
Сначала нам, конечно же, надо инициализировать все действующие компоненты нашей сети
#импортируем numpy — это библиотека языка Python, добавляющая поддержку больших многомерных массивов и матриц
import numpy
# импортируем scipy.special , -scipy содержит модули для оптимизации, интегрирования, специальных функций, обработки изображений и многих других задач, нам же здесь нужна наша функция активации, имя которой -Сигмоида
import scipy.special
#Вероятно, нам понадобится визуализировать наши данные
import matplotlib.pyplot
# Определяем наш класс нейронной сети
class neuralNetwork:
# Инициализация нашей нейронной сети
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate): #В параметрах мы записываем обязательный self, входные данные, данные скрытого слоя, выходные данные ,скорость обучения соответственно)
# устанавливаем количество узлов для входного , скрытого слоя, выходного слоя
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# Тут обозначены веса матрицы, wih - вес между входным и скрытым слоем , а так же who- вес между скрытым и выходным слоем
self.wih = numpy.random.rand(self.hnodes, self.inodes)
self.who = numpy.random.rand(self.onodes, self.hnodes)
# Скорость обучения -это наш гиперпараметр, то есть, параметр , который мы подбираем ручками, и в зависимости от того, как нам это удобно нам, и , конечно же, нейронной сети
self.lr = learningrate
# Наша Сигмоида- функция активации
self.activation_function = lambda x: scipy.special.expit(x)
Немного о том, как выглядит узел в нейронной сети
На картинке изображен самый, что ни на есть узел, только представлен он обычно в виде круга, а не прямоугольника. Как мы видим, внутри прямоугольника(ну или круга) — это все абстрактно, находятся 2 функции:
1-я Функция занимается тем, что получает все входные, с учетом весов, данные, и иногда даже с учетом нейрона смещения(специальный нейрон, который просто позволяет графикам подвинуться, а не смешиваться в одну некрасивую кучу, вот и все)
2-я Функция принимает в качестве параметра то самое значение, которое насуммировала первая функция, и эта вторая функция называется функцией активации. В нашем случае -Сигмоида
Продолжаем:
Часть 2. Тренировка Нейронной Сети
def train(self, inputs_list, targets_list):
# Конвертируем наш список в двумерный массив
inputs = numpy.array(inputs_list, ndmin=2).T # поступающие на вход данные input
targets = numpy.array(targets_list, ndmin=2).T #целевые значения targets
# Подсчет сигнала в скрытом слое
hidden_inputs = numpy.dot(self.wih, inputs)
# Подсчет сигналов, выходящих из скрытого слоя к выходному слою. Тут в нашем узле, куда поступали все данные в переменную hidden_inputs (1я функция), эта переменная подается как параметр в Сигмоиду - функцию активации (2я функция)
hidden_outputs = self.activation_function(hidden_inputs)
# Подсчет сигналов в конечном(выходном) слое
final_inputs = numpy.dot(self.who, hidden_outputs)
# Подсчет сигналов, подающихся в функцию активации
final_outputs = self.activation_function(final_inputs)
# Значение ошибки (Ожидание - Реальность)
output_errors = targets - final_outputs
# Ошибка скрытого слоя становится ошибкой ,которую мы получили для <b>ошибки выходного слоя</b>, но уже <b>распределенные по весам между скрытым и выходным слоями</b>(иначе говоря с учетом умножения соответствующих весов)
hidden_errors = numpy.dot(self.who.T, output_errors)
# Обновление весов между скрытым слоем и выходным (Явление того, что люди зовут ошибкой обратного распространения)
self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
# Обновление весов между скрытым слоем и входным(Та же ошибка ошибка обратного распространения в действии)
self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
pass
И вот мы приближаемся к концу
Часть 3. Опрос нейронной сети
#Создаем функцию , которая будет принимать входные данные
def query(self, inputs_list):
# Конвертируем поданный список входных данных в двумерный массив
inputs = numpy.array(inputs_list, ndmin=2).T
# Подсчет сигналов в скрытом слое
hidden_inputs = numpy.dot(self.wih, inputs)
# Подсчет сигналов, поданных в функцию активации
hidden_outputs = self.activation_function(hidden_inputs)
#Подсчет сигналов в конечном выходном слое
final_inputs = numpy.dot(self.who, hidden_outputs)
#Подсчет сигналов в конечном выходном слое, переданных в функцию активации
final_outputs = self.activation_function(final_inputs)
return final_outputs
Доводим дело до конца
#Подаем конкретное значение для входного , скрытого ,выходного слоев соответственно(указываем количество <b>нод</b>- узлов в ряду входного, скрытого, выходного соответственно
input_nodes = 3
hidden_nodes = 3
output_nodes = 3
# Возьмем коэффициент обучения - скорость обучения равной, например... 0.3!
learning_rate = 0.3
# Создаем нейронную сеть(n это объект класса neuralNetwork , при его создании запустится конструктор __init__ , и дальше все будет включаться по цепочке
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes, learning_rate)
P.S
Выше была представлена простейшая модель нейронной сети, способной на вычисления. Но какого-то конкретного применения показано не было.
При желании, можно продолжить этот код, добавив в него возможность распознавания рукописного текста MNIST, для этого вы можете полностью разобраться(или просто позабавиться), имея этот jupyter-файл , моя же задача была продемонстировать код и по возможности разжевать для что и для чего. Ссылки на теорию, как и обещал, прикреплю в конце, ну а так же вы найдете Github и книгу Тарика Рашида, их я тоже оставлю
1.Github
2.Книга «Создай свою нейронную сеть»
3.Теория по машинному обучению 1
4.Теория по машинному обучению 2
5.Теория по машинному обучению 3
6.Теория по машинному обучению 4
Также можно ознакомиться с этим курсом.
Комментарии (19)
Vinchi
13.02.2019 17:02на sklearn подобная задача делается в несколько строчек кода да еще и быстрее.
scikit-learn.org/stable/modules/neural_networks_supervised.html0xUL Автор
13.02.2019 17:11Моя задача была пошагово объяснить устройство простой нейронной сети начинающим. Это даже указано в заголовке статьи
Sychuan
13.02.2019 21:37+1Я как-то не очень понимаю за что заминусовали автора. Вроде как из библиотек он взял нампай для матричного умножения и скипай для какой-то функции. Ну, конечно, можно было еще и матрицы перемножать самостоятельно, только зачем? Это вроде и так должно быть очевидно
tuxi
13.02.2019 18:46Листал Хабр, бац! вижу «Знакомство с простейшей нейронной сетью и ее пошаговая реализация» «Машинное обучение», «Программирование»
Ура! Наконец то появилась статья не про то как подключать библиотеки на питоне, а про внутреннюю реализацию таких сетей!
У меня же висит технический долг перед самим собой, создать сеть распознающую определенную категорию геометрических объектов! Так чего же ждем? Вперед! К новым вершинам знаний!
Потираю руки, наливаю кофе, откидываюсь в кресле, тынц!
…
1. берем питон
2. делаем импорт либ
3. вызываем из либы сеть
4. профит!
<тут картинка с недопитым кофем и пустым вращающимся креслом >
Чем дальше, тем сильнее ощущение, что тут питонистам индульгенция выдана по теме «нейронные сети и машинное обучение: расскажите всем какие замечательные у вас есть библиотеки» :)Alyoshka1976
13.02.2019 20:08Если технический английский — не слишком большая проблема, то вот — www.analog.com/media/en/technical-documentation/dsp-book/dsp_book_Ch26.pdf — от ребят из Analog Devices, весьма подробно, формулы только по делу, картинки опять же, хотя и черно-белые. И без лишних комплексов — примеры приведены на Бейсике ;-)
Sychuan
13.02.2019 21:383. вызываем из либы сеть
Покажите пожалуйста строчку кода, где это происходит. Я так просмотрел бегло. Библиотек по машинному обучению и нейронным сетям вроде как у автора нетtuxi
13.02.2019 22:09+1«Функция активации, имя которой -Сигмоида» это разве не оно?
На самом деле, автору надо было всего лишь указать 3 хаба в списке хабов,
— «Питон»
— «Машинное обучение»
— «Программирование»
Я думаю, что в этом случае, многие просто прошли бы мимо и не выразили бы свое возмущение. Плюс, зачем делать сознательно чрезмерно завлекательный первый абзац?
…
По этой же книге я и хочу пройтись пошагово, а именно по практической части — написанию кода простой нейронной сети.
…
Эта статья для тех, кто хочет заниматься нейронными сетями и машинным обучением, но пока с трудом понимает эту удивительную область науки. Ниже будет описан самый простой скелет кода нейронной сети, чтобы многие поняли простейший принцип построения и взаимодействия всего того, из чего состоит эта нейронная сеть
Sychuan
13.02.2019 22:33Функция активации, имя которой -Сигмоида» это разве не оно
Ну это просто функция 1/(1+e^-x)
Ее можно было и в ручную написать. И было бы у автора не
import scipy.special self.activation_function = lambda x: scipy.special.expit(x)
а что-нибудь типа:
self.activation_function = lambda x: 1/(1+e**-x)
На самом деле, автору надо было всего лишь указать 3 хаба в списке хабов,
— «Питон»
— «Машинное обучение»
— «Программирование»
Ну да, я согласен, наверное стоило бы подчеркнуть, что речь пойдет про питон. Люди, которые не знают питоновских библиотек или тем более смутно понимают питоновский синтаксис останутся разочарованными.tuxi
13.02.2019 22:53+1И объяснить хотя бы бегло в 1 абзаце, что такое сигмоида и почему выбрана она. В сети куча картинок на тему «сигмоида» vs «линейная» vs «ступенчатая» функции активации нейрона. Вот первая попавшаяся ссылка например.
Я не сомневаюсь, что этой статьей автор делает хорошее дело, но все же имеет смысл дать возможность людям понять, что такое «сигмоида» и почему она лучше для задач классификации/распознавания.
webviktor
13.02.2019 20:31+1Зашел сюда, потому как в нейронных сетях полный валянок, но очень хочу разобраться.
Пожалуйста, кто-нибудь, дайте ссылку/напишите статью/ткните пальцем как сделать с все с нуля?
И существует ли вообще вариант для технаря (аля поставить галочки в какой-то софтине/сервисе/онлайн, чтоб создать и обучить чему-то сеть)?Sychuan
13.02.2019 21:41Самая простая статья на понимание нейросетей была у этого товарища на мой взгляд neuralnetworksanddeeplearning.com
И существует ли вообще вариант для технаря (аля поставить галочки в какой-то софтине/сервисе/онлайн, чтоб создать и обучить чему-то сеть)?
Библиотеки scikit-learn.org/stable/index.html или Keras в принципе позволяют за несколько строчек все сделать. Вариант отдельной программы не знаю
raamid
14.02.2019 16:15Похоже в соседней теме то что вам нужно:
Пример простой нейросети на C++
Там конечно не так няшно и аккуратно как здесь, зато там есть торты и можно ими кидаться :)
ZNY
14.02.2019 16:16есть стандарты типа
import numpy as np
а то новички понатырят кода с разных источников и будут сидеть дуплить почему Ваш кусок не работает с другими.
raamid
15.02.2019 03:41Попробовал сделать пример по вашей статье, столкнулся со следующими проблемами:
1. В строках (в первом блоке)
self.wih = numpy.random.rand(self.hnodes, self.inodes))
self.who = numpy.random.rand(self.onodes, self.hnodes))
лишняя закрывающая скобка
2. При копировании кусков программы из разных мест статьи иногда ломаются отступы, а для Python'а это критично. Возможно лучше было бы весь код поместить в один блок.
3. Все-таки новичку не совсем понятно, что делать дальше с полученной в самом конце перменной n. Правильно ли я понимаю, что теперь нужно будет загрузить где-то данные для тренировки и затем вызвать:
n.train(mydata) // тренировать нейросеть
n.query(myquery) // посмотреть как она работает
DartAlex
Объясню в чём суть, для тех кто не разбирается в программировании. Вот смотрите, есть библиотека которая делает нейронную сеть. У этой библиотеки есть следующие функции: принять_начальные_данные, запустить_нейронную_сеть, показать_результаты. И что мы делаем? Как думаете?
Библиотека.принять_начальные_данные
Библиотека.запустить_нейронную_сеть
Библиотека.показать_результаты