Функция стоимости растет с моим градиентным спуском и не уверена в теории, которую я прочитал - PullRequest
0 голосов
/ 04 апреля 2020

Я пытаюсь построить нейронную сеть, используя NumPy, и я знаю, что есть тысячи примеров, но я пытаюсь только с теорией, которую я прочитал из курса Coursera Machine Learning от Andrew Ng. Сначала я попробовал векторизованную реализацию и подумал, что я ее неправильно кодировал, но потом я попытался снова закодировать ее с помощью векторизации и получил ту же проблему, функция стоимости начинает расти, иногда нет, но прогнозы даже близко не соответствуют учиться. Я использовал градиентную проверку и обнаружил, что проблема действительно в обратном распространении, поэтому я хотел спросить, может ли кто-нибудь сказать мне, не понимаю ли я теорию или плохо ее кодирую! Вот код (я знаю, что моя реализация ужасна, но это для обучения, хуже всего - проверка градиента ...), Эндрю не объяснил, что делать с производными от терминов смещения, но мой вывод был Суммируйте условия ошибок, умноженные на веса:

import numpy as np

def sigmoid(z):
    return 1/(1+np.exp(-z))

class NeuralNetwork:

    def __init__(self,arch_):
        self.arch = arch_
        self.layers = arch_.size
        self.w, self.b = self.random_initialization(arch_)
        self.lamb = 0
        self.epochs = 1000
        self.alpha = 0.01

    def random_initialization(self,arch):
        w = [np.random.randn(arch[1],arch[0])*np.sqrt(2/arch[0])]
        b = np.array([np.random.randn(self.arch[i+1])*np.sqrt(2/arch[i]) for i in range(1,self.arch.size-1)])
        for i in range(1,arch.size-1):
            w.append(np.random.randn(arch[i+1],arch[i])*np.sqrt(2/arch[i]))
        return np.array(w), b

    def forward_propagation(self,x):
        a = sigmoid(np.dot(self.w[0],x))
        a_m = [x,a]
        for i in range(1,self.layers-1):
            a = sigmoid(np.dot(self.w[i],a)+self.b[i-1])
            a_m.append(a)
        return a_m

    def cost_function(self,x,y):
        h = np.array([self.forward_propagation(i)[-1] for i in x])
        reg = np.square(self.w[0]).sum()
        for i in range(1,self.layers-1):
            reg += np.square(self.w[i][:,1:]).sum()
        return -1/y.shape[0]*(np.log(1-h)*(1-y) + np.log(h)*y).sum() + self.lamb/(2*y.shape[0])*reg

    def backward_propagation(self,nabla_w,nabla_b,a,y):
        d_l = a[-1] - y
        d = [d_l]
        for i in range(1,self.layers-1)[::-1]:
            nabla_b[i-1] += (d_l * self.b[i-1])
            d_l = np.dot(d_l,self.w[i])*a[i]*(1-a[i])
            d.insert(0,d_l)
        for i in range(len(d))[::-1]:
            nabla_w[i] += (d[i][None,:] * a[i][None,:].T).T

    def gradient(self,x,y):
        nabla_w = []
        for i in range(self.arch.size-1):
            nabla_w.append(np.zeros((self.arch[i+1],self.arch[i])))
        nabla_b = np.array([np.zeros(self.arch[i+1]) for i in range(1,self.arch.size-1)])
        for i in range(x.shape[0]):
            self.backward_propagation(nabla_w,nabla_b,self.forward_propagation(x[i]),y[i])
        delta = []
        for i in range(self.w.size):
            delta.append(nabla_w[i]+self.lamb*self.w[i])
        return ((1/y.size)*np.array(delta)),(1/(y.size)*nabla_b)

    def train(self,x,y):
        for i in range(self.epochs):
            d_w, d_b = self.gradient(x,y)
            self.w -= self.alpha * d_w
            self.b -= self.alpha * d_b

    def gradient_checking(self,x,y):

        e = 10**-6

        g_1 = []
        for i in range(self.w.shape[0]):
            g_2 = []
            for j in range(self.w[i].shape[0]):
                g_3 = []
                for k in range(self.w[i][j].shape[0]):
                    self.w[i][j][k] += e
                    m = self.cost_function(x,y)
                    self.w[i][j][k] -= 2*e
                    n = self.cost_function(x,y)
                    self.w[i][j][k] += e
                    g_3.append((m-n)/(2*e))
                g_2.append(np.array(g_3))
            g_1.append(np.array(g_2))

        b_1 = []
        for i in range(self.b.shape[0]):
            b_2 = []
            for j in range(self.b[i].shape[0]):
                self.b[i][j] += e
                m = self.cost_function(x,y)
                self.b[i][j] -= 2*e
                n = self.cost_function(x,y)
                self.b[i][j] += e
                b_2.append((m-n)/(2*e))
            b_1.append(np.array(b_2))

        return np.array(g_1), np.array(b_1)

x = np.array([[1,4],[4,3],[8,9],[12,5],[12,7],[15,9]])
y = np.array([[1,0],[1,0],[0,1],[0,1],[0,1],[0,1]])

k = NeuralNetwork(np.array([2,3,2]))
k.train(x,y) 
...