machine_learning_workbench 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/machine_learning_workbench/compressor.rb +2 -1
- data/lib/machine_learning_workbench/compressor/copy_vq.rb +47 -0
- data/lib/machine_learning_workbench/compressor/{online_vector_quantization.rb → decaying_learning_rate_vq.rb} +2 -2
- data/lib/machine_learning_workbench/compressor/vector_quantization.rb +42 -23
- data/lib/machine_learning_workbench/neural_network/base.rb +5 -13
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0677a5bd2af361c57794f13c2c62ceb353bab987
|
4
|
+
data.tar.gz: 160f5d7f06abc3c4520a7753cd4fa0f155bbb09e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
- **
|
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.
|
@@ -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
|
-
#
|
2
|
+
# VQ with per-centroid decaying learning rates.
|
3
3
|
# Optimized for online training.
|
4
|
-
class
|
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,
|
6
|
-
|
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
|
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 `
|
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
|
-
|
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
|
-
#
|
67
|
-
|
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
|
-
|
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.
|
76
|
-
tot = 1 if tot
|
77
|
-
|
78
|
-
|
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:
|
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
|
-
|
102
|
-
max_idx
|
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:
|
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
|
-
-> (
|
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
|
-
-> (
|
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
|
-
-> (
|
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.
|
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-
|
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/
|
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
|