Глубокая нейронная сеть с реализацией обратного распространения не работает - python - PullRequest
0 голосов
/ 27 февраля 2020

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

  • Я реализовал реализацию с входным слоем 784 (28x28), двумя (L) скрытыми слоями 300 и выходом из 10 классов. , У меня есть предвзятость в каждом слое (кроме последнего ...)
  • Выходная активация - softmax, а скрытая активация - ReLU.
  • Я использую мини-партии из 600 примеров для набора данных из 60 тыс. Примеров с 50–500 эпочами.

Здесь ядро ​​моего кода:

Подготовка:

from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

fashion_mnist = keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()

L = 2
K = len(np.unique(train_labels))
lr = 0.001
nb_epochs = 50
node_per_hidden_layer = 300
nb_batches = 100
W = []
losses_test = []

X_train = np.reshape(train_images, (train_images.shape[0], train_images.shape[1]*train_images.shape[2]))
X_test = np.reshape(test_images, (test_images.shape[0], train_images.shape[1]*train_images.shape[2]))

Y_train = np.zeros((train_labels.shape[0], K))
Y_train[np.arange(Y_train.shape[0]), train_labels] = 1

Y_test = np.zeros((test_labels.shape[0], K))
Y_test[np.arange(Y_test.shape[0]), test_labels] = 1

W.append(np.random.normal(0, 0.01, (X_train.shape[1]+1, node_per_hidden_layer)))
for i in range(L-1):
    W.append(np.random.normal(0, 0.01, (node_per_hidden_layer+1, node_per_hidden_layer)))
W.append(np.random.normal(0, 0.01, (node_per_hidden_layer+1, K)))

Вспомогательная функция:

def softmax(z):
    exp = np.exp(z - z.max(1)[:,np.newaxis])
    return np.array(exp / exp.sum(1)[:,np.newaxis])


def softmax_derivative(z):
    sm = softmax(z)
    return sm * (1-sm)


def ReLU(z):
    return np.maximum(z, 0)


def ReLU_derivative(z):
    return (z >= 0).astype(int)


def get_loss(y, y_pred):
    return -np.sum(y * np.log(y_pred))

установка

def fit():
    minibatch_size = len(X_train) // nb_batches

    for epoch in range(nb_epochs):
        permutaion = list(np.random.permutation(X_train.shape[0]))
        X_shuffle = X_train[permutaion]
        Y_shuffle = Y_train[permutaion]
        print("Epoch----------------", epoch)

        for batche in range(0, X_shuffle.shape[0], minibatch_size):
            Z = [None] * (L + 2)
            a = [None] * (L + 2)
            delta = [None] * (L + 2)
            X = X_train[batche:batche+minibatch_size]
            Y = Y_shuffle[batche:batche+minibatch_size]

            ### forward propagation
            a[0] = np.append(X, np.ones((minibatch_size, 1)), axis=1)
            for i in range(L):
                Z[i + 1] = a[i] @ W[i]
                a[i + 1] = np.append(ReLU(Z[i+1]), np.ones((minibatch_size, 1), dtype=int), axis=1)

            Z[-1] = a[L] @ W[L]
            a[-1] = softmax(Z[-1])

            ### back propagation
            delta[-1] = (Y - a[-1]) * softmax_derivative(Z[-1])
            for i in range(L, 0, -1):
                delta[i] = (delta[i+1] @ W[i].T)[:,:-1] * ReLU_derivative(Z[i])

            for i in range(len(W)):
                g = a[i].T @ delta[i+1] / minibatch_size
                W[i] = W[i] + lr * g

        get_loss_on_test()   

потеря


def get_loss_on_test():
    Z_test = [None] * (L + 2)
    a_test = [None] * (L + 2)

    a_test[0] = np.append(X_test, np.ones((len(X_test), 1)), axis=1)
    for i in range(L):
        Z_test[i + 1] = a_test[i] @ W[i]
        a_test[i + 1] = np.append(ReLU(Z_test[i+1]), np.ones((len(X_test), 1)), axis=1)

    Z_test[-1] = a_test[L] @ W[L]
    a_test[-1] = softmax(Z_test[-1])

    losses_test.append(get_loss(Y_test, a_test[-1]))

основная

losses_test.clear()
fit()
plt.plot(losses_test)
plt.show()

Если вы хотите увидеть это в моей записной книжке с примером графика потерь, здесь ссылка: https://github.com/beurnii/INF8225/blob/master/tp2/jpt.ipynb

Если вы хотите получить более подробную информацию о моем назначении, это часть 1b (страница 2 для engli sh): https://github.com/beurnii/INF8225/blob/master/tp2/INF8225_TP2_2020.pdf

...