Как реализовать трехслойный NN для изучения функции x²? - PullRequest
0 голосов
/ 13 мая 2019

Мы должны написать простую трехслойную NN, которая выучит f (x) = x² с функцией активации softplus в конце.

В моей реализации результаты просто мусор, и я не знаю,что я делаю не так.

import autograd.numpy as np
from autograd import grad
from autograd import elementwise_grad
from autograd import hessian
import random

class Neural_Net(object):
    def __init__(self, inputSize, hiddenSize, outputSize,
                 learning_rate=0.0001, epochs=100,
                 activation1="sigmoid", activation2="softplus"):
        self.inputSize = inputSize
        self.outputSize = outputSize
        self.hiddenSize = hiddenSize
        self.learning_rate = learning_rate
        self.epochs = epochs

        if activation1 == 'softplus':
            self.activation1 = softplus
            self.activation1_grad = softplus_grad
        if activation1 == 'sigmoid':
            self.activation1 = sigmoid
            self.activation1_grad = sigmoid_grad
        if activation1 == 'tanh':
            self.activation1 = np.tanh
            self.activation1_grad = tanh_grad

        if activation2 == 'softplus':
            self.activation2 = softplus
            self.activation2_grad = softplus_grad
        if activation2 == 'sigmoid':
            self.activation2 = sigmoid
            self.activation2_grad = sigmoid_grad
        if activation2 == 'tanh':
            self.activation2 = np.tanh
            self.activation2_grad = tanh_grad

        self.W1 = np.random.randn(self.inputSize, self.hiddenSize)
        self.b1 = np.ones((1, self.hiddenSize))
        self.W2 = np.random.randn(self.hiddenSize, self.outputSize)
        self.b2 = np.ones((1, self.outputSize))

    def forward_prop(self, X):    
        self.Z1 = np.dot(X, self.W1) + self.b1
        self.A1 = self.activation1(self.Z1)
        self.Z2 = np.dot(self.A1, self.W2) + self.b2
        self.A2 = self.activation2(self.Z2)

        return self.A2

    def back_prop(self, X, Y):
        self.dA2 = (self.A2 - Y)*self.activation2_grad(self.Z2)
        self.dA1 = (np.dot(self.dA2,self.W2.T))*self.activation1_grad(self.Z1)

        self.W1 -= self.learning_rate*X.T.dot(self.dA1)
        self.b1 -= self.learning_rate*self.dA1

        self.W2 -= self.learning_rate*np.dot(self.A1.T, self.dA2)
        self.b2 -= self.learning_rate*self.dA2

    def train(self, X, Y):
        self.forward_prop(X)
        self.back_prop(X, Y)

def softplus(x):
    return np.log(1 + np.exp(x))

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

softplus_grad = elementwise_grad(softplus)
sigmoid_grad = elementwise_grad(sigmoid)
tanh_grad = elementwise_grad(np.tanh)


NN1 = Neural_Net(inputSize=1, hiddenSize=1, outputSize=1, epochs=10000)
for epoch in range(NN1.epochs):
    X = np.array(([[random.randint(1, 100)]]))
    Y = np.square(X)
    A2 = NN1.forward_prop(X)
    print("Input: " + str(X))
    print("Actual Output: " + str(Y))
    print("Predicted Output: " + str(A2))
    print("Loss: " + str(np.mean(np.square(Y - A2))))
    print("\n")
    NN1.train(X, Y)

Ожидаемый результат просто увеличивается, и в зависимости от того, какие параметры я выбираю, он становится NaN или inf до его завершения

Ответы [ 2 ]

0 голосов
/ 13 мая 2019

Больше проблем:

, если hiddensize = 1, это означает, что у вас есть только один нейрон в середине.Недостаточно приблизительно x * 2.

, если активация выхода сигмовидная, она может выводить только числа от 0 до 1. Как вы выводите числа от 1 до 100 в квадрате?1**2=1, 2**2=4, ..., 100**2=10000, в то время как ваше устройство вывода может выводить только цифры от 0 до 1.

0 голосов
/ 13 мая 2019

Так же, как на шаге вперед вы вычисляете Z1, затем A1, затем Z2, затем A2, на шаге назад вы должны вычислять градиенты в обратном порядке: dA2, затем dZ2, затем dA1, затем dZ1.Вы не рассчитываете dZ2 или dZ1, поэтому он не может работать.Возможно, у вас есть и другие проблемы, но эта является наиболее очевидной.

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

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