Обучение нейронной сети XOR без матриц - PullRequest
0 голосов
/ 09 января 2019

Хотел построить типичную обучаемую нейронную сеть, управляемую XOR, чтобы помочь мне учиться. Однако я не хотел использовать матрицы, потому что это то, что делал каждый учебник, и я хотел убедиться, что я действительно понимаю, что происходит, а не просто копировать и вставлять код и обманывать себя, думая, что я его понял.

Структура сети 3 слоя. 2 входа, 2 скрытых узла и 1 выход.

nn = NeuralNet.NN(2, 2, 1)
print("Training: ")
nn.train([0, 0], 0)  # (trainingData[0][0][0], trainingData[0][1][0])
for x in range(100):
    randomChoice = random.randint(0, 3)
    if randomChoice == 0:
        nn.train([0, 0], 0)
    if randomChoice == 1:
        nn.train([0, 1], 1)
    if randomChoice == 2:
        nn.train([1, 0], 1)
    if randomChoice == 3:
        nn.train([1, 1], 0)

print("Final Test: ")
nn.inputNeurons = [0, 0]
finalOutput = nn.feedForward()
print(str(finalOutput))

nn.inputNeurons = [0, 1]
finalOutput = nn.feedForward()
print(str(finalOutput))

nn.inputNeurons = [1, 0]
finalOutput = nn.feedForward()
print(str(finalOutput))

nn.inputNeurons = [1, 1]
finalOutput = nn.feedForward()
print(str(finalOutput))

класс NN:

inputNeurons = []
hiddenNeurons = []

inputWeights = None
hiddenWeights = None

def __init__(self, inputNeuronsSize, hiddenNeuronsSize, outputNeuronsSize):

    for x in range(inputNeuronsSize):
        self.inputNeurons.append(0) # initializing all weights to 0
    for x in range(hiddenNeuronsSize):
        self.hiddenNeurons.append(0)  # initializing all weights to 0

    self.inputWeights = [[0 for x in range(inputNeuronsSize)] for y in range(hiddenNeuronsSize)]
    self.hiddenWeights = [0 for x in range(hiddenNeuronsSize)]

    print("IN: "+str(self.inputNeurons))
    print("HN: "+str(self.hiddenNeurons))

    print("-Weights-")

    print(str(self.inputWeights))
    print(str(self.hiddenWeights))

def train(self, inputData, target):
    learningRate = 0.01
    self.inputNeurons = inputData
    output = self.feedForward()
    print("Training output: "+str(output))
    hiddenLayerError = target - output  # obtaining error
    # print("THEE ERROR: "+str(hiddenLayerError)+" | "+str(output)+" | "+str(target))

    hiddenLayerDelta = hiddenLayerError * self.dSigmoid(output) * learningRate  # obtaining how much to change hidden layer by
    #print("\tHLE: "+str(hiddenLayerError)+" | dSigmoid(output): "+str(self.dSigmoid(output)))
    #print("\tHLD: "+str(hiddenLayerDelta))

    inputLayerError = 0  # obtaining amount of error the input weights contributed
    for i in range(len(self.inputWeights)):
        for j in range(len(self.inputWeights[i])):
            inputLayerError += hiddenLayerDelta * self.inputWeights[i][j]

    inputLayerDot = 0  # dot product of inputs and their weights
    for i in range(len(self.inputWeights)):
        for j in range(len(self.inputWeights[i])):
            inputLayerDot += inputData[i] * self.inputWeights[i][j]

    #print(str("ILD: "+str(inputLayerDot)+" | sigmoid(ILD):"+str(self.sigmoid(inputLayerDot))))
    #print("")
    inputLayerDelta = inputLayerError * self.sigmoid(inputLayerDot) * learningRate  # obtaining how much to change input layer
    print("\tILE: "+str(inputLayerError)+" | sigmoid(ILD): "+str(self.sigmoid(inputLayerDot)))
    #print("ILD: "+str(inputLayerDelta))

    # changing input layer weights
    for i in range(len(self.inputWeights)):
        for j in range(len(self.inputWeights[i])):
            self.inputWeights[i][j] += inputLayerDelta #* inputData[j]

    # changing hidden layer weights
    for i in range(len(self.hiddenWeights)):
        self.hiddenWeights[i] += hiddenLayerDelta #* self.hiddenNeurons[i]

    print("\tNew Input Weights: "+str(self.inputWeights))
    print("\tNew Hidden Weights: "+str(self.hiddenWeights))

    def feedForward(self):
    #print("lenHN: "+str(len(self.hiddenNeurons)))
    for i in range(len(self.hiddenNeurons)):
        self.hiddenNeurons[i] = 0
        for j in range(len(self.inputWeights[i])):
            self.hiddenNeurons[i] += self.inputNeurons[j] * self.inputWeights[i][j]
            #print("\t"+str(self.inputNeurons[j])+" | "+str(self.inputWeights[i][j]))
        self.hiddenNeurons[i] = self.sigmoid(self.hiddenNeurons[i])
    #print("Finished with hidden calcs")
    output = 0
    for i in range(len(self.hiddenWeights)):
        output += self.hiddenNeurons[i] * self.hiddenWeights[i]
        #print(str(self.hiddenNeurons[i])+" | "+str(self.hiddenWeights[i]))

def sigmoid(self, x):
        return 1 / (1 + math.exp(-x))

def dSigmoid(self, y):
    return y * (1 - y)

сколько бы раз я ни тренировал его, я получаю такой тип вывода:

Final Test: 
0.5
0.9830156970671703
0.9830156970671703
0.9997015683209125

Я почти уверен, что моя ошибка лежит в методе train (), так как это единственная часть, которую я не чувствую, я полностью понимаю.

Edit:

...