Class: NeuralNet

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeNeuralNet

Returns a new instance of NeuralNet.



9
10
11
12
13
# File 'lib/neuralnet.rb', line 9

def initialize
  @id = UUID.new.to_s.split(':')[1].chop
  @network = []
  @sigma = 0.05
end

Instance Attribute Details

#idObject

Returns the value of attribute id.



6
7
8
# File 'lib/neuralnet.rb', line 6

def id
  @id
end

#inputObject

Returns the value of attribute input.



6
7
8
# File 'lib/neuralnet.rb', line 6

def input
  @input
end

#networkObject (readonly)

Returns the value of attribute network.



7
8
9
# File 'lib/neuralnet.rb', line 7

def network
  @network
end

Instance Method Details

#cloneObject



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/neuralnet.rb', line 180

def clone
  clone = NeuralNet.new
  clone.sigma = self.sigma
  clone.tau = self.tau
  clone.width = self.width
  clone.height = self.height
  
  #iterate in through each tier
  @network.each do |tier|
    nodes = []
    tier.each do |node|
      cloned_node = node.clone
      cloned_node.detatch_all_forward_nodes
      nodes << cloned_node
    end
    clone.network << nodes
  end
  #now relink the network
  clone.link_tiers
  #and send back our clone
  clone
end

#evaluateObject



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/neuralnet.rb', line 15

def evaluate 
  #we expect to find one input value in input for each of our input nodes
  input_nodes = @network.first
  
  i = 0
  input_nodes.each do |node|
    node.input_value = @input[i]
    i += 1
  end
  
  @network.each do |tier|
    tier.each do |node|
      node.evaluate
    end
  end
  
  self.output
end

#fingerprintObject



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/neuralnet.rb', line 119

def fingerprint
  topline = ""
  fingerprint = ""
  @network.each do |tier|
    topline << "#{tier.count},"
    tier.each do |node| 
      fingerprint << node.fingerprint
    end
  end  
  topline.chop + "\n" + @sigma.to_s + "\n" + @tau.to_s + "\n" + @width.to_s + "\n" + @height.to_s + "\n"+ fingerprint
end

#generate(options) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/neuralnet.rb', line 46

def generate options 
  inputs = 1
  if options[:inputs]
    inputs = options[:inputs]
  end
  outputs = 1
  if options[:outputs]
    outputs = options[:outputs]
  end
  tiers = 2
  if options[:tiers]
    tiers = options[:tiers]
  end
  @width = 0
  if options[:width]
    @width = options[:width]
  end
  @height = 0
  if options [:height]
    @height = options[:height]
  end

  @network = []
  input_nodes = []
  inputs.times do 
    input_nodes << Node.new(@sigma)
  end
  if input_nodes.count > 0
    @network << input_nodes
  end
  if height > 1 && width > 1

    if width == height
      #ok, slightly impure but this is our clue
      #that we're dealing with a 2D board and we're going 
      #to insert a special layer to reflect the board topology
      tiers = tiers -1
      tier = []
      n = 2
      i = 0
      j = 0
      (height - n).times do
        (width - n).times do
          node = Node.new(@sigma)
        end    
        n  = n + 1
        i += 1
      end
      @network << tier
    else
      #for now we will not bother with rectangles 
    end
   
  end
  (tiers - 2).times do
    tier = []
    10.times do
      tier << Node.new(@sigma)
    end
    @network << tier
  end
  
  output_nodes = []
  outputs.times do
    output_nodes << Node.new(@sigma)
  end
  if output_nodes.count >0
    @network << output_nodes
  end
  link_tiers
  recalculate_tau
end

#load_from_file(file) ⇒ Object



210
211
212
213
214
215
216
217
218
219
# File 'lib/neuralnet.rb', line 210

def load_from_file file
  fingerprint = []
  File.open(file, 'r') do |f|
    @id = f.gets.chop
    while line = f.gets do
      fingerprint << line
    end
  end
  reload fingerprint
end

#mutateObject

Nets can make small changes (mutations) to themselves



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/neuralnet.rb', line 163

def mutate
  #for the time being we won't take on
  #the ability to mutate the number of
  #nodes and their configuration
  #focussing instead on simple node weight mutation
  
  #first we mutate sigma
  @sigma = @sigma * Math.exp(@tau * gaussian_random)
  @network.each do |tier|
    tier.each do |node|
      node.sigma = @sigma
      node.mutate
    end
  end
  self
end

#outputObject



34
35
36
# File 'lib/neuralnet.rb', line 34

def output
  @network.last
end

#output_valueObject



38
39
40
41
42
43
44
# File 'lib/neuralnet.rb', line 38

def output_value
  value = 0
  self.output.each do |node|
    value += node.output_value
  end
  value
end

#reload(fingerprint) ⇒ Object



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/neuralnet.rb', line 131

def reload fingerprint
  #fingerprint contains an array of strings
  i = 0
  tiers = fingerprint[i].split(',').to_a
  i += 1
  @sigma = fingerprint[i].to_f
  i += 1
  @tau = fingerprint[i].to_f
  i += 1
  @width = fingerprint[i].to_i
  i += 1
  @height = fingerprint[i].to_i
  i += 1
      
  @network = []
  tiers.each do |tier|
    nodes = []
    tier.to_i.times do
      node_fingerprint = fingerprint[i]
      i += 1
      node = Node.new(@sigma)
      node.reload node_fingerprint
      nodes << node
    end
    @network << nodes
  end

  link_tiers
  true
end

#save_to_file(file) ⇒ Object



203
204
205
206
207
208
# File 'lib/neuralnet.rb', line 203

def save_to_file file
  File.open(file, 'w')  do |f|
     f.puts id
     f.write(self.fingerprint) 
  end
end