import numpy import math import random from matplotlib import pyplot class Neural: # constructor def __init__(self, n_input, n_hidden, n_output): self.hidden_weight = numpy.random.random_sample((n_hidden, n_input + 1)) self.output_weight = numpy.random.random_sample((n_output, n_hidden + 1)) self.hidden_momentum = numpy.zeros((n_hidden, n_input + 1)) self.output_momentum = numpy.zeros((n_output, n_hidden + 1)) # public method def train(self, X, T, epsilon, mu, epoch): self.error = numpy.zeros(epoch) N = X.shape[0] for epo in range(epoch): for i in range(N): x = X[i, :] t = T[i, :] self.__update_weight(x, t, epsilon, mu) self.error[epo] = self.__calc_error(X, T) def predict(self, X): N = X.shape[0] C = numpy.zeros(N).astype('int') Y = numpy.zeros((N, X.shape[1])) for i in range(N): x = X[i, :] z, y = self.__forward(x) Y[i] = y C[i] = y.argmax() return (C, Y) def error_graph(self): pyplot.ylim(0.0, 2.0) pyplot.plot(numpy.arange(0, self.error.shape[0]), self.error) pyplot.show() # private method def __sigmoid(self, arr): return numpy.vectorize(lambda x: 1.0 / (1.0 + math.exp(-x)))(arr) def __forward(self, x): # z: output in hidden layer, y: output in output layer z = self.__sigmoid(self.hidden_weight.dot(numpy.r_[numpy.array([1]), x])) y = self.__sigmoid(self.output_weight.dot(numpy.r_[numpy.array([1]), z])) return (z, y) def __update_weight(self, x, t, epsilon, mu): z, y = self.__forward(x) # update output_weight output_delta = (y - t) * y * (1.0 - y) _output_weight = self.output_weight self.output_weight -= epsilon * output_delta.reshape((-1, 1)) * numpy.r_[numpy.array([1]), z] - mu * self.output_momentum self.output_momentum = self.output_weight - _output_weight # update hidden_weight hidden_delta = (self.output_weight[:, 1:].T.dot(output_delta)) * z * (1.0 - z) _hidden_weight = self.hidden_weight self.hidden_weight -= epsilon * hidden_delta.reshape((-1, 1)) * numpy.r_[numpy.array([1]), x] self.hidden_momentum = self.hidden_weight - _hidden_weight def __calc_error(self, X, T): N = X.shape[0] err = 0.0 for i in range(N): x = X[i, :] t = T[i, :] z, y = self.__forward(x) err += (y - t).dot((y - t).reshape((-1, 1))) / 2.0 return err