@Agamendon

Как правильно настроить нейросеть?

Решил написать нейросеть XOR по примеру отсюда:
В итоге сеть правильно просчитывает ответ, а вот с обратным распространением не все так гладко. При тесте с одинаковыми входными значениями при вводе примера из статьи просчет нормальный, при вводе 1, 1 значение ответа сначала падают к нулю, затем стремятся к 0.5. При случайных числах на ввод как правило в какой-то момент значение ответа падает ниже 0.3 и в большинстве случаев идентично для любого ввода.
Буду очень признателен за любую помощью.
Классы нейронов:
import math
from classes import *


class Neuron:

    def __init__(self, previousLayer, selfValue, weightsToNextLayer):
        self.selfValue = selfValue
        self.previousLayer = previousLayer
        self.weightsToNextLayer = weightsToNextLayer
        self.numberInLayer = None
        self.sumFromNextLayer = 0
        self.nextLayer = None
        self.network = None
        self.previousIterations = None
        if self.weightsToNextLayer:
            self.previousIterations = [0 for x in range(len(self.weightsToNextLayer))]

    def counterVectors(self):
        counter = 0
        if self.previousLayer:
            for x in range(self.previousLayer.getLengthOfLayer()):
                counter+= self.previousLayer.getNeuronValueByNumber(x) * self.previousLayer.getNeuronWeightByNumber(x, self.numberInLayer)
        return counter

    def sigmoid(self):
        vectorsResult = self.counterVectors()
        return 1 / (1 + math.exp(-vectorsResult))

    def selfValueDefine(self):
        self.selfValue = self.sigmoid()

    def getSelfValue(self):
        return self.selfValue

    def setNumberInLayer(self, number):
        self.numberInLayer = number

    def functionIn(self):
        return (1 - self.selfValue) * self.selfValue

    def gradient(self, number):
        return self.selfValue * self.nextLayer.neuronsInLayer[number].delta()

    def deltaWeight(self, number):
        return self.network.epsilon * self.gradient(number) + self.network.alpha * self.previousIterations[number]

    def changeWeights(self):
        for x in range(len(self.weightsToNextLayer)):
            self.weightsToNextLayer[x] += self.deltaWeight(x)
            self.previousIterations[x] = self.deltaWeight(x)

    def backpropagation(self):
        self.changeWeights()

    def sumToPreviousLayer(self):
        if self.previousLayer:
            for x in self.previousLayer:
                x.sumFromNextLayer+= self.delta() * x.weightsToNextLayer[self.numberInLayer]


class HiddenNeuron(Neuron):

    def delta(self):
        sum = 0
        for x in range(len(self.weightsToNextLayer)):
            sum += self.weightsToNextLayer[x] * self.nextLayer.getNeuronValueByNumber(x)
        return sum * self.functionIn()


class OutputNeuron(Neuron):

    def __init__(self, previousLayer, selfValue):
        super().__init__(previousLayer, selfValue, None)
        self.idealResult = self.selfValue
        self.selfValue = 0

    def delta(self):
        return (self.idealResult - self.selfValue) * self.functionIn()

    def setIdeal(self, ideal):
        self.idealResult = ideal


class InputNeuron(Neuron):

    def __init__(self, selfValue, weightsToNextLayer):
        super().__init__(None, selfValue, weightsToNextLayer)

    def selfValueDefine(self):
        return self.selfValue

    def getSelfValue(self):
        return self.selfValue


class BiasNeuron(Neuron):

    def __init__(self, weightsToNextLayer):
        super().__init__(None, 1, weightsToNextLayer)

Классы слоя и сети:
import math
from neuron_classes import *


class Layer:

    def __init__(self, neuronsInLayer):
        self.neuronsInLayer = neuronsInLayer
        self.nextLayer = None
        self.network = None

    def initNeurons(self):
        for x in self.neuronsInLayer:
            x.nextLayer = self.nextLayer
            x.network = self.network



    def getNeuronValueByNumber(self, neuronNumber):
        return self.neuronsInLayer[neuronNumber].selfValue

    def getNeuronWeightByNumber(self, neuronNumber, weightNumber):
        return self.neuronsInLayer[neuronNumber].weightsToNextLayer[weightNumber]

    def getLengthOfLayer(self):
        return len(self.neuronsInLayer)

    def calculateNeurons(self):
        counter = 0
        for x in self.neuronsInLayer:
            x.setNumberInLayer(counter)
            x.selfValueDefine()
            counter+= 1

    def layerToString(self):
        convertedLayer = ''
        for x in self.neuronsInLayer:
            convertedLayer += str(x.getSelfValue)
        print(convertedLayer)
        return convertedLayer

    def backpropagation(self):
        for x in self.neuronsInLayer:
            x.backpropagation()



