Нейронная сеть: как уменьшить количество выходных линий, чем входных? - PullRequest
0 голосов
/ 05 августа 2020

Как сделать НС, например, с 4 входами и только одним выходом? Точнее, (4,4) входная матрица ---> (1,1) выходная матрица вместо (4,1) выходная матрица.

Прошло несколько недель, что меня заинтересовало NN и я разобрались в математике solid. У меня есть шаблон, который отлично работает, и я пытаюсь обобщить его, чтобы можно было добавить больше слоев. Работа еще продолжается, но я только что понял, что не могу производить меньше, чем вводимые ресурсы. Зачем ? Это кажется довольно обычным, например, при классификации изображений у вас есть тысячи входов и около 10 выходов.

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

    import numpy as np
    from matplotlib import pyplot as plt
    
    # Activation function
    def sigmoid(t):
        return 1 / (1 + np.exp(-t))
    
    # Derivative of sigmoid
    def sigmoid_derivative(p):
        return p * (1 - p)

# Class definition
class NeuralNetwork:
    error_history = []
    hidden_size = 4
    layers = 1 # Number of hidden layers with fixed size
    layers_list = [] # Layers list. Useful to add new layers
    w_list = [] # Weights list

    def __init__(self, x, y):
        self.input = x
        self.y = y

        # Input special case. 
        self.w_list.append(np.random.rand(self.input.shape[1], self.hidden_size))

        #More weights for more hidden layers
        for i in range(self.layers-1): # adds nothing if only one layer
           self.w_list.append(np.random.rand(self.hidden_size, self.hidden_size))

        # Output special case
        self.w_list.append(np.random.rand(self.hidden_size, y.shape[1])) #y.shape[1] used to be 1
        self.output = np.zeros(y.shape) #NN output

        # Init layers
        self.layers_list.append(np.zeros((self.input.shape[0], self.hidden_size)))

        # More layers
        for i in range(self.layers - 1):  # adds nothing if only one layer
            self.layers_list.append(np.zeros((self.hidden_size, self.hidden_size)))

        self.layers_list.append(np.zeros((4, 1))) # LAST LAYER to OUTPUT
        # The "1" is very practical to give neat results, like the end on an logical equation.
        #  0 1 0 -> 1. Otherwise we end up with double arrays

    def feedforward(self):
        self.layers_list[0] = sigmoid(np.dot(self.input, self.w_list[0]))
        for i in range (self.layers):
            self.layers_list[i+1] = sigmoid(np.dot(self.layers_list[i], self.w_list[i+1]))
        self.output = self.layers_list[-1] #last layer.

    def backprop(self):
        delta = 2 * (self.y - self.output) * sigmoid_derivative(self.output)
        d_weights2 = np.dot(self.layers_list[0].T, delta )
        #special case : input weights
        d_weights1 = np.dot(self.input.T, np.dot(delta,self.w_list[1].T) * sigmoid_derivative(self.layers_list[0]))
        self.w_list[0] += d_weights1
        self.w_list[1] += d_weights2

    def train(self, epochs):
        for i in range(epochs):  # trains the NN a lot of times
            self.feedforward()
            self.backprop()
            self.error_history.append(self.loss())

    # This should ONLY be called after training the NN.
    # apply this and just read last layer. careful of input dimensions
    def predict(self, entry):
        self.input = entry
        self.feedforward()
        print("test result: ")
        print(self.output)

    # Standard loss function of the NN
    def loss(self):
        return np.mean(np.square(self.y - self.layers_list[1]))

    # Showing the error converging to a minimum ! Hopefully.
    def graph(self):
        plt.plot(self.error_history)
        plt.show()
        plt.xlabel("Error")
        plt.ylabel("Epochs")

if __name__ == "__main__":
    # Each row is a training example, each column is a feature  [X1, X2, X3]
    X = np.array(([0, 0, 1],
                  [0, 1, 1],
                  [1, 0, 1],
                  [1, 1, 1]), dtype=float)
    y = np.array(([0],
                  [1],
                  [1],
                  [0]), dtype=float)

    X2 = np.array(([0], [0],[1],[1]), dtype=float)


    X3 = np.array(([0], [0], [1]), dtype=float)
    X32 = np.array(([0, 0, 1],
                  [0, 1, 1],
                  [1, 1, 1]), dtype=float)
    y3 = np.array(([0],[1], [1]), dtype=float)

# This example shows NN learning AND gate.
    X_and = np.array(([0, 0],
                  [0, 1],
                  [1, 0],
                  [1, 1]), dtype=float)
    y_and = np.array(([0],
                  [0],
                  [0],
                  [1]), dtype=float)
    and_test = np.array(([1, 0],
                        [0, 1],
                        [1,1],
                        [0, 1]), dtype=float)

    nn = NeuralNetwork(X_and, y_and)
    nn.train(1500)
    print("layer1")
    print(nn.layers_list[0])
    print("layer2")
    print(nn.layers_list[1])
    nn.predict(and_test)
    nn.graph()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...