class Newral::Networks::Network

Attributes

layers[R]
neurons[R]
output[R]

Public Class Methods

define( &block ) click to toggle source
# File lib/newral/networks/network.rb, line 18
def self.define( &block )
  layout = self.new 
  layout.instance_eval( &block )
  layout
end
new() click to toggle source
# File lib/newral/networks/network.rb, line 12
def initialize
  @layers = {}
  @neurons = {}
  @layer_identifier = "input"
end

Public Instance Methods

add_layer( identifier, &block ) click to toggle source
# File lib/newral/networks/network.rb, line 24
def add_layer( identifier, &block )
  @layer_identifier = identifier
  @layers[ identifier ] = Layer.new( identifier: identifier )
  self.instance_eval &block if block_given?
end
add_neuron( identifier, neuron: nil, weights: nil, bias: nil, weight_length: nil, type: 'sigmoid' ) click to toggle source
# File lib/newral/networks/network.rb, line 30
def add_neuron( identifier, neuron: nil, weights: nil, bias: nil, weight_length: nil, type: 'sigmoid' )
  raise Errors::IdentifierExists if @neurons[ identifier ] && (  neuron || weights || bias )
  unless neuron 
    neuron = case type.to_s 
      when 'perceptron' then Perceptron.new( weights: weights, bias: bias, weight_length: weight_length  )
      when 'sigmoid' then Sigmoid.new( weights: weights, bias: bias , weight_length: weight_length )
    else 
      raise Errors::InvalidType
    end 
  end 
      
  @neurons[ identifier ] = neuron
  @layers[ @layer_identifier ].add_neuron( neuron )
end
calculate( input ) click to toggle source

by implementing these functions we can use a network for all training algorithms (although this is really just a proove of concept as using Greedy for Neural Networks does not lead to great results)

# File lib/newral/networks/network.rb, line 102
def calculate( input )
  update_with_vector( input )
end
calculate_error( input: [],output: [] ) click to toggle source
# File lib/newral/networks/network.rb, line 106
def calculate_error( input: [],output: [] )
  expected_values = [] # output can be longer than input
  calculated_values = []
  input.each_with_index do |x,idx|
    calculated_values << calculate( x )
    expected_values << output[idx] 
  end 
  Newral::ErrorCalculation.mean_square( calculated_values, expected_values  )/2
end
connect( from: nil, to: nil ) click to toggle source

specify the identifiers of the two neurons to connect

# File lib/newral/networks/network.rb, line 46
def connect( from: nil, to: nil )
  input_neuron = @neurons[ to ]
  output_neuron  = @neurons[ from ]
  input_neuron.add_input( output_neuron  )
end
move( direction: 0, step:0.01, step_percentage: nil ) click to toggle source
# File lib/newral/networks/network.rb, line 120
def move( direction: 0, step:0.01, step_percentage: nil )
  raise Errors::InvalidDirection if direction >= number_of_directions
  new_network = Marshal.load(Marshal.dump(self))
  idx = 0
  new_network.neurons.each do |key,neuron|
    if idx+neuron.number_of_directions-1 >= direction #
      meuron = neuron.dup.move( direction: direction-idx, step: step, step_percentage: step_percentage)
      return new_network 
    end 
    idx = idx+neuron.number_of_directions
  end
  new_network
end
move_random( low_range: -0.9, high_range: 0.9 ) click to toggle source
# File lib/newral/networks/network.rb, line 134
def move_random( low_range: -0.9, high_range: 0.9 ) 
  number_of_directions.times do |direction|
    step = low_range+rand()*(high_range.to_f-low_range.to_f) 
    move( direction: direction, step: step )
  end
  self
end
number_of_directions() click to toggle source
# File lib/newral/networks/network.rb, line 116
def number_of_directions
  @neurons.sum{ |n| n[1].number_of_directions }
end
output_of_neuron( identifier ) click to toggle source
# File lib/newral/networks/network.rb, line 85
def output_of_neuron( identifier )
  @neurons[ identifier ].output
end
set_weights_and_bias( layer: 'hidden', weights: [], bias: []) click to toggle source
# File lib/newral/networks/network.rb, line 93
def set_weights_and_bias( layer: 'hidden', weights: [], bias: [])
  @layers[layer].neurons.each_with_index do |neuron,idx|
    neuron.set_weights_and_bias( weights: weights[ idx ], bias: bias[idx])
  end 
end
train( inputs: [], output: [] ) click to toggle source
# File lib/newral/networks/network.rb, line 89
def train( inputs: [], output: [] )
  raise Errors::NotImplemented, "Use Subclass Backpropagation Training"
end
update( &block ) click to toggle source

use this for simple networks were neurons are set by hand

# File lib/newral/networks/network.rb, line 79
def update( &block )
  self.instance_eval( &block ) if block_given?  
  update_layers
  @output
end
update_first_layer_with_vector( input ) click to toggle source
# File lib/newral/networks/network.rb, line 52
def update_first_layer_with_vector( input )
  layer = @layers.first
  @output = layer[1].neurons.collect do |n|
    n.update_with_vector input
  end
  @output 
end
update_layers( start:0 ) click to toggle source
# File lib/newral/networks/network.rb, line 64
def update_layers( start:0 )
  @layers.to_a[start..@layers.size].each do |layer |
    @output = layer[1].neurons.collect do |n|
        n.output
    end 
  end
end
update_neuron( identifier, input ) click to toggle source
# File lib/newral/networks/network.rb, line 60
def update_neuron( identifier, input  )
  @neurons[ identifier ].update_with_vector( input )
end
update_with_vector( input ) click to toggle source
# File lib/newral/networks/network.rb, line 72
def update_with_vector( input )
  update_first_layer_with_vector( input )
  update_layers( start: 1)
  @output 
end