Градиентный спуск не тренирует Правильно Проблема XOR Gate - PullRequest
0 голосов
/ 29 сентября 2019

Я работаю над школьным заданием.Я должен обучить нейронную сеть так, чтобы она могла решить проблему XOR Gate.

Мой дизайн - это нейронная сеть с входным слоем из двух нейронов, скрытым слоем из двух нейронов и выходным слоем толькоодна сеть.Я использую функцию sigmoid и соответствующую ей производную в качестве функции активации.Я уже много раз проверял алгоритм, пытаясь найти что-то не так, но кажется, что шаги выполняются правильно, но когда дело доходит до вычисления среднеквадратичной ошибки, он застревает в значениях около 0.5000.

Может кто-нибудь помочь?Я опубликую свой код, чтобы вы могли проверить его и сказать мне, если вы видите что-то необычное.У меня есть класс с именем Adaline и сценарий, который использует этот класс, веса создаются автоматически в значениях от -1 до 1, а скорость обучения, которую я использую, составляет 0,1.Смещения добавляются во входные данные, добавляя 1 к ним, каждый раз, когда это необходимо.

Что следует сделать, так это то, что если среднеквадратичная ошибка достигнет значения, меньшего allowed_error, это будет означать, чтоон правильно обучен, и пришло время попробовать его еще раз с примерами, и он должен показать значение, очень близкое к ожидаемому с проблемой XOR.

Заранее спасибо.

import numpy as np

class Adaline(object):

def __init__(self, no_of_inputs, learning_rate = 0.1):
    self.weights = np.random.uniform(-1, 1, no_of_inputs + 1)
    self.delta = 0
    self.current_error = 0
    self.propagation_output = 0
    self.learning_rate = learning_rate

def sigmoid(self, prediction):
    return 1 / (1 + np.exp(-prediction))

def derivative(self):
    return self.sigmoid(self.propagation_output) * (1 - self.sigmoid(self.propagation_output))

def summation(self, inputs):
    summation = np.dot(inputs, self.weights)
    return summation

def calculate_output(self, inputs):
    summation = self.summation(inputs)
    self.propagation_output = self.sigmoid(summation)

def train(self, inputs):
    self.weights += self.learning_rate * inputs * self.delta

Скрипт для обучения нейронной сети

import numpy as np
from adaline import Adaline

adaline1 = Adaline(no_of_inputs = 2)
adaline2 = Adaline(no_of_inputs = 2)
adaline3 = Adaline(no_of_inputs = 2)

allowed_error = 0.1
keep_iterating = True

inputs = np.array([
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1],
])

outputs = np.array([
    0,
    1,
    1,
    0
])

network = []
hidden_layer = []
output_layer = []

hidden_layer.append(adaline1)
hidden_layer.append(adaline2)
output_layer.append(adaline3)

network.append(hidden_layer)
network.append(output_layer)

errors = np.empty(outputs.shape)

while keep_iterating:
    sample_number = 0
    for sample, expected_output in zip(inputs, outputs):

        temp_inputs = np.insert(sample, 0, 1) #preprend 1 for the bias

        #propagation
        for i in range(len(network)):
            for j in range(len(network[i])):
                if i != 0:
                    temp_inputs = np.random.rand(len(network[i - 1]) + 1)
                    temp_inputs[0] = 1
                    for _ in (number + 1 for number in range(len(network[i - 1]))):
                        temp_inputs[_] = network[i - 1][_ - 1].propagation_output

                network[i][j].calculate_output(temp_inputs)

        #backpropagating the error
        for i in reversed(range(len(network))):
            for j in range(len(network[i])):
                if i == 1:
                    error = expected_output - network[i][j].propagation_output
                    errors[sample_number] = (error**2)
                    local_gradient = error * network[i][j].derivative()
                else:
                    local_gradient = 0
                    for _ in (range(len(network[i + 1]))):
                        local_gradient += network[i + 1][_].weights[j + 1] * network[i + 1][_].delta
                    local_gradient *= network[i][j].derivative()

                network[i][j].delta = local_gradient

        #updating weights
        for i in range(len(network)):
            for j in range(len(network[i])):
                if i == 0:
                    temp_inputs = np.insert(sample, 0, 1) #preprend 1 for the bias
                else:
                    temp_inputs = np.random.rand(len(network[i - 1]) + 1)
                    temp_inputs[0] = 1
                    for _ in (number + 1 for number in range(len(network[i - 1]))):
                        temp_inputs[_] = network[i - 1][_ - 1].propagation_output

                network[i][j].train(temp_inputs)

        sample_number += 1

    global_error = errors.sum() / 2
    print(global_error)
    print('\n')

    if global_error <= allowed_error:
        keep_iterating = False

print("salidas")
for sample, expected_output in zip(inputs, outputs):
    # propagation
    for i in range(len(network)):
        for j in range(len(network[i])):
            if i != 0:
                temp_inputs = np.random.rand(len(network[i - 1]) + 1)
                temp_inputs[0] = 1 #prepren 1 for the bias
                for _ in (number + 1 for number in range(len(network[i - 1]))):
                    temp_inputs[_] = network[i - 1][_ - 1].propagation_output

            network[i][j].calculate_output(temp_inputs)

            if i == 1:
                print(network[i][j].propagation_output)
...