Advertisement
Guest User

Untitled

a guest
Mar 28th, 2019
562
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.37 KB | None | 0 0
  1. # Backprop on the Seeds self.dataset
  2. from random import seed
  3. from random import randrange
  4. from random import random
  5. from csv import reader
  6. from math import exp
  7. import csv
  8. from pandas import DataFrame
  9. import pandas as pd
  10. import pickle
  11. import collections
  12. import numpy as np
  13. import math
  14.  
  15. class BP:
  16.     def __init__(self,n_inputs, n_outputs, n_neurons, n_folds, l_rate, n_epoch, n_of_network,activation_function="sigmoid", optimizer='none', filename="dataset_", derivated=0, parents=[], bias=0):
  17.         self.n_inputs = n_inputs
  18.         self.n_outputs = n_outputs
  19.         self.n_neurons = n_neurons      #is a list where each element rappresent the number of neurons in each layer of the nn
  20.         self.n_folds = n_folds
  21.         self.l_rate = l_rate
  22.         self.n_epoch = n_epoch
  23.         self.n_hidden_layers = len(self.n_neurons)
  24.         #for other networks select the dataset file correct
  25.         if n_of_network != 0:
  26.             self.filename = filename
  27.         else :
  28.             self.filename = filename
  29.         self.n_gains = list()
  30.         self.n_gains.append(n_inputs)
  31.         self.network_output = list()
  32.         self.n_of_network=n_of_network
  33.         self.accurancy = 0
  34.         self.derivated = derivated          #indicates if a nn has others nn as input
  35.         self.parents = parents              #list of nns which output is part of the input of the new nn
  36.         self.bias = bias                    #add a bias
  37.         self.a = 0
  38.  
  39.         #this for is used for create a nn with a desired number of neurons in each layer
  40.         for i in range(len(self.n_neurons)):
  41.             self.n_gains.append(self.n_neurons[i])
  42.  
  43.         self.activation_function = activation_function    #activation functions "relu" or "sigmoid"
  44.         #used in adam optimization algorithm
  45.         self.optimizer = optimizer
  46.         self.alpha = l_rate
  47.         self.beta_1 = 0.9
  48.         self.beta_2 = 0.999  # initialize the values of the parameters
  49.         self.epsilon = 1e-8
  50.         self.m_t = 0
  51.         self.v_t = 0
  52.         self.t = 0
  53.  
  54.  
  55.     # Load a CSV file
  56.     def load_csv(self, filename):
  57.         self.dataset = list()
  58.         with open(filename, 'r') as file:
  59.             csv_reader = reader(file)
  60.             for row in csv_reader:
  61.                 if not row:
  62.                     continue
  63.                 self.dataset.append(row)
  64.                 #add bias
  65.                 if self.bias !=0:
  66.                     temp= self.dataset[-1][-1]
  67.                     self.dataset[-1][-1] = '1'
  68.                     self.dataset[-1].extend('0')
  69.                     self.dataset[-1][-1]= temp
  70.         return self.dataset
  71.  
  72.     def load_derivated_csv(self, filename):
  73.         self.dataset = list()
  74.         j = 0
  75.         print (filename)
  76.         with open(filename, 'r') as file:
  77.             csv_reader = reader(file)
  78.             for row in csv_reader:
  79.                 if not row:
  80.                     continue
  81.                 self.dataset.append(row[:-1])
  82.                 for i in range(len(self.parents)):
  83.                     self.dataset[-1].extend([str(h) for h in self.parents[i].network_output[j]])
  84.                 j = j+1
  85.                 #add bias
  86.                 if self.bias !=0:
  87.                     self.dataset[-1].extend(['1'])
  88.                 self.dataset[-1].extend([row[-1]])
  89.                 #self.dataset[-1] = [str(i) for i in self.dataset]
  90.         return self.dataset
  91.  
  92.  
  93.     # Convert string column to float
  94.     def str_column_to_float(self, dataset, column):
  95.         for row in dataset:
  96.             row[column] = float(row[column].strip())
  97.  
  98.  
  99.     # Convert string column to integer
  100.     def str_column_to_int(self, dataset, column):
  101.         class_values = [row[column] for row in dataset]
  102.         unique = set(class_values)
  103.         lookup = dict()
  104.         for i, value in enumerate(unique):
  105.             lookup[value] = i
  106.         for row in dataset:
  107.             row[column] = lookup[row[column]]
  108.         return lookup
  109.  
  110.  
  111.     # Find the min and max values for each column
  112.     def dataset_minmax(self, dataset):
  113.         minmax = list()
  114.         stats = [[min(column), max(column)] for column in zip(*dataset)]
  115.         return stats
  116.  
  117.  
  118.     # Rescale self.dataset columns to the range 0-1
  119.     def normalize_dataset(self, dataset, minmax):
  120.         for row in dataset:
  121.             for i in range(len(row) - 1):
  122.                 if (minmax[i][1] - minmax[i][0]) != 0:
  123.                     row[i] = (row[i] - minmax[i][0]) / (minmax[i][1] - minmax[i][0])
  124.  
  125.  
  126.     # Split a self.dataset into k folds
  127.     def cross_validation_split(self, dataset, n_folds):
  128.         dataset_split = list()
  129.         dataset_copy = list(dataset)
  130.         fold_size = int(len(dataset) / n_folds)
  131.         for i in range(n_folds):
  132.             fold = list()
  133.             while len(fold) < fold_size:
  134.                 index = randrange(len(dataset_copy))
  135.                 fold.append(dataset_copy.pop(index))
  136.             dataset_split.append(fold)
  137.         return dataset_split
  138.  
  139.     # Calculate accuracy percentage
  140.     def accuracy_metric(self,actual, predicted):
  141.         correct = 0
  142.         for i in range(len(actual)):
  143.             if actual[i] == predicted[i]:
  144.                 correct += 1
  145.         return correct / float(len(actual)) * 100.0
  146.  
  147.  
  148.     # Evaluate an algorithm using a cross validation split
  149.     def evaluate_algorithm(self, dataset, algorithm, n_folds, *args):
  150.         folds = self.cross_validation_split(dataset, n_folds)
  151.         scores = list()
  152.         for fold in folds:
  153.             train_set = list(folds)
  154.             train_set.remove(fold)
  155.             train_set = sum(train_set, [])
  156.             test_set = list()
  157.             for row in fold:
  158.                 row_copy = list(row)
  159.                 test_set.append(row_copy)
  160.                 row_copy[-1] = None
  161.             predicted = algorithm(train_set, test_set, *args)
  162.             actual = [row[-1] for row in fold]
  163.             accuracy = self.accuracy_metric(actual, predicted)
  164.             scores.append(accuracy)
  165.         return scores
  166.  
  167.  
  168.     # Calculate neuron activation for an input
  169.     def activate(self,weights, inputs):
  170.         activation = weights[-1]
  171.         for i in range(len(weights) - 1):
  172.             activation += weights[i] * inputs[i]
  173.         return activation
  174.  
  175.  
  176.     # Transfer neuron activation
  177.     def transfer(self,activation):
  178.         if self.activation_function == 'sigmoid':
  179.             return 1.0 / (1.0 + exp(-activation))
  180.         elif self.activation_function == 'relu':
  181.             if activation>=0:
  182.                 return activation
  183.             else:
  184.                 return 0.1*activation           #leaky relu
  185.  
  186.     # Forward propagate input to a network output
  187.     def forward_propagate(self,network, row):
  188.         inputs = row
  189.         for layer in network:
  190.             new_inputs = []
  191.             for neuron in layer:
  192.                 activation = self.activate(neuron['weights'], inputs)
  193.                 neuron['output'] = self.transfer(activation)
  194.                 new_inputs.append(neuron['output'])
  195.                 neuron['activation']= activation            #added so that can be use in relu activation function
  196.             inputs = new_inputs
  197.         return inputs
  198.  
  199.     # Calculate the derivative of an neuron output
  200.     def transfer_derivative(self,output):
  201.         if self.activation_function == 'sigmoid':
  202.             return output * (1.0 - output)
  203.         elif self.activation_function == 'relu':
  204.             if output >=0:
  205.                 return 1
  206.             else:
  207.                 return 0.1              #leaky relu
  208.  
  209.     # Backpropagate error and store in neurons
  210.     def backward_propagate_error(self,network, expected):
  211.         for i in reversed(range(len(network))):
  212.             layer = network[i]
  213.             errors = list()
  214.             #for all layers apart the last one
  215.             if i != len(network) - 1:
  216.                 for j in range(len(layer)):
  217.                     error = 0.0
  218.                     for neuron in network[i + 1]:
  219.                         error += (neuron['weights'][j] * neuron['delta'])
  220.                     errors.append(error)
  221.             #for the last layer
  222.             else:
  223.                 for j in range(len(layer)):
  224.                     neuron = layer[j]
  225.                     errors.append(expected[j] - neuron['output'])
  226.             #in the previous it's just calculated the delta*weights and now is processed the same operation for all layers that is multiply what we got for the derivative
  227.             for j in range(len(layer)):
  228.                 neuron = layer[j]
  229.                 #
  230.                 if self.optimizer == 'none':
  231.                     if self.activation_function == 'sigmoid':
  232.                         neuron['delta'] = errors[j] * self.transfer_derivative(neuron['output'])
  233.                     elif self.activation_function == 'relu':
  234.                         neuron['delta'] = errors[j] * self.transfer_derivative(neuron['activation'])
  235.                 elif self.optimizer == 'adam':
  236.                     if self.activation_function == 'sigmoid':
  237.                         neuron['delta'] = self.transfer_derivative(neuron['output'])
  238.                     elif self.activation_function == 'relu':
  239.                         neuron['delta'] = self.transfer_derivative(neuron['activation'])
  240.  
  241.     # Update network weights with error
  242.     def update_weights(self,network, row, l_rate):
  243.         for i in range(len(network)):
  244.             inputs = row[:-1]
  245.             if i != 0:
  246.                 inputs = [neuron['output'] for neuron in network[i - 1]]
  247.             for neuron in network[i]:
  248.                 for j in range(len(inputs)):
  249.                     if self.optimizer == 'none':
  250.                         neuron['weights'][j] += l_rate * neuron['delta'] * inputs[j]
  251.                         neuron['weights'][-1] += l_rate * neuron['delta']
  252.                     elif self.optimizer == 'adam':
  253.                         neuron['weights'][j] += neuron['delta'] * inputs[j]
  254.                         g_t = neuron['delta']  # computes the gradient of the stochastic function
  255.                         self.m_t = self.beta_1 * self.m_t + (1 - self.beta_1) * g_t  # updates the moving averages of the gradient
  256.                         self.v_t = self.beta_2 * self.v_t + (1 - self.beta_2) * (g_t * g_t)  # updates the moving averages of the squared gradient
  257.                         m_cap = self.m_t / (1 - (self.beta_1 ** self.t))  # calculates the bias-corrected estimates
  258.                         v_cap = self.v_t / (1 - (self.beta_2 ** self.t))  # calculates the bias-corrected estimates
  259.                         previous_weight = neuron['weights'][j]
  260.                         neuron['weights'][-1] +=  (self.alpha * m_cap) / (math.sqrt(v_cap) + self.epsilon)  # updates the parameters
  261.  
  262.     # Train a network for a fixed number of epochs
  263.     def train_network(self,network, train, l_rate, n_epoch, n_outputs):
  264.         #outputs_dataframe=pd.DataFrame([],columns=[1,2,3])
  265.         for epoch in range(n_epoch):
  266.             self.t += 1  # used in adam algorithm
  267.             for row in train:
  268.                 outputs = self.forward_propagate(network, row)
  269.                 expected = [0 for i in range(n_outputs)]
  270.                 expected[row[-1]] = 1
  271.                 self.backward_propagate_error(network, expected)
  272.                 self.update_weights(network, row, l_rate)
  273.  
  274.     # Initialize a network
  275.     def initialize_network(self,n_inputs, n_hidden, n_outputs):
  276.         network = list()
  277.         #this part allow to create a desired number of neurons for each layer
  278.         hidden_layer = [[{'weights': [random() for l in range(self.n_gains[j])]} for i in range(self.n_neurons[j])] for j in
  279.                         range(self.n_hidden_layers)]
  280.         for i in range(len(hidden_layer)):
  281.             network.append(hidden_layer[i])
  282.         output_layer = [{'weights': [random() for i in range(self.n_gains[-1])]} for i in range(n_outputs)]
  283.         network.append(output_layer)
  284.         return network
  285.  
  286.  
  287.     # Make a prediction with a network
  288.     def predict(self,network, row):
  289.         outputs = self.forward_propagate(network, row)
  290.         self.network_output.append(outputs)
  291.         return outputs.index(max(outputs))
  292.  
  293.  
  294.     # Backpropagation Algorithm With Stochastic Gradient Descent
  295.     def back_propagation(self,train, test, l_rate, n_epoch, n_hidden):
  296.         self.network = self.initialize_network(self.n_inputs, self.n_hidden_layers, self.n_outputs)
  297.         self.train_network(self.network, train, l_rate, n_epoch, self.n_outputs)
  298.         self.save_nnt()
  299.         predictions = list()
  300.         for row in test:
  301.             prediction = self.predict(self.network, row)
  302.             predictions.append(prediction)
  303.         return (predictions)
  304.  
  305.     #function used for save nn trained
  306.     def save_nnt(self):
  307.         save_nnt_name = "trained_network_"+str(self.n_of_network)
  308.         with open(save_nnt_name, 'wb') as fp:
  309.             pickle.dump(self.network, fp)
  310.  
  311.     # function used for load nn trained
  312.     def load_nnt(self):
  313.         load_nnt_name = "trained_network_"+str(self.n_of_network)
  314.         with open(load_nnt_name, 'rb') as fp:
  315.             self.network = pickle.load(fp)
  316.  
  317.     #used for debugging purpose
  318.     def print_weights(self):
  319.         for i in range(len(self.network)):
  320.             for neuron in self.network[i]:
  321.                 print ("Layer: {}\tWeight: {}".format(i, neuron['weights']))
  322.  
  323.     def main_program(self):
  324.         self.dataset = self.load_csv(self.filename)
  325.         if self.derivated == 0:
  326.             self.dataset = self.load_csv(self.filename)
  327.         else:
  328.             self.dataset = self.load_derivated_csv(self.filename)
  329.         for i in range(len(self.dataset[0]) - 1):
  330.             self.str_column_to_float(self.dataset, i)
  331.         # convert class column to integers
  332.         self.str_column_to_int(self.dataset, len(self.dataset[0]) - 1)
  333.         # normalize input variables
  334.         minmax = self.dataset_minmax(self.dataset)
  335.         self.normalize_dataset(self.dataset, minmax)
  336.         scores = self.evaluate_algorithm(self.dataset, self.back_propagation, self.n_folds, self.l_rate, self.n_epoch, self.n_hidden_layers)
  337.         #print('Scores: %s' % scores)
  338.         self.accurancy = (sum(scores) / float(len(scores)))
  339.         print('Mean Accuracy: %.3f%%' % self.accurancy)
  340.         return self.accurancy
  341.  
  342. acc=list()
  343. bp = list()
  344. bp.append(BP(4, 3, [4], 5, 0.3, 500, 0,"sigmoid", "none","IrisDataTrain.csv", 0, [], 0))
  345. bp[0].main_program()
  346. bp[0].print_weights()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement