Нейронная сеть всегда выдает один и тот же результат - PullRequest
0 голосов
/ 09 мая 2020

Мне пришлось написать нейронную сеть, которая могла бы классифицировать рукописные числа из набора данных MNIST. Однако кажется, что он всегда предсказывает один и тот же класс. Я нашел этот вопрос , который описывает очень похожий случай. Однако методы отладки, описанные в одном из ответов, мне не помогли. Я пробовал использовать разное количество вершин и скрытых слоев, я пытался сократить обучающий набор до двух или свободных случаев, но нейронная система net по-прежнему предпочитает один конкретный класс. Я также не мог нарисовать график, потому что моя функция потерь не определена, когда цель содержит ноль. (Я не уверен, должно ли так быть, и я мог что-то перепутать в своей энтропийной функции, но когда я пытаюсь изменить знаки в gLoss_der(), я просто получаю еще один столбец постоянных ответов). Вот код самого моего класса нейрон onet

import numpy as np
class neuronet():

    def __init__(self, L, l_rate = 0.5):        # TODO: add comments

        self.L      = L
        self.size   = len(L)
        self.l_rate = l_rate

        self.W = [np.random.rand(self.L[i+1], self.L[i]) for i in range(self.size-1)]   # W - an array of matrixes with weights
        self.B = [np.random.rand(self.L[i+1]) for i in range(self.size-1)]              # B - an array of vectors with bias weights

        self.I = [None for i in range(self.size)]                                       # I - an array of vectors with inputs of the activation functions
        self.O = [None for i in range(self.size)]                                       # O - an array of vectors with outputs of the activation functions

        self.dW = [np.zeros((self.L[i+1], self.L[i])) for i in range(self.size-1)]
        self.dB = [np.zeros((self.L[i+1],))  for i in range(self.size-1)]

    def feed_forward(self, inp):        # TODO: add comments

        self.I[0] = inp

        for i in range(self.size-1):
            self.O[i]   = self.f(self.I[i])
            self.I[i+1] = self.W[i].dot(self.O[i]) + self.B[i]

        self.O[self.size-1] = self.g(self.I[self.size-1])

    def back_propagation(self, inp, target):    # TODO: add comments

        self.feed_forward(inp)
        dLdI = self.gLoss_der(self.O[self.size-1], target)                                      # dLdI - a vector of partial derivatives d/dI (Loss)

        for i in range(self.size-2, -1, -1):

            temp = dLdI.reshape(self.L[i+1], 1) @ self.O[i].reshape(1, self.L[i])
            self.dW[i] = temp * self.l_rate                                                     # TODO: add support for batch training
            self.dB[i] = dLdI * self.l_rate

            dLdI = self.f_der(self.I[i]) * (dLdI.dot(self.W[i]))

    def train(self, inps, targets, l_rate=-1, batch_size=1):
        if l_rate == -1:
            l_rate = self.l_rate

        for i in range(len(inps)):
            self.back_propagation(inps[i], targets[i])

            for i in range(self.size-1):
                self.W[i] -= self.dW[i]
                self.B[i] -= self.dB[i]

        return #self.Loss(self.O[-1], targets[-1])

    def predict(self, inp):
        self.feed_forward(inp)
        return self.O[self.size-1]

    def f(self, x):
        return 1/(1+np.exp(-x))
    def g(self, x):
        temp = np.exp(x)
        return temp/np.sum(temp)
    def Loss(self, y, target):
        return -np.sum(y*np.log(target))
    def gLoss_der(self, y, target):
        return y-target
    def f_der(self, x):
        return self.f(x)*(1-self.f(x))

Вот функция, которую я использую для масштабирования ввода:

def scale_input(inp):
    s = np.sum(inp)
    return inp/s

А вот часть тестирования. Это беспорядочно, поскольку я пробовал все советы по отладке нейронных сетей, которые мог найти, и просто не удосужился написать чистый код. Извините

train_input = []
train_target = []
test_input = []
test_target = []

data_file = open("/PATH_TO_MNIST/mnist/mnist_train_100.csv")
train_data = np.asfarray([line.split(",") for line in data_file.readlines()])
data_file.close()
for i in range(len(train_data)):

    train_input.append(scale_input(train_data[i%3][1:]))

    x = [0 for j in range(10)]
    x[int(train_data[i%3][0])] = 1
    train_target.append(np.array(x))

input_nodes = 784
hidden_nodes = 150
output_nodes = 10
learning_rate = 0.00005
epochs = 100
net = neuronet([input_nodes, hidden_nodes,  output_nodes], learning_rate)

for epoch in range(epochs):
    net.train(train_input, train_target)

hits = 0
for i in range(len(train_input)):
    prediction = net.predict(train_input[i])
    prediction = np.argmax(prediction)
    print(prediction)
    if train_target[i][prediction] == 1:
        hits += 1
print('%d%%' % ((100*hits/len(train_input))))

Каждый раз, когда я запускаю эту программу, я получаю столбец из 5. Что я делаю не так? Я пробовал менять разные числа, но это не помогло. Я пытался научить свой нейронный net выполнять XOR двух чисел из набора {0, 1}, и ему удалось научиться, поэтому в некоторых случаях он работает, и я не знаю, как и почему. Вот тот же код на GitHub

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