Это седьмой день моего участия в августовском испытании обновлений, подробности о мероприятии:Испытание августовского обновления.
Оригинальный адрес:Simplest artificial neural network
Оригинальный автор: Гиви Одикадзе (уполномоченный)
Переводчик и корректор: HelloGitHub — Bear & Braised Egg
предисловие
Я не разбираюсь в машинном обучении, но в прошлом месяце нашел его на GitHub.Минималистичный учебник по нейронной сети начального уровня.. Он лаконичен и прост для понимания и может объяснить правду одной строкой формулы, не написав чепухи, я зацепился после прочтения.
Такую хорошую вещь нужно увидеть большему количеству людей, но исходный текст на английском языке и не может быть передан напрямую, поэтому вам нужно связаться с автором, чтобы получить разрешение на перевод, а затем медвежонок переводит этот проект, и, наконец, вы видите эту статью статьи. Нелегко провести месяц в процессе. Если вы думаете, что это хорошо после прочтения, пожалуйста, поставьте лайк и поделитесь этим с большим количеством людей.
Содержание разделено на две части:
- первая часть:Простейшая искусственная нейронная сеть
- Вторая часть:Самый простой алгоритм обратного распространения
Искусственная нейронная сеть — это основа искусственного интеллекта, и только закрепив ее, мы сможем играть в магию ИИ!
温馨提示
: Формул хоть и много, но выглядят они как блеф, на самом деле понять их несложно, если внимательно их прочитать. Начинается следующий текст!
Простейшая искусственная нейронная сеть
Простейшая искусственная нейронная сеть объяснена и продемонстрирована с помощью теории и кода.
Образец кода:GitHub.com/okadina/love-…
теория
смоделированные нейроны
Вдохновленные тем, как работает человеческий мозг, искусственные нейронные сети имеют взаимосвязанные аналоговые нейроны, которые хранят шаблоны и взаимодействуют друг с другом. В своей простейшей форме аналоговый нейрон имеет одно или несколько входных значений.и выходное значение, каждый, из которыхимеет вес.
Проще говоря, выходное значение представляет собой сумму входного значения, умноженного на вес.
простой пример
Роль сети заключается в передаче нескольких параметровСмоделируйте сложную функцию, чтобы при заданном ряде входных значенийполучить конкретное выходное значение, когда, и эти параметрыОбычно нам трудно сформулировать себя.
Предположим, у нас теперь есть сеть с двумя входными значениями,, они соответствуют двум значениям весаи.
Теперь нам нужно настроить веса так, чтобы они давали наши предустановленные выходные значения.
Во время инициализации, поскольку мы не знаем оптимального значения, веса часто назначаются случайным образом, здесь мы для простоты инициализируем их равными 1.
В этом случае мы получаем
разница
Если выходное значениеЕсли оно не соответствует ожидаемому выходному значению, возникает ошибка.
Например, если мы хотим, чтобы целевое значение было, тогда разница здесь
Обычно мы используем дисперсию (то есть функцию стоимости) для измерения ошибки:
Если имеется несколько наборов входных и выходных значений, то ошибка представляет собой среднее значение отклонений каждого набора.
Мы используем дисперсию для измерения разницы между результирующим выходным значением и желаемым целевым значением. Возведением в квадрат можно устранить влияние отрицательных отклонений, и отклонения с большими отклонениями (независимо от положительных и отрицательных) могут быть более заметными.
Чтобы исправить ошибку, нам нужно настроить значения веса так, чтобы результат был близок к нашему целевому значению. В нашем примереСнижение с 1,0 до 0,5 приведет к цели, потому что
Однако нейронные сети часто включают множество различных входных и выходных значений, и в этом случае нам нужен алгоритм обучения, чтобы автоматизировать этот шаг.
градиентный спуск
Теперь нужно использовать ошибку, чтобы помочь нам найти значение веса, которое следует скорректировать, чтобы минимизировать ошибку. Но перед этим давайте разберемся с концепцией градиента.
Что такое градиент?
Градиент — это, по сути, вектор, указывающий на максимальный наклон функции. Мы используемдля представления градиента, который является просто векторной формой частной производной функциональной переменной.
Для функции двух переменных она принимает вид:
Давайте смоделируем простой пример с некоторыми числами. Предположим, у нас есть функция, которая, то градиент будет
Что такое градиентный спуск?
Спуск можно просто понимать как нахождение направления максимального наклона нашей функции через градиент, а затем путем многократных попыток небольшими шагами в обратном направлении найти вес, минимизирующий глобальное (а иногда и локальное) значение ошибки функция.
Мы используемскорость обученияпостоянная для представления этого небольшого шага в противоположном направлении, в формуле, которую мы используемохарактеризовать.
еслиЕсли значение слишком велико, можно напрямую пропустить минимум, но если значение слишком мало, то нашей сети потребуется больше времени для обучения, и она также может попасть в неглубокий локальный минимум.
Для двух значений веса в нашем примереи, нам нужно найти градиент этих двух весовых значений относительно функции ошибок
Помните нашу формулу вышеи? заи, мы можем взять его и вычислить его градиент отдельно по цепному правилу вывода в исчислении
Для краткости далее будем использоватьэтот термин для обозначения.
Как только у нас будет градиент, возьмите предложенную скорость обучения.Внесите, вы можете обновить значение веса следующими способами:
Затем этот процесс повторяется до тех пор, пока значение ошибки не станет минимальным и не приблизится к нулю.
пример кода
В прилагаемом примере используется градиентный спуск для обучения нейронной сети с двумя входами и одним выходом в следующем наборе данных:
После обучения сеть будет выводить ~0 при вводе двух единиц и ~1 при вводе 1 и 0.
Как это работает?
Go
PS D:\github\ai-simplest-network-master\src> go build -o bin/test.exe
PS D:\github\ai-simplest-network-master\bin> ./test.exe
err: 1.7930306267024234
err: 1.1763080417089242
……
err: 0.00011642621631266815
err: 0.00010770190838306002
err: 9.963134967988221e-05
Finished after 111 iterations
Results ----------------------
[1 1] => [0.007421243532258703]
[1 0] => [0.9879921757260246]
Docker
docker build -t simplest-network .
docker run --rm simplest-network
Во-вторых, самый простой алгоритм обратного распространения
Обратное распространение (сокращенно BP), сокращение от «обратное распространение ошибки», является распространенным методом, используемым в сочетании с методами оптимизации, такими как градиентный спуск, для обучения искусственных нейронных сетей.
Методы обратного распространения можно использовать для обучения нейронных сетей хотя бы с одним скрытым слоем. Начнем с теории и объединим код, чтобы выигратьАлгоритм обратного распространения.
Образец кода:GitHub.com/okadina/love-…
теория
Введение в персептрон
Персептрон — это процессор, принимающий входные данные., используя функцию активациипреобразовать его и вывести результат.
В нейронной сети входное значение представляет собой взвешенную сумму выходных значений узлов в предыдущем слое плюс ошибка предыдущего слоя:
Если мы рассматриваем ошибку как еще один узел в слое с константой -1, то мы можем упростить эту формулу до
функция активации
Зачем нужны функции активации? Если нет, то вывод каждого из наших узлов будет линейным, так что вся нейронная сеть будет выводом линейной операции на основе входного значения. Поскольку комбинация линейных функций по-прежнему является линейной, необходимо ввести нелинейные функции, чтобы нейронные сети отличались от моделей линейной регрессии.
против, типичная функция активации имеет следующий вид:
Сигмовидная функция:
Функция линейного выпрямления:
тан функция:
обратное распространение
Алгоритм обратного распространения можно использовать для обучения искусственных нейронных сетей, особенно для сетей с более чем двумя слоями.
Принцип заключается в использовании прямого прохода для вычисления выходного значения сети и ошибки, а затем обратном обновлении значения веса входного слоя в соответствии с градиентом ошибки.
срок
- — входные значения узлов слоя I, J, K соответственно.
- являются выходными значениями узлов в слоях I, J и K соответственно.
- является ожидаемым выходным значением выходного узла K.
- - значения веса слоев от I до J и слоев от J до K соответственно.
- Представляет текущий набор ассоциаций в наборе T ассоциаций.
В приведенном ниже примере мы применим следующие функции активации к различным узлам слоя:
- входной слой -> функция идентификации
- Скрытый слой -> Сигмовидная функция
- выходной слой -> функция идентификации
The forward pass
В прямом проходе мы принимаем входные данные на входном слое и получаем результат на выходном слое.
Вход в каждый узел скрытого слоя представляет собой взвешенную сумму входных значений входного слоя:
Поскольку функция активации скрытого слоя является сигмовидной, вывод будет:
Точно так же входное значение выходного слоя равно
Поскольку мы назначаем функцию идентификации в качестве функции активации, выход этого слоя будет равен входному значению.
Как только входное значение распространяется по сети, мы можем вычислить значение ошибки. Если есть несколько наборов ассоциаций, помните дисперсию, которую мы узнали в первой части? Здесь мы можем использовать среднюю дисперсию для вычисления ошибки.
The backward pass
Теперь, когда у нас есть ошибка, мы можем использовать ее для исправления весов сети путем обратного распространения.
Из первой части обучения мы знаем, что корректировка веса может быть основана на частной производной ошибки по весу, умноженной на скорость обучения, которая имеет вид
Градиент ошибки вычисляем по цепному правилу следующим образом:
Поэтому коррекция веса
Для нескольких ассоциаций корректировка веса будет суммой значений корректировки веса для каждой ассоциации
Аналогично, для корректировки веса между скрытыми слоями, продолжая пример выше, корректировка веса между входным слоем и первым скрытым слоем
Затем корректировка веса на основе всех ассоциаций представляет собой сумму значений корректировки, рассчитанных для каждой ассоциации
рассчитать
Мы здесьДальнейшее исследование может быть сделано. Выше мы видим.
за первую половину, мы можем иметь
на вторую половину, поскольку мы используем сигмовидную функцию в этом слое, мы знаем, что производная форма сигмоидальной функции, следовательно, существует
В сумме можно получитьФормула расчета следующая
Краткое описание алгоритма
Во-первых, присвойте небольшое случайное значение значению веса сети.
Повторяйте следующие шаги, пока ошибка не станет равной 0:
- Для каждой ассоциации пройдите через нейронную сеть, чтобы получить выходное значение.
- Вычислить ошибку для каждого выходного узла ()
- Стекирование вычисляет градиент каждого выходного веса ()
- Рассчитать значение каждого узла в скрытом слое()
- Stacking вычисляет градиент веса каждого скрытого слоя ()
- Обновить все значения веса, сбросить градиент стека ()
Графическое обратное распространение
В этом примере мы моделируем каждый шаг в нейронной сети с реальными данными. Входное значение — [1,0, 1,0], а ожидаемое выходное значение — [0,5]. Для простоты мы установили вес инициализации равным 0,5 (хотя на практике часто используются случайные значения). Для входного, скрытого и выходного слоев мы используем функцию идентичности, сигмовидную функцию и функцию идентичности в качестве функций активации соответственно, а скорость обученияустановлен на 0,01.
Forward pass
В начале операции мы устанавливаем входное значение узла входного слоя как.
Поскольку мы используем функцию идентификации в качестве функции активации для входного слоя, мы имеем.
Затем мы передаем сеть вперед к слоям J по взвешенной сумме предыдущих слоев следующим образом
Затем мы вводим значение узла слоя J в сигмовидную функцию (будетПодставьте, получите 0,731) для активации.
Наконец, мы передаем этот результат в окончательный выходной слой.
Поскольку функция активации нашего выходного слоя также является функцией тождества, поэтому
Backward pass
Первым шагом в обратном распространении является вычисление выходного узла.,
использоватьВычислите весовой градиент между узлами в слоях J и K:
Затем таким же образом рассчитайте значение каждого скрытого слоя.Значения (в данном примере только один скрытый слой):
Градиенты, рассчитанные для весов узлов на слоях I и J, следующие:
Последний шаг — обновить все значения веса с помощью рассчитанных градиентов. Обратите внимание, что если у нас есть более одной ассоциации, мы можем накапливать градиенты для каждого набора ассоциаций, а затем обновлять веса.
Видно, что это значение веса меняется очень мало, но если мы снова запустим прямой проход с этим весом, то в целом получим меньшую ошибку, чем раньше. Давайте посмотрим сейчас...
В первый раз мы получили, рассчитанный с использованием нового значения веса.
таким образом,,и.
Видно, что погрешность уменьшилась! Хотя значение уменьшения невелико, оно вполне репрезентативно для реальной сцены. При многократном срабатывании алгоритма в итоге погрешность может быть сведена к 0, и обучение нейронной сети завершено.
пример кода
В этом примере сеть 2X2X1 обучена давать эффект оператора XOR.
Здесь f — сигмовидная функция активации скрытого слоя.
Обратите внимание, что оператор XOR не может быть смоделирован линейной сетью в первой части, потому что распределение набора данных нелинейно. То есть вы не можете правильно разделить четыре входных значения XOR на два класса прямой линией. Если мы заменим сигмовидную функцию функцией тождества, эта сеть также станет невозможной.
После стольких разговоров пришла твоя очередь сделать это самому! Попробуйте разные функции активации, скорости обучения и топологии сети и посмотрите, как это работает?
Наконец
Поздравляем с прочтением этой статьи! Вы научились этому?
обрати внимание наHelloGitHubОфициальный аккаунт получил обновление в кратчайшие сроки.
Есть больше представлений о проектах с открытым исходным кодом и ценных проектов, которые ждут вас.