machine_learning_workbench 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: afdd4f1bf99c2abbe10f4c348531f4efabde3c73
4
- data.tar.gz: 2334e9b7e5c4f276f94e75dd50164f8fa78cc699
3
+ metadata.gz: 0677a5bd2af361c57794f13c2c62ceb353bab987
4
+ data.tar.gz: 160f5d7f06abc3c4520a7753cd4fa0f155bbb09e
5
5
  SHA512:
6
- metadata.gz: 4f51ca6077627401bb1c27dfaed60cb84e5d70bdebe2f7c6d366abae299040e32ec7a4a1ad1ee3dc8ccc9aaa536a4125e91c2e97eaf043115d21e5e41d6a8e70
7
- data.tar.gz: 884493c20fde5e8ac707f6c00b442d924a7dab5d783cf011926c2425b92116eea2bd1f10116a026b9b55db2210d918aa533eb0a6bc259b7bd0704df217b0985b
6
+ metadata.gz: d7e2872adb965b394cfc23c0cdd16f905e336c17ef0f91f7f53a05abc32a5e176720e9adaa163430898b80f873213dacda8fbfe346fc49c0cee589f1b6830cee
7
+ data.tar.gz: 49671433cb861a17a73414c0cd1c5b4f3249122ea809dec4ed2c7c14ddd4587cdbb1f8c688d5bdb59ab0d97adf4ff81ac0b4c3911c3344c5c5677a26e96942cf
data/README.md CHANGED
@@ -58,4 +58,4 @@ Please feel free to contribute to this list (see `Contributing` above).
58
58
  - **UL-ELR** stands for Unsupervised Learning plus Evolutionary Reinforcement Learning, from the paper _"Intrinsically Motivated Neuroevolution for Vision-Based Reinforcement Learning" (ICDL2011)_. Check [here](https://exascale.info/members/giuseppe-cuccu/) for citation reference and pdf.
59
59
  - **BD-NES** stands for Block Diagonal Natural Evolution Strategy, from the homonymous paper _"Block Diagonal Natural Evolution Strategies" (PPSN2012)_. Check [here](https://exascale.info/members/giuseppe-cuccu/) for citation reference and pdf.
60
60
  - **RNES** stands for Radial Natural Evolution Strategy, from the paper _"Novelty-Based Restarts for Evolution Strategies" (CEC2011)_. Check [here](https://exascale.info/members/giuseppe-cuccu/) for citation reference and pdf.
61
- - **Online VQ** stands for Online Vector Quantization, from the paper _"Intrinsically Motivated Neuroevolution for Vision-Based Reinforcement Learning" (ICDL2011)_. Check [here](https://exascale.info/members/giuseppe-cuccu/) for citation reference and pdf.
61
+ - **DLR-VQ** stands for Decaying Learning Rate Vector Quantization, from the algorithm originally named _*Online VQ*_ in the paper _"Intrinsically Motivated Neuroevolution for Vision-Based Reinforcement Learning" (ICDL2011)_. Check [here](https://exascale.info/members/giuseppe-cuccu/) for citation reference and pdf.
@@ -1,2 +1,3 @@
1
1
  require_relative 'compressor/vector_quantization'
2
- require_relative 'compressor/online_vector_quantization'
2
+ require_relative 'compressor/decaying_learning_rate_vq'
3
+ require_relative 'compressor/copy_vq'
@@ -0,0 +1,47 @@
1
+ module MachineLearningWorkbench::Compressor
2
+ # Train-less VQ, copying new images into centroids
3
+ # Optimized for online training.
4
+ class CopyVQ < VectorQuantization
5
+
6
+ attr_reader :equal_simil, :next_train
7
+
8
+ def initialize **opts
9
+ puts "Ignoring learning rate: `lrate: #{opts[:lrate]}`" if opts[:lrate]
10
+ puts "Ignoring similarity: `simil_type: #{opts[:simil_type]}`" if opts[:simil_type]
11
+ # TODO: try different epsilons to reduce the number of states
12
+ # for example, in qbert we care what is lit and what is not, not the colors
13
+ @equal_simil = opts.delete(:equal_simil) || 0.0
14
+ super **opts.merge({lrate: nil, simil_type: nil})
15
+ @ntrains << 0 # to count duplicates, images we skip the train on
16
+ @next_train = 0 # pointer to the next centroid to train
17
+ end
18
+
19
+ def ntrains; @ntrains[0...-1]; end
20
+ def ntrains_skip; @ntrains.last; end
21
+
22
+ # Overloading lrate check from original VQ
23
+ def check_lrate lrate; nil; end
24
+
25
+ # Train on one vector:
26
+ # - train only if the image is not already in dictionary
27
+ # - find the next untrained centroid
28
+ # - training is just overwriting it
29
+ # @return [Integer] index of trained centroid
30
+ def train_one vec, eps: equal_simil
31
+ mses = centrs.map do |centr|
32
+ ((centr-vec)**2).sum / centr.size
33
+ end
34
+ # BEWARE: I am currently not handling the case where we run out of centroids!
35
+ # => Will be addressed directly by dynamic dictionary size
36
+ # return -1 if mses.min < eps
37
+ return -1 if mses.min < eps || next_train == ncentrs
38
+ trg_idx = next_train
39
+ @next_train += 1
40
+ # require 'pry'; binding.pry if next_train == ncentrs
41
+ puts "Overwriting centr #{next_train}"
42
+ centrs[trg_idx] = vec
43
+ trg_idx
44
+ end
45
+
46
+ end
47
+ end
@@ -1,7 +1,7 @@
1
1
  module MachineLearningWorkbench::Compressor
2
- # Online Vector Quantization: VQ with per-centroid decaying learning rates.
2
+ # VQ with per-centroid decaying learning rates.
3
3
  # Optimized for online training.
4
- class OnlineVectorQuantization < VectorQuantization
4
+ class DecayingLearningRateVQ < VectorQuantization
5
5
 
6
6
  attr_reader :lrate_min, :lrate_min_den, :decay_rate
7
7
 
@@ -2,17 +2,20 @@ module MachineLearningWorkbench::Compressor
2
2
 
3
3
  # Standard Vector Quantization
4
4
  class VectorQuantization
5
- attr_reader :ncentrs, :centrs, :dims, :vrange, :init_centr_vrange, :lrate, :simil_type, :rng, :ntrains
6
- Verification = MachineLearningWorkbench::Tools::Verification
5
+ attr_reader :ncentrs, :centrs, :dims, :vrange, :init_centr_vrange, :lrate,
6
+ :simil_type, :encoding_type, :rng, :ntrains, :utility, :ncodes
7
+ attr_writer :utility, :ncodes # allows access from outside
8
+
9
+ def initialize ncentrs:, dims:, vrange:, lrate:, simil_type: nil, encoding_type: nil, init_centr_vrange: nil, rseed: Random.new_seed
10
+
11
+ @rng = Random.new rseed # TODO: RNG CURRENTLY NOT USED!!
7
12
 
8
- def initialize ncentrs:, dims:, vrange:, lrate:, simil_type: nil, init_centr_vrange: nil, rseed: Random.new_seed
9
- # TODO: RNG CURRENTLY NOT USED!!
10
- @rng = Random.new rseed
11
13
  @ncentrs = ncentrs
12
14
  @dims = Array(dims)
13
- check_lrate lrate # hack: so that we can overload it in online_vq
15
+ check_lrate lrate # hack: so that we can overload it in dlr_vq
14
16
  @lrate = lrate
15
17
  @simil_type = simil_type || :dot
18
+ @encoding_type = encoding_type || :ensemble_norm
16
19
  @init_centr_vrange ||= vrange
17
20
  @vrange = case vrange
18
21
  when Array
@@ -24,10 +27,12 @@ module MachineLearningWorkbench::Compressor
24
27
  end
25
28
  init_centrs
26
29
  @ntrains = [0]*ncentrs # useful to understand what happens
30
+ @utility = NArray.zeros [ncentrs] # trace how 'useful' are centroids to encodings
31
+ @ncodes = 0
27
32
  end
28
33
 
29
34
  # Verify lrate to be present and withing unit bounds
30
- # As a separate method only so it can be overloaded in `OnlineVectorQuantization`
35
+ # As a separate method only so it can be overloaded in `DecayingLearningRateVQ`
31
36
  def check_lrate lrate
32
37
  raise ArgumentError, "Pass a `lrate` between 0 and 1" unless lrate&.between?(0,1)
33
38
  end
@@ -57,30 +62,45 @@ module MachineLearningWorkbench::Compressor
57
62
  # Computes similarities between vector and all centroids
58
63
  def similarities vec, type: simil_type
59
64
  raise NotImplementedError if vec.shape.size > 1
60
- centrs.map { |centr| SIMIL[type].call centr, vec }
65
+ simil_fn = SIMIL[type] || raise(ArgumentError, "Unrecognized simil #{type}")
66
+ NArray[*centrs.map { |centr| simil_fn.call centr, vec }]
61
67
  # require 'parallel'
62
- # Parallel.map(centrs) { |c| c.dot(vec).first }
68
+ # NArray[*Parallel.map(centrs) { |c| c.dot(vec).first }]
63
69
  end
64
70
 
65
71
  # Encode a vector
66
- # TODO: optimize for Numo
67
- def encode vec, type: :most_similar
72
+ # tracks utility of centroids based on how much they contribute to encoding
73
+ # TODO: `encode = Encodings.const_get(type)` in initialize`
74
+ # NOTE: hashes of lambdas or modules cannot access ncodes and utility
75
+ def encode vec, type: encoding_type
68
76
  simils = similarities vec
69
77
  case type
70
78
  when :most_similar
71
- simils.index simils.max
79
+ code = simils.max_index
80
+ @ncodes += 1
81
+ @utility[code] += 1
82
+ code
72
83
  when :ensemble
73
- simils
84
+ code = simils
85
+ tot = simils.sum
86
+ tot = 1 if tot < 1e-5 # HACK: avoid division by zero
87
+ contrib = code / tot
88
+ @ncodes += 1
89
+ @utility += (contrib - utility) / ncodes # cumulative moving average
90
+ code
74
91
  when :ensemble_norm
75
- tot = simils.reduce(:+)
76
- tot = 1 if tot == 0 # HACK: avoid division by zero
77
- simils.map { |s| s/tot }
78
- else raise ArgumentError, "unrecognized encode type: #{type}"
92
+ tot = simils.sum
93
+ tot = 1 if tot < 1e-5 # HACK: avoid division by zero
94
+ code = simils / tot
95
+ @ncodes += 1
96
+ @utility += (code - utility) / ncodes # cumulative moving average
97
+ code
98
+ else raise ArgumentError, "Unrecognized encode #{type}"
79
99
  end
80
100
  end
81
101
 
82
102
  # Reconstruct vector from its code (encoding)
83
- def reconstruction code, type: :most_similar
103
+ def reconstruction code, type: encoding_type
84
104
  case type
85
105
  when :most_similar
86
106
  centrs[code]
@@ -98,14 +118,13 @@ module MachineLearningWorkbench::Compressor
98
118
  # followed by the corresponding similarity
99
119
  def most_similar_centr vec
100
120
  simils = similarities vec
101
- max_simil = simils.max
102
- max_idx = simils.index max_simil
103
- [max_idx, max_simil]
121
+ max_idx = simils.max_index
122
+ [max_idx, simils[max_idx]]
104
123
  end
105
124
 
106
125
  # Per-pixel errors in reconstructing vector
107
126
  # @return [NArray] residuals
108
- def reconstr_error vec, code: nil, type: :most_similar
127
+ def reconstr_error vec, code: nil, type: encoding_type
109
128
  code ||= encode vec, type: type
110
129
  (vec - reconstruction(code, type: type)).abs.sum
111
130
  end
@@ -129,7 +148,7 @@ module MachineLearningWorkbench::Compressor
129
148
  vec_lst.each_with_index do |vec, i|
130
149
  trained_idx = train_one vec
131
150
  print '.' if debug
132
- ntrains[trained_idx] += 1
151
+ @ntrains[trained_idx] += 1
133
152
  end
134
153
  end
135
154
  end
@@ -162,31 +162,23 @@ module MachineLearningWorkbench::NeuralNetwork
162
162
 
163
163
  ## Activation functions
164
164
 
165
- # Traditional sigmoid with variable steepness
165
+ # Traditional sigmoid (logistic) with variable steepness
166
166
  def sigmoid k=0.5
167
167
  # k is steepness: 0<k<1 is flatter, 1<k is flatter
168
168
  # flatter makes activation less sensitive, better with large number of inputs
169
- -> (x) { 1.0 / (NMath.exp(-k * x) + 1.0) }
170
- end
171
-
172
- # Traditional logistic
173
- def logistic
174
- -> (x) do
175
- exp = NMath.exp(x)
176
- # exp.infinite? ? exp : exp / (1.0 + exp)
177
- exp / (1.0 + exp)
178
- end
169
+ -> (vec) { 1.0 / (NMath.exp(-k * vec) + 1.0) }
179
170
  end
171
+ alias logistic sigmoid
180
172
 
181
173
  # LeCun hyperbolic activation
182
174
  # @see http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf Section 4.4
183
175
  def lecun_hyperbolic
184
- -> (x) { 1.7159 * NMath.tanh(2.0*x/3.0) + 1e-3*x }
176
+ -> (vec) { 1.7159 * NMath.tanh(2.0*vec/3.0) + 1e-3*vec }
185
177
  end
186
178
 
187
179
  # Rectified Linear Unit (ReLU)
188
180
  def relu
189
- -> (x) { (x>0).all? && x || x.class.zeros(x.shape) }
181
+ -> (vec) { (vec>0).all? && vec || vec.class.zeros(vec.shape) }
190
182
  end
191
183
 
192
184
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: machine_learning_workbench
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Giuseppe Cuccu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-06 00:00:00.000000000 Z
11
+ date: 2018-04-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -202,7 +202,8 @@ files:
202
202
  - examples/neuroevolution.rb
203
203
  - lib/machine_learning_workbench.rb
204
204
  - lib/machine_learning_workbench/compressor.rb
205
- - lib/machine_learning_workbench/compressor/online_vector_quantization.rb
205
+ - lib/machine_learning_workbench/compressor/copy_vq.rb
206
+ - lib/machine_learning_workbench/compressor/decaying_learning_rate_vq.rb
206
207
  - lib/machine_learning_workbench/compressor/vector_quantization.rb
207
208
  - lib/machine_learning_workbench/monkey.rb
208
209
  - lib/machine_learning_workbench/neural_network.rb