Class: CooCoo::VectorLayer

Inherits:
Object show all
Defined in:
lib/coo-coo/vector_layer.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(num_inputs, size, activation_function = CooCoo.default_activation) ⇒ VectorLayer

Returns a new instance of VectorLayer.



16
17
18
19
20
21
22
# File 'lib/coo-coo/vector_layer.rb', line 16

def initialize(num_inputs, size, activation_function = CooCoo.default_activation)
  @activation_function = activation_function
  @num_inputs = num_inputs.to_i
  @size = size.to_i
  @weights = @activation_function.initial_weights(@num_inputs, @size)
  @bias = @activation_function.initial_bias(@size)
end

Instance Attribute Details

#activation_functionObject

Returns the value of attribute activation_function.



12
13
14
# File 'lib/coo-coo/vector_layer.rb', line 12

def activation_function
  @activation_function
end

#biasObject (readonly)

Returns the value of attribute bias.



13
14
15
# File 'lib/coo-coo/vector_layer.rb', line 13

def bias
  @bias
end

#weightsObject (readonly)

Returns the value of attribute weights.



14
15
16
# File 'lib/coo-coo/vector_layer.rb', line 14

def weights
  @weights
end

Class Method Details

.from_hash(h, network = nil) ⇒ Object



147
148
149
150
151
152
# File 'lib/coo-coo/vector_layer.rb', line 147

def from_hash(h, network = nil)
  self.new(h[:neurons][0][:num_inputs],
           h[:outputs],
           ActivationFunctions.from_name(h[:neurons][0][:f])).
    update_from_hash!(h)
end

Instance Method Details

#==(other) ⇒ Object



138
139
140
141
142
143
144
# File 'lib/coo-coo/vector_layer.rb', line 138

def ==(other)
  other.kind_of?(self.class) &&
    size == other.size &&
    bias == other.bias &&
    weights == other.weights &&
    activation_function == other.activation_function
end

#activate(input) ⇒ Object



40
41
42
# File 'lib/coo-coo/vector_layer.rb', line 40

def activate(input)
  @weights.dot(num_inputs, size, input, 1, num_inputs) + @bias
end

#add_inputs!(new_size) ⇒ Object



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/coo-coo/vector_layer.rb', line 105

def add_inputs!(new_size)
  if new_size != num_inputs
    w = CooCoo::Vector.zeros(new_size * size)
    w.set2d!(new_size, @weights, num_inputs, 0, 0)
    w.set2d!(new_size, @activation_func.initial_weights(size, 1), 1, new_size - 1, 0)
    @weights = w
    @num_inputs = new_size
  end
  
  self
end

#add_neurons!(new_size) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/coo-coo/vector_layer.rb', line 89

def add_neurons!(new_size)
  if new_size != @size
    w = CooCoo::Vector.zeros(num_inputs * new_size)
    w[0, @weights.size] = @weights
    w[@weights.size, num_inputs] = @activation_func.initial_weights(num_inputs, 1)
    @weights = w

    @bias = CooCoo::Vector.ones(new_size).set(@bias)
    @bias[-1] = @activation_func.initial_bias(1)[0]

    @size = new_size
  end
  
  self
end

#adjust_weights!(deltas) ⇒ Object



61
62
63
64
65
66
# File 'lib/coo-coo/vector_layer.rb', line 61

def adjust_weights!(deltas)
  @bias -= deltas.bias_deltas
  @weights -= deltas.weight_deltas

  self
end

#backprop(input, output, errors, hidden_state) ⇒ Object



44
45
46
47
# File 'lib/coo-coo/vector_layer.rb', line 44

def backprop(input, output, errors, hidden_state)
  # Properly: return errors * @activation_func.derivative(activate(input), output), hidden_state
  return errors * @activation_function.derivative(nil, output), hidden_state
end

#forward(input, hidden_state) ⇒ Object



32
33
34
# File 'lib/coo-coo/vector_layer.rb', line 32

def forward(input, hidden_state)
  return transfer(activate(input)), hidden_state
end

#neuron_hashObject



79
80
81
82
83
84
85
86
87
# File 'lib/coo-coo/vector_layer.rb', line 79

def neuron_hash
  @weights.each_slice(num_inputs).with_index.collect do |neuron_weights, i|
    { num_inputs: num_inputs,
      weights: neuron_weights.to_a,
      bias: @bias[i],
      f: @activation_function.name
    }      
  end
end

#num_inputsObject



24
25
26
# File 'lib/coo-coo/vector_layer.rb', line 24

def num_inputs
  @num_inputs
end

#sizeObject



28
29
30
# File 'lib/coo-coo/vector_layer.rb', line 28

def size
  @size
end

#to_hash(network = nil) ⇒ Object



72
73
74
75
76
77
# File 'lib/coo-coo/vector_layer.rb', line 72

def to_hash(network = nil)
  { type: self.class.to_s,
    outputs: size,
    neurons: neuron_hash
  }
end

#transfer(activations) ⇒ Object



36
37
38
# File 'lib/coo-coo/vector_layer.rb', line 36

def transfer(activations)
  @activation_function.call(activations)
end

#transfer_error(deltas) ⇒ Object



49
50
51
# File 'lib/coo-coo/vector_layer.rb', line 49

def transfer_error(deltas)
  deltas.dot(size, 1, @weights, num_inputs, size)
end

#transfer_input_error(expecting) ⇒ Object



53
54
55
# File 'lib/coo-coo/vector_layer.rb', line 53

def transfer_input_error(expecting)
  (output - expecting).to_a
end

#update_from_hash!(h) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
# File 'lib/coo-coo/vector_layer.rb', line 126

def update_from_hash!(h)
  @activation_function = ActivationFunctions.from_name(h[:neurons][0][:f])
  add_neurons!(h[:outputs])
  add_inputs!(h[:neurons][0][:num_inputs])
  
  h[:outputs].times do |i|
    update_neuron_from_hash!(i, h[:neurons][i])
  end

  self
end

#update_neuron_from_hash!(neuron_index, h) ⇒ Object



117
118
119
120
121
122
123
124
# File 'lib/coo-coo/vector_layer.rb', line 117

def update_neuron_from_hash!(neuron_index, h)
  if neuron_index > size
    add_neurons!(neuron_index)
  end

  @weights[neuron_index * num_inputs, num_inputs] = h[:weights]
  @bias[neuron_index] = h[:bias]
end

#update_weights!(inputs, deltas) ⇒ Object



57
58
59
# File 'lib/coo-coo/vector_layer.rb', line 57

def update_weights!(inputs, deltas)
  adjust_weights!(weight_deltas(inputs, deltas))
end

#weight_deltas(inputs, deltas) ⇒ Object



68
69
70
# File 'lib/coo-coo/vector_layer.rb', line 68

def weight_deltas(inputs, deltas)
  WeightDeltas.new(deltas, deltas.dot(1, size, inputs, num_inputs, 1))
end