Сколько строк кода может реализовать нейронную сеть и понять алгоритм обратного распространения.
import numpy as np
X = np.array([[0,0,1], [0,1,1], [1,0,1], [1,1,1]])
y = np.array([[0, 0, 1, 1]]).T
syn = 2 * np.random.random((3, 1)) - 1
for i in range(10000):
l = 1 / (1 + np.exp(-np.dot(X, syn)))
l_delta = (y - l) * (l * (1 - l))
syn += np.dot(X.T, l_delta)
Как и выше, обучение выполняется на выходе заданного ввода, и, наконец, вывод прогнозируется в соответствии с заданным вводом.
x1 | x2 | x3 | y |
---|---|---|---|
0 | 0 | 1 | 0 |
1 | 1 | 1 | 1 |
1 | 0 | 1 | 1 |
0 | 1 | 1 | 0 |
Данные для тренировки такие же, как и выше.
Код объясняется ниже:
X: указывает выходные данные
y: представляет выходные данные
syn: 3 * 1 размерные инициализированные случайные веса
Структура сети следующая:
Процесс примерно такой:
Входные данныеx
Умножить на соответствующий весw
, полученное значениеz
Прогнозируемое значение получается путем преобразования нелинейной функции (сигмоида)l
.
рассчитатьl
целевое значениеy
ошибка. Цель обучения — минимизировать ошибку, чтобы ее можно было скорректировать, изменив входные данные.x
и весаw
. так какx
Для входных данных он не может быть скорректирован. Итак, цель такова: постоянно корректируя весаw
, чтобы ошибка между полученным предсказанным значением и целевым значением была наименьшей (или меньше определенного порога), и обучение было завершено. можно использовать весыw
Делайте прогнозы на новые входные данные.
Итеративный процесс — это последние 3 строки кода с небольшим пояснением:
Строка 6: вводx
умножить на весw
,проходить черезsigmoid
изменить функцию, чтобы получитьl
.
Строка 7: процесс минимизации ошибок — это постоянная корректировка.w
процесс. По цепному правилу найтиloss
оw
Производная от , чтобы найти самый быстрый способ уменьшить функцию потерь. Как показано на картинке выше:
loss
оw
Производная от =loss
оl
Производная от *l
оz
Производная от *z
оw
Производная от , которая является содержанием двух последних строк.
Ниже я немного расширю код для лучшего понимания:
import numpy as np
def sigmoid(z):
return 1 / (1 + np.exp(-z))
def sigmoid_derivative(x):
return x * (1 - x)
X = np.array([[0,0,1], [0,1,1], [1,0,1], [1,1,1]])
y = np.array([[0, 0, 1, 1]]).T
syn = 2 * np.random.random((3, 1)) - 1
for i in range(10000):
l = sigmoid(np.dot(X, syn))
loss = (y - l) ** 2
if i % 1000 == 0:
print("Loss: ", np.sum(loss))
loss_derivative = 2 * (y - l)
l_delta = loss_derivative * sigmoid_derivative(l)
syn += np.dot(X.T, l_delta)
print("syn:\n" ,syn)
print("l:\n", l)
Вот результат печати:
Loss: 0.8505452956411994
Loss: 0.0013461667714825178
Loss: 0.0006585827213748538
Loss: 0.0004348364571153864
Loss: 0.00032425670465056856
Loss: 0.0002583897080090336
Loss: 0.00021470251268552865
Loss: 0.00018361751185635365
Loss: 0.000160374621766103
Loss: 0.00014234163846899023
syn:
[[10.38061079]
[-0.20679655]
[-4.98439294]]
l:
[[0.00679775]
[0.00553486]
[0.99548654]
[0.9944554 ]]
Видно, что по мере увеличения числа итераций потери становятся все меньше и меньше, указывая на то, что расчетное значение ближе к истинному значению.
Синхронизированные окончательные распечатанные веса и прогнозируемые значенияl
также доказал это.
Позже мы планируем добавить скрытые слои, чтобы улучшить способность нейронной сети к обобщению.
Использованная литература:
A Neural Network in 11 lines of Python (Part 1)
Алгоритм обратного распространения для глубокого обучения вверх/вниз, часть 3, версия 0.9 бета