Расчет стоимости Numpy нейронных сетей: изменение результатов после первого запуска - PullRequest
0 голосов
/ 28 февраля 2019

В python3.7 у меня проблема с вычислением стоимости нейронной сети.
При первом запуске compute_cost_nn я получаю правильную стоимость 0.28762916516131887, но при всех последующих запусках стоимость меняется на 0.3262751145707298, что довольно раздражает.
Похоже, проблема исходит от моего params;если я перезагружаю их каждый раз перед расчетом стоимости, все работает нормально.Но я не могу перезапустить функцию с другими параметрами и получить правильные затраты без повторного запуска всего сценария.

Нейронная сеть имеет 400 входных блоков, 1 скрытый слой с 25 блоками и 10 выходных блоков.

Вот входные данные:

data = loadmat("ex4data1.mat")
y = data['y']
X = data['X']
X = np.c_[np.ones((X.shape[0], 1)), X]

weights = loadmat("ex4weights.mat")
Theta1 = weights['Theta1']
Theta2 = weights['Theta2']
params = np.r_[Theta1.ravel(), Theta2.ravel()]

Матричные формы:

>> X: (5000, 401)
>> y: (5000, 1)
>> Theta1: (25, 401)
>> Theta2: (10, 26)
>> params: (10285,)

И функция стоимости:

def compute_cost_nn(params,
                    input_layer_size,
                    hidden_layer_size,
                    num_labels,
                    X, y, lambda_):

    m = len(y)

    # Retrieve Theta1 and Theta2 from flattened params
    t1_items = (input_layer_size + 1) * hidden_layer_size
    Theta1 = params[0:t1_items].reshape(
        hidden_layer_size, 
        input_layer_size+1
        )
    Theta2 = params[t1_items:].reshape(
        num_labels, 
        hidden_layer_size+1
        )

    # transform y vector column (5000x1) with labels 
    # into 5000x10 matrix with 0s and 1s
    y_mat = np.eye(num_labels)[(y-1).ravel(), :]

    # Forward propagation
    a1 = X
    z2 = a1 @ Theta1.T
    a2 = sigmoid(z2)
    a2 = np.c_[np.ones((m,1)), a2]
    z3 = a2 @ Theta2.T
    a3 = sigmoid(z3)

    # Compute cost
    func = y_mat.T @ np.log(a3) + (1-y_mat).T @ np.log(1-a3)
    cost = func.trace()
    t1reg = (Theta1[:,1:].T @ Theta1[:,1:]).trace()
    t2reg = (Theta2[:,1:].T @ Theta2[:,1:]).trace()
    cost_r = -1/m * cost + lambda_/(2*m) * (t1reg + t2reg)

    # Gradients (excluding Theta0)
    d3 = a3 - y_mat
    d2 = (d3 @ Theta2[:,1:]) * sigmoid_gradient(z2) #5000*25

    Delta1 = d2.T @ a1
    Delta2 = d3.T @ a2
    Theta1_grad = 1/m * Delta1
    Theta2_grad = 1/m * Delta2

    # Gradient regularization
    Theta1[:,1] = 0
    Theta2[:,1] = 0
    Theta1_grad = Theta1_grad + lambda_/m * Theta1
    Theta2_grad = Theta2_grad + lambda_/m * Theta2

    return cost_r, Theta1_grad, Theta2_grad

И я получаю стоимость, запустив:

compute_cost_nn(params, 400, 25, 10, X, y, 0)[0]

Первый запуск: 0.28762916516131887
Затем: 0.3262751145707298

Любые советы с благодарностью:)

1 Ответ

0 голосов
/ 02 марта 2019

Я не проверял ваш код с фиктивными данными, но, бросив быстрый взгляд на него, кажется, что вы импортируете весовые коэффициенты из файла .mat (MATLAB).MATLAB хранит элементы массивов в главном порядке столбцов (он же порядок стиля Fortran), в то время как Python - главный ряд (порядок в стиле C).

Следовательно, когда вы в первый раз ravel() свои веса, Numpy сгладитмассив, принимающий порядок в стиле CТа же самая история, когда вы меняете раскрученные веса в своих функциях.Вы можете добавить порядок в качестве аргумента к любой функции, поэтому:

params = np.r_[Theta1.ravel(order='F'), Theta2.ravel('F')]

Должен исправить вашу проблему.

Возможно, прочитайте о порядке строк и столбцов, если вы никогда не приходиличерез него: https://en.wikipedia.org/wiki/Row-_and_column-major_order

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...