123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- import numpy as np
- class NeuralNetwork(object):
- def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):
- # Set number of nodes in input, hidden and output layers.
- self.input_nodes = input_nodes
- self.hidden_nodes = hidden_nodes
- self.output_nodes = output_nodes
- # Initialize weights
- self.weights_input_to_hidden = np.random.normal(0.0, self.input_nodes**-0.5,
- (self.input_nodes, self.hidden_nodes))
- self.weights_hidden_to_output = np.random.normal(0.0, self.hidden_nodes**-0.5,
- (self.hidden_nodes, self.output_nodes))
- self.lr = learning_rate
- self.activation_function = lambda x: 1/(1 + np.exp(-x))
- def train(self, features, targets):
- """Train the network on batch of features and targets.
- Arguments:
- - features: 2D array, each row is one data record,
- each column is a feature
- - targets: 1D array of target values
- """
- n_records = features.shape[0]
- delta_weights_i_h = np.zeros(self.weights_input_to_hidden.shape)
- delta_weights_h_o = np.zeros(self.weights_hidden_to_output.shape)
- for X, y in zip(features, targets):
- final_outputs, hidden_outputs = self.forward_pass_train(X)
- delta_weights_i_h, delta_weights_h_o = self.backpropagation(final_outputs, hidden_outputs, X, y,
- delta_weights_i_h, delta_weights_h_o)
- self.update_weights(delta_weights_i_h, delta_weights_h_o, n_records)
- def forward_pass_train(self, X):
- """Forward Pass Method.
- Arguments:
- - X: features batch
- """
- hidden_inputs = np.dot(X, self.weights_input_to_hidden)
- hidden_outputs = self.activation_function(hidden_inputs)
- final_inputs = np.dot(hidden_outputs, self.weights_hidden_to_output)
- final_outputs = final_inputs
- return final_outputs, hidden_outputs
- def backpropagation(self, final_outputs, hidden_outputs, X, y,
- delta_weights_i_h, delta_weights_h_o):
- """Backpropagation.
- Arguments:
- - final_outputs: output from forward pass
- - y: target (i.e. label) batch
- - delta_weights_i_h: change in weights from input to hidden layers
- - delta_weights_h_o: change in weights from hidden to output layers
- """
- # Calculate error: difference between desired target & output
- error = y - final_outputs
- # Calculate the hidden layer's contribution to the error
- hidden_error = np.dot(self.weights_hidden_to_output, error)
- # Backpropagated error terms
- output_error_term = error * 1.0
- hidden_error_term = hidden_error * hidden_outputs * (1 - hidden_outputs)
- # Weight step (input to hidden)
- delta_weights_i_h += hidden_error_term * X[:, None]
- # Weight step (hidden to output)
- delta_weights_h_o += output_error_term * hidden_outputs[:, None]
- return delta_weights_i_h, delta_weights_h_o
- def update_weights(self, delta_weights_i_h, delta_weights_h_o, n_records):
- """Update weights on gradient descent step.
- Arguments:
- - delta_weights_i_h: change in weights from input to hidden layers
- - delta_weights_h_o: change in weights from hidden to output layers
- - n_records: number of records
- """
- # Update hidden-to-output weights with gradient descent step
- self.weights_hidden_to_output += self.lr * delta_weights_h_o/n_records
- # Update input-to-hidden weights with gradient descent step
- self.weights_input_to_hidden += self.lr * delta_weights_i_h/n_records
- def run(self, features):
- """Run a forward pass through the network with input features.
- Arguments:
- - features: 1D array of feature values
- """
- hidden_inputs = np.dot(features, self.weights_input_to_hidden)
- hidden_outputs = self.activation_function(hidden_inputs)
- final_inputs = np.dot(hidden_outputs, self.weights_hidden_to_output)
- final_outputs = final_inputs
- return final_outputs
- #########################################################
- # Set your hyperparameters here
- #########################################################
- iterations = 5000
- learning_rate = 0.5
- hidden_nodes = 10
- output_nodes = 1
|