Как исправить код матрицы путаницы нейронной сети - PullRequest
0 голосов
/ 01 мая 2019

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

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

Изменение параметров, таких как скорость обучения, количество скрытых узлов и т. Д., Ничего не дает.Матрица путаницы из модели со случайными весами и отсутствием обучения явно неверна, и она практически не меняется в процессе обучения.

Соответствующий класс:

import numpy as np

class neuralnet:
        """one hidden layer neural network"""
        def __init__(self,inputs,targets,nHid,eta,momentum):
                self.nIn = np.shape(inputs)[1]
                self.nHid = nHid
                self.nOut = np.shape(targets)[1]
                self.eta = eta
                self.nData = np.shape(inputs)[0]
                self.momentum = momentum

                # create random weights, including for bias node
                self.inWeights = np.random.rand(self.nHid,self.nIn+1)*0.1 -0.05
                self.outWeights = np.random.rand(self.nOut,self.nHid+1)*0.1 -0.05

                # for momentum calculation
                self.priorIn = self.inWeights
                self.priorOut = self.outWeights

        def reweight(self):
                # create random weights, including for bias node
                self.inWeights = np.random.rand(self.nHid,self.nIn+1)*0.1 -0.05
                self.OutWeights = np.random.rand(self.nOut,self.nHid+1)*0.1 -0.05

                # for momentum calculation
                self.priorIn = self.inWeights
                self.priorOut = self.outWeights

        def train(self, inputs, targets, eta, rounds, reweight = 0):
                # train for fixed number of rounds

                # reweight
                if reweight:
                        self.reweight()

                # add bias input nodes
                inputs = np.concatenate((inputs,np.ones((self.nData,1))),axis=1)

                # train for # of rounds specified, for each data point
                for _ in range(rounds):
                        for i in range(self.nData):
                                self.outputs = self.step(inputs[i],targets[i])

        def step(self, inputs, targets):
                # one epoch

                # input nodes output
                inOut = np.dot(self.inWeights,inputs.T)

                # hidden node activation function
                hidIn = sigmoid(inOut)

                # add the bias hidden node
                hidIn = np.concatenate((hidIn,[1]),axis=0)

                # hidden nodes output
                hidOut = np.dot(self.outWeights,hidIn)

                # output nodes activation function
                outIn = sigmoid(hidOut)

                outputs = outIn


                # update errors and weights

                #save for momentum calculation
                tempIn = self.priorIn
                tempOut = self.priorOut

                self.priorIn = self.inWeights
                self.priorOut = self.outWeights

                # output node errors
                outErrors = outputs*(1.0-outputs)*(targets - outputs)
                # hidden to output node weight update, including momentum (ignoring bias node)
                self.outWeights += self.eta*np.dot(outErrors,self.outWeights) + self.momentum*(self.outWeights - tempOut)

                # hidden node errors
                hidErrors = hidIn*(1.0-hidIn)*np.dot(self.outWeights.T,outErrors)
                # input to hidden node weight update, including momentum (ignoring bias node)
                self.inWeights += self.eta*np.dot(hidErrors[:-1],self.inWeights) + self.momentum*(self.inWeights - tempIn)

                return outputs

        def eval(self, inputs):
                # run without training

                # add bias node
                inputs = np.concatenate((inputs,[1]))

                # input to hidden
                inOut = np.dot(self.inWeights,inputs.T)
                hidIn = sigmoid(inOut)

                # add bias hidden node
                hidIn = np.concatenate((hidIn,[1]),axis=0)

                # hidden to output
                hidOut = np.dot(self.outWeights,hidIn)
                outIn = sigmoid(hidOut)

                return outIn


        def conMat(self, inputs, targets, p=1):
                # calculate (and print) confusion matrix

                # get number of data points to test
                nTests = np.shape(inputs)[0]

                right = 0
                wrong = 0
                conmat = np.zeros((self.nOut,self.nOut),dtype=int)
                for i in range(nTests):
                        # get result without updating weights
                        output = self.eval(inputs[i])
                        outMax = output.argmax() # one-hot of results
                        targMax = targets[i].argmax() #one-hot of inputs
                        if outMax == targMax:
                                right += 1
                        else:
                                wrong += 1
                        conmat[outMax][targMax] += 1
                if p: #print
                        print(right)
                        print(wrong)
                        print(conmat)
                        print("out/tar")
                        print(output)
                        print(targets[i])

                return right/(right + wrong)


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

[[   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   4   26   50   62    5   21    1    0   37    1]
 [   0    0    0    0    0    0    0    0    0    0]
 [5919 6716 5908 6069 5837 5400 5917 6265 5814 5948]
 [   0    0    0    0    0    0    0    0    0    0]]

дляобучение и

[[   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [   0   12    5    5    0    8    0    0    1    0]
 [   0    0    0    0    0    0    0    0    0    0]
 [ 980 1123 1027 1005  982  884  958 1028  973 1009]
 [   0    0    0    0    0    0    0    0    0    0]]

для проверки данных.

Обучение по сути не тренируется, хотя конкретные цифры меняются немного.

Я подтвердил, что данныеподготовлено правильно, с горячими значениями 0,1 для 0 и 0,9 для 1.

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