tensor_stream 1.0.0 → 1.0.1
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/.gitignore +1 -0
- data/.rubocop.yml +1 -0
- data/Gemfile +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +34 -34
- data/Rakefile +3 -3
- data/USAGE_GUIDE.md +235 -0
- data/bin/stubgen +20 -0
- data/exe/model_utils +2 -2
- data/lib/tensor_stream.rb +45 -44
- data/lib/tensor_stream/constant.rb +2 -2
- data/lib/tensor_stream/control_flow.rb +1 -1
- data/lib/tensor_stream/debugging/debugging.rb +2 -2
- data/lib/tensor_stream/dynamic_stitch.rb +2 -2
- data/lib/tensor_stream/evaluator/base_evaluator.rb +18 -18
- data/lib/tensor_stream/evaluator/buffer.rb +1 -1
- data/lib/tensor_stream/evaluator/evaluator.rb +2 -2
- data/lib/tensor_stream/evaluator/operation_helpers/array_ops_helper.rb +41 -41
- data/lib/tensor_stream/evaluator/operation_helpers/math_helper.rb +1 -1
- data/lib/tensor_stream/evaluator/ruby/array_ops.rb +39 -39
- data/lib/tensor_stream/evaluator/ruby/check_ops.rb +2 -2
- data/lib/tensor_stream/evaluator/ruby/images_ops.rb +18 -18
- data/lib/tensor_stream/evaluator/ruby/math_ops.rb +13 -14
- data/lib/tensor_stream/evaluator/ruby/nn_ops.rb +33 -36
- data/lib/tensor_stream/evaluator/ruby/random_ops.rb +20 -21
- data/lib/tensor_stream/evaluator/ruby_evaluator.rb +36 -49
- data/lib/tensor_stream/exceptions.rb +1 -1
- data/lib/tensor_stream/generated_stub/ops.rb +691 -0
- data/lib/tensor_stream/generated_stub/stub_file.erb +24 -0
- data/lib/tensor_stream/graph.rb +18 -18
- data/lib/tensor_stream/graph_builder.rb +17 -17
- data/lib/tensor_stream/graph_deserializers/protobuf.rb +97 -97
- data/lib/tensor_stream/graph_deserializers/yaml_loader.rb +1 -1
- data/lib/tensor_stream/graph_keys.rb +3 -3
- data/lib/tensor_stream/graph_serializers/graphml.rb +33 -33
- data/lib/tensor_stream/graph_serializers/packer.rb +23 -23
- data/lib/tensor_stream/graph_serializers/pbtext.rb +38 -42
- data/lib/tensor_stream/graph_serializers/serializer.rb +3 -2
- data/lib/tensor_stream/graph_serializers/yaml.rb +5 -5
- data/lib/tensor_stream/helpers/infer_shape.rb +56 -56
- data/lib/tensor_stream/helpers/op_helper.rb +8 -9
- data/lib/tensor_stream/helpers/string_helper.rb +15 -15
- data/lib/tensor_stream/helpers/tensor_mixins.rb +17 -17
- data/lib/tensor_stream/images.rb +1 -1
- data/lib/tensor_stream/initializer.rb +1 -1
- data/lib/tensor_stream/math_gradients.rb +28 -187
- data/lib/tensor_stream/monkey_patches/array.rb +1 -1
- data/lib/tensor_stream/monkey_patches/float.rb +1 -1
- data/lib/tensor_stream/monkey_patches/integer.rb +1 -1
- data/lib/tensor_stream/monkey_patches/op_patch.rb +5 -5
- data/lib/tensor_stream/monkey_patches/patch.rb +1 -1
- data/lib/tensor_stream/nn/nn_ops.rb +17 -15
- data/lib/tensor_stream/op_maker.rb +180 -0
- data/lib/tensor_stream/operation.rb +17 -17
- data/lib/tensor_stream/ops.rb +95 -384
- data/lib/tensor_stream/ops/add.rb +23 -0
- data/lib/tensor_stream/ops/argmax.rb +14 -0
- data/lib/tensor_stream/ops/argmin.rb +14 -0
- data/lib/tensor_stream/ops/case.rb +17 -0
- data/lib/tensor_stream/ops/cast.rb +15 -0
- data/lib/tensor_stream/ops/ceil.rb +15 -0
- data/lib/tensor_stream/ops/const.rb +0 -0
- data/lib/tensor_stream/ops/cos.rb +10 -0
- data/lib/tensor_stream/ops/div.rb +21 -0
- data/lib/tensor_stream/ops/equal.rb +15 -0
- data/lib/tensor_stream/ops/expand_dims.rb +17 -0
- data/lib/tensor_stream/ops/fill.rb +19 -0
- data/lib/tensor_stream/ops/floor.rb +15 -0
- data/lib/tensor_stream/ops/floor_div.rb +15 -0
- data/lib/tensor_stream/ops/greater.rb +11 -0
- data/lib/tensor_stream/ops/greater_equal.rb +11 -0
- data/lib/tensor_stream/ops/less_equal.rb +15 -0
- data/lib/tensor_stream/ops/log.rb +14 -0
- data/lib/tensor_stream/ops/mat_mul.rb +60 -0
- data/lib/tensor_stream/ops/max.rb +15 -0
- data/lib/tensor_stream/ops/min.rb +15 -0
- data/lib/tensor_stream/ops/mod.rb +23 -0
- data/lib/tensor_stream/ops/mul.rb +21 -0
- data/lib/tensor_stream/ops/negate.rb +14 -0
- data/lib/tensor_stream/ops/ones_like.rb +19 -0
- data/lib/tensor_stream/ops/pow.rb +25 -0
- data/lib/tensor_stream/ops/prod.rb +60 -0
- data/lib/tensor_stream/ops/random_uniform.rb +18 -0
- data/lib/tensor_stream/ops/range.rb +20 -0
- data/lib/tensor_stream/ops/rank.rb +13 -0
- data/lib/tensor_stream/ops/reshape.rb +24 -0
- data/lib/tensor_stream/ops/round.rb +15 -0
- data/lib/tensor_stream/ops/shape.rb +14 -0
- data/lib/tensor_stream/ops/sigmoid.rb +10 -0
- data/lib/tensor_stream/ops/sign.rb +12 -0
- data/lib/tensor_stream/ops/sin.rb +10 -0
- data/lib/tensor_stream/ops/size.rb +16 -0
- data/lib/tensor_stream/ops/sub.rb +24 -0
- data/lib/tensor_stream/ops/sum.rb +27 -0
- data/lib/tensor_stream/ops/tan.rb +12 -0
- data/lib/tensor_stream/ops/tanh.rb +10 -0
- data/lib/tensor_stream/ops/tile.rb +19 -0
- data/lib/tensor_stream/ops/zeros.rb +15 -0
- data/lib/tensor_stream/placeholder.rb +2 -2
- data/lib/tensor_stream/profile/report_tool.rb +3 -3
- data/lib/tensor_stream/session.rb +36 -38
- data/lib/tensor_stream/tensor.rb +2 -2
- data/lib/tensor_stream/tensor_shape.rb +4 -4
- data/lib/tensor_stream/train/adadelta_optimizer.rb +8 -8
- data/lib/tensor_stream/train/adagrad_optimizer.rb +3 -3
- data/lib/tensor_stream/train/adam_optimizer.rb +11 -11
- data/lib/tensor_stream/train/learning_rate_decay.rb +2 -2
- data/lib/tensor_stream/train/momentum_optimizer.rb +7 -7
- data/lib/tensor_stream/train/optimizer.rb +9 -9
- data/lib/tensor_stream/train/rmsprop_optimizer.rb +16 -16
- data/lib/tensor_stream/train/saver.rb +14 -14
- data/lib/tensor_stream/train/slot_creator.rb +6 -6
- data/lib/tensor_stream/train/utils.rb +12 -12
- data/lib/tensor_stream/trainer.rb +10 -10
- data/lib/tensor_stream/types.rb +1 -1
- data/lib/tensor_stream/utils.rb +33 -32
- data/lib/tensor_stream/utils/freezer.rb +5 -5
- data/lib/tensor_stream/variable.rb +5 -5
- data/lib/tensor_stream/variable_scope.rb +1 -1
- data/lib/tensor_stream/version.rb +1 -1
- data/samples/{iris.data → datasets/iris.data} +0 -0
- data/samples/jupyter_notebooks/linear_regression.ipynb +463 -0
- data/samples/{iris.rb → neural_networks/iris.rb} +21 -23
- data/samples/{mnist_data.rb → neural_networks/mnist_data.rb} +8 -8
- data/samples/neural_networks/raw_neural_net_sample.rb +112 -0
- data/samples/{rnn.rb → neural_networks/rnn.rb} +28 -31
- data/samples/{nearest_neighbor.rb → others/nearest_neighbor.rb} +12 -12
- data/samples/regression/linear_regression.rb +63 -0
- data/samples/{logistic_regression.rb → regression/logistic_regression.rb} +14 -16
- data/tensor_stream.gemspec +9 -8
- metadata +89 -19
- data/data_1.json +0 -4764
- data/data_2.json +0 -4764
- data/data_actual.json +0 -28
- data/data_expected.json +0 -28
- data/data_input.json +0 -28
- data/samples/error.graphml +0 -2755
- data/samples/gradient_sample.graphml +0 -1255
- data/samples/linear_regression.rb +0 -69
- data/samples/multigpu.rb +0 -73
- data/samples/raw_neural_net_sample.rb +0 -112
@@ -1,6 +1,6 @@
|
|
1
1
|
module TensorStream
|
2
2
|
module CheckOps
|
3
|
-
def
|
3
|
+
def self.included(klass)
|
4
4
|
klass.class_eval do
|
5
5
|
register_op :assert_equal do |context, tensor, inputs|
|
6
6
|
result = call_vector_op(tensor, :equal, inputs[0], inputs[1], context) { |t, u| t == u }
|
@@ -14,4 +14,4 @@ module TensorStream
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
end
|
17
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require "chunky_png"
|
2
2
|
|
3
3
|
module TensorStream
|
4
4
|
module ImagesOps
|
5
|
-
def
|
5
|
+
def self.included(klass)
|
6
6
|
klass.class_eval do
|
7
7
|
register_op :decode_png do |_context, tensor, inputs|
|
8
8
|
content = inputs[0]
|
@@ -26,26 +26,26 @@ module TensorStream
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
image_data = image.pixels.collect
|
29
|
+
image_data = image.pixels.collect { |pixel|
|
30
30
|
color_values = if channels == 4
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
[ChunkyPNG::Color.r(pixel),
|
32
|
+
ChunkyPNG::Color.g(pixel),
|
33
|
+
ChunkyPNG::Color.b(pixel),
|
34
|
+
ChunkyPNG::Color.a(pixel),]
|
35
|
+
elsif channels == 3
|
36
|
+
[ChunkyPNG::Color.r(pixel),
|
37
|
+
ChunkyPNG::Color.g(pixel),
|
38
|
+
ChunkyPNG::Color.b(pixel),]
|
39
|
+
elsif channels == 1
|
40
|
+
[ChunkyPNG::Color.r(pixel)]
|
41
|
+
else
|
42
|
+
raise "Invalid channel value #{channels}"
|
43
|
+
end
|
44
44
|
|
45
45
|
color_values.map!(&:to_f) if fp_type?(tensor.data_type)
|
46
46
|
|
47
47
|
color_values
|
48
|
-
|
48
|
+
}
|
49
49
|
TensorShape.reshape(image_data, [image.height, image.width, channels])
|
50
50
|
end
|
51
51
|
|
@@ -85,4 +85,4 @@ module TensorStream
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
end
|
88
|
-
end
|
88
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module TensorStream
|
2
2
|
module MathOps
|
3
|
-
def
|
3
|
+
def self.included(klass)
|
4
4
|
klass.class_eval do
|
5
5
|
register_op :tanh, no_eval: true do |context, _tensor, inputs|
|
6
6
|
call_op(inputs[0], context) { |t, _b| Math.tanh(t) }
|
7
7
|
end
|
8
8
|
|
9
9
|
register_op :tan, no_eval: true do |context, tensor, inputs|
|
10
|
-
call_op(inputs[0], context) { |t, _b| Math.tan(t) }
|
10
|
+
call_op(inputs[0], context) { |t, _b| Math.tan(t) }
|
11
11
|
end
|
12
12
|
|
13
13
|
register_op :atan, no_eval: true do |context, _tensor, inputs|
|
@@ -20,7 +20,7 @@ module TensorStream
|
|
20
20
|
|
21
21
|
register_op :add, no_eval: true do |context, tensor, inputs|
|
22
22
|
a, b = inputs
|
23
|
-
call_vector_op(tensor, :add, a, b, context) { |t, u|
|
23
|
+
call_vector_op(tensor, :add, a, b, context) { |t, u| t + u }
|
24
24
|
end
|
25
25
|
|
26
26
|
register_op :add_n, no_eval: true do |context, tensor, inputs|
|
@@ -58,7 +58,7 @@ module TensorStream
|
|
58
58
|
|
59
59
|
register_op :mul, no_eval: true do |context, tensor, inputs|
|
60
60
|
a, b = inputs
|
61
|
-
call_vector_op(tensor, :mul, a, b, context)
|
61
|
+
call_vector_op(tensor, :mul, a, b, context) { |t, u| t * u }
|
62
62
|
end
|
63
63
|
|
64
64
|
register_op :pow, no_eval: true do |context, tensor, inputs|
|
@@ -141,13 +141,13 @@ module TensorStream
|
|
141
141
|
raise TensorStream::InvalidArgumentError, "Expected dimension in the range [#{-rank},#{rank}) but got #{axis}" if axis < -rank || axis >= rank
|
142
142
|
|
143
143
|
new_shape = shape_eval(inputs[0])
|
144
|
-
ns = new_shape.each_with_index.collect
|
144
|
+
ns = new_shape.each_with_index.collect { |shape, index|
|
145
145
|
next nil if index == axis
|
146
146
|
|
147
147
|
shape
|
148
|
-
|
148
|
+
}.compact
|
149
149
|
|
150
|
-
Tensor.cast_dtype(TensorShape.reshape(get_op_with_axis(inputs[0], axis, 0, :max), ns), tensor.
|
150
|
+
Tensor.cast_dtype(TensorShape.reshape(get_op_with_axis(inputs[0], axis, 0, :max), ns), tensor.options[:output_type])
|
151
151
|
end
|
152
152
|
|
153
153
|
register_op(%i[argmin arg_min]) do |_context, tensor, inputs|
|
@@ -156,13 +156,13 @@ module TensorStream
|
|
156
156
|
raise TensorStream::InvalidArgumentError, "Expected dimension in the range [#{-rank},#{rank}) but got #{axis}" if axis < -rank || axis >= rank
|
157
157
|
|
158
158
|
new_shape = shape_eval(inputs[0])
|
159
|
-
ns = new_shape.each_with_index.collect
|
159
|
+
ns = new_shape.each_with_index.collect { |shape, index|
|
160
160
|
next nil if index == axis
|
161
161
|
|
162
162
|
shape
|
163
|
-
|
163
|
+
}.compact
|
164
164
|
|
165
|
-
Tensor.cast_dtype(TensorShape.reshape(get_op_with_axis(inputs[0], axis, 0, :min), ns), tensor.
|
165
|
+
Tensor.cast_dtype(TensorShape.reshape(get_op_with_axis(inputs[0], axis, 0, :min), ns), tensor.options[:output_type])
|
166
166
|
end
|
167
167
|
|
168
168
|
register_op :cumprod do |context, tensor, inputs|
|
@@ -179,9 +179,9 @@ module TensorStream
|
|
179
179
|
arr = [1] + arr if exclusive
|
180
180
|
|
181
181
|
start_prod = arr[0]
|
182
|
-
mapped = arr[1...count].map
|
182
|
+
mapped = arr[1...count].map { |v|
|
183
183
|
start_prod = vector_op(start_prod, v) { |a, b| a * b }
|
184
|
-
|
184
|
+
}
|
185
185
|
|
186
186
|
arr = [arr[0]] + mapped
|
187
187
|
reverse_option ? arr.reverse : arr
|
@@ -190,7 +190,6 @@ module TensorStream
|
|
190
190
|
end
|
191
191
|
|
192
192
|
register_op :sum, noop: true do |context, tensor, _inputs|
|
193
|
-
|
194
193
|
reduction(context, tensor) do |arr|
|
195
194
|
reduced_val = arr[0]
|
196
195
|
arr[1..arr.size].each do |v|
|
@@ -269,4 +268,4 @@ module TensorStream
|
|
269
268
|
end
|
270
269
|
end
|
271
270
|
end
|
272
|
-
end
|
271
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module TensorStream
|
2
2
|
## Collection of machine learning related ops
|
3
3
|
module NNOps
|
4
|
-
def
|
4
|
+
def self.included(klass)
|
5
5
|
klass.class_eval do
|
6
6
|
register_op :apply_gradient_descent do |context, tensor, inputs|
|
7
7
|
target_var, learning_rate, delta = inputs
|
@@ -17,10 +17,10 @@ module TensorStream
|
|
17
17
|
assign_acc = tensor.inputs[1]
|
18
18
|
assign_acc.container = multi_array_op(->(t, u) { t * momentum + u }, momentum_var, grad)
|
19
19
|
assign.container = if tensor.options[:use_nesterov]
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
multi_array_op(->(v, g, acc) { v - (g * learning_rate + acc * momentum * learning_rate) }, target_var, grad, momentum_var)
|
21
|
+
else
|
22
|
+
multi_array_op(->(v, acc) { v - acc * learning_rate }, target_var, momentum_var)
|
23
|
+
end
|
24
24
|
|
25
25
|
assign.container
|
26
26
|
end
|
@@ -52,9 +52,9 @@ module TensorStream
|
|
52
52
|
assign_m = tensor.inputs[1]
|
53
53
|
assign_v = tensor.inputs[2]
|
54
54
|
|
55
|
-
assign_m.container = multi_array_op(->(u_d
|
56
|
-
assign_v.container = multi_array_op(->(u_d
|
57
|
-
assign.container = multi_array_op(->(t, m_d
|
55
|
+
assign_m.container = multi_array_op(->(u_d, g) { u_d + (g - u_d) * (1.0 - beta1_t) }, m, grad)
|
56
|
+
assign_v.container = multi_array_op(->(u_d, v_d) { u_d + (v_d**2 - u_d) * (1.0 - beta2_t)}, v, grad)
|
57
|
+
assign.container = multi_array_op(->(t, m_d, v_d) { t - ((m_d * alpha) / (Math.sqrt(v_d) + epsilon_t)) }, target_var, assign_m.container, assign_v.container)
|
58
58
|
assign.container
|
59
59
|
end
|
60
60
|
|
@@ -123,11 +123,11 @@ module TensorStream
|
|
123
123
|
labels = last_axis(inputs[1])
|
124
124
|
num_classes = input_shape.last
|
125
125
|
|
126
|
-
labels = labels.map
|
126
|
+
labels = labels.map { |l|
|
127
127
|
one_hot = Array.new(num_classes) { 0 }
|
128
128
|
one_hot[l] = 1
|
129
129
|
one_hot
|
130
|
-
|
130
|
+
}
|
131
131
|
|
132
132
|
func = lambda { |logits, label|
|
133
133
|
c = logits.max
|
@@ -173,9 +173,9 @@ module TensorStream
|
|
173
173
|
if input_shape.size == 1
|
174
174
|
func.call(last_dimen_list)
|
175
175
|
else
|
176
|
-
arr = last_dimen_list.collect
|
176
|
+
arr = last_dimen_list.collect { |list|
|
177
177
|
func.call(list)
|
178
|
-
|
178
|
+
}
|
179
179
|
TensorShape.reshape(arr, input_shape)
|
180
180
|
end
|
181
181
|
end
|
@@ -202,9 +202,9 @@ module TensorStream
|
|
202
202
|
if input_shape.size == 1
|
203
203
|
func.call(last_dimen_list, last_grad_list)
|
204
204
|
else
|
205
|
-
arr = last_dimen_list.zip(last_grad_list).collect
|
205
|
+
arr = last_dimen_list.zip(last_grad_list).collect { |list, last_grad|
|
206
206
|
func.call(list, last_grad)
|
207
|
-
|
207
|
+
}
|
208
208
|
TensorShape.reshape(arr, input_shape)
|
209
209
|
end
|
210
210
|
end
|
@@ -226,32 +226,31 @@ module TensorStream
|
|
226
226
|
|
227
227
|
_batch, height, width, _channels = shape_eval(inputs[0])
|
228
228
|
padding = conv2d_padding_options(padding_option, filter_shape, height, width, height_stride, width_stride)
|
229
|
-
inputs[0].collect
|
229
|
+
inputs[0].collect { |image|
|
230
230
|
f_height, f_width, _input_channels, _output_channels = filter_shape
|
231
|
-
(-padding[0]...height).step(height_stride).map
|
231
|
+
(-padding[0]...height).step(height_stride).map { |y|
|
232
232
|
next if (y + f_height) > (height + padding[2])
|
233
233
|
|
234
|
-
(-padding[1]...width).step(width_stride).map
|
234
|
+
(-padding[1]...width).step(width_stride).map { |x|
|
235
235
|
next if (x + f_width) > (width + padding[3])
|
236
236
|
|
237
|
-
filter_result = (0...f_height).map
|
238
|
-
(0...f_width).map
|
237
|
+
filter_result = (0...f_height).map { |f_y|
|
238
|
+
(0...f_width).map { |f_x|
|
239
239
|
f_element = filter[f_y][f_x]
|
240
240
|
|
241
241
|
next if (x + f_x >= width) || (x + f_x < 0)
|
242
242
|
next if (y + f_y >= height) || (y + f_y < 0)
|
243
243
|
|
244
|
-
|
245
244
|
image[y + f_y][x + f_x].zip(f_element).map do |image_channel, filter_channels|
|
246
245
|
filter_channels.map { |c| image_channel * c }
|
247
246
|
end
|
248
|
-
|
249
|
-
|
247
|
+
}.compact
|
248
|
+
}.flatten(2)
|
250
249
|
|
251
250
|
filter_result.transpose.map { |e| e.reduce(:+) }
|
252
|
-
|
253
|
-
|
254
|
-
|
251
|
+
}.compact
|
252
|
+
}.compact
|
253
|
+
}.compact
|
255
254
|
end
|
256
255
|
|
257
256
|
register_op :conv2d_backprop_input do |_context, tensor, inputs|
|
@@ -285,15 +284,14 @@ module TensorStream
|
|
285
284
|
img_grad = grad[b][(y + padding[0]) / height_stride][(x + padding[1]) / width_stride]
|
286
285
|
|
287
286
|
channels.times.each do |c|
|
288
|
-
g = Array.new(output_channels)
|
287
|
+
g = Array.new(output_channels) { |o_c|
|
289
288
|
filter[f_y][f_x][c][o_c] * img_grad[o_c]
|
290
|
-
|
289
|
+
}.reduce(:+)
|
291
290
|
|
292
291
|
image_gradient[y + f_y][x + f_x][c] += g
|
293
292
|
end
|
294
293
|
end
|
295
294
|
end
|
296
|
-
|
297
295
|
end
|
298
296
|
end
|
299
297
|
|
@@ -319,19 +317,19 @@ module TensorStream
|
|
319
317
|
|
320
318
|
((0 - padding[0])...height).step(height_stride).each do |y|
|
321
319
|
((0 - padding[1])...width).step(width_stride).each do |x|
|
322
|
-
filter_result = (0...f_height).map
|
320
|
+
filter_result = (0...f_height).map { |f_y|
|
323
321
|
(0...f_width).map do |f_x|
|
324
322
|
next Array.new(input_channels * output_channels) { 0.0 } if x + f_x >= width || (x + f_x < 0) || ((x + f_width) > (width + padding[3]))
|
325
323
|
next Array.new(input_channels * output_channels) { 0.0 } if y + f_y >= height || (y + f_y < 0) || ((y + f_height) > (height + padding[2]))
|
326
324
|
|
327
|
-
image_grad = grad[index][(y + padding[0]) / height_stride][(x + padding[1])/ width_stride]
|
325
|
+
image_grad = grad[index][(y + padding[0]) / height_stride][(x + padding[1]) / width_stride]
|
328
326
|
image[y + f_y][x + f_x].map do |image_channel|
|
329
327
|
Array.new(output_channels) do |o_c|
|
330
328
|
image_channel * image_grad[o_c]
|
331
329
|
end
|
332
330
|
end
|
333
331
|
end
|
334
|
-
|
332
|
+
}.flatten
|
335
333
|
|
336
334
|
filter_gradient_sum = multi_array_op(->(a, b) { a + b }, filter_gradient_sum, filter_result)
|
337
335
|
end
|
@@ -341,17 +339,16 @@ module TensorStream
|
|
341
339
|
TensorShape.reshape(filter_gradient_sum, filter_shape)
|
342
340
|
end
|
343
341
|
|
344
|
-
|
345
342
|
def conv2d_padding_options(padding_option, filter_shape, height, width, h_stride, w_stride)
|
346
343
|
case padding_option
|
347
|
-
when
|
344
|
+
when "SAME"
|
348
345
|
[
|
349
346
|
calc_pad(height, h_stride, filter_shape[0]),
|
350
347
|
calc_pad(width, w_stride, filter_shape[1]),
|
351
348
|
calc_pad(height, h_stride, filter_shape[0], true),
|
352
|
-
calc_pad(width, w_stride, filter_shape[1], true)
|
349
|
+
calc_pad(width, w_stride, filter_shape[1], true),
|
353
350
|
]
|
354
|
-
when
|
351
|
+
when "VALID"
|
355
352
|
[0, 0, 0, 0]
|
356
353
|
else
|
357
354
|
raise TensorStream::ValueError, "Unsupported padding value #{padding_option}, valid values 'SAME', 'VALID'"
|
@@ -369,4 +366,4 @@ module TensorStream
|
|
369
366
|
end
|
370
367
|
end
|
371
368
|
end
|
372
|
-
end
|
369
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module TensorStream
|
2
2
|
## Collection of machine learning related ops
|
3
3
|
module RandomOps
|
4
|
-
def
|
4
|
+
def self.included(klass)
|
5
5
|
klass.class_eval do
|
6
6
|
register_op :glorot_uniform, no_eval: true do |_context, tensor, _inputs|
|
7
7
|
seed = tensor.options[:seed]
|
@@ -9,12 +9,12 @@ module TensorStream
|
|
9
9
|
|
10
10
|
shape = tensor.options[:shape] || tensor.shape.shape
|
11
11
|
fan_in, fan_out = if shape.size.zero?
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
[1, 1]
|
13
|
+
elsif shape.size == 1
|
14
|
+
[1, shape[0]]
|
15
|
+
else
|
16
|
+
[shape[0], shape.last]
|
17
|
+
end
|
18
18
|
|
19
19
|
limit = Math.sqrt(6.0 / (fan_in + fan_out))
|
20
20
|
|
@@ -46,7 +46,6 @@ module TensorStream
|
|
46
46
|
generate_vector(shape, generator: generator)
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
49
|
register_op :truncated_normal, no_eval: true do |_context, tensor, inputs|
|
51
50
|
seed = tensor.options[:seed]
|
52
51
|
random = _get_randomizer(tensor, seed)
|
@@ -54,14 +53,14 @@ module TensorStream
|
|
54
53
|
random = _get_randomizer(tensor, seed)
|
55
54
|
generator = -> { r.rand }
|
56
55
|
shape = inputs[0] || tensor.shape.shape
|
57
|
-
random_values = Array.new(shape.reduce(:*) || 1)
|
56
|
+
random_values = Array.new(shape.reduce(:*) || 1) {
|
58
57
|
generator.call
|
59
|
-
|
58
|
+
}
|
60
59
|
mean = random_values.reduce(:+) / random_values.size
|
61
60
|
|
62
61
|
# standard deviation
|
63
62
|
|
64
|
-
stddev = Math.sqrt(
|
63
|
+
stddev = Math.sqrt(random_values.map { |v| (v - mean)**2 }.reduce(:+) / (random_values.size - 1))
|
65
64
|
minval = random_values.min
|
66
65
|
maxval = random_values.max
|
67
66
|
max_iterations = 100
|
@@ -73,14 +72,14 @@ module TensorStream
|
|
73
72
|
maxval = a
|
74
73
|
stddev = -stddev
|
75
74
|
end
|
76
|
-
|
77
|
-
norm_min = (minval - mean) / stddev;
|
78
|
-
norm_max = (maxval - mean) / stddev;
|
79
|
-
sqrt_factor = Math.sqrt((norm_min * norm_min) + 4.0);
|
80
|
-
cutoff = 2.0 * Math.exp( 0.5 + (norm_min * (norm_min - sqrt_factor)) / 4.0 ) / (norm_min + sqrt_factor)
|
81
|
-
diff = norm_max - norm_min;
|
82
75
|
|
83
|
-
|
76
|
+
norm_min = (minval - mean) / stddev
|
77
|
+
norm_max = (maxval - mean) / stddev
|
78
|
+
sqrt_factor = Math.sqrt((norm_min * norm_min) + 4.0)
|
79
|
+
cutoff = 2.0 * Math.exp(0.5 + (norm_min * (norm_min - sqrt_factor)) / 4.0) / (norm_min + sqrt_factor)
|
80
|
+
diff = norm_max - norm_min
|
81
|
+
|
82
|
+
val = random_values.map { |v|
|
84
83
|
iterations = 0
|
85
84
|
pick = v
|
86
85
|
while (pick > norm_max) || (pick < norm_min)
|
@@ -92,12 +91,12 @@ module TensorStream
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
95
|
-
pick
|
96
|
-
|
94
|
+
pick
|
95
|
+
}
|
97
96
|
|
98
97
|
TensorShape.reshape(val, shape)
|
99
98
|
end
|
100
99
|
end
|
101
100
|
end
|
102
101
|
end
|
103
|
-
end
|
102
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
1
|
+
require "tensor_stream/evaluator/operation_helpers/random_gaussian"
|
2
|
+
require "tensor_stream/evaluator/operation_helpers/array_ops_helper"
|
3
|
+
require "tensor_stream/evaluator/operation_helpers/math_helper"
|
4
|
+
require "tensor_stream/evaluator/base_evaluator"
|
5
|
+
require "tensor_stream/evaluator/ruby/math_ops"
|
6
|
+
require "tensor_stream/evaluator/ruby/nn_ops"
|
7
|
+
require "tensor_stream/evaluator/ruby/array_ops"
|
8
|
+
require "tensor_stream/evaluator/ruby/random_ops"
|
9
|
+
require "tensor_stream/evaluator/ruby/images_ops"
|
10
|
+
require "tensor_stream/evaluator/ruby/check_ops"
|
11
11
|
|
12
12
|
module TensorStream
|
13
13
|
module Evaluator
|
@@ -49,12 +49,12 @@ module TensorStream
|
|
49
49
|
|
50
50
|
child_context = execution_context.dup
|
51
51
|
res = if tensor.is_a?(Operation)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
52
|
+
eval_operation(tensor, child_context)
|
53
|
+
elsif !tensor.is_a?(Tensor)
|
54
|
+
tensor
|
55
|
+
else
|
56
|
+
tensor.op
|
57
|
+
end
|
58
58
|
execution_context.deep_merge!(returns: child_context[:returns])
|
59
59
|
res
|
60
60
|
end
|
@@ -84,6 +84,7 @@ module TensorStream
|
|
84
84
|
|
85
85
|
def prepare_input(tensor, context, options = {})
|
86
86
|
return nil unless tensor
|
87
|
+
|
87
88
|
if options[:noop]
|
88
89
|
tensor
|
89
90
|
elsif options[:no_eval]
|
@@ -102,10 +103,10 @@ module TensorStream
|
|
102
103
|
end
|
103
104
|
|
104
105
|
register_op(:cast) do |context, tensor, inputs|
|
105
|
-
call_op(inputs[0], context)
|
106
|
+
call_op(inputs[0], context) { |t, _b| Tensor.cast_dtype(t, tensor.data_type) }
|
106
107
|
end
|
107
108
|
|
108
|
-
register_op(:sign) do |context,
|
109
|
+
register_op(:sign) do |context, _tensor, inputs|
|
109
110
|
call_op(inputs[0], context) do |x, _b|
|
110
111
|
if x.zero? || (x.is_a?(Float) && x.nan?)
|
111
112
|
0
|
@@ -114,7 +115,7 @@ module TensorStream
|
|
114
115
|
elsif x > 0
|
115
116
|
1
|
116
117
|
else
|
117
|
-
raise
|
118
|
+
raise "assert: cannot be here"
|
118
119
|
end
|
119
120
|
end
|
120
121
|
end
|
@@ -213,7 +214,7 @@ module TensorStream
|
|
213
214
|
end
|
214
215
|
|
215
216
|
register_op :print do |_context, tensor, inputs|
|
216
|
-
puts "#{tensor.options.fetch(:message,
|
217
|
+
puts "#{tensor.options.fetch(:message, "")} #{inputs[1]}"
|
217
218
|
inputs[0]
|
218
219
|
end
|
219
220
|
|
@@ -245,12 +246,12 @@ module TensorStream
|
|
245
246
|
val = savable.container
|
246
247
|
packed_data = Zlib::Deflate.deflate(TensorStream::Packer.pack(val, savable.data_type))
|
247
248
|
variables[savable.name] = {
|
248
|
-
|
249
|
-
|
249
|
+
"shape" => shape_eval(val),
|
250
|
+
"data" => Base64.strict_encode64(packed_data),
|
250
251
|
}
|
251
252
|
end
|
252
253
|
|
253
|
-
File.write(outputfile, {
|
254
|
+
File.write(outputfile, {"variables" => variables}.to_yaml)
|
254
255
|
nil
|
255
256
|
end
|
256
257
|
|
@@ -262,10 +263,10 @@ module TensorStream
|
|
262
263
|
input_dump = YAML.safe_load(File.read(filename), [Symbol])
|
263
264
|
vars = tensor.graph.get_collection(GraphKeys::GLOBAL_VARIABLES)
|
264
265
|
|
265
|
-
vars.select! { |v| input_dump[
|
266
|
+
vars.select! { |v| input_dump["variables"].key?(v.name) && tensor_names.include?(v.name) }
|
266
267
|
vars.each do |variable|
|
267
|
-
data = TensorStream::Packer.unpack(Zlib::Inflate.inflate(Base64.decode64(input_dump[
|
268
|
-
shape = input_dump[
|
268
|
+
data = TensorStream::Packer.unpack(Zlib::Inflate.inflate(Base64.decode64(input_dump["variables"][variable.name]["data"])), variable.data_type)
|
269
|
+
shape = input_dump["variables"][variable.name]["shape"]
|
269
270
|
variable.buffer = nil
|
270
271
|
variable.value = TensorShape.reshape(data, shape)
|
271
272
|
end
|
@@ -277,6 +278,7 @@ module TensorStream
|
|
277
278
|
message = tensor.options[:message]
|
278
279
|
call_op(inputs[0], context) do |t, _b|
|
279
280
|
raise TensorStream::InvalidArgumentError, "#{message} Invalid argument" if t.nan? || t.infinite?
|
281
|
+
|
280
282
|
t
|
281
283
|
end
|
282
284
|
end
|
@@ -289,9 +291,7 @@ module TensorStream
|
|
289
291
|
# puts "result done ruby #{object_id}: #{tensor.name}"
|
290
292
|
# assertions to make sure inferred shapes == actual evaluated shapes
|
291
293
|
if tensor.shape.known? && (result.is_a?(Array) || result.is_a?(Float) || result.is_a?(Integer))
|
292
|
-
if shape_eval(result) != tensor.shape.shape
|
293
|
-
raise "assert error #{tensor.name} #{shape_eval(result)} != #{tensor.shape.shape}"
|
294
|
-
end
|
294
|
+
raise "assert error #{tensor.name} #{shape_eval(result)} != #{tensor.shape.shape}" if shape_eval(result) != tensor.shape.shape
|
295
295
|
end
|
296
296
|
|
297
297
|
if tensor.breakpoint
|
@@ -308,7 +308,7 @@ module TensorStream
|
|
308
308
|
shape: shape_eval(result),
|
309
309
|
source: tensor.source,
|
310
310
|
description: tensor.to_math(true, 1),
|
311
|
-
value: result
|
311
|
+
value: result,
|
312
312
|
}
|
313
313
|
end
|
314
314
|
@context[tensor.name] = result
|
@@ -317,22 +317,9 @@ module TensorStream
|
|
317
317
|
raise e, "error #{e.message} while evaluating #{tensor.name} defined at #{tensor.source}"
|
318
318
|
rescue TensorStreamError => e
|
319
319
|
raise e, "error #{e.message} while evaluating #{tensor.name} defined at #{tensor.source}"
|
320
|
-
rescue
|
321
|
-
|
320
|
+
rescue => e
|
321
|
+
puts e.message
|
322
322
|
puts e.backtrace.join("\n")
|
323
|
-
# shape_a = a.shape.shape if a
|
324
|
-
# shape_b = b.shape.shape if b
|
325
|
-
# dtype_a = a.data_type if a
|
326
|
-
# dtype_b = b.data_type if b
|
327
|
-
# a = complete_eval(a, child_context)
|
328
|
-
# b = complete_eval(b, child_context)
|
329
|
-
# puts "name: #{tensor.given_name}"
|
330
|
-
# # puts "op: #{tensor.to_math(true, 1)}"
|
331
|
-
# puts "A #{shape_a} #{dtype_a}: #{a}" if a
|
332
|
-
# puts "B #{shape_b} #{dtype_b}: #{b}" if b
|
333
|
-
# dump_intermediates if @log_intermediates
|
334
|
-
# File.write('/home/jedld/workspace/tensor_stream/samples/error.graphml', TensorStream::Graphml.new.get_string(tensor, @session))
|
335
|
-
# File.write('/Users/josephemmanueldayo/workspace/gradients.graphml', TensorStream::Graphml.new.get_string(tensor, @session))
|
336
323
|
raise EvaluatorExcecutionException.new(e, tensor), "error #{e.message} while evaluating #{tensor.name} : #{tensor.to_math(true, 1)} defined at #{tensor.source}"
|
337
324
|
end
|
338
325
|
|
@@ -367,7 +354,7 @@ module TensorStream
|
|
367
354
|
TensorStream.send(op.to_sym, a, b)
|
368
355
|
end
|
369
356
|
|
370
|
-
def process_vector_math_op(tensor, a, b,
|
357
|
+
def process_vector_math_op(tensor, a, b, child_context, &block)
|
371
358
|
eval_a = global_eval(tensor, a, child_context) unless a.nil?
|
372
359
|
eval_b = global_eval(tensor, b, child_context) unless b.nil?
|
373
360
|
|
@@ -390,7 +377,7 @@ module TensorStream
|
|
390
377
|
# multi array ops on ruby arrays with same sizes
|
391
378
|
def multi_array_op(func, *args)
|
392
379
|
elem = args[0]
|
393
|
-
if
|
380
|
+
if elem.is_a?(Array)
|
394
381
|
elem.each_with_index.collect do |_item, index|
|
395
382
|
indexed_args = args.collect { |a| a[index] }
|
396
383
|
multi_array_op(func, *indexed_args)
|
@@ -497,10 +484,10 @@ module TensorStream
|
|
497
484
|
end
|
498
485
|
arr << "============== end ====================="
|
499
486
|
str = arr.join("\n")
|
500
|
-
File.write(
|
487
|
+
File.write("/tmp/intermediates.txt", str)
|
501
488
|
end
|
502
489
|
end
|
503
490
|
end
|
504
491
|
end
|
505
492
|
|
506
|
-
TensorStream::Evaluator.register_evaluator(TensorStream::Evaluator::RubyEvaluator,
|
493
|
+
TensorStream::Evaluator.register_evaluator(TensorStream::Evaluator::RubyEvaluator, "ruby")
|