- Ваши вычисления не полностью верны.Например,
reduce
вызывается на l1_err
и l2_err
, где его следует вызывать на l1
и l2
. - Вы выполняете стохастический градиентный спуск.В этом случае при таких нескольких параметрах он сильно колеблется.В этом случае используйте полный градиентный спуск.
- Единицы смещения отсутствуют.Хотя вы все еще можете учиться без предвзятости, технически.
Я попытался переписать ваш код с минимальными изменениями.Я прокомментировал ваши строки, чтобы показать изменения.
#!/usr/bin/python3
import matplotlib.pyplot as plt
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def reduce(x):
return x*(1-x)
l0=np.array ([np.array([1,1,0,0]),
np.array([1,0,1,0]),
np.array([1,1,1,0]),
np.array([0,1,0,1]),
np.array([0,0,1,0]),
]);
output=np.array ([[0],[1],[1],[0],[1]]);
syn0=np.random.random((4,4))
syn1=np.random.random((4,1))
final_err = list ();
gamma = 0.05
maxiter = 100000
for justanumber in range(maxiter):
syn0_del = np.zeros_like (syn0);
syn1_del = np.zeros_like (syn1);
l2_err_sum = 0;
for i in range(len(l0)):
this_data = l0[i,np.newaxis];
l1=sigmoid(np.matmul(this_data,syn0))[:]
l2=sigmoid(np.matmul(l1,syn1))[:]
l2_err=(output[i,:]-l2[:])
#l2_delta=reduce(l2_err)
l2_delta=np.dot (reduce(l2), l2_err)
l1_err=np.dot (syn1, l2_delta)
#l1_delta=reduce(l1_err)
l1_delta=np.dot(reduce(l1), l1_err)
# Accumulate gradient for this point for layer 1
syn1_del += np.matmul(l2_delta, l1).T;
#syn1=syn1.T
#syn1+=l1.T*l2_delta
#syn1=syn1.T
# Accumulate gradient for this point for layer 0
syn0_del += np.matmul(l1_delta, this_data).T;
#syn0=syn0.T
#syn0-=l0[i,:].T*l1_delta
#syn0=syn0.T
# The error for this datpoint. Mean sum of squares
l2_err_sum += np.mean (l2_err ** 2);
l2_err_sum /= l0.shape[0]; # Mean sum of squares
syn0 += gamma * syn0_del;
syn1 += gamma * syn1_del;
print ("iter: ", justanumber, "error: ", l2_err_sum);
final_err.append (l2_err_sum);
# Predicting
l1=sigmoid(np.matmul(l0,syn0))[:]# 1 x d * d x 4 = 1 x 4;
l2=sigmoid(np.matmul(l1,syn1))[:] # 1 x 4 * 4 x 1 = 1 x 1
print ("Predicted: \n", l2)
print ("Actual: \n", output)
plt.plot (np.array (final_err));
plt.show ();
Вывод, который я получаю:
Predicted:
[[0.05214011]
[0.97596354]
[0.97499515]
[0.03771324]
[0.97624119]]
Actual:
[[0]
[1]
[1]
[0]
[1]]
Поэтому сеть смогла предсказать все примеры обучения игрушкам.(Обратите внимание, что в реальных данных вы не хотели бы соответствовать данным в лучшем виде, поскольку это приводит к переобучению).Обратите внимание, что вы можете получить немного другой результат, так как инициализация веса отличается.Кроме того, попробуйте инициализировать вес между [-0.01, +0.01]
, как правило, когда вы не работаете над конкретной проблемой и вам конкретно известна инициализация.
Вот график конвергенции. ![enter image description here](https://i.stack.imgur.com/lsAOE.png)
Обратите внимание, что вам не нужно фактически выполнять итерации по каждому примеру, вместо этого вы можете выполнять матричное умножение сразу, что намного быстрее.Кроме того, приведенный выше код не имеет единицы смещения.При повторной реализации кода убедитесь, что у вас есть единицы смещения.
Я бы порекомендовал вам пройти через нейронные сети Рауля Рохаса , систематическое введение , главы 4, 6 и 7.Глава 7 расскажет вам, как реализовать более глубокие сети простым способом.