tensor_stream 0.7.0 → 0.8.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 +5 -5
- data/.rubocop.yml +6 -1
- data/CHANGELOG.md +10 -0
- data/README.md +35 -0
- data/lib/tensor_stream.rb +2 -2
- data/lib/tensor_stream/debugging/debugging.rb +2 -1
- data/lib/tensor_stream/dynamic_stitch.rb +23 -24
- data/lib/tensor_stream/evaluator/base_evaluator.rb +27 -18
- data/lib/tensor_stream/evaluator/opencl/kernels/apply_momentum.cl +16 -0
- data/lib/tensor_stream/evaluator/opencl/kernels/pack.cl +24 -0
- data/lib/tensor_stream/evaluator/opencl/kernels/softmax_cross.cl +6 -1
- data/lib/tensor_stream/evaluator/opencl/opencl_buffer.rb +6 -6
- data/lib/tensor_stream/evaluator/opencl/opencl_evaluator.rb +237 -107
- data/lib/tensor_stream/evaluator/operation_helpers/array_ops_helper.rb +97 -7
- data/lib/tensor_stream/evaluator/ruby_evaluator.rb +230 -123
- data/lib/tensor_stream/exceptions.rb +1 -0
- data/lib/tensor_stream/graph_builder.rb +2 -3
- data/lib/tensor_stream/graph_deserializers/protobuf.rb +22 -23
- data/lib/tensor_stream/graph_serializers/graphml.rb +26 -29
- data/lib/tensor_stream/graph_serializers/pbtext.rb +22 -19
- data/lib/tensor_stream/helpers/string_helper.rb +4 -5
- data/lib/tensor_stream/math_gradients.rb +141 -77
- data/lib/tensor_stream/nn/nn_ops.rb +4 -6
- data/lib/tensor_stream/operation.rb +139 -120
- data/lib/tensor_stream/ops.rb +36 -3
- data/lib/tensor_stream/session.rb +7 -11
- data/lib/tensor_stream/tensor.rb +3 -3
- data/lib/tensor_stream/tensor_shape.rb +5 -0
- data/lib/tensor_stream/train/gradient_descent_optimizer.rb +4 -37
- data/lib/tensor_stream/train/momentum_optimizer.rb +48 -0
- data/lib/tensor_stream/train/optimizer.rb +129 -0
- data/lib/tensor_stream/train/saver.rb +0 -1
- data/lib/tensor_stream/train/slot_creator.rb +62 -0
- data/lib/tensor_stream/train/utils.rb +11 -12
- data/lib/tensor_stream/trainer.rb +3 -0
- data/lib/tensor_stream/utils.rb +18 -11
- data/lib/tensor_stream/variable.rb +19 -12
- data/lib/tensor_stream/variable_scope.rb +1 -1
- data/lib/tensor_stream/version.rb +1 -1
- data/samples/iris.rb +2 -1
- data/samples/linear_regression.rb +3 -1
- data/samples/nearest_neighbor.rb +2 -0
- data/test_samples/neural_network_raw.py +101 -0
- data/test_samples/raw_neural_net_sample.rb +6 -4
- data/test_samples/test2.py +73 -27
- metadata +9 -3
@@ -25,8 +25,8 @@ module TensorStream
|
|
25
25
|
logits = tf.convert_to_tensor(logits, name: 'logits')
|
26
26
|
labels = tf.convert_to_tensor(labels, name: 'labels')
|
27
27
|
labels = tf.cast(labels, logits.dtype)
|
28
|
-
|
29
|
-
|
28
|
+
output = _op(:softmax_cross_entropy_with_logits_v2, logits, labels)
|
29
|
+
output[0]
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
@@ -45,10 +45,8 @@ module TensorStream
|
|
45
45
|
relu_logits = tf.where(cond, logits, zeros)
|
46
46
|
neg_abs_logits = tf.where(cond, -logits, logits)
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
tf.log1p(tf.exp(neg_abs_logits)),
|
51
|
-
name: name)
|
48
|
+
tf.add(relu_logits - logits * labels,
|
49
|
+
tf.log1p(tf.exp(neg_abs_logits)), name: name)
|
52
50
|
end
|
53
51
|
end
|
54
52
|
end
|
@@ -87,124 +87,124 @@ module TensorStream
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
def to_math(name_only = false, max_depth = 99,
|
90
|
+
def to_math(name_only = false, max_depth = 99, cur_depth = 0)
|
91
91
|
return @name if max_depth.zero?
|
92
92
|
|
93
|
-
sub_input = auto_math(inputs[0], name_only, max_depth - 1,
|
94
|
-
sub_input2 = auto_math(inputs[1], name_only, max_depth - 1,
|
93
|
+
sub_input = auto_math(inputs[0], name_only, max_depth - 1, cur_depth + 1)
|
94
|
+
sub_input2 = auto_math(inputs[1], name_only, max_depth - 1, cur_depth + 1) if inputs[1]
|
95
95
|
|
96
96
|
out = case operation
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
["\n",(
|
97
|
+
when :argmax
|
98
|
+
"argmax(#{sub_input},#{options[:axis]})"
|
99
|
+
when :negate
|
100
|
+
"-#{sub_input}"
|
101
|
+
when :index
|
102
|
+
"#{sub_input}[#{sub_input2}]"
|
103
|
+
when :slice
|
104
|
+
"#{sub_input}[#{sub_input2}]"
|
105
|
+
when :assign_sub
|
106
|
+
"(#{inputs[0] ? inputs[0].name : 'self'} -= #{auto_math(inputs[1], name_only, 1)})"
|
107
|
+
when :assign_add
|
108
|
+
"(#{inputs[0] ? inputs[0].name : 'self'} += #{auto_math(inputs[1], name_only, 1)})"
|
109
|
+
when :assign
|
110
|
+
"(#{inputs[0] ? inputs[0].name : 'self'} = #{auto_math(inputs[1], name_only, 1)})"
|
111
|
+
when :sin, :cos, :tanh
|
112
|
+
"#{operation}(#{sub_input})"
|
113
|
+
when :add
|
114
|
+
"(#{sub_input} + #{sub_input2})"
|
115
|
+
when :sub
|
116
|
+
"(#{sub_input} - #{sub_input2})"
|
117
|
+
when :pow
|
118
|
+
"(#{sub_input}^#{sub_input2})"
|
119
|
+
when :div
|
120
|
+
"(#{sub_input} / #{sub_input2})"
|
121
|
+
when :mul
|
122
|
+
if auto_math(inputs[0]) == 1
|
123
|
+
sub_input2
|
124
|
+
elsif auto_math(inputs[1]) == 1
|
125
|
+
sub_input
|
126
|
+
else
|
127
|
+
"(#{sub_input} * #{sub_input2})"
|
128
|
+
end
|
129
|
+
when :sum
|
130
|
+
"sum(|#{sub_input}|, axis=#{sub_input2})"
|
131
|
+
when :mean
|
132
|
+
"mean(|#{sub_input}|, axis=#{sub_input2})"
|
133
|
+
when :prod
|
134
|
+
"prod(|#{sub_input}|, axis=#{sub_input2})"
|
135
|
+
when :gradients
|
136
|
+
"gradient(#{sub_input})"
|
137
|
+
when :stop_gradient
|
138
|
+
sub_input
|
139
|
+
when :mat_mul
|
140
|
+
"#{sub_input}.matmul(#{sub_input2})"
|
141
|
+
when :eye
|
142
|
+
"eye(#{sub_input})"
|
143
|
+
when :transpose
|
144
|
+
"transpose(#{sub_input})"
|
145
|
+
when :shape
|
146
|
+
"#{sub_input}.shape"
|
147
|
+
when :exp
|
148
|
+
"e^#{sub_input})"
|
149
|
+
when :ones
|
150
|
+
"ones(#{sub_input})"
|
151
|
+
when :ones_like
|
152
|
+
"ones_like(#{sub_input})"
|
153
|
+
when :flow_group
|
154
|
+
"flow_group(#{inputs.collect { |i| auto_math(i, name_only, max_depth - 1, cur_depth) }.join(',')})"
|
155
|
+
when :zeros
|
156
|
+
"zeros(#{sub_input})"
|
157
|
+
when :reshape
|
158
|
+
"reshape(#{sub_input},#{sub_input2})"
|
159
|
+
when :rank
|
160
|
+
"#{sub_input}.rank"
|
161
|
+
when :cond
|
162
|
+
"(#{auto_math(options[:pred], name_only, max_depth - 1, cur_depth)} ? #{sub_input} : #{sub_input2})"
|
163
|
+
when :less
|
164
|
+
"#{sub_input} < #{sub_input2}"
|
165
|
+
when :less_equal
|
166
|
+
"#{sub_input} <= #{sub_input2}"
|
167
|
+
when :greater
|
168
|
+
"#{sub_input} > #{sub_input2}"
|
169
|
+
when :greater_equal
|
170
|
+
"#{sub_input} >= #{sub_input2}"
|
171
|
+
when :square
|
172
|
+
"#{sub_input}\u00B2"
|
173
|
+
when :log
|
174
|
+
"log(#{sub_input})"
|
175
|
+
when :identity
|
176
|
+
"identity(#{sub_input})"
|
177
|
+
when :print
|
178
|
+
"print(#{sub_input})"
|
179
|
+
when :pad
|
180
|
+
"pad(#{sub_input},#{auto_math(options[:paddings])})"
|
181
|
+
when :equal
|
182
|
+
"#{sub_input} == #{sub_input2}"
|
183
|
+
when :not_equal
|
184
|
+
"#{sub_input} != #{sub_input2}"
|
185
|
+
when :logical_and
|
186
|
+
"#{sub_input} && #{sub_input2}"
|
187
|
+
when :sqrt
|
188
|
+
"sqrt(#{sub_input})"
|
189
|
+
when :log1p
|
190
|
+
"log1p(#{sub_input})"
|
191
|
+
when :zeros_like
|
192
|
+
"zeros_like(#{sub_input})"
|
193
|
+
when :where
|
194
|
+
"where(#{auto_math(options[:pred], name_only, max_depth - 1, cur_depth)}, #{sub_input}, #{sub_input2})"
|
195
|
+
when :max
|
196
|
+
"max(#{sub_input},#{sub_input2})"
|
197
|
+
when :cast
|
198
|
+
"cast(#{sub_input}, #{data_type})"
|
199
|
+
when :broadcast_transform
|
200
|
+
"broadcast_transform(#{sub_input},#{sub_input2})"
|
201
|
+
when :broadcast_gradient_args
|
202
|
+
"broadcast_transform(#{sub_input},#{sub_input2})"
|
203
|
+
else
|
204
|
+
"#{operation}(#{sub_input})" if sub_input
|
205
|
+
"#{operation}(#{sub_input}, #{sub_input2})" if sub_input && sub_input2
|
206
|
+
end
|
207
|
+
["\n", Array.new(cur_depth + 1) { ' ' }, out].flatten.join
|
208
208
|
end
|
209
209
|
|
210
210
|
def run
|
@@ -232,7 +232,7 @@ module TensorStream
|
|
232
232
|
|
233
233
|
axis = inputs[1].is_a?(Tensor) ? inputs[1].value : inputs[1]
|
234
234
|
|
235
|
-
axis = [
|
235
|
+
axis = [axis] unless axis.is_a?(Array)
|
236
236
|
return input_shape.each_with_index.map do |s, index|
|
237
237
|
next nil if axis.include?(index)
|
238
238
|
s
|
@@ -240,6 +240,7 @@ module TensorStream
|
|
240
240
|
when :reshape
|
241
241
|
new_shape = inputs[1] && inputs[1].value ? inputs[1].value : nil
|
242
242
|
return nil if new_shape.nil?
|
243
|
+
return nil if inputs[0].shape.nil?
|
243
244
|
|
244
245
|
input_shape = inputs[0].shape.shape
|
245
246
|
return new_shape if input_shape.nil?
|
@@ -257,11 +258,29 @@ module TensorStream
|
|
257
258
|
shape1 = inputs[0].shape.shape.nil? ? nil : inputs[0].shape.shape[0]
|
258
259
|
shape2 = inputs[1].shape.shape.nil? ? nil : inputs[1].shape.shape[1]
|
259
260
|
return [shape1, shape2]
|
261
|
+
when :transpose
|
262
|
+
return nil unless shape_full_specified(inputs[0])
|
263
|
+
return nil if inputs[1].is_a?(Tensor)
|
264
|
+
|
265
|
+
rank = inputs[0].shape.shape.size
|
266
|
+
perm = inputs[1] || (0...rank).to_a.reverse
|
267
|
+
return perm.map { |p| inputs[0].shape.shape[p] }
|
268
|
+
when :stack
|
269
|
+
return nil unless shape_full_specified(inputs[0])
|
270
|
+
|
271
|
+
axis = options[:axis] || 0
|
272
|
+
new_shape = [inputs.size]
|
273
|
+
inputs[0].shape.shape.inject(new_shape) { |ns, s| ns << s }
|
274
|
+
rank = inputs[0].shape.shape.size + 1
|
275
|
+
axis = rank + axis if axis < 0
|
276
|
+
rotated_shape = Array.new(axis + 1) { new_shape.shift }
|
277
|
+
rotated_shape.rotate! + new_shape
|
278
|
+
when :tile
|
279
|
+
nil
|
260
280
|
else
|
281
|
+
return nil if inputs[0].nil?
|
261
282
|
return inputs[0].shape.shape if inputs.size == 1
|
262
|
-
if inputs.size == 2 && inputs[0] && inputs[1]
|
263
|
-
return TensorShape.infer_shape(inputs[0].shape.shape, inputs[1].shape.shape)
|
264
|
-
end
|
283
|
+
return TensorShape.infer_shape(inputs[0].shape.shape, inputs[1].shape.shape) if inputs.size == 2 && inputs[0] && inputs[1]
|
265
284
|
end
|
266
285
|
|
267
286
|
nil
|
@@ -287,8 +306,8 @@ module TensorStream
|
|
287
306
|
input.flatten.compact.each do |t|
|
288
307
|
t.send(:setup_output, self) if t.is_a?(Tensor)
|
289
308
|
end
|
290
|
-
|
291
|
-
input.send(:setup_output, self)
|
309
|
+
elsif input.is_a?(Tensor) && (input.name != name)
|
310
|
+
input.send(:setup_output, self)
|
292
311
|
end
|
293
312
|
end
|
294
313
|
end
|
data/lib/tensor_stream/ops.rb
CHANGED
@@ -245,7 +245,7 @@ module TensorStream
|
|
245
245
|
##
|
246
246
|
# Concatenates tensors along one dimension.
|
247
247
|
def concat(values, axis, name: 'concat')
|
248
|
-
_op(:concat, values,
|
248
|
+
_op(:concat, *values, axis: axis, name: name)
|
249
249
|
end
|
250
250
|
|
251
251
|
##
|
@@ -318,6 +318,13 @@ module TensorStream
|
|
318
318
|
_op(:acos, input, name: name)
|
319
319
|
end
|
320
320
|
|
321
|
+
##
|
322
|
+
# Computes atan of input element-wise
|
323
|
+
def atan(input, name: nil)
|
324
|
+
check_allowed_types(input, FLOATING_POINT_TYPES)
|
325
|
+
_op(:atan, input, name: name)
|
326
|
+
end
|
327
|
+
|
321
328
|
##
|
322
329
|
# Returns x - y element-wise.
|
323
330
|
#
|
@@ -582,8 +589,8 @@ module TensorStream
|
|
582
589
|
|
583
590
|
##
|
584
591
|
# Transposes a. Permutes the dimensions according to perm.
|
585
|
-
def transpose(tensor, perm
|
586
|
-
_op(:transpose, tensor,
|
592
|
+
def transpose(tensor, perm = nil, name: 'transpose')
|
593
|
+
_op(:transpose, tensor, perm, name: name)
|
587
594
|
end
|
588
595
|
|
589
596
|
##
|
@@ -612,5 +619,31 @@ module TensorStream
|
|
612
619
|
op_result = _op(:broadcast_gradient_args, shape_a, shape_b, name: name)
|
613
620
|
[op_result[0], op_result[1]]
|
614
621
|
end
|
622
|
+
|
623
|
+
##
|
624
|
+
# Gather slices from params and axis according to indices.
|
625
|
+
#
|
626
|
+
def gather(params, indices, validate_indices: nil,
|
627
|
+
name: nil,
|
628
|
+
axis: 0)
|
629
|
+
_op(:gather, params, indices, validate_indices: validate_indices, name: name, axis: axis)
|
630
|
+
end
|
631
|
+
|
632
|
+
def stack(values, axis: 0, name: 'stack')
|
633
|
+
_op(:stack, *values, axis: axis, name: name)
|
634
|
+
end
|
635
|
+
|
636
|
+
def setdiff1d(x, y, index_dtype: :int32, name: nil)
|
637
|
+
result = _op(:setdiff1d, x, y, index_dtype: index_dtype, name: name)
|
638
|
+
[result[0], result[1]]
|
639
|
+
end
|
640
|
+
|
641
|
+
def cumprod(x, axis: 0, exclusive: false, reverse: false, name: nil)
|
642
|
+
_op(:cumprod, x, axis: axis, exclusive: exclusive, reverse: reverse, name: name)
|
643
|
+
end
|
644
|
+
|
645
|
+
def invert_permutation(x, name: nil)
|
646
|
+
_op(:invert_permutation, x, name: name)
|
647
|
+
end
|
615
648
|
end
|
616
649
|
end
|
@@ -22,7 +22,7 @@ module TensorStream
|
|
22
22
|
if evaluators.empty?
|
23
23
|
TensorStream::Evaluator.default_evaluators
|
24
24
|
else
|
25
|
-
evaluators.collect { |name|
|
25
|
+
evaluators.collect { |name| Object.const_get("TensorStream::Evaluator::#{camelize(name.to_s)}") }
|
26
26
|
end
|
27
27
|
elsif evaluators.nil?
|
28
28
|
TensorStream::Evaluator.default_evaluators
|
@@ -52,9 +52,7 @@ module TensorStream
|
|
52
52
|
# scan for placeholders and assign value
|
53
53
|
if options[:feed_dict]
|
54
54
|
options[:feed_dict].keys.each do |k|
|
55
|
-
if k.is_a?(Placeholder)
|
56
|
-
context[k.name.to_sym] = options[:feed_dict][k]
|
57
|
-
end
|
55
|
+
context[k.name.to_sym] = options[:feed_dict][k] if k.is_a?(Placeholder)
|
58
56
|
end
|
59
57
|
end
|
60
58
|
|
@@ -77,7 +75,7 @@ module TensorStream
|
|
77
75
|
end
|
78
76
|
|
79
77
|
def list_devices
|
80
|
-
TensorStream::Evaluator.evaluators.collect do |
|
78
|
+
TensorStream::Evaluator.evaluators.collect do |_k, v|
|
81
79
|
v[:class].query_supported_devices.collect do |device|
|
82
80
|
device
|
83
81
|
end
|
@@ -102,10 +100,10 @@ module TensorStream
|
|
102
100
|
|
103
101
|
def dump_ops(tensor, selector)
|
104
102
|
graph = tensor.graph
|
105
|
-
graph.nodes.select { |k, v| selector.call(k, v) }.collect
|
103
|
+
graph.nodes.select { |k, v| selector.call(k, v) }.collect do |k, node|
|
106
104
|
next unless @last_session_context[node.name]
|
107
105
|
"#{k} #{node.to_math(true, 1)} = #{@last_session_context[node.name]}"
|
108
|
-
|
106
|
+
end.compact
|
109
107
|
end
|
110
108
|
|
111
109
|
def graph_ml(tensor, filename)
|
@@ -115,9 +113,7 @@ module TensorStream
|
|
115
113
|
def delegate_to_evaluator(tensor_arr, session_context, context)
|
116
114
|
arr = tensor_arr.is_a?(Array) ? tensor_arr : [tensor_arr]
|
117
115
|
result = arr.collect do |tensor|
|
118
|
-
if session_context[:_cache][:placement][tensor.name].nil?
|
119
|
-
session_context[:_cache][:placement][tensor.name] = assign_evaluator(tensor)
|
120
|
-
end
|
116
|
+
session_context[:_cache][:placement][tensor.name] = assign_evaluator(tensor) if session_context[:_cache][:placement][tensor.name].nil?
|
121
117
|
|
122
118
|
session_context[:_cache][:placement][tensor.name][1].run_with_buffer(tensor, session_context, context)
|
123
119
|
end
|
@@ -144,7 +140,7 @@ module TensorStream
|
|
144
140
|
|
145
141
|
raise "no evaluator available to execute #{tensor.operation}" if device.nil?
|
146
142
|
|
147
|
-
key = "#{device.evaluator
|
143
|
+
key = "#{device.evaluator}/#{device.name}"
|
148
144
|
if @evaluators.key?(key)
|
149
145
|
@evaluators[key]
|
150
146
|
else
|
data/lib/tensor_stream/tensor.rb
CHANGED
@@ -4,9 +4,9 @@ module TensorStream
|
|
4
4
|
# Base class that defines a tensor like interface
|
5
5
|
class Tensor
|
6
6
|
include OpHelper
|
7
|
-
|
7
|
+
attr_reader :graph
|
8
8
|
attr_accessor :name, :data_type, :shape, :rank, :native_buffer, :is_const,
|
9
|
-
:value, :breakpoint, :internal, :source, :given_name,
|
9
|
+
:value, :breakpoint, :internal, :source, :given_name,
|
10
10
|
:consumers, :outputs, :device
|
11
11
|
|
12
12
|
def initialize(data_type, rank, shape, options = {})
|
@@ -174,7 +174,7 @@ module TensorStream
|
|
174
174
|
end
|
175
175
|
|
176
176
|
def op
|
177
|
-
is_const ? _op(:const, self, nil, name: name) : _op(:variable, self, nil, name: name)
|
177
|
+
@op ||= is_const ? _op(:const, self, nil, name: name) : _op(:variable, self, nil, name: name)
|
178
178
|
end
|
179
179
|
|
180
180
|
def eval(options = {})
|