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,19 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :ones_like do |op|
|
2
|
+
op.what_it_does "Creates a tensor with all elements set to 1."
|
3
|
+
op.what_it_does "Given a single tensor (tensor), this operation returns a"
|
4
|
+
op.what_it_does "tensor of the same type and shape as tensor with all elements set to 1."
|
5
|
+
op.what_it_does "Optionally, you can specify a new type (dtype) for the returned tensor."
|
6
|
+
|
7
|
+
|
8
|
+
op.parameter :input, "A tensor"
|
9
|
+
op.option :dtype, "Optional new data type to cast into", :nil, alias: :data_type
|
10
|
+
op.option :name, "Optional name", :nil
|
11
|
+
|
12
|
+
op.define_shape do |tensor|
|
13
|
+
tensor.inputs[0].shape.shape
|
14
|
+
end
|
15
|
+
|
16
|
+
op.define_gradient do |grad, node, params|
|
17
|
+
nil # non differentiable
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :pow do |op|
|
2
|
+
op.what_it_does "Computes the power of one value to another 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
|
+
z = node
|
15
|
+
sx = ts.shape(x)
|
16
|
+
sy = ts.shape(y)
|
17
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
18
|
+
gx = ts.reduce_sum(grad * y * ts.pow(x, y - 1), rx)
|
19
|
+
|
20
|
+
log_x = ts.where(x > 0, ts.log(x), ts.zeros_like(x))
|
21
|
+
gy = ts.reduce_sum(grad * z * log_x, ry)
|
22
|
+
|
23
|
+
[gx, gy]
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :prod do |op|
|
2
|
+
op.other_names %w(reduce_prod)
|
3
|
+
op.what_it_does "Computes the product of elements across dimensions of a tensor."
|
4
|
+
op.what_it_does "Reduces input_tensor along the dimensions given in axis. Unless keepdims is true, the rank of the"
|
5
|
+
op.what_it_does "tensor is reduced by 1 for each entry in axis. If keepdims is true, the reduced dimensions are"
|
6
|
+
op.what_it_does "retained with length 1."
|
7
|
+
op.what_it_does "If axis has no entries, all dimensions are reduced, and a tensor with a single element is returned."
|
8
|
+
|
9
|
+
op.parameter :input_a, "tensor X"
|
10
|
+
op.parameter :axis, "tensor X", :nil, validate: 'INTEGER_TYPES'
|
11
|
+
|
12
|
+
op.option :name, "Optional name", :nil
|
13
|
+
op.option :keepdims, "If true, retains reduced dimensions with length 1.", :false
|
14
|
+
|
15
|
+
op.add_custom "input_a = TensorStream.convert_to_tensor(input_a)"
|
16
|
+
op.add_custom "return input_a if input_a.shape.scalar?"
|
17
|
+
op.add_custom "axis = cast_axis(input_a, axis)"
|
18
|
+
|
19
|
+
op.define_gradient do |grad, node, params|
|
20
|
+
x, y = params
|
21
|
+
input_shape = ts.shape(x)
|
22
|
+
y = ts.range(0, ts.rank(x)) if y.nil?
|
23
|
+
reduction_indices = ts.reshape(y, [-1])
|
24
|
+
|
25
|
+
output_shape_kept_dims = ts.reduced_shape(input_shape, y)
|
26
|
+
tile_scaling = _safe_shape_div(input_shape, output_shape_kept_dims)
|
27
|
+
grad = ts.reshape(grad, output_shape_kept_dims)
|
28
|
+
grad = ts.tile(grad, tile_scaling)
|
29
|
+
|
30
|
+
perm, reduced_num, other_num = ts.device("/cpu:0") {
|
31
|
+
rank = ts.rank(x)
|
32
|
+
reduction_indices = (reduction_indices + rank) % rank
|
33
|
+
reduced = ts.cast(reduction_indices, :int32)
|
34
|
+
idx = ts.range(0, rank)
|
35
|
+
other, = ts.setdiff1d(idx, reduced)
|
36
|
+
[ts.concat([reduced, other], 0),
|
37
|
+
ts.reduce_prod(ts.gather(input_shape, reduced)),
|
38
|
+
ts.reduce_prod(ts.gather(input_shape, other)),]
|
39
|
+
}
|
40
|
+
|
41
|
+
permuted = ts.transpose(x, perm)
|
42
|
+
permuted_shape = ts.shape(permuted)
|
43
|
+
|
44
|
+
reshaped = ts.reshape(permuted, [reduced_num, other_num])
|
45
|
+
|
46
|
+
# Calculate product, leaving out the current entry
|
47
|
+
left = ts.cumprod(reshaped, axis: 0, exclusive: true)
|
48
|
+
right = ts.cumprod(reshaped, axis: 0, exclusive: true, reverse: true)
|
49
|
+
y = ts.reshape(left * right, permuted_shape)
|
50
|
+
|
51
|
+
# Invert the transpose and reshape operations.
|
52
|
+
# Make sure to set the statically known shape information through a reshape.
|
53
|
+
out = grad * ts.transpose(y, ts.invert_permutation(perm))
|
54
|
+
[ts.reshape(out, input_shape, name: "prod"), nil]
|
55
|
+
end
|
56
|
+
|
57
|
+
op.define_shape do |tensor|
|
58
|
+
_infer_reduction_op_shape(tensor)
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :random_uniform do |op|
|
2
|
+
op.what_it_does "Outputs random values from a uniform distribution."
|
3
|
+
|
4
|
+
op.parameter :shape, "A 1-D integer Tensor or array. The shape of the output tensor."
|
5
|
+
|
6
|
+
op.option :name, "Optional name", :nil
|
7
|
+
op.option :dtype, "The type of the output: float16, float32, float64, int32, or int64", ":float32"
|
8
|
+
op.option :minval, "A 0-D Tensor or ruby value of type dtype. The lower bound on the range of random values to generate. Defaults to 0.", 0
|
9
|
+
op.option :maxval, "A 0-D Tensor or ruby value of type dtype. The upper bound on the range of random values to generate. Defaults to 1 if dtype is floating point.", 1
|
10
|
+
op.option :seed, " A ruby integer. Used to create a random seed for the distribution. See set_random_seed for behavior.", :nil
|
11
|
+
|
12
|
+
op.define_shape do |tensor|
|
13
|
+
a_shape = tensor.inputs[0] ? tensor.inputs[0].const_value : tensor.options[:shape]
|
14
|
+
next nil if a_shape.nil?
|
15
|
+
|
16
|
+
a_shape.is_a?(Array) ? a_shape : [a_shape]
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :range do |op|
|
2
|
+
op.what_it_does "Creates a sequence of numbers."
|
3
|
+
op.what_it_does "Creates a sequence of numbers that begins at start and extends by increments of delta up to but not including limit."
|
4
|
+
|
5
|
+
op.parameter :start, "Acts as first entry in the range if limit is not nil; otherwise, acts as range limit and first entry defaults to 0.", "0"
|
6
|
+
op.parameter :limit, "Upper limit of sequence, exclusive. If nil, defaults to the value of start while the first entry of the range defaults to 0.", "0"
|
7
|
+
op.parameter :delta, "Number that increments start. Defaults to 1.", 1
|
8
|
+
|
9
|
+
op.option :name, " A name for the operation. Defaults to \"range\".", "\"range\""
|
10
|
+
op.option :dtype, "The type of the elements of the resulting tensor.", :nil
|
11
|
+
op.option :output_type, "Output data type defaults to int32", ":int32"
|
12
|
+
|
13
|
+
op.define_gradient do |grad, node, params|
|
14
|
+
nil # non differentiable
|
15
|
+
end
|
16
|
+
|
17
|
+
op.define_shape do |tensor|
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :rank do |op|
|
2
|
+
op.what_it_does "Returns the rank of a tensor"
|
3
|
+
|
4
|
+
op.parameter :input, "A tensor"
|
5
|
+
op.option :name, "Optional name", :nil
|
6
|
+
|
7
|
+
op.add_custom "input = convert_to_tensor(input)"
|
8
|
+
op.add_custom "return cons(input.shape.ndims) if input.shape.known?"
|
9
|
+
|
10
|
+
op.define_shape do |tensor|
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :reshape do |op|
|
2
|
+
op.what_it_does "Reshapes a tensor."
|
3
|
+
op.what_it_does "Given tensor, this operation returns a tensor that has the same values as tensor with shape shape."
|
4
|
+
|
5
|
+
op.parameter :input, "A tensor"
|
6
|
+
op.parameter :shape, "A new tensor shape"
|
7
|
+
op.option :name, "Optional name", :nil
|
8
|
+
|
9
|
+
op.define_gradient do |grad, node, params|
|
10
|
+
[ts.reshape(grad, ts.shape(node.inputs[0])), nil]
|
11
|
+
end
|
12
|
+
|
13
|
+
op.define_shape do |tensor|
|
14
|
+
new_shape = tensor.inputs[1]&.const_value ? tensor.inputs[1].const_value : nil
|
15
|
+
next nil if new_shape.nil?
|
16
|
+
next nil if tensor.inputs[0].shape.nil?
|
17
|
+
|
18
|
+
input_shape = tensor.inputs[0].shape.shape
|
19
|
+
next new_shape if input_shape.nil? && !new_shape.include?(-1) && !new_shape.include?(nil)
|
20
|
+
next nil if input_shape.nil? || input_shape.include?(nil)
|
21
|
+
|
22
|
+
TensorStream::TensorShape.fix_inferred_elements(new_shape, input_shape.reduce(:*))
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :round do |op|
|
2
|
+
op.what_it_does "Rounds the values of a tensor to the nearest integer, element-wise"
|
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,14 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :shape do |op|
|
2
|
+
op.what_it_does "This operation returns a 1-D integer tensor representing the shape of input"
|
3
|
+
|
4
|
+
op.parameter :input, "A tensor"
|
5
|
+
op.option :name, "Optional name", :nil
|
6
|
+
op.option :out_type, "Optional output type", ":int32"
|
7
|
+
|
8
|
+
op.add_custom 'return constant(shape_eval(input, out_type), dtype: out_type, name: "Shape/#{name}") if input.is_a?(Array) && !input[0].is_a?(Tensor)'
|
9
|
+
op.add_custom 'return constant(input.shape.shape, dtype: out_type, name: "Shape/#{input.name}_c") if shape_full_specified(input)'
|
10
|
+
|
11
|
+
op.define_shape do |tensor|
|
12
|
+
tensor.inputs[0].shape.shape ? [tensor.inputs[0].shape.shape.size] : nil
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :sigmoid do |op|
|
2
|
+
op.what_it_does "Computes sigmoid of x 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
|
+
i_op(:sigmoid_grad, params[0], grad)
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :sign do |op|
|
2
|
+
op.what_it_does "Computes sign of input element-wise."
|
3
|
+
op.what_it_does_code "y = sign(x) = -1 if x < 0; 0 if x == 0 or tf.is_nan(x); 1 if x > 0."
|
4
|
+
op.what_it_does "Zero is returned for NaN inputs."
|
5
|
+
|
6
|
+
op.parameter :input_a, "tensor X"
|
7
|
+
op.option :name, "Optional name", :nil
|
8
|
+
|
9
|
+
op.define_gradient do |grad, node, params|
|
10
|
+
ts.zeros(ts.shape(params[0]), dtype: params[0].data_type)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :sin do |op|
|
2
|
+
op.what_it_does "Computes sin 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.cos(params[0])
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :size do |op|
|
2
|
+
op.what_it_does "Returns the size of a tensor."
|
3
|
+
op.what_it_does "Returns a 0-D Tensor representing the number of elements in input of type out_type. Defaults to :int32."
|
4
|
+
|
5
|
+
op.parameter :input, "A tensor"
|
6
|
+
op.option :name, "Optional name", :nil
|
7
|
+
op.option :out_type, "Optional output type", ":int32"
|
8
|
+
|
9
|
+
op.define_gradient do |grad, node, params|
|
10
|
+
nil # non differentiable
|
11
|
+
end
|
12
|
+
|
13
|
+
op.define_shape do |tensor|
|
14
|
+
[]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :sub do |op|
|
2
|
+
op.other_names %w(subtract)
|
3
|
+
op.what_it_does "Returns x - y element-wise."
|
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 :name, "Optional name", :nil
|
12
|
+
|
13
|
+
op.define_gradient do |grad, node, params|
|
14
|
+
x, y = params
|
15
|
+
next [grad, -grad] if shapes_fully_specified_and_equal(x, y)
|
16
|
+
|
17
|
+
sx = ts.shape(x, name: "sub/shape_x")
|
18
|
+
sy = ts.shape(y, name: "sub/shape_y")
|
19
|
+
rx, ry = _broadcast_gradient_args(sx, sy)
|
20
|
+
|
21
|
+
[ts.reshape(ts.reduce_sum(grad, rx, name: "add/reduce_sub_x"), sx),
|
22
|
+
-ts.reshape(ts.reduce_sum(grad, ry, name: "add/reduce_sub_y"), sy),]
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :sum do |op|
|
2
|
+
op.other_names %w(reduce_sum)
|
3
|
+
op.what_it_does "Computes the sum of elements across dimensions of a tensor."
|
4
|
+
op.what_it_does "Reduces input_tensor along the dimensions given in axis. Unless keepdims is true, the rank of the"
|
5
|
+
op.what_it_does "tensor is reduced by 1 for each entry in axis. If keepdims is true, the reduced dimensions are"
|
6
|
+
op.what_it_does "retained with length 1."
|
7
|
+
op.what_it_does "If axis has no entries, all dimensions are reduced, and a tensor with a single element is returned."
|
8
|
+
|
9
|
+
op.parameter :input_a, "tensor X"
|
10
|
+
op.parameter :axis, "tensor X", :nil, validate: 'INTEGER_TYPES'
|
11
|
+
|
12
|
+
op.option :name, "Optional name", :nil
|
13
|
+
op.option :keepdims, "If true, retains reduced dimensions with length 1.", :false
|
14
|
+
|
15
|
+
op.add_custom "input_a = TensorStream.convert_to_tensor(input_a)"
|
16
|
+
op.add_custom "return input_a if input_a.shape.scalar?"
|
17
|
+
op.add_custom "axis = cast_axis(input_a, axis)"
|
18
|
+
|
19
|
+
op.define_gradient do |grad, node, params|
|
20
|
+
x, y = params
|
21
|
+
_sum_grad(x, y, grad)
|
22
|
+
end
|
23
|
+
|
24
|
+
op.define_shape do |tensor|
|
25
|
+
_infer_reduction_op_shape(tensor)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :tan do |op|
|
2
|
+
op.what_it_does "Computes tan 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
|
+
secx = ts.reciprocal(ts.cos(params[0]))
|
9
|
+
secx2 = ts.square(secx)
|
10
|
+
grad * secx2
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :tanh do |op|
|
2
|
+
op.what_it_does "Computes tanh 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 * i_op(:tanh_grad, params[0])
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :tile do |op|
|
2
|
+
op.what_it_does "Constructs a tensor by tiling a given tensor."
|
3
|
+
op.what_it_does "This operation creates a new tensor by replicating input multiples times."
|
4
|
+
op.what_it_does "The output tensor's i'th dimension has input.dims(i) * multiples[i] elements,"
|
5
|
+
op.what_it_does "and the values of input are replicated multiples[i] times along the 'i'th dimension. For example, tiling [a b c d] by [2] produces [a b c d a b c d]."
|
6
|
+
|
7
|
+
op.parameter :input, "A tensor"
|
8
|
+
op.parameter :multiples, "Must be one of the following types: int32, int64. 1-D. Length must be the same as the number of dimensions in input"
|
9
|
+
op.option :name, "Optional name", :nil
|
10
|
+
|
11
|
+
|
12
|
+
op.define_gradient do |grad, node, params|
|
13
|
+
nil # non differentiable
|
14
|
+
end
|
15
|
+
|
16
|
+
op.define_shape do |tensor|
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
TensorStream::OpMaker.define_operation :zeros do |op|
|
2
|
+
op.what_it_does "Creates a tensor with all elements set to zero"
|
3
|
+
|
4
|
+
op.parameter :shape, "A 1-D integer Tensor or ruby array. The shape of the output tensor."
|
5
|
+
|
6
|
+
op.option :dtype, "Optional name", ":float32"
|
7
|
+
op.option :name, "Optional name", :nil
|
8
|
+
|
9
|
+
op.define_shape do |tensor|
|
10
|
+
a_shape = tensor.inputs[0] ? tensor.inputs[0].const_value : tensor.options[:shape]
|
11
|
+
next nil if a_shape.nil?
|
12
|
+
|
13
|
+
a_shape.is_a?(Array) ? a_shape : [a_shape]
|
14
|
+
end
|
15
|
+
end
|
@@ -10,12 +10,12 @@ module TensorStream
|
|
10
10
|
@value = nil
|
11
11
|
@is_const = false
|
12
12
|
|
13
|
-
@name = [@graph.get_name_scope, options[:name] || build_name].compact.reject(&:empty?).join(
|
13
|
+
@name = [@graph.get_name_scope, options[:name] || build_name].compact.reject(&:empty?).join("/")
|
14
14
|
@op = Graph.get_default_graph.add_op!(:placeholder, data_type: @data_type, shape: @shape, internal_name: @name)
|
15
15
|
end
|
16
16
|
|
17
17
|
def inspect
|
18
|
-
"Placeholder(#{@name} shape: #{@shape ||
|
18
|
+
"Placeholder(#{@name} shape: #{@shape || "?"} data_type: #{@data_type})"
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -4,9 +4,9 @@ module TensorStream
|
|
4
4
|
class ReportTool
|
5
5
|
def self.profile_for(session, order_by: :slowest)
|
6
6
|
context = session.last_session_context
|
7
|
-
eval_times = context[:profile][:operations].map
|
7
|
+
eval_times = context[:profile][:operations].map { |name, profile|
|
8
8
|
[name, profile[:op], profile[:eval_time], profile[:shape]]
|
9
|
-
|
9
|
+
}
|
10
10
|
|
11
11
|
if order_by == :slowest
|
12
12
|
eval_times.sort_by { |a| a[2] }.reverse!
|
@@ -15,4 +15,4 @@ module TensorStream
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
18
|
-
end
|
18
|
+
end
|
@@ -19,16 +19,16 @@ module TensorStream
|
|
19
19
|
|
20
20
|
def get_evaluator_classes(evaluators)
|
21
21
|
@evaluator_classes = if evaluators.is_a?(Array)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
if evaluators.empty?
|
23
|
+
TensorStream::Evaluator.default_evaluators
|
24
|
+
else
|
25
|
+
evaluators.collect { |name| Object.const_get("TensorStream::Evaluator::#{camelize(name.to_s)}") }
|
26
|
+
end
|
27
|
+
elsif evaluators.nil?
|
28
|
+
TensorStream::Evaluator.default_evaluators
|
29
|
+
else
|
30
|
+
[Object.const_get("TensorStream::Evaluator::#{camelize(evaluators.to_s)}")]
|
31
|
+
end
|
32
32
|
end
|
33
33
|
|
34
34
|
def clear_session_cache
|
@@ -41,10 +41,10 @@ module TensorStream
|
|
41
41
|
|
42
42
|
def run(*args)
|
43
43
|
options = if args.last.is_a?(Hash)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
44
|
+
args.pop
|
45
|
+
else
|
46
|
+
{}
|
47
|
+
end
|
48
48
|
|
49
49
|
@evaluator_options[:thread_pool] = @thread_pool
|
50
50
|
@evaluator_options[:log_intermediates] = options[:log_intermediates]
|
@@ -52,25 +52,23 @@ module TensorStream
|
|
52
52
|
context = {
|
53
53
|
_cache: @session_cache,
|
54
54
|
_options: options.merge(@evaluator_options),
|
55
|
-
profile: {
|
55
|
+
profile: {step: 0, operations: {}},
|
56
56
|
}
|
57
57
|
|
58
58
|
# scan for placeholders and assign value
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
raise "Invalid placeholder type passed key must be a string or a placeholder type"
|
73
|
-
end
|
59
|
+
options[:feed_dict]&.each_key do |k|
|
60
|
+
if k.is_a?(Placeholder)
|
61
|
+
context[k.name.to_sym] = options[:feed_dict][k]
|
62
|
+
elsif k.is_a?(String)
|
63
|
+
target_graph = args[0].graph
|
64
|
+
node = target_graph.get_node(k)
|
65
|
+
raise "Cannot find placeholder with the name of #{k}" if node.operation != :placeholder
|
66
|
+
|
67
|
+
context[k.to_sym] = options[:feed_dict][k]
|
68
|
+
elsif k.is_a?(Operation) && k.operation == :placeholder
|
69
|
+
context[k.name.to_sym] = options[:feed_dict][k]
|
70
|
+
else
|
71
|
+
raise "Invalid placeholder type passed key must be a string or a placeholder type"
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
@@ -82,21 +80,21 @@ module TensorStream
|
|
82
80
|
puts "#{k} : #{v[0].name}"
|
83
81
|
end
|
84
82
|
end
|
85
|
-
result = args.collect
|
83
|
+
result = args.collect { |e|
|
86
84
|
next e.value if e.is_a?(Tensor) && e.is_const && e.value
|
87
85
|
|
88
86
|
value = delegate_to_evaluator(e, context, {})
|
89
87
|
recursive_eval(value)
|
90
|
-
|
88
|
+
}
|
91
89
|
args.size == 1 ? result.first : result
|
92
90
|
end
|
93
91
|
|
94
92
|
def list_devices
|
95
|
-
TensorStream::Evaluator.evaluators.collect
|
93
|
+
TensorStream::Evaluator.evaluators.collect { |_k, v|
|
96
94
|
v[:class].query_supported_devices.collect do |device|
|
97
95
|
device
|
98
96
|
end
|
99
|
-
|
97
|
+
}.flatten
|
100
98
|
end
|
101
99
|
|
102
100
|
def close
|
@@ -117,11 +115,11 @@ module TensorStream
|
|
117
115
|
|
118
116
|
def dump_ops(tensor, selector)
|
119
117
|
graph = tensor.graph
|
120
|
-
graph.nodes.select { |k, v| selector.call(k, v) }.collect
|
118
|
+
graph.nodes.select { |k, v| selector.call(k, v) }.collect { |k, node|
|
121
119
|
next unless @last_session_context[node.name]
|
122
120
|
|
123
121
|
"#{k} #{node.to_math(true, 1)} = #{@last_session_context[node.name]}"
|
124
|
-
|
122
|
+
}.compact
|
125
123
|
end
|
126
124
|
|
127
125
|
def graph_ml(tensor, filename)
|
@@ -143,12 +141,12 @@ module TensorStream
|
|
143
141
|
end
|
144
142
|
|
145
143
|
def assign_evaluator(tensor)
|
146
|
-
device = @evaluator_classes.map
|
144
|
+
device = @evaluator_classes.map { |klass|
|
147
145
|
next nil if tensor.is_a?(Operation) && !klass.ops.include?(tensor.operation.to_sym)
|
148
146
|
next klass.default_device if tensor.device.nil?
|
149
147
|
|
150
148
|
klass.query_device(tensor.device)
|
151
|
-
|
149
|
+
}.compact.first
|
152
150
|
|
153
151
|
raise "no evaluator available to execute #{tensor.operation}" if device.nil?
|
154
152
|
|