Class: RubyNN::NeuralNetwork

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(layer_parameters, alpha = 0.001) ⇒ NeuralNetwork

Returns a new instance of NeuralNetwork.



6
7
8
9
10
11
# File 'lib/neural_network.rb', line 6

def initialize(layer_parameters, alpha = 0.001)
  @alpha = alpha
  @weight_matrix = []
  @layer_parameters = layer_parameters
  @error = 0
end

Instance Attribute Details

#alphaObject (readonly)

Returns the value of attribute alpha.



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

def alpha
  @alpha
end

#errorObject (readonly)

Returns the value of attribute error.



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

def error
  @error
end

#layer_parametersObject (readonly)

Returns the value of attribute layer_parameters.



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

def layer_parameters
  @layer_parameters
end

Instance Method Details

#back_propagate(predictions, target_output) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/neural_network.rb', line 94

def back_propagate(predictions, target_output)
  reversed_weight_matrix = @weight_matrix.reverse
  last_weighted = []
  predictions.reverse.each_with_index do |prediction, i|
    delta_set = find_deltas(prediction, target_output) if i == 0
    if i != 0
      delta_set = back_propagation_multiplyer(last_weighted, relu_derivative(prediction))
    end
    weighted = multiply_vector(delta_set, reversed_weight_matrix[i].transpose)
    last_weighted = weighted
    update_weights(delta_set, i)
  end
end

#back_propagation_multiplyer(v1, v2) ⇒ Object



181
182
183
# File 'lib/neural_network.rb', line 181

def back_propagation_multiplyer(v1, v2)
  v1.zip(v2).map { |set| set[0] * set[1] }
end

#calculate_deltas(input, deltas) ⇒ Object



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/neural_network.rb', line 137

def calculate_deltas(input, deltas)
  weighted_deltas = []
  deltas.each { weighted_deltas.push([]) }

  deltas.size.times do |index|
    input.size.times do |count|
      weighted_deltas[index][count] = input[count] * deltas[index]
    end
  end

  weighted_deltas
end

#calculate_outcomes(abstraction) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/neural_network.rb', line 158

def calculate_outcomes(abstraction)
  first = 0.0
  second = 0.0
  third = 0.0
  abstraction.setups.each do |setup|
    white_wins = setup.outcomes[:white_wins].to_f
    black_wins = setup.outcomes[:black_wins].to_f
    draws = setup.outcomes[:draws].to_f

    if setup.position_signature[-1] == 'w'
      first += white_wins
      second += black_wins
    else
      second += black_wins
      first += white_wins
    end

    third = draws
  end

  [first, second, third]
end

#calculate_prediction(input) ⇒ Object



56
57
58
59
60
61
62
63
64
65
# File 'lib/neural_network.rb', line 56

def calculate_prediction(input)
  predictions = []
  layer_parameters[0..-2].each_with_index do |layer, i|
    input_value = i == 0 ? input : predictions[i - 1]
    prediction_vector = multiply_vector(input_value, @weight_matrix[i])
    prediction_vector = leaky_relu(prediction_vector) if layer_parameters[0..-2][i + 1]
    predictions << prediction_vector
  end
  predictions
end

#find_deltas(predictions, outcomes) ⇒ Object



115
116
117
118
119
120
121
122
123
124
# File 'lib/neural_network.rb', line 115

def find_deltas(predictions, outcomes)
  deltas = []
  predictions.size.times do |index|
    delta = predictions[index] - outcomes[index]
    deltas[index] = delta
    @error = delta ** 2
  end

  deltas
end

#find_weights(i, weights) ⇒ Object



84
85
86
87
# File 'lib/neural_network.rb', line 84

def find_weights(i, weights)
  weight_amount, offset, slice_value = weight_counts[i], offsets[i], layer_parameters[i]
  weights[(offset)...(offset + weight_amount)].each_slice(slice_value).to_a
end

#get_weightsObject



196
197
198
# File 'lib/neural_network.rb', line 196

def get_weights
  @weight_matrix
end

#initialize_weightsObject



13
14
15
16
17
18
19
20
# File 'lib/neural_network.rb', line 13

def initialize_weights
  weights = []
  weight_counts.reduce(0, :+).times { weights << rand }
  layer_parameters[0..-2].each_with_index do |layer, i|
    @weight_matrix[i] = find_weights(i, weights)
  end
  @weight_matrix
end

#leaky_relu(input) ⇒ Object



150
151
152
# File 'lib/neural_network.rb', line 150

def leaky_relu(input)
  input.map { |value| value > 0 ? value : 0.0001 }
end

#multiply_vector(input, weight_matrix) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/neural_network.rb', line 76

def multiply_vector(input, weight_matrix)
  predictions = []
  weight_matrix.size.times do |index|
    predictions[index] = weighted_sum(input, weight_matrix[index])
  end
  predictions
end

#offsetsObject



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/neural_network.rb', line 22

def offsets
  if @offsets
    @offsets
  else
    @offsets = [0]
    weight_count_size = weight_counts.size

    weight_counts.each_with_index do |weight_count, i|
      if weight_count_size > i + 1
        @offsets << @offsets.last + weight_count
      end
    end
    @offsets
  end
end

#relu_derivative(output) ⇒ Object



154
155
156
# File 'lib/neural_network.rb', line 154

def relu_derivative(output)
  output.map { |value| value > 0 ? 1 : 0.0001 }
end

#save_weights(filename) ⇒ Object



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

def save_weights(filename)
  File.open(filename, "w") do |f|
    f.write(@weight_matrix.to_json)
  end
  puts 'saved weights to ' + filename
end

#set_weights(weight_matrix) ⇒ Object



38
39
40
# File 'lib/neural_network.rb', line 38

def set_weights(weight_matrix)
  @weight_matrix = weight_matrix
end

#softmax(vector) ⇒ Object



185
186
187
188
189
190
191
192
193
194
# File 'lib/neural_network.rb', line 185

def softmax(vector)
  sum = vector.sum.to_f
  vector.map do |value|
    if value == 0
      0
    else
      value / sum
    end
  end
end

#train(input, target_output) ⇒ Object



89
90
91
92
# File 'lib/neural_network.rb', line 89

def train(input, target_output)
  predictions = calculate_prediction(input)
  back_propagate(predictions, target_output)
end

#update_weights(weighted_deltas, i) ⇒ Object



126
127
128
129
130
131
132
133
134
135
# File 'lib/neural_network.rb', line 126

def update_weights(weighted_deltas, i)
  reversed_weight_matrix = @weight_matrix.reverse
  @weight_matrix.reverse[i].size.times do |index|
    @weight_matrix.reverse[i][index].size.times do |count|
      weight = @weight_matrix.reverse[i][index][count]
      adjusted_value = (weight - (@alpha * weighted_deltas[index]))
      @weight_matrix.reverse[i][index][count] = adjusted_value if adjusted_value > 0
    end
  end
end

#weight_countsObject



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/neural_network.rb', line 42

def weight_counts
  if @weight_counts
    @weight_counts
  else
    @weight_counts = []
    layer_parameters.each_with_index do |count, i|
      if layer_parameters[i + 1]
        @weight_counts << (layer_parameters[i] * layer_parameters[i + 1])
      end
    end
    @weight_counts
  end
end

#weighted_sum(input, weights) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/neural_network.rb', line 67

def weighted_sum(input, weights)
  total_weight = 0
  raise raise NeuralNetworkError, 'arrays are not equal length' if input.size != weights.size
  input.size.times do |index|
    total_weight += input[index] * weights[index]
  end
  total_weight
end