tensor_stream 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 +5 -5
- data/CHANGELOG.md +9 -0
- data/benchmark_ryzen_amd.txt +36 -0
- data/lib/tensor_stream/dynamic_stitch.rb +28 -0
- data/lib/tensor_stream/evaluator/base_evaluator.rb +32 -3
- data/lib/tensor_stream/evaluator/opencl/kernels/floor_div.cl +48 -0
- data/lib/tensor_stream/evaluator/opencl/kernels/mod.cl +3 -0
- data/lib/tensor_stream/evaluator/opencl/kernels/squared_difference.cl +53 -0
- data/lib/tensor_stream/evaluator/opencl/opencl_buffer.rb +1 -2
- data/lib/tensor_stream/evaluator/opencl/opencl_evaluator.rb +44 -24
- data/lib/tensor_stream/evaluator/opencl/opencl_template_helper.rb +2 -0
- data/lib/tensor_stream/evaluator/operation_helpers/array_ops_helper.rb +21 -11
- data/lib/tensor_stream/evaluator/ruby_evaluator.rb +165 -48
- data/lib/tensor_stream/graph_serializers/pbtext.rb +8 -0
- data/lib/tensor_stream/helpers/op_helper.rb +41 -4
- data/lib/tensor_stream/math_gradients.rb +64 -64
- data/lib/tensor_stream/nn/nn_ops.rb +6 -2
- data/lib/tensor_stream/operation.rb +17 -3
- data/lib/tensor_stream/ops.rb +47 -0
- data/lib/tensor_stream/session.rb +9 -1
- data/lib/tensor_stream/tensor.rb +15 -0
- data/lib/tensor_stream/utils.rb +5 -1
- data/lib/tensor_stream/version.rb +1 -1
- data/lib/tensor_stream.rb +1 -0
- data/samples/nearest_neighbor.rb +1 -1
- data/test_samples/raw_neural_net_sample.rb +6 -7
- metadata +8 -3
@@ -16,22 +16,17 @@ module TensorStream
|
|
16
16
|
node.consumers.include?(tensor.name) || node.equal?(tensor)
|
17
17
|
end.compact + [wrt_dx.name]
|
18
18
|
|
19
|
-
grad = i_op(:
|
19
|
+
grad = i_op(:fill, tf.shape(tensor), tf.constant(1, dtype: wrt_dx.data_type))
|
20
20
|
|
21
|
-
|
22
|
-
i_op(:truncate, result, tf.shape(wrt_dx))
|
21
|
+
_propagate(grad, tensor, wrt_dx, nodes_to_compute, options[:stop_gradients] || [] ) || i_op(:zeros_like, wrt_dx)
|
23
22
|
end
|
24
23
|
|
25
24
|
def self._propagate(grad, tensor, stop_tensor, nodes_to_compute, stop_gradients = [])
|
26
|
-
return grad
|
27
|
-
return
|
28
|
-
return
|
25
|
+
return grad if stop_tensor.equal?(tensor)
|
26
|
+
return nil if stop_gradients && _include?(stop_gradients, tensor)
|
27
|
+
return nil unless tensor.is_a?(Operation)
|
29
28
|
|
30
|
-
computed_op =
|
31
|
-
_compute_derivative(tensor, _broadcast_transform(tensor, grad)[1])
|
32
|
-
else
|
33
|
-
_compute_derivative(tensor, grad)
|
34
|
-
end
|
29
|
+
computed_op = _compute_derivative(tensor, grad)
|
35
30
|
|
36
31
|
if computed_op.is_a?(Array)
|
37
32
|
partials = []
|
@@ -43,9 +38,9 @@ module TensorStream
|
|
43
38
|
end
|
44
39
|
end
|
45
40
|
|
46
|
-
partials.reduce(:+)
|
41
|
+
partials.compact.reduce(:+)
|
47
42
|
else
|
48
|
-
return
|
43
|
+
return nil if computed_op.nil?
|
49
44
|
_propagate(computed_op, tensor.inputs[0], stop_tensor, nodes_to_compute, stop_gradients)
|
50
45
|
end
|
51
46
|
end
|
@@ -57,66 +52,74 @@ module TensorStream
|
|
57
52
|
|
58
53
|
case node.operation
|
59
54
|
when :add
|
60
|
-
return [grad, grad] if
|
61
|
-
|
55
|
+
return [grad, grad] if shapes_fully_specified_and_equal(x, y)
|
62
56
|
sx = tf.shape(x, name: 'add/shape_x')
|
63
57
|
sy = tf.shape(y, name: 'add/shape_y')
|
64
58
|
rx, ry = _broadcast_gradient_args(sx, sy)
|
65
|
-
keep_dims_x = tf.rank(x) == tf.rank(grad)
|
66
|
-
keep_dims_y = tf.rank(y) == tf.rank(grad)
|
67
59
|
|
68
|
-
[tf.reduce_sum(grad, rx, name: 'add/reduce_sum_x',
|
69
|
-
|
60
|
+
[ tf.reshape(tf.reduce_sum(grad, rx, name: 'add/reduce_sum_x'),sx),
|
61
|
+
tf.reshape(tf.reduce_sum(grad, ry, name: 'add/reduce_sum_y'),sy) ]
|
70
62
|
when :sub
|
71
|
-
return [grad, -grad] if
|
63
|
+
return [grad, -grad] if shapes_fully_specified_and_equal(x, y)
|
72
64
|
|
73
65
|
sx = tf.shape(x, name: 'sub/shape_x')
|
74
66
|
sy = tf.shape(y, name: 'sub/shape_y')
|
75
67
|
rx, ry = _broadcast_gradient_args(sx, sy)
|
76
|
-
|
68
|
+
|
69
|
+
[ tf.reshape(tf.reduce_sum(grad, rx, name: 'add/reduce_sub_x'),sx),
|
70
|
+
-tf.reshape(tf.reduce_sum(grad, ry, name: 'add/reduce_sub_y'),sy) ]
|
77
71
|
when :mul
|
78
72
|
sx = tf.shape(x)
|
79
73
|
sy = tf.shape(y)
|
80
74
|
rx, ry = _broadcast_gradient_args(sx, sy)
|
81
75
|
|
82
|
-
[ tf.reduce_sum(tf.mul(grad, y), rx),
|
83
|
-
tf.reduce_sum(tf.mul(x, grad), ry)]
|
76
|
+
[ tf.reshape(tf.reduce_sum(tf.mul(grad, y), rx), sx),
|
77
|
+
tf.reshape(tf.reduce_sum(tf.mul(x, grad), ry), sy)]
|
84
78
|
when :div
|
85
79
|
sx = i_op(:shape, x)
|
86
80
|
sy = i_op(:shape, y)
|
87
81
|
rx, ry = _broadcast_gradient_args(sx, sy)
|
88
82
|
|
89
|
-
[
|
90
|
-
|
91
|
-
|
83
|
+
[
|
84
|
+
tf.reshape(tf.reduce_sum(tf.div(grad, y), rx), sx),
|
85
|
+
tf.reshape(tf.reduce_sum(grad * tf.div(tf.div(-x, y), y),
|
86
|
+
ry), sy)]
|
87
|
+
when :mod
|
88
|
+
sx = tf.shape(x)
|
89
|
+
sy = tf.shape(y)
|
90
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
91
|
+
floor_xy = tf.floor_div(x, y)
|
92
|
+
gx = tf.reshape(tf.reduce_sum(grad, rx), sx)
|
93
|
+
gy = tf.reshape(tf.reduce_sum(grad * tf.negative(floor_xy), ry), sy)
|
94
|
+
|
95
|
+
[gx, gy]
|
96
|
+
when :squared_difference
|
97
|
+
sx = i_op(:shape, x)
|
98
|
+
sy = i_op(:shape, y)
|
99
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
100
|
+
|
101
|
+
x_grad = tf.mul(2.0, grad) * (x - y)
|
102
|
+
|
103
|
+
[ tf.reshape(tf.reduce_sum(x_grad, rx), sx),
|
104
|
+
tf.reshape(-tf.reduce_sum(x_grad, ry), sy)]
|
92
105
|
when :matmul
|
93
106
|
t_a = node.options[:transpose_a]
|
94
107
|
t_b = node.options[:transpose_b]
|
95
108
|
|
96
|
-
s0 = tf.shape(x)
|
97
|
-
s1 = tf.shape(y)
|
98
|
-
|
99
|
-
identity_0 = tf.ones([ s0[0], s1[1] ], dtype: x.data_type, name: 'matmul/identity0')
|
100
|
-
identity_1 = tf.ones([ s0[0], s1[1] ], dtype: y.data_type, name: 'matmul/identity1')
|
101
|
-
|
102
|
-
grad_a, grad_b = nil
|
103
109
|
if !t_a && !t_b
|
104
|
-
grad_a = tf.matmul(
|
105
|
-
grad_b = tf.matmul(x,
|
110
|
+
grad_a = tf.matmul(grad, y, transpose_b: true)
|
111
|
+
grad_b = tf.matmul(x, grad, transpose_a: true)
|
106
112
|
elsif !ta && tb
|
107
|
-
grad_a = tf.matmul(
|
108
|
-
grad_b = tf.matmul(
|
113
|
+
grad_a = tf.matmul(grad, y)
|
114
|
+
grad_b = tf.matmul(grad, x, transpose_a: true)
|
109
115
|
elsif t_a && !t_b
|
110
|
-
grad_a = tf.matmul(y,
|
111
|
-
grad_b = tf.matmul(x,
|
116
|
+
grad_a = tf.matmul(y, grad, transpose_b: true)
|
117
|
+
grad_b = tf.matmul(x, grad)
|
112
118
|
elsif t_a && t_b
|
113
|
-
grad_a = tf.matmul(y,
|
114
|
-
grad_b = tf.matmul(
|
119
|
+
grad_a = tf.matmul(y, grad, transpose_a: true, transpose_b: true)
|
120
|
+
grad_b = tf.matmul(grad, x, transpose_a: true, transpose_b: true)
|
115
121
|
end
|
116
122
|
|
117
|
-
grad_a = i_op(:mul, grad, grad_a, name: 'matmul/grad_a_norm_mul_da')
|
118
|
-
grad_b = i_op(:mul, grad, grad_b, name: 'matmul/grad_b_norm_mul_db')
|
119
|
-
|
120
123
|
[grad_a, grad_b]
|
121
124
|
when :sin
|
122
125
|
grad * tf.cos(x)
|
@@ -153,7 +156,7 @@ module TensorStream
|
|
153
156
|
-grad
|
154
157
|
when :exp
|
155
158
|
grad * node
|
156
|
-
when :identity
|
159
|
+
when :identity, :print
|
157
160
|
grad
|
158
161
|
when :sum
|
159
162
|
_sum_grad(x, y, grad)
|
@@ -175,7 +178,7 @@ module TensorStream
|
|
175
178
|
y_cond = i_op(:cond, i_op(:zeros_like, x), i_op(:ones_like, x), pred: node.options[:pred])
|
176
179
|
[x_cond * grad, y_cond * grad]
|
177
180
|
when :mean
|
178
|
-
sum_grad
|
181
|
+
sum_grad = _sum_grad(x, y, grad)[0]
|
179
182
|
input_shape = tf.shape(x)
|
180
183
|
output_shape = tf.shape(node)
|
181
184
|
factor = _safe_shape_div(tf.reduce_prod(input_shape), tf.reduce_prod(output_shape))
|
@@ -186,6 +189,10 @@ module TensorStream
|
|
186
189
|
i_op(:sigmoid_grad, x, grad)
|
187
190
|
when :softmax
|
188
191
|
i_op(:softmax_grad, x, grad)
|
192
|
+
when :softmax_cross_entropy_with_logits_v2
|
193
|
+
# -grad * tf.reciprocal(i_op(:softmax, x))
|
194
|
+
[i_op(:softmax_cross_entropy_with_logits_v2_grad, x, y, grad), nil]
|
195
|
+
# i_op(:softmax_grad, x, -grad * tf.reciprocal(i_op(:softmax, x)))
|
189
196
|
when :floor, :ceil
|
190
197
|
# non differentiable
|
191
198
|
nil
|
@@ -202,7 +209,8 @@ module TensorStream
|
|
202
209
|
end
|
203
210
|
|
204
211
|
def self._broadcast_gradient_args(input_a, input_b)
|
205
|
-
|
212
|
+
res = _op(:broadcast_gradient_args, input_a, input_b)
|
213
|
+
[res[0], res[1]]
|
206
214
|
end
|
207
215
|
|
208
216
|
def self._broadcast_transform(input_a, input_b)
|
@@ -210,11 +218,18 @@ module TensorStream
|
|
210
218
|
end
|
211
219
|
|
212
220
|
def self._safe_shape_div(x, y)
|
213
|
-
x
|
221
|
+
_op(:floor_div, x , tf.maximum(y, 1))
|
214
222
|
end
|
215
223
|
|
216
224
|
def self._sum_grad(x, y, grad)
|
217
|
-
|
225
|
+
input_shape = _op(:shape, x)
|
226
|
+
output_shape_kept_dims = tf.reduced_shape(input_shape, y)
|
227
|
+
tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims)
|
228
|
+
new_grad = _op(:reshape, grad, output_shape_kept_dims)
|
229
|
+
|
230
|
+
grad = _op(:cond, _op(:fill, input_shape, grad) , _op(:tile, new_grad, tile_scaling), pred: _op(:rank, grad) == 0 )
|
231
|
+
|
232
|
+
[grad, nil ]
|
218
233
|
end
|
219
234
|
|
220
235
|
def self._op_supports_broadcast?(node)
|
@@ -233,20 +248,5 @@ module TensorStream
|
|
233
248
|
arr.each { |a| return true if a.equal?(obj) }
|
234
249
|
false
|
235
250
|
end
|
236
|
-
|
237
|
-
def self._shapes_fully_specified_and_equal(x, y)
|
238
|
-
return false if !_shape_full_specified(x) || !_shape_full_specified(y)
|
239
|
-
return false if x.shape.shape != y.shape.shape
|
240
|
-
|
241
|
-
true
|
242
|
-
end
|
243
|
-
|
244
|
-
def self._shape_full_specified(tensor)
|
245
|
-
return false if tensor.shape.nil?
|
246
|
-
return false if tensor.shape.shape.nil?
|
247
|
-
|
248
|
-
tensor.shape.shape.each { |s| return false if s.nil? }
|
249
|
-
true
|
250
|
-
end
|
251
251
|
end
|
252
252
|
end
|
@@ -15,12 +15,16 @@ module TensorStream
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.softmax_cross_entropy_with_logits(labels: nil, logits: nil, name: nil)
|
18
|
-
|
18
|
+
softmax_cross_entropy_with_logits_v2(labels, logits, name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.softmax_cross_entropy_with_logits_v2(labels: nil, logits: nil, name: nil)
|
22
|
+
TensorStream.name_scope(name, default: 'softmax_cross_entropy_with_logits', values: [logits, labels]) do
|
19
23
|
tf = TensorStream
|
20
24
|
logits = tf.convert_to_tensor(logits, name: 'logits')
|
21
25
|
labels = tf.convert_to_tensor(labels, name: 'labels')
|
22
26
|
labels = tf.cast(labels, logits.dtype)
|
23
|
-
softmax_logits =
|
27
|
+
softmax_logits = _op(:softmax_cross_entropy_with_logits_v2, logits, labels)
|
24
28
|
tf.reduce_sum(softmax_logits, tf.rank(logits) - 1)
|
25
29
|
end
|
26
30
|
end
|
@@ -69,10 +69,12 @@ module TensorStream
|
|
69
69
|
|
70
70
|
def set_data_type(passed_data_type)
|
71
71
|
case operation
|
72
|
+
when :fill
|
73
|
+
@inputs[1].data_type
|
72
74
|
when :greater, :less, :equal, :not_equal, :greater_equal, :less_equal, :logical_and
|
73
75
|
:boolean
|
74
76
|
when :shape, :rank
|
75
|
-
:int32
|
77
|
+
options[:out_type] || :int32
|
76
78
|
when :random_normal, :random_uniform, :glorot_uniform
|
77
79
|
passed_data_type || :float32
|
78
80
|
when :index
|
@@ -282,13 +284,25 @@ module TensorStream
|
|
282
284
|
def propagate_consumer(consumer)
|
283
285
|
super
|
284
286
|
@inputs.compact.each do |input|
|
285
|
-
input.
|
287
|
+
if input.is_a?(Array)
|
288
|
+
input.flatten.compact.each do |t|
|
289
|
+
t.send(:propagate_consumer, consumer) if t.is_a?(Tensor)
|
290
|
+
end
|
291
|
+
else
|
292
|
+
input.send(:propagate_consumer, consumer) if input.name != name
|
293
|
+
end
|
286
294
|
end
|
287
295
|
end
|
288
296
|
|
289
297
|
def propagate_outputs
|
290
298
|
@inputs.compact.each do |input|
|
291
|
-
input.
|
299
|
+
if input.is_a?(Array)
|
300
|
+
input.flatten.compact.each do |t|
|
301
|
+
t.send(:setup_output, self) if t.is_a?(Tensor)
|
302
|
+
end
|
303
|
+
else
|
304
|
+
input.send(:setup_output, self) if input.is_a?(Tensor) && (input.name != self.name)
|
305
|
+
end
|
292
306
|
end
|
293
307
|
end
|
294
308
|
|
data/lib/tensor_stream/ops.rb
CHANGED
@@ -89,6 +89,9 @@ module TensorStream
|
|
89
89
|
##
|
90
90
|
# This operation returns a 1-D integer tensor representing the shape of input
|
91
91
|
def shape(input, name: nil, out_type: :int32)
|
92
|
+
return constant(shape_eval(input, out_type), dtype: out_type, name: name) if input.is_a?(Array)
|
93
|
+
return constant(input.shape.shape, dtype: out_type, name: "Shape/#{input.name}") if shape_full_specified(input)
|
94
|
+
|
92
95
|
_op(:shape, input, nil, name: name, out_type: out_type)
|
93
96
|
end
|
94
97
|
|
@@ -287,6 +290,24 @@ module TensorStream
|
|
287
290
|
_op(:sub, input_a, input_b, name: name)
|
288
291
|
end
|
289
292
|
|
293
|
+
##
|
294
|
+
# Returns element-wise remainder of division.
|
295
|
+
def mod(input_a, input_b, name: nil)
|
296
|
+
input_a, input_b = check_data_types(input_a, input_b)
|
297
|
+
_op(:mod, input_a, input_b, name: name)
|
298
|
+
end
|
299
|
+
|
300
|
+
##
|
301
|
+
# Returns element-wise integer divistion.
|
302
|
+
def floor_div(input_a, input_b, name: nil)
|
303
|
+
input_a, input_b = check_data_types(input_a, input_b)
|
304
|
+
_op(:floor_div, input_a, input_b, name: name)
|
305
|
+
end
|
306
|
+
|
307
|
+
def range(start, limit, delta = 1, dtype: nil, name: 'range')
|
308
|
+
_op(:range, start, limit, delta, data_type: dtype, name: name)
|
309
|
+
end
|
310
|
+
|
290
311
|
##
|
291
312
|
# Returns x - y element-wise.
|
292
313
|
#
|
@@ -476,6 +497,19 @@ module TensorStream
|
|
476
497
|
_op(:exp, input, nil, name: name)
|
477
498
|
end
|
478
499
|
|
500
|
+
##
|
501
|
+
# Creates a tensor filled with a scalar value.
|
502
|
+
#
|
503
|
+
# This operation creates a tensor of shape dims and fills it with value.
|
504
|
+
#
|
505
|
+
# For example:
|
506
|
+
# Output tensor has shape [2, 3].
|
507
|
+
# fill([2, 3], 9) => [[9, 9, 9]
|
508
|
+
# [9, 9, 9]]
|
509
|
+
def fill(dims, value, name: nil)
|
510
|
+
_op(:fill, dims, value, name: name)
|
511
|
+
end
|
512
|
+
|
479
513
|
##
|
480
514
|
# Computes sigmoid of x element-wise.
|
481
515
|
def sigmoid(input, name: nil)
|
@@ -512,5 +546,18 @@ module TensorStream
|
|
512
546
|
def check_numerics(tensor, message, name: nil)
|
513
547
|
_op(:check_numerics, tensor, nil, message: message, name: name)
|
514
548
|
end
|
549
|
+
|
550
|
+
def size(tensor, name: nil, out_type: :int32)
|
551
|
+
_op(:size, tensor, name: name, out_type: out_type)
|
552
|
+
end
|
553
|
+
|
554
|
+
def squared_difference(input_a, input_b, name: nil)
|
555
|
+
_op(:squared_difference, input_a, input_b, name: name)
|
556
|
+
end
|
557
|
+
|
558
|
+
def broadcast_gradient_args(shape_a, shape_b, name: nil)
|
559
|
+
op_result = _op(:broadcast_gradient_args, shape_a, shape_b, name: name)
|
560
|
+
[op_result[0], op_result[1]]
|
561
|
+
end
|
515
562
|
end
|
516
563
|
end
|
@@ -71,7 +71,7 @@ module TensorStream
|
|
71
71
|
end
|
72
72
|
result = args.collect do |e|
|
73
73
|
value = delegate_to_evaluator(e, context, {})
|
74
|
-
value
|
74
|
+
recursive_eval(value)
|
75
75
|
end
|
76
76
|
result.size == 1 ? result.first : result
|
77
77
|
end
|
@@ -122,6 +122,14 @@ module TensorStream
|
|
122
122
|
|
123
123
|
protected
|
124
124
|
|
125
|
+
def recursive_eval(value, depth = 2)
|
126
|
+
if value.is_a?(Array) && depth > 0
|
127
|
+
value.collect { |v| recursive_eval(v, depth - 1) }
|
128
|
+
else
|
129
|
+
value.respond_to?(:to_ruby) ? value.to_ruby : value
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
125
133
|
def assign_evaluator(tensor)
|
126
134
|
device = @evaluator_classes.map do |klass|
|
127
135
|
next nil if tensor.is_a?(Operation) && !klass.ops.include?(tensor.operation.to_sym)
|
data/lib/tensor_stream/tensor.rb
CHANGED
@@ -87,6 +87,19 @@ module TensorStream
|
|
87
87
|
_op(:negate, self, nil)
|
88
88
|
end
|
89
89
|
|
90
|
+
def %(other)
|
91
|
+
_a, other = TensorStream.check_data_types(self, other)
|
92
|
+
_op(:mod, self, TensorStream.convert_to_tensor(other, dtype: data_type))
|
93
|
+
end
|
94
|
+
|
95
|
+
def floor
|
96
|
+
TensorStream.floor(self)
|
97
|
+
end
|
98
|
+
|
99
|
+
def ceil
|
100
|
+
TensorStream.ceil(self)
|
101
|
+
end
|
102
|
+
|
90
103
|
def ==(other)
|
91
104
|
_a, other = TensorStream.check_data_types(self, other)
|
92
105
|
_op(:equal, self, other)
|
@@ -199,6 +212,8 @@ module TensorStream
|
|
199
212
|
:int32
|
200
213
|
elsif value.is_a?(Array)
|
201
214
|
return detect_type(value[0])
|
215
|
+
elsif value.is_a?(Tensor)
|
216
|
+
value.data_type
|
202
217
|
else
|
203
218
|
:float32
|
204
219
|
end
|
data/lib/tensor_stream/utils.rb
CHANGED
@@ -141,6 +141,10 @@ module TensorStream
|
|
141
141
|
TensorStream::ControlFlow.new(:group, inputs, nil, name: name)
|
142
142
|
end
|
143
143
|
|
144
|
+
def dynamic_stitch(indices, data, name: nil)
|
145
|
+
TensorStream::DynamicStitch.new(:dynamic_stitch, [indices, data], name: name)
|
146
|
+
end
|
147
|
+
|
144
148
|
def get_variable(name, dtype: nil, shape: nil, initializer: nil, trainable: true, collections: nil)
|
145
149
|
TensorStream::Variable.new(dtype || :float32, nil, shape, collections: collections, name: name, initializer: initializer, trainable: trainable)
|
146
150
|
end
|
@@ -204,7 +208,7 @@ module TensorStream
|
|
204
208
|
input_a = convert_to_tensor(input_a)
|
205
209
|
input_b = convert_to_tensor(input_b)
|
206
210
|
end
|
207
|
-
|
211
|
+
|
208
212
|
if norm_dtype(input_a.data_type) != norm_dtype(input_b.data_type)
|
209
213
|
raise "Value Error: Tensor conversion requested dtype #{input_a.data_type} for tensor type #{input_b.data_type}"
|
210
214
|
end
|
data/lib/tensor_stream.rb
CHANGED
@@ -16,6 +16,7 @@ require 'tensor_stream/variable'
|
|
16
16
|
require 'tensor_stream/operation'
|
17
17
|
require 'tensor_stream/placeholder'
|
18
18
|
require 'tensor_stream/control_flow'
|
19
|
+
require 'tensor_stream/dynamic_stitch'
|
19
20
|
require 'tensor_stream/trainer'
|
20
21
|
require 'tensor_stream/nn/nn_ops'
|
21
22
|
require 'tensor_stream/evaluator/evaluator'
|