Class: Noggin::Network

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

Constant Summary collapse

DEFAULTS =
{
  learning_rate: 0.3,
  momentum: 1,
  training_laps: 50000,
  hidden_layer_size: 1,
  hidden_layer_node_size: 2,
  min_training_error: 0.001
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**opts) ⇒ Network

Returns a new instance of Network.



15
16
17
18
19
# File 'lib/noggin/network.rb', line 15

def initialize **opts
  @options = DEFAULTS.merge opts
  @layers = []
  @ready = false
end

Instance Attribute Details

#forward_inputObject

Returns the value of attribute forward_input.



4
5
6
# File 'lib/noggin/network.rb', line 4

def forward_input
  @forward_input
end

#forward_outputObject

Returns the value of attribute forward_output.



4
5
6
# File 'lib/noggin/network.rb', line 4

def forward_output
  @forward_output
end

#layersObject

Returns the value of attribute layers.



4
5
6
# File 'lib/noggin/network.rb', line 4

def layers
  @layers
end

#optionsObject

Returns the value of attribute options.



4
5
6
# File 'lib/noggin/network.rb', line 4

def options
  @options
end

Instance Method Details

#input_set_sizeObject



119
120
121
# File 'lib/noggin/network.rb', line 119

def input_set_size
  forward_input.first[:input].size
end

#pretty_printObject



123
124
125
# File 'lib/noggin/network.rb', line 123

def pretty_print
  Noggin::PrettyPrinter.print_network self
end

#run(input) ⇒ Object



41
42
43
44
45
# File 'lib/noggin/network.rb', line 41

def run input
  setup_input input
  run_forwards input
  layers.last.neurons.first.forward_output
end

#run_backwardsObject



56
57
58
# File 'lib/noggin/network.rb', line 56

def run_backwards
  layers.reverse[1..-1].each(&:backward_activate!)
end

#run_for_error(input) ⇒ Object



47
48
49
50
# File 'lib/noggin/network.rb', line 47

def run_for_error input
  run_forwards input
  layers.last.neurons.inject(0){ |sum, neuron| sum += neuron.forward_error_output }
end

#run_forwards(input) ⇒ Object



52
53
54
# File 'lib/noggin/network.rb', line 52

def run_forwards input
  layers[1..-1].each(&:forward_activate!)
end

#setup_backwardsObject



108
109
110
111
112
113
# File 'lib/noggin/network.rb', line 108

def setup_backwards
  layers.last.neurons.each do |output_neuron|
    output_neuron.backward_activate_error!
    output_neuron.backward_activate!
  end
end

#setup_expected(expected) ⇒ Object



115
116
117
# File 'lib/noggin/network.rb', line 115

def setup_expected expected
  layers.last.neurons.each { |neuron| neuron.expected = expected }
end

#setup_hidden_layersObject



82
83
84
85
86
87
88
89
# File 'lib/noggin/network.rb', line 82

def setup_hidden_layers
  options[:hidden_layer_size].times do |i|
    hidden_layer = Layer.new
    hidden_layer.neurons = Array.new(options[:hidden_layer_node_size]){ Noggin::Neuron.new }
    Noggin::Layer.connect_layers layers.last, hidden_layer, options[:momentum]
    layers << hidden_layer
  end
end

#setup_input(set) ⇒ Object



98
99
100
101
102
103
104
105
106
# File 'lib/noggin/network.rb', line 98

def setup_input set
  layers.first.neurons.each_with_index do |neuron, i|
    neuron.forward_input = neuron.forward_output = set[i]
    neuron.dests.each do |edge|
      edge.forward_input = neuron.forward_output
      edge.forward_activate!
    end
  end
end

#setup_input_layerObject



76
77
78
79
80
# File 'lib/noggin/network.rb', line 76

def setup_input_layer
  input_layer = Layer.new
  input_layer.neurons = Array.new(input_set_size){ Noggin::Neuron.new }
  layers << input_layer
end

#setup_layersObject



69
70
71
72
73
74
# File 'lib/noggin/network.rb', line 69

def setup_layers
  setup_input_layer
  setup_hidden_layers
  setup_output_layer
  @ready = true
end

#setup_output_layerObject



91
92
93
94
95
96
# File 'lib/noggin/network.rb', line 91

def setup_output_layer
  output_layer = Layer.new
  output_layer.neurons = [ Noggin::Neuron.new ]
  Noggin::Layer.connect_layers layers.last, output_layer, options[:momentum]
  layers << output_layer
end

#train(data_set) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/noggin/network.rb', line 21

def train data_set
  @forward_input = data_set
  setup_layers unless @ready
  error = Float::INFINITY
  laps = 0
  until laps >= options[:training_laps] || error < options[:min_training_error] do
    laps += 1
    error = 0
    data_set.each do |set|
      setup_input set[:input]
      setup_expected set[:expected]
      error += run_for_error set[:input]
      setup_backwards
      run_backwards
      update_weights
    end
  end
  { total_error: error, training_laps_needed: laps }
end

#update_weightsObject



60
61
62
63
64
65
66
67
# File 'lib/noggin/network.rb', line 60

def update_weights
  layers.each do |layer|
    layer.bias.learn! if layer.bias
    layer.neurons.each do |neuron|
      neuron.dests.each(&:learn!)
    end
  end
end