Я получаю одинаковый вывод для всех входных данных после обучения моей нейронной сети (2000 входов, 1 выход) - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь реализовать нейронную сеть, которая имеет около 2000 входов.

Я сделал несколько тестов с набором данных радужной оболочки, чтобы проверить его, и он, кажется, работает, но когда я запускаю свой тест, он выдает неправильные результаты, большую часть времени, для всех тестов, я получаю то же самое вывод для каждых данных. Боюсь, если это как-то связано с процессом смещения и обновлением градиента, может быть, вы, ребята, заметите ошибку или дадите мне несколько советов. Вот часть кода для процесса обратного распространения.

def backward_propagation(parameters, cache, X, Y):

    #weights
    W1 = parameters['W1']
    W2 = parameters['W2']
    #Outputs after activation function
    A1 = cache['A1']
    A2 = cache['A2']
    dZ2= A2 - Y
    dW2 = np.dot(dZ2, A1.T)
    db2 = np.sum(dZ2, axis=1, keepdims=True)
    dZ1 = np.multiply(np.dot(W2.T, dZ2), 1 - np.power(A1, 2))
    dW1 = np.dot(dZ1, X.T)
    db1 = np.sum(dZ1, axis=1, keepdims=True)
    gradient = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}    
    return gradient

1 Ответ

0 голосов
/ 15 января 2019

Чрезвычайно трудно понять, работает ли он действительно так, как следует, если вы не предоставите функцию прогнозирования и форвард.

Таким образом, мы можем точно знать, что делается, и посмотреть, действительно ли обратное распространение верно.

Вы неправильно выводите сигмовидную функцию, и я думаю, что вы также неправильно применяете правило цепочки.

Из того, что я вижу, вы используете эту архитектуру:

enter image description here

Градиенты будут (применять правило цепи):

enter image description here

В вашем коде это переводится следующим образом:

W1 = parameters['W1']
W2 = parameters['W2']
#Outputs after activation function
A1 = cache['A1']
A2 = cache['A2']
dA2= A2 - Y

dfc2 = dA2*A2*(1 - A2)
dA1 = np.dot(dfc2, W2.T)
dW2 = np.dot(A1.T, dfc2)
db2 = np.sum(dA2, axis=1, keepdims=True)


dfc1 = dA1*A1*(1 - A1)
dA1 = np.dot(dfc1, W1.T)
dW1 = np.dot(X.T, dfc1)
db1 = np.sum(dA1, axis=1, keepdims=True)
gradient = {
    "dW1": np.sum(dW1, axis=0),
    "db1": np.sum(db1, axis=0),
    "dW2": np.sum(dW2, axis=0),
    "db2": np.sum(db2, axis=0)
}

Я проверяю, выполнив следующий код:

import numpy as np

W1 = np.random.rand(30, 10)
b1 = np.random.rand(10)
W2 = np.random.rand(10, 1)
b2 = np.random.rand(1)
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

X = np.random.rand(100, 30)
Y = np.ones(shape=(100, 1)) #...

for i in range(100000000):
    fc1 = X.dot(W1) + b1
    A1 = sigmoid(fc1)

    fc2 = A1.dot(W2) + b2
    A2 = sigmoid(fc2)
    L = np.sum(A2 - Y)**2
    print(L)

    dA2= A2 - Y
    dfc2 = dA2*A2*(1 - A2)
    dA1 = np.dot(dfc2, W2.T)
    dW2 = np.dot(A1.T, dfc2)
    db2 = np.sum(dA2, axis=1, keepdims=True)


    dfc1 = dA1*A1*(1 - A1)
    dA1 = np.dot(dfc1, W1.T)
    dW1 = np.dot(X.T, dfc1)
    db1 = np.sum(dA1, axis=1, keepdims=True)
    gradient = {
        "dW1": dW1,
        "db1": db1,
        "dW2": dW2,
        "db2": db2
    }

    W1 -= 0.1*np.sum(dW1, axis=0)
    W2 -= 0.1*np.sum(dW2, axis=0)
    b1 -= 0.1*np.sum(db1, axis=0)
    b2 -= 0.1*np.sum(db2, axis=0)

Если ваша последняя активация является сигмоидом, значение будет между 0 и 1. Следует помнить, что обычно это используется для указания вероятности и что перекрестная энтропия обычно используется как потеря.

...