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
@@ -0,0 +1,23 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :add do |op|
|
2
|
+
op.what_it_does "Returns x + y element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
x, y = params
|
14
|
+
next [grad, grad] if shapes_fully_specified_and_equal(x, y)
|
15
|
+
|
16
|
+
sx = ts.shape(x, name: "add/shape_x")
|
17
|
+
sy = ts.shape(y, name: "add/shape_y")
|
18
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
19
|
+
|
20
|
+
[ts.reshape(ts.reduce_sum(grad, rx, name: "add/reduce_sum_x"), sx),
|
21
|
+
ts.reshape(ts.reduce_sum(grad, ry, name: "add/reduce_sum_y"), sy),]
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :argmax do |op|
|
2
|
+
op.what_it_does "Returns the index with the largest value across axes of a tensor."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", validate: 'NUMERIC_TYPES'
|
5
|
+
op.parameter :axis, "Describes which axis of the input tensor to reduce across. For vectors, use axis = 0", :nil, validate: 'INTEGER_TYPES'
|
6
|
+
|
7
|
+
op.option :name, "Optional name", :nil
|
8
|
+
op.option :dimension, "Same as axis", :nil
|
9
|
+
op.option :output_type, "Output data type defaults to int32", ":int32"
|
10
|
+
|
11
|
+
op.define_gradient do |grad, node, params|
|
12
|
+
[nil, nil]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :argmin do |op|
|
2
|
+
op.what_it_does "Returns the index with the smallest value across axes of a tensor."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", validate: 'NUMERIC_TYPES'
|
5
|
+
op.parameter :axis, "Describes which axis of the input tensor to reduce across. For vectors, use axis = 0", :nil, validate: 'INTEGER_TYPES'
|
6
|
+
|
7
|
+
op.option :name, "Optional name", :nil
|
8
|
+
op.option :dimension, "Same as axis", :nil
|
9
|
+
op.option :output_type, "Output data type defaults to int32", ":int32"
|
10
|
+
|
11
|
+
op.define_gradient do |grad, node, params|
|
12
|
+
[nil, nil]
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :case do |op|
|
2
|
+
op.exclude!
|
3
|
+
|
4
|
+
op.define_gradient do |grad, node, params|
|
5
|
+
n_preds = node.inputs.size - 2
|
6
|
+
|
7
|
+
case_grads = Array.new(n_preds) { |index|
|
8
|
+
i_op(:case_grad, index, node.inputs[0], node.inputs[2 + index], grad)
|
9
|
+
}
|
10
|
+
|
11
|
+
[nil, i_op(:case_grad, -1, node.inputs[0], node.inputs[1], grad)] + case_grads
|
12
|
+
end
|
13
|
+
|
14
|
+
op.define_shape do |tensor|
|
15
|
+
tensor.inputs[2]&.shape&.shape
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :cast do |op|
|
2
|
+
op.exclude!
|
3
|
+
|
4
|
+
op.define_gradient do |grad, node, params|
|
5
|
+
t = %i[float16 float32 float64]
|
6
|
+
src_type = node.inputs[0].data_type
|
7
|
+
dst_type = grad.data_type
|
8
|
+
|
9
|
+
if t.key?(src_type) && t.key?(dst_type)
|
10
|
+
next ts.cast(grad, src_type)
|
11
|
+
end
|
12
|
+
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :ceil do |op|
|
2
|
+
op.what_it_does "Returns element-wise smallest integer in not less than x"
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", validate: 'FLOATING_POINT_TYPES'
|
5
|
+
|
6
|
+
op.option :name, "Optional name", :nil
|
7
|
+
|
8
|
+
op.define_gradient do |grad, node, params|
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
op.define_shape do |tensor|
|
13
|
+
tensor.inputs[0].shape.shape
|
14
|
+
end
|
15
|
+
end
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :cos do |op|
|
2
|
+
op.what_it_does "Computes cos of input element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", validate: 'FLOATING_POINT_TYPES'
|
5
|
+
op.option :name, "Optional name", :nil
|
6
|
+
|
7
|
+
op.define_gradient do |grad, node, params|
|
8
|
+
-grad * ts.sin(params[0])
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :div do |op|
|
2
|
+
op.what_it_does "Returns x / y element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
x, y = params
|
14
|
+
sx = i_op(:shape, x)
|
15
|
+
sy = i_op(:shape, y)
|
16
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
17
|
+
|
18
|
+
[ts.reshape(ts.reduce_sum(ts.div(grad, y), rx), sx),
|
19
|
+
ts.reshape(ts.reduce_sum(grad * ts.div(ts.div(-x, y), y), ry), sy),]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :equal do |op|
|
2
|
+
op.what_it_does "Returns the truth value of (x == y) element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
_min_or_max_grad(node.inputs, grad, ->(a, b) { ts.equal(a, b) })
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :expand_dims do |op|
|
2
|
+
op.what_it_does "Inserts a dimension of 1 into a tensor's shape. "
|
3
|
+
op.what_it_does "Given a tensor input, this operation inserts a dimension of 1 at the dimension index axis of input's shape. The "
|
4
|
+
op.what_it_does "dimension index axis starts at zero; if you specify a negative number for axis it is counted backward from the end."
|
5
|
+
|
6
|
+
op.parameter :input, "A tensor"
|
7
|
+
op.parameter :axis, "Specifies the dimension index at which to expand the shape of input. Must be in the range [-rank(input) - 1, rank(input)]."
|
8
|
+
op.option :name, "Optional name", :nil
|
9
|
+
|
10
|
+
op.define_gradient do |grad, node, params|
|
11
|
+
[_reshape_to_input(node, grad), nil]
|
12
|
+
end
|
13
|
+
|
14
|
+
op.define_shape do |tensor|
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :fill do |op|
|
2
|
+
op.what_it_does "This operation creates a tensor of shape dims and fills it with value."
|
3
|
+
|
4
|
+
op.parameter :dims, "tensor shape"
|
5
|
+
op.parameter :value, "scalar value to fill with"
|
6
|
+
|
7
|
+
op.option :name, "Optional name", :nil
|
8
|
+
|
9
|
+
op.define_gradient do |grad, node, params|
|
10
|
+
[nil, TensorStream.reduce_sum(grad)]
|
11
|
+
end
|
12
|
+
|
13
|
+
op.define_shape do |tensor|
|
14
|
+
a_shape = tensor.inputs[0] ? tensor.inputs[0].const_value : tensor.options[:shape]
|
15
|
+
next nil if a_shape.nil?
|
16
|
+
|
17
|
+
a_shape.is_a?(Array) ? a_shape : [a_shape]
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :floor do |op|
|
2
|
+
op.what_it_does "Returns element-wise largest integer not greater than x."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", validate: 'FLOATING_POINT_TYPES'
|
5
|
+
|
6
|
+
op.option :name, "Optional name", :nil
|
7
|
+
|
8
|
+
op.define_gradient do |grad, node, params|
|
9
|
+
nil
|
10
|
+
end
|
11
|
+
|
12
|
+
op.define_shape do |tensor|
|
13
|
+
tensor.inputs[0].shape.shape
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :floor_div do |op|
|
2
|
+
op.what_it_does "Returns element-wise integer divistion."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
[nil, nil]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :greater do |op|
|
2
|
+
op.what_it_does "Returns the truth value of (x > y) element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :greater_equal do |op|
|
2
|
+
op.what_it_does "Returns the truth value of (x >= y) element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :less_equal do |op|
|
2
|
+
op.what_it_does "Returns the truth value of (x <= y) element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
_min_or_max_grad(node.inputs, grad, ->(a, b) { ts.greater_equal(a, b) })
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :log do |op|
|
2
|
+
op.what_it_does "Computes natural logarithm of x element-wise."
|
3
|
+
|
4
|
+
op.parameter :input, "tensor X"
|
5
|
+
op.option :name, "Optional name", :nil
|
6
|
+
|
7
|
+
op.define_gradient do |grad, node, params|
|
8
|
+
grad * TensorStream.reciprocal(params[0])
|
9
|
+
end
|
10
|
+
|
11
|
+
op.define_shape do |tensor|
|
12
|
+
tensor.inputs[0].shape.shape
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :mat_mul do |op|
|
2
|
+
op.other_names %w(matmul)
|
3
|
+
op.what_it_does "Multiplies matrix a by matrix b, producing a * b. The inputs must, following any transpositions, be tensors of rank 2 ."
|
4
|
+
|
5
|
+
op.parameter :input_a, "tensor X"
|
6
|
+
op.parameter :input_b, "tensor Y"
|
7
|
+
|
8
|
+
op.apply_data_type_coercion!
|
9
|
+
op.supports_broadcasting!
|
10
|
+
|
11
|
+
op.option :transpose_a, "Transpose matrix A first", :false
|
12
|
+
op.option :transpose_b, "Transpose matrix B first", :false
|
13
|
+
op.option :name, "Optional name", :nil
|
14
|
+
|
15
|
+
op.define_gradient do |grad, node, params|
|
16
|
+
x, y = params
|
17
|
+
t_a = node.options[:transpose_a]
|
18
|
+
t_b = node.options[:transpose_b]
|
19
|
+
|
20
|
+
if !t_a && !t_b
|
21
|
+
grad_a = ts.matmul(grad, y, transpose_b: true)
|
22
|
+
grad_b = ts.matmul(x, grad, transpose_a: true)
|
23
|
+
elsif !ta && tb
|
24
|
+
grad_a = ts.matmul(grad, y)
|
25
|
+
grad_b = ts.matmul(grad, x, transpose_a: true)
|
26
|
+
elsif t_a && !t_b
|
27
|
+
grad_a = ts.matmul(y, grad, transpose_b: true)
|
28
|
+
grad_b = ts.matmul(x, grad)
|
29
|
+
elsif t_a && t_b
|
30
|
+
grad_a = ts.matmul(y, grad, transpose_a: true, transpose_b: true)
|
31
|
+
grad_b = ts.matmul(grad, x, transpose_a: true, transpose_b: true)
|
32
|
+
end
|
33
|
+
|
34
|
+
[grad_a, grad_b]
|
35
|
+
end
|
36
|
+
|
37
|
+
op.define_shape do |tensor|
|
38
|
+
next nil if tensor.inputs[0].shape.shape.nil? || tensor.inputs[1].shape.shape.nil?
|
39
|
+
next [] if tensor.inputs[0].shape.shape.empty? || tensor.inputs[1].shape.shape.empty?
|
40
|
+
next nil if tensor.inputs[0].shape.shape.size != 2 || tensor.inputs[1].shape.shape.size != 2
|
41
|
+
|
42
|
+
shape1, m = if tensor.options[:transpose_a]
|
43
|
+
[tensor.inputs[0].shape.shape[0], tensor.inputs[0].shape.shape[1]]
|
44
|
+
else
|
45
|
+
[tensor.inputs[0].shape.shape[1], tensor.inputs[0].shape.shape[0]]
|
46
|
+
end
|
47
|
+
|
48
|
+
shape2, n = if tensor.options[:transpose_b]
|
49
|
+
[tensor.inputs[1].shape.shape[1], tensor.inputs[1].shape.shape[0]]
|
50
|
+
else
|
51
|
+
[tensor.inputs[1].shape.shape[0], tensor.inputs[1].shape.shape[1]]
|
52
|
+
end
|
53
|
+
|
54
|
+
next nil if shape1.nil? || shape2.nil? || shape1 < 0 || shape2 < 0
|
55
|
+
|
56
|
+
raise TensorStream::ValueError, "incompatible shape sizes for matrix multiplication (#{shape1} != #{shape2}) #{tensor.inputs[0].shape.shape} vs #{tensor.inputs[1].shape.shape}" if shape1 != shape2
|
57
|
+
|
58
|
+
[m, n]
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :max do |op|
|
2
|
+
op.what_it_does "Returns the max of x and y (i.e. x > y ? x : y) element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", nil, validate: 'NUMERIC_TYPES'
|
5
|
+
op.parameter :input_b, "tensor Y", nil, validate: 'NUMERIC_TYPES'
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
_min_or_max_grad(node.inputs, grad, ->(a, b) { ts.greater_equal(a, b) })
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :min do |op|
|
2
|
+
op.what_it_does "Returns the min of x and y (i.e. x < y ? x : y) element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X", nil, validate: 'NUMERIC_TYPES'
|
5
|
+
op.parameter :input_b, "tensor Y", nil, validate: 'NUMERIC_TYPES'
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
_min_or_max_grad(node.inputs, grad, ->(a, b) { ts.less_equal(a, b) })
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :mod do |op|
|
2
|
+
op.what_it_does "Returns element-wise remainder of division."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
x, y = params
|
14
|
+
sx = ts.shape(x)
|
15
|
+
sy = ts.shape(y)
|
16
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
17
|
+
floor_xy = ts.floor_div(x, y)
|
18
|
+
gx = ts.reshape(ts.reduce_sum(grad, rx), sx)
|
19
|
+
gy = ts.reshape(ts.reduce_sum(grad * ts.negative(floor_xy), ry), sy)
|
20
|
+
|
21
|
+
[gx, gy]
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :mul do |op|
|
2
|
+
op.what_it_does "Returns x * y element-wise."
|
3
|
+
|
4
|
+
op.parameter :input_a, "tensor X"
|
5
|
+
op.parameter :input_b, "tensor Y"
|
6
|
+
|
7
|
+
op.apply_data_type_coercion!
|
8
|
+
op.supports_broadcasting!
|
9
|
+
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
x, y = params
|
14
|
+
sx = ts.shape(x)
|
15
|
+
sy = ts.shape(y)
|
16
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
17
|
+
|
18
|
+
[ts.reshape(ts.reduce_sum(ts.mul(grad, y), rx), sx),
|
19
|
+
ts.reshape(ts.reduce_sum(ts.mul(x, grad), ry), sy)]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :negate do |op|
|
2
|
+
op.what_it_does "Computes numerical negative value element-wise."
|
3
|
+
|
4
|
+
op.parameter :input, "tensor X"
|
5
|
+
op.option :name, "Optional name", :nil
|
6
|
+
|
7
|
+
op.define_gradient do |grad, node, params|
|
8
|
+
-grad
|
9
|
+
end
|
10
|
+
|
11
|
+
op.define_shape do |tensor|
|
12
|
+
tensor.inputs[0].shape.shape
|
13
|
+
end
|
14
|
+
end
|