Class: Newral::Networks::Network

Inherits:
Object
  • Object
show all
Defined in:
lib/newral/networks/network.rb

Direct Known Subclasses

BackpropagationNetwork

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNetwork

Returns a new instance of Network.



12
13
14
15
16
# File 'lib/newral/networks/network.rb', line 12

def initialize
  @layers = {}
  @neurons = {}
  @layer_identifier = "input"
end

Instance Attribute Details

#layersObject (readonly)

Returns the value of attribute layers.



10
11
12
# File 'lib/newral/networks/network.rb', line 10

def layers
  @layers
end

#neuronsObject (readonly)

Returns the value of attribute neurons.



10
11
12
# File 'lib/newral/networks/network.rb', line 10

def neurons
  @neurons
end

#outputObject (readonly)

Returns the value of attribute output.



10
11
12
# File 'lib/newral/networks/network.rb', line 10

def output
  @output
end

Class Method Details

.define(&block) ⇒ Object



18
19
20
21
22
# File 'lib/newral/networks/network.rb', line 18

def self.define( &block )
  layout = self.new 
  layout.instance_eval( &block )
  layout
end

Instance Method Details

#add_layer(identifier, &block) ⇒ Object



24
25
26
27
28
# 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') ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 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) ⇒ Object

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)



102
103
104
# File 'lib/newral/networks/network.rb', line 102

def calculate( input )
  update_with_vector( input )
end

#calculate_error(input: [], output: []) ⇒ Object



106
107
108
109
110
111
112
113
114
# 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) ⇒ Object

specify the identifiers of the two neurons to connect



46
47
48
49
50
# 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) ⇒ Object

Raises:

  • (Errors::InvalidDirection)


120
121
122
123
124
125
126
127
128
129
130
131
132
# 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) ⇒ Object



134
135
136
137
138
139
140
# 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_directionsObject



116
117
118
# 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) ⇒ Object



85
86
87
# 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: []) ⇒ Object



93
94
95
96
97
# 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: []) ⇒ Object



89
90
91
# File 'lib/newral/networks/network.rb', line 89

def train( inputs: [], output: [] )
  raise Errors::NotImplemented, "Use Subclass Backpropagation Training"
end

#update(&block) ⇒ Object

use this for simple networks were neurons are set by hand



79
80
81
82
83
# 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) ⇒ Object



52
53
54
55
56
57
58
# 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) ⇒ Object



64
65
66
67
68
69
70
# 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) ⇒ Object



60
61
62
# File 'lib/newral/networks/network.rb', line 60

def update_neuron( identifier, input  )
  @neurons[ identifier ].update_with_vector( input )
end

#update_with_vector(input) ⇒ Object



72
73
74
75
76
# 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