С математикой у меня всегда было гораздо хуже, чем с программированием. Получив (с трудом) высшее математическое образование, я счастливо вздохнул и забыл о нём (хотя кошмары про экзамен снились ещё долго).
Тема нейросеток для меня долгое время оставалась "запретной". Банально потому что там сплошная математика. Но потом я выяснил, что меня пугает не математика, а формулы. Как только я вижу что-то сложнее a + b = c, у меня просто отключается мозг.
И тогда я стал искать объяснения про нейросети понятным языком.
В качестве альтернативы рекомендую почитать статьи про нейросети на канале IT.Как это работает? – как по мне, там написано наиболее понятно, но без программирования. А у нас будет и программирование тоже.
Ну ладно, поехали. Начнём, как водится, издалека.
Нейрон
Клетка, основная функция которой – возбуждаться. Возбуждение это повышение уровня какого-то химического вещества, так что нейрон легко можно представить в виде одного числа от 0 до 1, где 0 это совсем не возбуждённый, а 1 – предельно возбуждённый. Никакой другой функции и никакого сложного поведения у нейронов нет.
Нейронная связь
Физическая связь между двумя нейронами для передачи сигнала от одного к другому. Получив сигнал, нейрон возбуждается.
В программе нам не нужно моделировать никакую физическую связь. Мы можем просто добавить значение одного нейрона к значению другого нейрона.
Нейронная сеть
Множество нейронов и множество связей между ними. Каждый нейрон может иметь по несколько связей с другими нейронами.
Перцептрон
Название "перцептрон" происходит от слова "перцепция", то есть "восприятие". Это один из самых старых концептов нейронной сети, внедрённый ещё в 1950-х годах.
Перцептроном считается любая группа сигнальных нейронов, присоединённых к нейрону-сумматору. Сумматор получает сигналы от других нейронов и генерирует возбуждение, которое является предсказанием какого-то конкретного факта.
Давайте посмотрим на примере.
У нас в голове есть нейрон, который, когда возбуждается, создаёт в нашем сознании понятие "яблоко".
Как устроено наше сознание – огромная загадка, и ответ мы вряд ли получим. Но точно известно, что когда человек видит яблоко, и когда всего лишь думает о яблоке, возбуждается один и тот же нейрон, а точнее группа нейронов, но это неважно.
Наше сознание связывает возбуждение именно этого нейрона с понятием "яблоко".
Но почему возбуждается именно этот нейрон и именно на яблоко?
Друзья
У нашего нейрона есть друзья-информаторы – нейроны, от которых он получает входящие сигналы. Предположим, их пятеро. Один возбуждается, когда в понятии присутствует что-то круглое, другой – когда есть красный цвет, третий – когда есть сладкий вкус.
Четвёртый и пятый возбуждаются в связи с наличием чего-то железного или острого. Ну и так далее. Их может быть много, и все они возбуждаются по разным причинам.
Все они соединены с нашим нейроном-сумматором, и сигналы от них складываются в общую сумму.
Например, если пришли сигналы от "круглого", "красного" и "сладкого" – они сложились, и наш нейрон возбудился – ага, это же яблоко!
Но с другой стороны, если пришли сигналы от "железного", "красного" и "острого" – по сумме они составляют такую же величину, и наш нейрон обязан опять возбудиться и сообщить, что это яблоко.
Обучение
Поначалу так и происходит. Нейрон может ошибаться, называя яблоком что угодно. Но его ошибки вызывают реакцию, которая запускает какие-то химические процессы, и определённые входы нейрона понижаются в приоритете.
В следующий раз, когда "железное" и "острое" посылают сигналы нейрону, он на них реагирует слабее или вообще не реагирует. Т.е. он как бы говорит – вы мне хоть и друзья, но мне интересны только яблоки. Вы вводите меня в заблуждение. Поэтому слушать вас я не буду.
Иначе говоря, нейрон в результате обучения наращивает нужные связи и обрывает ненужные.
Когда мы долго что-то изучаем, а потом вдруг начинаем всё понимать – это значит, что правильные нейронные связи наконец-то выросли.
Веса
Не все полезные связи одинаково полезны. Например, красный цвет не определяет яблоко на 100% – яблоко может быть и жёлтое, и зелёное. Круглая форма тоже необязательна. Яблоко может быть кубической формы.
Поэтому яблочный нейрон связан и с тем нейроном, который отвечает за прямоугольники, но не доверяет ему полностью. Сигнал от "прямоугольного" нейрона в общую сумму попадает, но вклад вносит небольшой, потому что у него снижен вес. С другой стороны, у "круглого" и "сладкого" веса гораздо больше, и значит, на результат они влияют сильней.
Мы, собственно, пришли к необходимому набору данных для создания структуры нейросети. Это нейроны и веса.
Мы не храним связи, потому что считается, что один выходной нейрон связан со всеми входными нейронами. То есть нет необходимости указывать, где есть связь, а где нет – она просто есть везде между входом и выходом. А вот вес связи как раз указывает, будем мы её активно использовать или нет. Если вес равен 0, это равносильно отсутствию связи.
Слои
Выходные нейроны образуют слой. Сначала мы рассматривали только один выходной нейрон, поэтому добавим для наглядности ещё один. Пусть он распознаёт персики.
Возникает проблема – как отличить персик от яблока, ведь он тоже красный, круглый и сладкий?
Добавим новый входной сигнал – "бархатистость".
"Бархатистый" сигнал подключён и к "яблочному" нейрону, и к "персиковому". Через некоторое время обучения "яблочный" нейрон снизит вес этой связи не просто до нуля, а сделает его отрицательным. Тогда при наличии такого сигнала он будет сильно снижать общую сумму для яблока. В то время как "персиковый" нейрон, наоборот, сделает вес приоритетным:
Мы получили однослойный перцептрон. Чтобы не было путаницы, обратим внимание:
На схеме реально изображено два слоя: входные нейроны и выходные нейроны. Но входные в данном случае не считаются слоем, так как не принимают решений (у них нет входов и весов), а только дают сигналы. Считаются только выходные слои.
Теперь обратим внимание, что схема слишком схематичная. Входные нейроны обозначают понятия "круглый", "красный", "сладкий", но эти понятия – не примитивные. Чтобы их получить, необходимы дополнительные входные сигналы.
Если расширить схему и входным нейронам дать свои входные сигналы и веса, то каждый из них станет сумматором и сможет выдавать выходные сигналы и главное – обучаться.
В этом случае мы имеем уже двухслойный перцептрон, потому что в нём есть два выходных слоя. При этом выход одного слоя является входом для второго.
Как нетрудно догадаться, достраивать слои можно сколько угодно, причём и спереди, и сзади. Выходы "яблоко" и "персик" могут стать входами для следующего слоя.
Сколько конкретно нужно слоёв, и какие понятия они должны кодировать – задача настройки нейронной сети. То есть по сути нейронная сеть это вообще ничего сложного. Но вот правильные параметры для неё – как раз основная трудность.
В следующих выпусках начнём писать код и разбираться дальше.