Нейронная сеть обратного распространения плохо учится
Я борюсь с моей реализацией обучения обратному распространению. Единственное, что сети удается хорошо изучить - это ИЛИ с сетью 2-2-1. Он не может изучить все другие логические функции, оставаясь с большой ошибкой L2. Иногда (как в моем линейном примере) ошибка уменьшается, а затем начинает увеличиваться. Я пытался настроить скорость обучения, но она все еще не работала.
Я наименее уверен в своем уклоне. Для каждого слоя я создаю вектор с числом записей, равным количеству нейронов в следующем слое, и добавляю сумму всех этих чисел (эквивалентно взятию скалярного произведения с вектором всех единиц), который заменяет строка смещения в матрице весов. Затем во время обратного распространения я обновляю его только дельтами следующего слоя. Это правильный метод?
Однако я не думаю, что проблема (только) со смещением, потому что сеть также не изучает линейные функции, такие как (x+y+z)/3.
Вот мой учебный код:
def train(self, Xtrain, ytrain, alpha, niter):
for t in range(niter):
#pick one datapoint
i = np.random.randint(0, len(Xtrain))
X = Xtrain[i]
y = ytrain[i]
#compute ypred saving outputs for all hidden layers
results = [X] #"outputs" in the input layer, for nicer indexing
a = X
for i in range(self.nlayers-1):
a = self.g(np.dot(self.thetas[i], a) + np.sum(self.biases[i]))
results.append(a)
ypred = a[-1]
deltas = [None for _ in range(self.nlayers)]
#we compute deltas, which are errors propagated backwards
#deltas[0] should stay None, because we don't compute errors for inputs
deltas[self.nlayers-1] = (y-ypred) * self.dg(ypred)
#deltas[self.nlayers-1] = (y-ypred)
for i in range(self.nlayers-2, 0, -1):
deltas[i] = np.dot(self.thetas[i].T, deltas[i+1]) \
* self.dg(results[i])
#now we compute changes in weights, theta is exterior product
#of outputs from source layer and deltas of target layer
delta_thetas = []
for i in range(self.nlayers-1):
delta_thetas.append(np.dot(deltas[i+1], results[i].T))
#update weights by deltas * learning rate
self.thetas[i] += alpha * delta_thetas[i]
self.biases[i] += alpha * deltas[i+1]
И полный код здесь: http://pastebin.com/jbGbF0Dn
У кого-нибудь есть идеи как это исправить?
РЕДАКТИРОВАТЬ: я включаю несколько примеров журналов обучения, чтобы проиллюстрировать, что не так. Тестовый код:
def testLinear():
net = NN(3,[3,5,1])
Xtrain = [np.random.random(size=(3,1)) for i in range(1000)]
ytrain = [np.array(np.sum(X)/3).reshape((1,1)) for X in Xtrain]
net.train(Xtrain, ytrain, niter=50000, alpha=0.1)
Это ситуация, когда ошибка сначала красиво уменьшалась, а затем начинала увеличиваться все больше и больше после определенного момента.
Learning with alpha = 0.1
Iteration 0: L2 error [[ 28.66232059]]
Iteration 1000: L2 error [[ 27.25906508]]
...
Iteration 9000: L2 error [[ 7.32406859]]
Iteration 10000: L2 error [[ 6.25700023]]
Iteration 11000: L2 error [[ 5.45473646]]
...
Iteration 18000: L2 error [[ 4.90465238]]
...
Iteration 24000: L2 error [[ 6.24519747]]
...
Iteration 45000: L2 error [[ 17.46215826]]
Iteration 46000: L2 error [[ 18.96317493]]
Iteration 47000: L2 error [[ 20.00523661]]
Iteration 48000: L2 error [[ 21.38221063]]
Iteration 49000: L2 error [[ 22.24753724]]
Iteration 49999: L2 error [[ 22.24753724]]
Если я попробую меньшее количество итераций (как предложено несколько сотен), то ошибка вообще не станет низкой. Я пытался уменьшить скорость обучения, например, для
alpha = 0.01
ошибка уменьшилась до 0,4 после 150000 итераций, а затем осталась там и медленно увеличивалась в течение остального времени. За
alpha = 0.005
ошибка снизилась до 2,6, а затем начала увеличиваться.
Логика тестирования работает с сетью 2-2-1, затем, независимо от скорости обучения, ошибка остается равной 1 для XOR и 0,6 для AND. Это сходится для ИЛИ и ~ ИЛИ.