проблема обратного распространения;все выше и выше общая стоимость до бесконечности - PullRequest
0 голосов
/ 25 мая 2018

Я сделал нейронную сеть FC с numpy, основываясь на видео из лаборатории Уэлча, но когда я пытаюсь обучить его, у меня появляются взрывные градиенты при запуске, что странно, я записываю весь код, который можно тестировать на python3+.кажется, что только ценовая функция нарушает градиентный спуск, но я понятия не имею, что происходит.Может ли кто-нибудь умнее меня помочь?

РЕДАКТИРОВАТЬ: trng_input и trng_output не тот, который я использую, я использую большой набор данных

import numpy as np
import random

trng_input = [[random.random() for _ in range(7)] for _ in range(100)]
trng_output = [[random.random() for _ in range(2)] for _ in range(100)]

def relu(x):
    return x * (x > 0)

def reluprime(x):
    return (x>0).astype(x.dtype)


class Neural_Net():
    def __init__(self, data_input, data_output):
        self.data_input = data_input
        self.trng_output = trng_output
        self.bias = 0
        self.nodes = np.array([7, 2])
        self.LR = 0.01
        self.weightinit()
        self.training(1000, self.LR)

    def randomweight(self, n):
        output = []
        for i in range(n):
            output.append(random.uniform(-1,1))
        return output

    def weightinit(self):
        self.weights = []
        for n in range(len(self.nodes)-1):
            temp = []
            for _ in range(self.nodes[n]+self.bias):
                temp.append(self.randomweight(self.nodes[n+1]))
            self.weights.append(temp)
        self.weights = [np.array(tuple(self.weights[i])) for i in range(len(self.weights))]


    def forward(self, data):
        self.Z = []
        self.A = [np.array(data)]

        for layer in range(len(self.weights)):
            self.Z.append(np.dot(self.A[layer], self.weights[layer]))
            self.A.append(relu(self.Z[layer]))

        self.output = self.A[-1]
        return self.output

    def costFunction(self):
        self.totalcost = 0.5*sum((self.trng_output-self.output)**2)
        return self.totalcost

    def costFunctionPrime(self):
        self.forward(self.data_input)
        self.delta = [[] for x in range(len(self.weights))]
        self.DcostDw = [[] for x in range(len(self.weights))]

        for layer in reversed(range(len(self.weights))):
            Zprime = reluprime(self.Z[layer])
            if layer == len(self.weights)-1:
                self.delta[layer] = np.multiply(-(self.trng_output-self.output), Zprime)
            else:
                self.delta[layer] = np.dot(self.delta[layer+1], self.weights[layer+1].T) * Zprime
            self.DcostDw[layer] = np.dot(self.A[layer].T, self.delta[layer])

        return self.DcostDw

    def backprop(self, LR):
        self.DcostDw = (np.array(self.DcostDw)*LR).tolist()
        self.weights = (np.array(self.weights) - np.array(self.DcostDw)).tolist()

    def training(self, iteration, LR):
        for i in range(iteration):
            self.costFunctionPrime()
            self.backprop(LR)
            if (i/1000.0) == (i/1000):
                print(self.costFunction())
        print(sum(self.costFunction())/len(self.costFunction()))

NN = Neural_Net(trng_input, trng_output)

, как меня спросили, это ожидаемый результат (результатЯ использовал функцию активации сигмовидной кишки):

, как вы видите, цифры снижаются, и, таким образом, сеть обучается.

это результат использования функции активации relu:

Здесь сеть застревает и не обучается, она никогда не обучается с помощьюфункция активации relu и хотел бы понять, почему

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

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

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

Для некоторых проблем это также поможет снизить скорость обучения и сделать сеть глубже.Возможно, вы хотели бы настроить скорость обучения, например, если стоимость не уменьшается, умножьте LR на 0,5.

При наличии утечки ReLu, обучаемых отклонений и некоторого рефакторинга ваша модель может выглядеть следующим образом:

import numpy as np
trng_input = np.random.uniform(size=(1000, 7))
trng_output = np.column_stack([np.sin(trng_input).sum(axis=1), np.cos(trng_input).sum(axis=1)])

LEAK = 0.0001

def relu(x):
    return x * (x > 0) + LEAK * x * (x < 0)

def reluprime(x):
    return (x>0).astype(x.dtype) + LEAK * (x<0).astype(x.dtype)


class Neural_Net():
    def __init__(self, data_input, data_output):
        self.data_input = data_input
        self.trng_output = trng_output
        self.nodes = np.array([7, 10, 2])
        self.LR = 0.00001
        self.weightinit()
        self.training(2000, self.LR)

    def weightinit(self):
        self.weights = [np.random.uniform(-1, 1, size=self.nodes[i:(i+2)]) for i in range(len(self.nodes) - 1)]
        self.biases = [np.random.uniform(0, 1, size=self.nodes[i+1]) for i in range(len(self.nodes) - 1)]

    def forward(self, data):
        self.Z = []
        self.A = [np.array(data)]
        for layer in range(len(self.weights)):
            self.Z.append(np.dot(self.A[layer], self.weights[layer]) + self.biases[layer])
            self.A.append(relu(self.Z[layer]))
        self.output = self.A[-1]
        return self.output

    def costFunction(self):
        self.totalcost = 0.5*np.sum((self.trng_output-self.output)**2, axis=0)
        return self.totalcost

    def costFunctionPrime(self):
        self.forward(self.data_input)
        self.delta = [[] for x in range(len(self.weights))]
        self.DcostDw = [[] for x in range(len(self.weights))]
        self.DcostDb = [[] for x in range(len(self.weights))]
        for layer in reversed(range(len(self.weights))):
            Zprime = reluprime(self.Z[layer])
            if layer == len(self.weights)-1:
                self.delta[layer] = np.multiply(-(self.trng_output-self.output), Zprime)
            else:
                self.delta[layer] = np.dot(self.delta[layer+1], self.weights[layer+1].T) * Zprime
            self.DcostDw[layer] = np.dot(self.A[layer].T, self.delta[layer])
            self.DcostDb[layer] = np.sum(self.delta[layer], axis=0)

    def backprop(self, LR):
        for layer in range(len(self.weights)):
            self.weights[layer] -= self.DcostDw[layer] * LR
            self.biases[layer] -= self.DcostDb[layer] * LR

    def training(self, iteration, LR):
        for i in range(iteration):
            self.costFunctionPrime()
            self.backprop(LR)
            if (i/100.0) == (i/100):
                print(self.costFunction())
        print(sum(self.costFunction())/len(self.costFunction()))

NN = Neural_Net(trng_input, trng_output)
0 голосов
/ 31 мая 2018

Я думаю, что проблема заключается в вашей функции стоимости.

def costFunction(self):
    self.totalcost = 0.5*sum((self.trng_output-self.output)**2)
    return self.totalcost

В частности, эта строка,

self.totalcost = 0.5*sum((self.trng_output-self.output)**2)

Вы рассчитали стоимость путем суммирования всех ошибок.Поскольку вы упомянули, что используете очень большой набор данных, self.totalcost окажется очень большим.В свою очередь, рассчитанные градиенты также будут очень большими.

Попробуйте использовать Стохастический градиентный спуск или возьмите среднее значение, например,

self.totalcost = 0.5 * np.mean((self.trng_output-self.output)**2)
...