Формы обратного распространения не совпадают - PullRequest
0 голосов
/ 07 ноября 2018

Я пытался создать трехслойную (1 вход - 2 скрытый - 1 выход) нейронную сеть с нуля, используя numpy. Выходной слой имеет только 1 нейрон. Я пытаюсь использовать стохастический градиентный спуск с мини-партиями. Что я сделал до сих пор, так это:

N1 = 50 # number of neurons in the first hidden layer
N2 = 20 # number of neurons in the second hidden layer
for n in range(10000):

    weight_increment2 = 0
    weight_increment1 = 0
    weight_increment0 = 0

    for j in range( batch_size):

        # choose a sample randomly from training set
        index = np.random.randint( trainims.shape[2] - 1)
        layer0 = trainims[:,:,index]

        # convert it to a column vector and add 1 for bias
        layer0 = layer0.flatten()
        layer0 = np.append( layer0, 1)
        layer0 = layer0.reshape((1025,1))

        # feed forward
        layer1 = np.tanh( np.dot( w0.T, layer0))
        layer1 = np.append( layer1, 1)
        layer1 = layer1.reshape((N1+1,1))
        layer2 = np.tanh( np.dot( w1.T, layer1))
        layer2 = np.append( layer2, 1)
        layer2 = layer2.reshape((N2+1,1))
        layer3 = math.tanh( np.dot( w2.T, layer2))

        # backpropagation
        layer3_error = trainlbls[0,index] - layer3
        layer3_gradient = 1 - layer3 * layer3
        layer3_delta = layer3_error * layer3_gradient

        layer2_error = layer3_delta * w2
        layer2_gradient = 1 - np.multiply(layer2, layer2)
        layer2_delta = np.multiply(layer2_error, layer2_gradient)
        strippedlayer2delta = layer2_delta[0:N2,:]

        layer1_error = strippedlayer2delta.T * w1
        layer1_gradient = 1 - np.multiply( layer1, layer1)
        layer1_delta = np.multiply( layer1_error, layer1_gradient)
        strippedlayer1delta = layer1_delta[0:N1,:]


        weight_increment2 = weight_increment2 + learning_rate * layer2 * layer3_delta
        weight_increment1 = weight_increment1 + learning_rate * np.dot( layer1, strippedlayer2delta.T)
        weight_increment0 = weight_increment0 + learning_rate * np.dot( layer0, strippedlayer1delta.T)

    # update the weights
    w2 = w2 + weight_increment2
    w1 = w1 + weight_increment1
    w0 = w0 + weight_increment0
  • w0 - входные веса: 1025x50 (1024 = вход, +1 - член смещения)
  • w1 - первый вес скрытого слоя: 51x20 (50 = количество нейронов первого скрытого слоя, +1 - термин смещения)
  • w2 - вес второго скрытого слоя: 21x1 (20 = количество вторых скрытых нейронов Лайера, +1 - термин смещения)
  • layer0 - это вектор входного слоя: входная выборка (1024x1) и 1, добавленные в конец, что делает layer0 вектором 1025x1.
  • layer1 - это первый вектор скрытого слоя: после вычисления tanh( np.dot( w0.T, layer0)) я добавляю 1 в конец, что дает вектор 51x1
  • layer2 - второй вектор скрытого слоя: после вычисления tanh( np.dot( w1.T, layer1)) я добавляю 1 в конец, что приводит к вектору 21x1
  • layer3 - выходной вектор: tanh( np.dot( w2.T, layer2)), который является просто nunmber
  • trainims - это тренировочный набор размером 32x32x1900, что означает 1900 изображений 32x32

При обратном распространении я опускаю последние строки layer2_delta и layer1_delta, но я точно не знаю, почему я это делаю. Я предполагаю, что это из-за пропуска 1 терминов, которые я добавляю к layer1 и layer2.

При попытке запустить код выдает следующую ошибку:

ValueError Traceback (most recent call last)
<ipython-input-11-98c3beb3b346> in <module>()
     62         print( "weight_increment1:", weight_increment1.shape)
     63 
---> 64         weight_increment0 = weight_increment0 + learning_rate * np.dot( layer0, strippedlayer1delta.T)
     65         print( "weight_increment0:", weight_increment0.shape)
     66 

ValueError: shapes (1025,1) and (20,50) not aligned: 1 (dim 1) != 20 (dim 0)

Я знаю, что размеры должны совпадать, чтобы получить матрицу 1025x50 и обновить w0, но я не смог найти решение. Может быть, я делаю обратное распространение неправильно, я не знаю. Кто-нибудь может предложить решение этой проблемы?

Edit: ОК, я заметил мою ошибку. Раньше я делал

layer1_error = strippedlayer2delta.T * w1

, который давал матрицу, но ошибка должна быть вектором для слоя, а не матрицей. Изменив эту строку на

layer1_error = np.dot( w1, strippedlayer2delta)

исправлена ​​ошибка формы.

Но все же, кто-нибудь может проверить, правильны ли мои реализации стохастического градиентного спуска с мини-пакетами и обратным распространением?

...