class Network:

    def __init__(self, layers, epsilon, alpha):
        self.layers = layers
        self.epsilon = epsilon
        self.alpha = alpha
        for x in range(len(layers) - 1):
            layers[x].network = self
            layers[x].nextLayer = layers[x + 1]
            layers[x].initNeurons()
        for x in range(len(layers) - 1):
            layers[x].nextLayer = layers[x + 1]
        self.forwardCounts = 0

    def forwardPass(self):
        for x in self.layers:
            x.calculateNeurons()
        self.forwardCounts+= 1
        n = self.layers[len(self.layers) - 1]
        return [self.layers[len(self.layers) - 1].getNeuronValueByNumber(x) for x in range(self.layers[len(self.layers) - 1].getLengthOfLayer())]

    def backpropagation(self):
        x = len(self.layers) - 1
        while x > 0:
            x -= 1
            self.layers[x].backpropagation()

    def setOutputIdealValues(self, outputIdealValues):
        counter = 0
        for x in self.layers[len(self.layers) - 1].neuronsInLayer:
            x.idealValue = outputIdealValues[counter]
            counter+= 1

    def setInputs(self, inputs):
        counter = 0
        for x in self.layers[0].neuronsInLayer:
            if type(x) != BiasNeuron:
                x.selfValue = inputs[counter]
                counter+= 1

    def checkNetwork(self):
        for y in range(len(self.layers)):
            string = ''
            for x in range(len(self.layers[y].neuronsInLayer)):
                string += str(self.layers[y].neuronsInLayer[x].getSelfValue())
                string += ' '
            print(string)


Класс удобного доступа к сети:
from classes import *
from neuron_classes import *


class PackagedNetwork:

    def __init__(self, inputNeuronsNumber, layersNumber, neuronsInLayer, outputNeuronsNumber, epsilon, alpha):
        self.inputNeuronsNumber = inputNeuronsNumber
        self.layersNumber = layersNumber
        self.neuronsInLayer = neuronsInLayer
        self.outputNeuronsNumber = outputNeuronsNumber
        self.epsilon = epsilon
        self.alpha = alpha
        self.layers = [None for x in range(self.layersNumber)]
        self.network = None
        for y in range(layersNumber):
            currentLayer = []
            # input
            if y == 0:
                for x in range(inputNeuronsNumber):
                    currentLayer.append(InputNeuron(0, [1 * (i + 1) for i in range(neuronsInLayer)]))

            # output
            elif y == layersNumber - 1:
                for x in range(outputNeuronsNumber):
                    currentLayer.append(OutputNeuron(self.layers[y - 1], 0))
            # hidden
            elif y == layersNumber - 2:
                for x in range(neuronsInLayer):
                    currentLayer.append(HiddenNeuron(self.layers[y - 1], None, [1 * (i + 1) for i in range(self.outputNeuronsNumber)]))

            else:
                for x in range(neuronsInLayer):
                    currentLayer.append(HiddenNeuron(self.layers[y - 1], None, [1 * (i + 1) for i in range(self.neuronsInLayer)]))

            layer = Layer(currentLayer)
            self.layers[y] = layer
        self.network = Network(self.layers, self.epsilon, self.alpha)

    def forwardPass(self):
        return self.network.forwardPass()

    def backpropagation(self):
        return self.network.backpropagation()

    def setOutputIdealValues(self, outputIdealValues):
        self.network.setOutputIdealValues(outputIdealValues)

    def setInputs(self, inputs):
        self.network.setInputs(inputs)

    def checkNetwork(self):
        self.network.checkNetwork()

Тест 1
from classes import *
from neuron_classes import *
import random

inputLayer = Layer([InputNeuron(1, [0.45, 0.78]), InputNeuron(0, [-0.12, 0.13])])
hiddenLayer = Layer([HiddenNeuron(inputLayer, None, [1.5]), HiddenNeuron(inputLayer, None, [-2.3])])
outputLayer = Layer([OutputNeuron(hiddenLayer, 1)])

network = Network([inputLayer, hiddenLayer, outputLayer], 0.7, 0.8)
for x in range(20):
    print(network.forwardPass())
    network.backpropagation()

Тест 2:
from package_classes import *
from neuron_classes import *
from classes import *
import random

network = PackagedNetwork(2, 3, 2, 1, 0.7, 0.3)

print('xor')
input1 = 0
input2 = 0
idealOutput = 0
for x in range(200):
    input1 = random.randint(0, 1)
    input2 = random.randint(0, 1)
    idealOutput = int(input1 != input2)
    network.setInputs([input1, input2])
    network.setOutputIdealValues([idealOutput])
    network.checkNetwork()
    print(network.forwardPass(), input1, input2, idealOutput)
    print()
    network.backpropagation()
  • Вопрос задан
  • 103 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы