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
@@ -2,10 +2,10 @@ module TensorStream
|
|
2
2
|
module OpPatch
|
3
3
|
def self.included(klass)
|
4
4
|
ops = if klass == Array
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
{:+ => "add", :- => "sub", :* => "mul"}
|
6
|
+
else
|
7
|
+
{:+ => "add", :- => "sub", :/ => "div", :% => "mod", :* => "mul", :** => "pow"}
|
8
|
+
end
|
9
9
|
|
10
10
|
ops.each do |m, name|
|
11
11
|
klass.send(:alias_method, :"_tensor_stream_#{name}_orig", m)
|
@@ -65,4 +65,4 @@ end
|
|
65
65
|
|
66
66
|
Integer.include TensorStream::OpPatch
|
67
67
|
Float.include TensorStream::OpPatch
|
68
|
-
Array.include TensorStream::OpPatch
|
68
|
+
Array.include TensorStream::OpPatch
|
@@ -27,7 +27,7 @@ module TensorStream
|
|
27
27
|
TensorStream.name_scope(name, "dropout", values: [x]) do
|
28
28
|
x = TensorStream.convert_to_tensor(x, name: "x")
|
29
29
|
raise TensorStream::ValueError, "x has to be a floating point tensor since it's going to be scaled. Got a #{x.data_type} tensor instead." unless fp_type?(x.data_type)
|
30
|
-
raise TensorStream::ValueError, "keep_prob must be a scalar tensor or a float in the range (0, 1], got #{keep_prob}" if keep_prob.is_a?(Float) && !(
|
30
|
+
raise TensorStream::ValueError, "keep_prob must be a scalar tensor or a float in the range (0, 1], got #{keep_prob}" if keep_prob.is_a?(Float) && !(keep_prob > 0 && keep_prob <= 1)
|
31
31
|
|
32
32
|
return x if keep_prob.is_a?(Float) && keep_prob.to_f == 1.0
|
33
33
|
|
@@ -35,10 +35,10 @@ module TensorStream
|
|
35
35
|
return x if keep_prob.value == 1.0
|
36
36
|
|
37
37
|
noise_shape = if noise_shape.nil?
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
TensorStream.shape(x)
|
39
|
+
else
|
40
|
+
noise_shape
|
41
|
+
end
|
42
42
|
|
43
43
|
random_tensor = keep_prob
|
44
44
|
random_tensor += TensorStream.random_uniform(noise_shape, seed: seed, dtype: x.dtype)
|
@@ -57,10 +57,10 @@ module TensorStream
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def softmax_cross_entropy_with_logits_v2(labels: nil, logits: nil, name: nil)
|
60
|
-
TensorStream.name_scope(name, default:
|
60
|
+
TensorStream.name_scope(name, default: "softmax_cross_entropy_with_logits", values: [logits, labels]) do
|
61
61
|
ts = TensorStream
|
62
|
-
logits = ts.convert_to_tensor(logits, name:
|
63
|
-
labels = ts.convert_to_tensor(labels, name:
|
62
|
+
logits = ts.convert_to_tensor(logits, name: "logits")
|
63
|
+
labels = ts.convert_to_tensor(labels, name: "labels")
|
64
64
|
labels = ts.cast(labels, logits.dtype)
|
65
65
|
|
66
66
|
output = _op(:softmax_cross_entropy_with_logits_v2, logits, labels)
|
@@ -80,11 +80,13 @@ module TensorStream
|
|
80
80
|
static_shapes_fully_defined = labels_static_shape.known? && logits.shape.known?
|
81
81
|
|
82
82
|
raise TensorStream::ValueError, "Logits cannot be scalars - received shape #{logits.shape.shape}." if logits.shape.known? && logits.shape.scalar?
|
83
|
-
|
84
|
-
"
|
83
|
+
if logits.shape.known? && (labels_static_shape.known? && labels_static_shape.ndims != logits.shape.ndims - 1)
|
84
|
+
raise TensorStream::ValueError, "Rank mismatch: Rank of labels (received #{labels_static_shape.ndims}) " \
|
85
|
+
"should equal rank of logits minus 1 (received #{logits.shape.ndims})."
|
86
|
+
end
|
85
87
|
if logits.shape.ndims == 2
|
86
88
|
cost = _op(:sparse_softmax_cross_entropy_with_logits,
|
87
|
-
|
89
|
+
precise_logits, labels, name: name)
|
88
90
|
if logits.data_type == :float16
|
89
91
|
return tf.cast(cost[0], :float16)
|
90
92
|
else
|
@@ -118,17 +120,17 @@ module TensorStream
|
|
118
120
|
end
|
119
121
|
|
120
122
|
def sigmoid_cross_entropy_with_logits(labels: nil, logits: nil, name: nil)
|
121
|
-
TensorStream.name_scope(name, default:
|
123
|
+
TensorStream.name_scope(name, default: "logistic_loss", values: [logits, labels]) do |_name|
|
122
124
|
tf = TensorStream
|
123
|
-
logits = tf.convert_to_tensor(logits, name:
|
124
|
-
labels = tf.convert_to_tensor(labels, name:
|
125
|
+
logits = tf.convert_to_tensor(logits, name: "logits")
|
126
|
+
labels = tf.convert_to_tensor(labels, name: "labels")
|
125
127
|
zeros = tf.zeros_like(logits, dtype: logits.dtype)
|
126
128
|
cond = (logits >= zeros)
|
127
129
|
relu_logits = tf.where(cond, logits, zeros)
|
128
130
|
neg_abs_logits = tf.where(cond, -logits, logits)
|
129
131
|
|
130
132
|
tf.add(relu_logits - logits * labels,
|
131
|
-
|
133
|
+
tf.log1p(tf.exp(neg_abs_logits)), name: name)
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
@@ -0,0 +1,180 @@
|
|
1
|
+
class TensorStream::OpMaker
|
2
|
+
attr_reader :operation, :description, :parameters,
|
3
|
+
:options, :gradient, :check_types,
|
4
|
+
:supports_broadcast, :data_type_coercion,
|
5
|
+
:aliases, :custom, :infer_type_proc, :exclude
|
6
|
+
|
7
|
+
def initialize(op)
|
8
|
+
@operation = op
|
9
|
+
@parameters = []
|
10
|
+
@options = {}
|
11
|
+
@gradient = nil
|
12
|
+
@supports_broadcast = false
|
13
|
+
@data_type_coercion = false
|
14
|
+
@exclude = false
|
15
|
+
@description = []
|
16
|
+
@aliases = []
|
17
|
+
@custom = []
|
18
|
+
@infer_type_proc = lambda { |tensor|
|
19
|
+
next nil if tensor.inputs[0].nil?
|
20
|
+
next tensor.inputs[0].shape.shape if tensor.inputs.size == 1
|
21
|
+
|
22
|
+
TensorStream::TensorShape.infer_shape(tensor.inputs[0].shape.shape, tensor.inputs[1].shape.shape) if tensor.inputs.size == 2 && tensor.inputs[0] && tensor.inputs[1]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def other_names(aliases)
|
27
|
+
@aliases += aliases
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_custom(custom_code)
|
31
|
+
@custom << custom_code
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.scan
|
35
|
+
op_files = Dir[File.join("lib", "tensor_stream", "ops", "*.rb")]
|
36
|
+
op_files.each { |file|
|
37
|
+
load File.join("tensor_stream", "ops", File.basename(file))
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.define_operation(op_code, &block)
|
42
|
+
@ops ||= {}
|
43
|
+
op_maker = TensorStream::OpMaker.new(op_code.to_sym)
|
44
|
+
block.call(op_maker)
|
45
|
+
@ops[op_code.to_sym] = op_maker
|
46
|
+
end
|
47
|
+
|
48
|
+
# call an operations' gradient definition
|
49
|
+
def self.gradient_op(context_caller, node, grad)
|
50
|
+
raise "No derivative op defined for #{node.operation}" if @ops[node.operation].nil? || @ops[node.operation].gradient.nil?
|
51
|
+
|
52
|
+
context_caller.instance_exec(grad, node, node.inputs, &@ops[node.operation].gradient)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.infer_shape(context_caller, tensor)
|
56
|
+
return nil unless @ops[tensor.operation]
|
57
|
+
|
58
|
+
context_caller.instance_exec(tensor, &@ops[tensor.operation].infer_type_proc)
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.each_op(&block)
|
62
|
+
@ops.values.sort_by { |op| op.operation }.reject(&:exclude).each do |op|
|
63
|
+
block.call(op)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def what_it_does(description)
|
68
|
+
@description << description
|
69
|
+
end
|
70
|
+
|
71
|
+
def what_it_does_code(description)
|
72
|
+
@description << "<tt>#{description}</tt>"
|
73
|
+
end
|
74
|
+
|
75
|
+
def exclude!
|
76
|
+
@exclude = true
|
77
|
+
end
|
78
|
+
|
79
|
+
def description_lines
|
80
|
+
description.map { |line| line.split("\n") }.flatten
|
81
|
+
end
|
82
|
+
|
83
|
+
def generate_body
|
84
|
+
body = []
|
85
|
+
parameters.select { |p| p[:validate] }.each do |p|
|
86
|
+
body << "check_allowed_types(#{p[:name]}, TensorStream::Ops::#{p[:validate]})"
|
87
|
+
end
|
88
|
+
if data_type_coercion?
|
89
|
+
body << "#{expand_params(false).join(', ')} = apply_data_type_coercion(#{expand_params(false).join(', ')})"
|
90
|
+
end
|
91
|
+
if check_types?
|
92
|
+
body << "check_data_types(#{expand_params(false).join(', ')})"
|
93
|
+
end
|
94
|
+
custom.each do |c|
|
95
|
+
body << c
|
96
|
+
end
|
97
|
+
body << "_op(:#{operation}, #{(expand_params(false) + options_call).join(', ')})"
|
98
|
+
body.map { |line| " #{line}"}.join("\n")
|
99
|
+
end
|
100
|
+
|
101
|
+
##
|
102
|
+
# adds a parameter to the op
|
103
|
+
#
|
104
|
+
def parameter(name, description, default_value = nil, validate: nil)
|
105
|
+
@parameters << {
|
106
|
+
name: name.to_s,
|
107
|
+
description: description,
|
108
|
+
default_value: default_value,
|
109
|
+
validate: validate
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
def option(name, description, default_value = nil, options = {})
|
114
|
+
@options[name] = { description: description, default_value: default_value, options: options }
|
115
|
+
end
|
116
|
+
|
117
|
+
def define_gradient(&block)
|
118
|
+
@gradient = block
|
119
|
+
end
|
120
|
+
|
121
|
+
def define_shape(&block)
|
122
|
+
@infer_type_proc = block
|
123
|
+
end
|
124
|
+
|
125
|
+
def expand_params(print_defaults)
|
126
|
+
@parameters.map { |param|
|
127
|
+
print_defaults && param[:default_value] ? "#{param[:name]} = #{default_with_nil(param[:default_value])}" : "#{param[:name]}"
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def parameters_must_have_same_data_type!
|
132
|
+
@check_types = true
|
133
|
+
end
|
134
|
+
|
135
|
+
def apply_data_type_coercion!
|
136
|
+
@data_type_coercion = true
|
137
|
+
end
|
138
|
+
|
139
|
+
def supports_broadcasting!
|
140
|
+
if (@parameters.size> 1)
|
141
|
+
@supports_broadcast = true
|
142
|
+
else
|
143
|
+
raise "Ops with parameters < 2 cannot support broadcasting"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def supports_broadcasting?
|
148
|
+
@supports_broadcast
|
149
|
+
end
|
150
|
+
|
151
|
+
def data_type_coercion?
|
152
|
+
@data_type_coercion
|
153
|
+
end
|
154
|
+
|
155
|
+
def check_types?
|
156
|
+
@check_types
|
157
|
+
end
|
158
|
+
|
159
|
+
def expand_options(print_defaults)
|
160
|
+
@options.map { |k, v|
|
161
|
+
print_defaults && v[:default_value] ? "#{k}: #{default_with_nil(v[:default_value])}" : "#{k}:"
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
def options_call
|
166
|
+
@options.map { |k, v|
|
167
|
+
if v.dig(:options, :alias)
|
168
|
+
"#{v.dig(:options, :alias)}: #{k}"
|
169
|
+
else
|
170
|
+
"#{k}: #{k}"
|
171
|
+
end
|
172
|
+
}
|
173
|
+
end
|
174
|
+
|
175
|
+
def default_with_nil(v)
|
176
|
+
v == :nil ? 'nil' : v
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
TensorStream::OpMaker.scan
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "tensor_stream/helpers/infer_shape"
|
2
2
|
module TensorStream
|
3
3
|
# TensorStream class that defines an operation
|
4
4
|
class Operation < Tensor
|
@@ -17,7 +17,7 @@ module TensorStream
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def inspect
|
20
|
-
"Op(#{operation} name: #{name} shape: #{@shape ||
|
20
|
+
"Op(#{operation} name: #{name} shape: #{@shape || "?"} data_type: #{data_type})"
|
21
21
|
end
|
22
22
|
|
23
23
|
def to_s
|
@@ -30,7 +30,7 @@ module TensorStream
|
|
30
30
|
name: name.to_s,
|
31
31
|
data_type: @data_type,
|
32
32
|
inputs: @inputs.map(&:name),
|
33
|
-
attrs: serialize_options
|
33
|
+
attrs: serialize_options,
|
34
34
|
}
|
35
35
|
end
|
36
36
|
|
@@ -145,11 +145,11 @@ module TensorStream
|
|
145
145
|
when :slice
|
146
146
|
"#{sub_input}[#{sub_input2}]"
|
147
147
|
when :assign_sub
|
148
|
-
"(#{inputs[0] ? inputs[0].name :
|
148
|
+
"(#{inputs[0] ? inputs[0].name : "self"} -= #{auto_math(inputs[1], name_only, 1)})"
|
149
149
|
when :assign_add
|
150
|
-
"(#{inputs[0] ? inputs[0].name :
|
150
|
+
"(#{inputs[0] ? inputs[0].name : "self"} += #{auto_math(inputs[1], name_only, 1)})"
|
151
151
|
when :assign
|
152
|
-
"(#{inputs[0] ? inputs[0].name :
|
152
|
+
"(#{inputs[0] ? inputs[0].name : "self"} = #{auto_math(inputs[1], name_only, 1)})"
|
153
153
|
when :sin, :cos, :tanh
|
154
154
|
"#{operation}(#{sub_input})"
|
155
155
|
when :add
|
@@ -193,7 +193,7 @@ module TensorStream
|
|
193
193
|
when :ones_like
|
194
194
|
"ones_like(#{sub_input})"
|
195
195
|
when :flow_group
|
196
|
-
"flow_group(#{inputs.collect { |i| auto_math(i, name_only, max_depth - 1, cur_depth) }.join(
|
196
|
+
"flow_group(#{inputs.collect { |i| auto_math(i, name_only, max_depth - 1, cur_depth) }.join(",")})"
|
197
197
|
when :zeros
|
198
198
|
"zeros(#{sub_input})"
|
199
199
|
when :reshape
|
@@ -243,8 +243,8 @@ module TensorStream
|
|
243
243
|
else
|
244
244
|
"#{operation}(#{sub_input})" if sub_input
|
245
245
|
"#{operation}(#{sub_input}, #{sub_input2})" if sub_input && sub_input2
|
246
|
-
|
247
|
-
["\n", Array.new(cur_depth + 1) {
|
246
|
+
end
|
247
|
+
["\n", Array.new(cur_depth + 1) { " " }, out].flatten.join
|
248
248
|
end
|
249
249
|
|
250
250
|
def run
|
@@ -260,21 +260,21 @@ module TensorStream
|
|
260
260
|
def serialize_options
|
261
261
|
excludes = %i[internal_name source]
|
262
262
|
|
263
|
-
@options.reject { |k, v| excludes.include?(k) || v.nil? }.map
|
263
|
+
@options.reject { |k, v| excludes.include?(k) || v.nil? }.map { |k, v|
|
264
264
|
v = case v.class.to_s
|
265
|
-
when
|
265
|
+
when "TensorStream::TensorShape"
|
266
266
|
v.shape
|
267
|
-
when
|
267
|
+
when "Array"
|
268
268
|
v
|
269
|
-
when
|
269
|
+
when "String", "Integer", "Float", "Symbol", "FalseClass", "TrueClass"
|
270
270
|
v
|
271
|
-
when
|
272
|
-
{
|
271
|
+
when "TensorStream::Variable"
|
272
|
+
{name: v.name, options: v.options, shape: v.shape.shape.dup}
|
273
273
|
else
|
274
274
|
raise "unknown type #{v.class}"
|
275
|
-
|
275
|
+
end
|
276
276
|
[k.to_sym, v]
|
277
|
-
|
277
|
+
}.to_h
|
278
278
|
end
|
279
279
|
|
280
280
|
def add_consumer(consumer)
|
data/lib/tensor_stream/ops.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
|
+
|
1
2
|
module TensorStream
|
2
3
|
# Class that defines all available ops supported by TensorStream
|
3
4
|
module Ops
|
5
|
+
if File.exists?(File.join(__dir__, 'generated_stub', 'ops.rb'))
|
6
|
+
require 'tensor_stream/generated_stub/ops'
|
7
|
+
include TensorStream::OpStub
|
8
|
+
end
|
9
|
+
|
4
10
|
class OutputHolder
|
5
11
|
def initialize(op)
|
6
12
|
@op = op
|
@@ -10,30 +16,6 @@ module TensorStream
|
|
10
16
|
INTEGER_TYPES = %i[uint8 int32 int int16 uint16 int64 uint32 uint64].freeze
|
11
17
|
NUMERIC_TYPES = FLOATING_POINT_TYPES + INTEGER_TYPES
|
12
18
|
|
13
|
-
##
|
14
|
-
# Returns the index with the largest value across axes of a tensor.
|
15
|
-
#
|
16
|
-
# Argmuments
|
17
|
-
#
|
18
|
-
# +input+ A Tensor. Must be one of the following types: float32, float64, int32, int16
|
19
|
-
# +axis+ Describes which axis of the input Tensor to reduce across. For vectors, use axis = 0
|
20
|
-
# +output_type+ Output data type defaults to int32
|
21
|
-
def argmax(input, axis = nil, name: nil, dimension: nil, output_type: :int32)
|
22
|
-
_op(:argmax, input, axis, name: name, dimension: dimension, data_type: output_type)
|
23
|
-
end
|
24
|
-
|
25
|
-
##
|
26
|
-
# Returns the index with the smallest value across axes of a tensor.
|
27
|
-
#
|
28
|
-
# Argmuments
|
29
|
-
#
|
30
|
-
# +input+ A Tensor. Must be one of the following types: float32, float64, int32, int16
|
31
|
-
# +axis+ Describes which axis of the input Tensor to reduce across. For vectors, use axis = 0
|
32
|
-
# +output_type+ Output data type defaults to int32
|
33
|
-
def argmin(input, axis = nil, name: nil, dimension: nil, output_type: :int32)
|
34
|
-
_op(:argmin, input, axis, name: name, dimension: dimension, data_type: output_type)
|
35
|
-
end
|
36
|
-
|
37
19
|
##
|
38
20
|
# Assert the condition x == y holds element-wise.
|
39
21
|
#
|
@@ -57,46 +39,39 @@ module TensorStream
|
|
57
39
|
# +tensor_ys+ : A Tensor or list of tensors to be differentiated.
|
58
40
|
# +wrt_xs+ : A Tensor or list of tensors to be used for differentiation.
|
59
41
|
# +stop_gradients+ : Optional. A Tensor or list of tensors not to differentiate through
|
60
|
-
def gradients(tensor_ys, wrt_xs, name:
|
42
|
+
def gradients(tensor_ys, wrt_xs, name: "gradients", stop_gradients: nil)
|
61
43
|
tensor_ys = tensor_ys.op
|
62
|
-
gs = wrt_xs.map(&:op).collect
|
63
|
-
stops = stop_gradients ? stop_gradients.map(&:name).join(
|
44
|
+
gs = wrt_xs.map(&:op).collect { |x|
|
45
|
+
stops = stop_gradients ? stop_gradients.map(&:name).join("_") : ""
|
64
46
|
gradient_program_name = "grad_#{tensor_ys.name}_#{x.name}_#{stops}".to_sym
|
65
47
|
tensor_graph = tensor_ys.graph
|
66
48
|
|
67
49
|
tensor_program = if tensor_graph.node_added?(gradient_program_name)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
50
|
+
tensor_graph.get_node(gradient_program_name)
|
51
|
+
else
|
52
|
+
tensor_graph.name_scope("gradient_wrt_#{x.name}") do
|
53
|
+
derivative_ops = TensorStream::MathGradients.derivative(tensor_ys, x, graph: tensor_graph,
|
54
|
+
stop_gradients: stop_gradients)
|
55
|
+
tensor_graph.add_node!(gradient_program_name, derivative_ops)
|
56
|
+
end
|
57
|
+
end
|
76
58
|
tensor_program
|
77
|
-
|
59
|
+
}
|
78
60
|
|
79
61
|
gs
|
80
62
|
end
|
81
63
|
|
82
|
-
##
|
83
|
-
# Outputs random values from a uniform distribution.
|
84
|
-
def random_uniform(shape, dtype: :float32, minval: 0, maxval: 1, seed: nil, name: nil)
|
85
|
-
options = { dtype: dtype, minval: minval, maxval: maxval, seed: seed, name: name }
|
86
|
-
_op(:random_uniform, shape, options)
|
87
|
-
end
|
88
|
-
|
89
64
|
##
|
90
65
|
# Outputs random values from a normal distribution.
|
91
66
|
def random_normal(shape, dtype: :float32, mean: 0.0, stddev: 1.0, seed: nil, name: nil)
|
92
|
-
options = {
|
67
|
+
options = {dtype: dtype, mean: mean, stddev: stddev, seed: seed, name: name}
|
93
68
|
_op(:random_standard_normal, shape, options)
|
94
69
|
end
|
95
70
|
|
96
71
|
##
|
97
72
|
# Outputs random values from a truncated normal distribution.
|
98
73
|
def truncated_normal(shape, dtype: :float32, mean: 0.0, stddev: 1.0, seed: nil, name: nil)
|
99
|
-
options = {
|
74
|
+
options = {dtype: dtype, mean: mean, stddev: stddev, seed: seed, name: name}
|
100
75
|
_op(:truncated_normal, shape, options)
|
101
76
|
end
|
102
77
|
|
@@ -118,14 +93,6 @@ module TensorStream
|
|
118
93
|
_op(:expand_dims, input, axis, name: name)
|
119
94
|
end
|
120
95
|
|
121
|
-
##
|
122
|
-
# This operation returns a 1-D integer tensor representing the shape of input
|
123
|
-
def shape(input, name: nil, out_type: :int32)
|
124
|
-
return constant(shape_eval(input, out_type), dtype: out_type, name: "Shape/#{name}") if input.is_a?(Array) && !input[0].is_a?(Tensor)
|
125
|
-
return constant(input.shape.shape, dtype: out_type, name: "Shape/#{input.name}_c") if shape_full_specified(input)
|
126
|
-
|
127
|
-
_op(:shape, input, name: name, out_type: out_type)
|
128
|
-
end
|
129
96
|
|
130
97
|
def shape_n(inputs, name: nil, out_type: :int32)
|
131
98
|
shapes_known = true
|
@@ -146,29 +113,6 @@ module TensorStream
|
|
146
113
|
end
|
147
114
|
end
|
148
115
|
|
149
|
-
##
|
150
|
-
# Constructs a tensor by tiling a given tensor.
|
151
|
-
#
|
152
|
-
# This operation creates a new tensor by replicating input multiples times.
|
153
|
-
# The output tensor's i'th dimension has input.dims(i) * multiples[i] elements,
|
154
|
-
# 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].
|
155
|
-
def tile(input, multiples, name: nil)
|
156
|
-
_op(:tile, input, multiples, name: name)
|
157
|
-
end
|
158
|
-
|
159
|
-
##
|
160
|
-
# Returns the rank of a tensor.
|
161
|
-
def rank(input, name: nil)
|
162
|
-
input = convert_to_tensor(input)
|
163
|
-
return cons(input.shape.ndims) if input.shape.known?
|
164
|
-
|
165
|
-
_op(:rank, input, name: name)
|
166
|
-
end
|
167
|
-
|
168
|
-
def constant_initializer(value, dtype: nil, verify_shape: false)
|
169
|
-
TensorStream::Initializer.new(-> { _op(:fill, nil, convert_to_tensor(value, dtype: dtype)) })
|
170
|
-
end
|
171
|
-
|
172
116
|
##
|
173
117
|
# initializer that generates tensors initialized to 0.
|
174
118
|
#
|
@@ -183,6 +127,10 @@ module TensorStream
|
|
183
127
|
TensorStream::Initializer.new(-> { _op(:ones, data_type: dtype) })
|
184
128
|
end
|
185
129
|
|
130
|
+
def constant_initializer(value, dtype: nil, verify_shape: false)
|
131
|
+
TensorStream::Initializer.new(-> { _op(:fill, nil, convert_to_tensor(value, dtype: dtype)) })
|
132
|
+
end
|
133
|
+
|
186
134
|
##
|
187
135
|
# The Glorot uniform initializer, also called Xavier uniform initializer.
|
188
136
|
#
|
@@ -209,119 +157,45 @@ module TensorStream
|
|
209
157
|
_op(:slice, input, start, size: size, name: name)
|
210
158
|
end
|
211
159
|
|
212
|
-
##
|
213
|
-
# Creates a tensor with all elements set to zero
|
214
|
-
def zeros(shape, dtype: :float32, name: nil)
|
215
|
-
_op(:zeros, shape, data_type: dtype, name: name)
|
216
|
-
end
|
217
|
-
|
218
160
|
##
|
219
161
|
# Creates a tensor with all elements set to 1.
|
220
162
|
def ones(shape, dtype: :float32, name: nil)
|
221
163
|
_op(:ones, shape, data_type: dtype, name: name)
|
222
164
|
end
|
223
165
|
|
224
|
-
##
|
225
|
-
# Returns element-wise largest integer not greater than x.
|
226
|
-
def floor(input, name: nil)
|
227
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
228
|
-
_op(:floor, input, name: name)
|
229
|
-
end
|
230
|
-
|
231
|
-
##
|
232
|
-
# Returns element-wise smallest integer in not less than x
|
233
|
-
def ceil(input, name: nil)
|
234
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
235
|
-
_op(:ceil, input, name: name)
|
236
|
-
end
|
237
|
-
|
238
166
|
##
|
239
167
|
# Returns the truth value of (x < y) element-wise.
|
240
168
|
# This operation supports broadcasting
|
241
169
|
def less(input_a, input_b, name: nil)
|
242
|
-
|
170
|
+
check_data_types(input_a, input_b)
|
243
171
|
_op(:less, input_a, input_b, name: name)
|
244
172
|
end
|
245
173
|
|
246
174
|
##
|
247
175
|
# Returns the truth value of x AND y element-wise.
|
248
176
|
def logical_and(input_a, input_b, name: nil)
|
249
|
-
|
177
|
+
check_data_types(input_a, input_b)
|
250
178
|
_op(:logical_and, input_a, input_b, name: name)
|
251
179
|
end
|
252
180
|
|
253
|
-
##
|
254
|
-
# Returns the truth value of (x > y) element-wise.
|
255
|
-
# This operation supports broadcasting
|
256
|
-
def greater(input_a, input_b, name: nil)
|
257
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
258
|
-
_op(:greater, input_a, input_b, name: name)
|
259
|
-
end
|
260
|
-
|
261
|
-
##
|
262
|
-
# Returns the truth value of (x >= y) element-wise.
|
263
|
-
#
|
264
|
-
# This operation supports broadcasting
|
265
|
-
def greater_equal(input_a, input_b, name: nil)
|
266
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
267
|
-
_op(:greater_equal, input_a, input_b, name: name)
|
268
|
-
end
|
269
|
-
|
270
|
-
##
|
271
|
-
# Returns the truth value of (x <= y) element-wise.
|
272
|
-
def less_equal(input_a, input_b, name: nil)
|
273
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
274
|
-
_op(:less_equal, input_a, input_b, name: name)
|
275
|
-
end
|
276
|
-
|
277
181
|
##
|
278
182
|
# Computes the mean of elements across dimensions of a tensor.
|
279
183
|
def reduce_mean(input_tensor, axis = nil, keepdims: false, name: nil)
|
280
184
|
reduce(:mean, input_tensor, axis, keepdims: keepdims, name: name)
|
281
185
|
end
|
282
186
|
|
283
|
-
##
|
284
|
-
# Computes the sum of elements across dimensions of a tensor.
|
285
|
-
#
|
286
|
-
# Reduces input_tensor along the dimensions given in axis. Unless keepdims is true,
|
287
|
-
# the rank of the tensor is reduced by 1 for each entry in axis. If keepdims is true,
|
288
|
-
# the reduced dimensions are retained with length 1.
|
289
|
-
# If axis has no entries, all dimensions are reduced, and a tensor with a single element
|
290
|
-
# is returned.
|
291
|
-
def reduce_sum(input_tensor, axis = nil, keepdims: false, name: nil)
|
292
|
-
reduce(:sum, input_tensor, axis, keepdims: keepdims, name: name)
|
293
|
-
end
|
294
|
-
|
295
|
-
##
|
296
|
-
# Computes the product of elements across dimensions of a tensor.
|
297
|
-
#
|
298
|
-
# Reduces input_tensor along the dimensions given in axis. Unless keepdims is true, the rank of the
|
299
|
-
# tensor is reduced by 1 for each entry in axis. If keepdims is true, the reduced dimensions are
|
300
|
-
# retained with length 1.
|
301
|
-
#
|
302
|
-
# If axis has no entries, all dimensions are reduced, and a tensor with a single element is returned.
|
303
|
-
def reduce_prod(input, axis = nil, keepdims: false, name: nil)
|
304
|
-
reduce(:prod, input, axis, keepdims: keepdims, name: name)
|
305
|
-
end
|
306
|
-
|
307
187
|
def reduce(op, input, axis = nil, keepdims: false, name: nil)
|
308
188
|
input = TensorStream.convert_to_tensor(input)
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
op
|
313
|
-
elsif input.shape.known?
|
314
|
-
(0...input.shape.ndims).to_a
|
315
|
-
else
|
316
|
-
range(0, rank(input))
|
317
|
-
end
|
189
|
+
return input if input.shape.scalar?
|
190
|
+
|
191
|
+
axis = cast_axis(input, axis)
|
318
192
|
|
319
193
|
_op(op, input, axis, keepdims: keepdims, name: name)
|
320
194
|
end
|
321
195
|
|
322
196
|
##
|
323
197
|
# Concatenates tensors along one dimension.
|
324
|
-
def concat(values, axis, name:
|
198
|
+
def concat(values, axis, name: "concat")
|
325
199
|
if values.is_a?(Array)
|
326
200
|
_op(:concat, axis, *values, name: name)
|
327
201
|
else
|
@@ -329,7 +203,7 @@ module TensorStream
|
|
329
203
|
end
|
330
204
|
end
|
331
205
|
|
332
|
-
def split(value, num_or_size_splits, axis: 0, num: nil, name:
|
206
|
+
def split(value, num_or_size_splits, axis: 0, num: nil, name: "split")
|
333
207
|
value = convert_to_tensor(value)
|
334
208
|
num_or_size_splits = convert_to_tensor(num_or_size_splits)
|
335
209
|
axis = convert_to_tensor(axis)
|
@@ -339,33 +213,33 @@ module TensorStream
|
|
339
213
|
res = _op(:split, value, num_or_size_splits, axis, name: name)
|
340
214
|
|
341
215
|
pieces = if value.shape.known? && num_or_size_splits.is_const && num_or_size_splits.value && axis.is_const
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
216
|
+
if num_or_size_splits.shape.scalar?
|
217
|
+
raise TensorStream::ValueError, "num_or_size_splits must divide dimension #{value.shape.shape[axis.value]} evenly" unless (value.shape.shape[axis.value] % num_or_size_splits.value).zero?
|
218
|
+
|
219
|
+
div = num_or_size_splits.value
|
220
|
+
n = value.shape.shape[axis.value] / div
|
221
|
+
|
222
|
+
Array.new(div) do
|
223
|
+
new_shape = value.shape.shape.dup
|
224
|
+
new_shape[axis.value] = n
|
225
|
+
new_shape
|
226
|
+
end
|
227
|
+
elsif num_or_size_splits.shape.ndims == 1
|
228
|
+
raise TensorStream::ValueError, "Sum of splits do not match total dimen in axis #{value.shape.shape[axis.value]} != #{num_or_size_splits.value.reduce(:+)}" if value.shape.shape[axis.value] != num_or_size_splits.value.reduce(:+)
|
229
|
+
|
230
|
+
num_or_size_splits.value.collect do |v|
|
231
|
+
new_shape = value.shape.shape.dup
|
232
|
+
new_shape[axis.value] = v
|
233
|
+
new_shape
|
234
|
+
end
|
235
|
+
else
|
236
|
+
raise TensorStream::ValueError, "Scalar or 1D Tensor expected for num_or_size_splits"
|
237
|
+
end
|
238
|
+
else
|
239
|
+
raise TensorStream::ValueError, "Cannot automatically determine num, please specify num: in options" if num.nil?
|
240
|
+
|
241
|
+
Array.new(num) { nil }
|
242
|
+
end
|
369
243
|
|
370
244
|
pieces.collect.with_index do |shape, i|
|
371
245
|
op = index(res, i, name: "split/index:#{i}")
|
@@ -395,13 +269,6 @@ module TensorStream
|
|
395
269
|
_op(:square, tensor, name: name)
|
396
270
|
end
|
397
271
|
|
398
|
-
##
|
399
|
-
# Rounds the values of a tensor to the nearest integer, element-wise
|
400
|
-
def round(tensor, name: nil)
|
401
|
-
check_allowed_types(tensor, FLOATING_POINT_TYPES)
|
402
|
-
_op(:round, tensor, name: name)
|
403
|
-
end
|
404
|
-
|
405
272
|
##
|
406
273
|
# Computes the reciprocal of x element-wise.
|
407
274
|
def reciprocal(tensor, name: nil)
|
@@ -420,15 +287,6 @@ module TensorStream
|
|
420
287
|
_op(:where, condition, true_t, false_t, name: name)
|
421
288
|
end
|
422
289
|
|
423
|
-
##
|
424
|
-
# Returns x + y element-wise.
|
425
|
-
#
|
426
|
-
# This operation supports broadcasting
|
427
|
-
def add(input_a, input_b, name: nil)
|
428
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
429
|
-
_op(:add, input_a, input_b, name: name)
|
430
|
-
end
|
431
|
-
|
432
290
|
##
|
433
291
|
# Adds all input tensors element-wise.
|
434
292
|
#
|
@@ -458,53 +316,20 @@ module TensorStream
|
|
458
316
|
_op(:atan, input, name: name)
|
459
317
|
end
|
460
318
|
|
461
|
-
##
|
462
|
-
# Returns x - y element-wise.
|
463
|
-
#
|
464
|
-
# This operation supports boradcasting
|
465
|
-
def sub(input_a, input_b, name: nil)
|
466
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
467
|
-
_op(:sub, input_a, input_b, name: name)
|
468
|
-
end
|
469
|
-
|
470
|
-
##
|
471
|
-
# Returns element-wise remainder of division.
|
472
|
-
def mod(input_a, input_b, name: nil)
|
473
|
-
input_a = convert_to_tensor(input_a)
|
474
|
-
input_b = convert_to_tensor(input_b)
|
475
|
-
|
476
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
477
|
-
_op(:mod, input_a, input_b, name: name)
|
478
|
-
end
|
479
|
-
|
480
319
|
##
|
481
320
|
# Returns element-wise integer divistion.
|
482
321
|
def floor_div(input_a, input_b, name: nil)
|
483
|
-
|
322
|
+
check_data_types(input_a, input_b)
|
484
323
|
_op(:floor_div, input_a, input_b, name: name)
|
485
324
|
end
|
486
325
|
|
487
|
-
def range(start, limit, delta = 1, dtype: nil, name: 'range')
|
488
|
-
_op(:range, start, limit, delta, data_type: dtype, name: name)
|
489
|
-
end
|
490
|
-
|
491
326
|
##
|
492
|
-
#
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
497
|
-
sub(input_a, input_b, name: name)
|
498
|
-
end
|
499
|
-
|
500
|
-
##
|
501
|
-
# Returns the max of x and y (i.e. x > y ? x : y) element-wise.
|
502
|
-
def max(input_a, input_b, name: nil)
|
503
|
-
check_allowed_types(input_a, NUMERIC_TYPES)
|
504
|
-
check_allowed_types(input_b, NUMERIC_TYPES)
|
327
|
+
# Casts a tensor to a new type, if needed
|
328
|
+
def cast(input, dtype, name: nil)
|
329
|
+
input = convert_to_tensor(input)
|
330
|
+
return input if input.data_type == dtype
|
505
331
|
|
506
|
-
|
507
|
-
_op(:max, input_a, input_b, name: name)
|
332
|
+
_op(:cast, input, data_type: dtype, name: name)
|
508
333
|
end
|
509
334
|
|
510
335
|
##
|
@@ -513,30 +338,12 @@ module TensorStream
|
|
513
338
|
max(input_a, input_b, name: name)
|
514
339
|
end
|
515
340
|
|
516
|
-
##
|
517
|
-
# Returns the min of x and y (i.e. x < y ? x : y) element-wise.
|
518
|
-
def min(input_a, input_b, name: nil)
|
519
|
-
check_allowed_types(input_a, NUMERIC_TYPES)
|
520
|
-
check_allowed_types(input_b, NUMERIC_TYPES)
|
521
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
522
|
-
_op(:min, input_a, input_b, name: name)
|
523
|
-
end
|
524
|
-
|
525
341
|
##
|
526
342
|
# Returns the min of x and y (i.e. x < y ? x : y) element-wise.
|
527
343
|
def minimum(input_a, input_b, name: nil)
|
528
344
|
min(input_a, input_b, name: name)
|
529
345
|
end
|
530
346
|
|
531
|
-
##
|
532
|
-
# Casts a tensor to a new type, if needed
|
533
|
-
def cast(input, dtype, name: nil)
|
534
|
-
input = convert_to_tensor(input)
|
535
|
-
return input if input.data_type == dtype
|
536
|
-
|
537
|
-
_op(:cast, input, data_type: dtype, name: name)
|
538
|
-
end
|
539
|
-
|
540
347
|
##
|
541
348
|
# Prints a list of tensors.
|
542
349
|
#
|
@@ -545,30 +352,17 @@ module TensorStream
|
|
545
352
|
_op(:print, input, data, message: message, name: name)
|
546
353
|
end
|
547
354
|
|
548
|
-
##
|
549
|
-
# Computes numerical negative value element-wise.
|
550
|
-
def negate(input, name: nil)
|
551
|
-
_op(:negate, input, name: name)
|
552
|
-
end
|
553
|
-
|
554
355
|
##
|
555
356
|
# Computes numerical negative value element-wise.
|
556
357
|
def negative(input, name: nil)
|
557
358
|
negate(input, name: name)
|
558
359
|
end
|
559
360
|
|
560
|
-
##
|
561
|
-
# Returns the truth value of (x == y) element-wise.
|
562
|
-
def equal(input_a, input_b, name: nil)
|
563
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
564
|
-
_op(:equal, input_a, input_b, name: name)
|
565
|
-
end
|
566
|
-
|
567
361
|
##
|
568
362
|
# Returns the truth value of (x != y) element-wise.
|
569
363
|
# This ops supports broadcasting
|
570
364
|
def not_equal(input_a, input_b, name: nil)
|
571
|
-
|
365
|
+
check_data_types(input_a, input_b)
|
572
366
|
_op(:not_equal, input_a, input_b, name: name)
|
573
367
|
end
|
574
368
|
|
@@ -600,33 +394,10 @@ module TensorStream
|
|
600
394
|
# Returns x * y element-wise.
|
601
395
|
# This operation supports broadcasting
|
602
396
|
def multiply(input_a, input_b, name: nil)
|
603
|
-
|
397
|
+
check_data_types(input_a, input_b)
|
604
398
|
_op(:mul, input_a, input_b, name: name)
|
605
399
|
end
|
606
400
|
|
607
|
-
##
|
608
|
-
# Returns x * y element-wise.
|
609
|
-
# This operation supports broadcasting
|
610
|
-
def mul(input_a, input_b, name: nil)
|
611
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
612
|
-
_op(:mul, input_a, input_b, name: name)
|
613
|
-
end
|
614
|
-
|
615
|
-
##
|
616
|
-
# Divides x / y elementwise
|
617
|
-
# This operation supports broadcasting
|
618
|
-
def div(input_a, input_b, name: nil)
|
619
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
620
|
-
_op(:div, input_a, input_b, name: name)
|
621
|
-
end
|
622
|
-
|
623
|
-
##
|
624
|
-
# Computes the power of one value to another.
|
625
|
-
def pow(input_a, input_e, name: nil)
|
626
|
-
input_a, input_e = check_data_types(input_a, input_e)
|
627
|
-
_op(:pow, input_a, input_e, name: name)
|
628
|
-
end
|
629
|
-
|
630
401
|
##
|
631
402
|
# Computes the absolute value of a tensor.
|
632
403
|
def abs(input, name: nil)
|
@@ -634,42 +405,6 @@ module TensorStream
|
|
634
405
|
end
|
635
406
|
|
636
407
|
##
|
637
|
-
# Returns an element-wise indication of the sign of a number.
|
638
|
-
# y = sign(x) = -1 if x < 0; 0 if x == 0 or tf.is_nan(x); 1 if x > 0.
|
639
|
-
# Zero is returned for NaN inputs.
|
640
|
-
def sign(input, name: nil)
|
641
|
-
_op(:sign, input, name: name)
|
642
|
-
end
|
643
|
-
|
644
|
-
##
|
645
|
-
# Computes sin of input element-wise.
|
646
|
-
def sin(input, name: nil)
|
647
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
648
|
-
_op(:sin, input, name: name)
|
649
|
-
end
|
650
|
-
|
651
|
-
##
|
652
|
-
# Computes cos of input element-wise.
|
653
|
-
def cos(input, name: nil)
|
654
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
655
|
-
_op(:cos, input, name: name)
|
656
|
-
end
|
657
|
-
|
658
|
-
##
|
659
|
-
# Computes tan of input element-wise.
|
660
|
-
def tan(input, name: nil)
|
661
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
662
|
-
_op(:tan, input, name: name)
|
663
|
-
end
|
664
|
-
|
665
|
-
##
|
666
|
-
# Computes tanh of input element-wise.
|
667
|
-
def tanh(input, name: nil)
|
668
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
669
|
-
_op(:tanh, input, name: name)
|
670
|
-
end
|
671
|
-
|
672
|
-
##
|
673
408
|
# Computes sec of input element-wise.
|
674
409
|
def sec(input, name: nil)
|
675
410
|
check_allowed_types(input, FLOATING_POINT_TYPES)
|
@@ -704,46 +439,16 @@ module TensorStream
|
|
704
439
|
_op(:exp, input, name: name)
|
705
440
|
end
|
706
441
|
|
707
|
-
##
|
708
|
-
# Creates a tensor filled with a scalar value.
|
709
|
-
#
|
710
|
-
# This operation creates a tensor of shape dims and fills it with value.
|
711
|
-
#
|
712
|
-
# For example:
|
713
|
-
# Output tensor has shape [2, 3].
|
714
|
-
# fill([2, 3], 9) => [[9, 9, 9]
|
715
|
-
# [9, 9, 9]]
|
716
|
-
def fill(dims, value, name: nil)
|
717
|
-
_op(:fill, dims, value, name: name)
|
718
|
-
end
|
719
|
-
|
720
|
-
##
|
721
|
-
# Computes sigmoid of x element-wise.
|
722
|
-
def sigmoid(input, name: nil)
|
723
|
-
check_allowed_types(input, FLOATING_POINT_TYPES)
|
724
|
-
_op(:sigmoid, input, name: name)
|
725
|
-
end
|
726
|
-
|
727
|
-
##
|
728
|
-
# Multiplies matrix a by matrix b, producing a * b.
|
729
|
-
# The inputs must, following any transpositions, be tensors of rank 2 .
|
730
|
-
def matmul(input_a, input_b, transpose_a: false,
|
731
|
-
transpose_b: false,
|
732
|
-
name: nil)
|
733
|
-
input_a, input_b = check_data_types(input_a, input_b)
|
734
|
-
_op(:mat_mul, input_a, input_b, transpose_a: transpose_a, transpose_b: transpose_b, name: name)
|
735
|
-
end
|
736
|
-
|
737
442
|
##
|
738
443
|
# Transposes a. Permutes the dimensions according to perm.
|
739
|
-
def transpose(tensor, perm = nil, name:
|
444
|
+
def transpose(tensor, perm = nil, name: "transpose")
|
740
445
|
_op(:transpose, tensor, perm, name: name)
|
741
446
|
end
|
742
447
|
|
743
448
|
##
|
744
449
|
# Pads a tensor.
|
745
450
|
# This operation pads a tensor according to the paddings you specify.
|
746
|
-
def pad(tensor, paddings, mode:
|
451
|
+
def pad(tensor, paddings, mode: "CONSTANT", name: nil)
|
747
452
|
_op(:pad, tensor, paddings, mode: mode, name: name)
|
748
453
|
end
|
749
454
|
|
@@ -754,10 +459,6 @@ module TensorStream
|
|
754
459
|
_op(:check_numerics, tensor, message: message, name: name)
|
755
460
|
end
|
756
461
|
|
757
|
-
def size(tensor, name: nil, out_type: :int32)
|
758
|
-
_op(:size, tensor, name: name, out_type: out_type)
|
759
|
-
end
|
760
|
-
|
761
462
|
def squared_difference(input_a, input_b, name: nil)
|
762
463
|
_op(:squared_difference, input_a, input_b, name: name)
|
763
464
|
end
|
@@ -771,36 +472,36 @@ module TensorStream
|
|
771
472
|
# Gather slices from params and axis according to indices.
|
772
473
|
#
|
773
474
|
def gather(params, indices, validate_indices: nil,
|
774
|
-
|
775
|
-
|
475
|
+
name: nil,
|
476
|
+
axis: 0)
|
776
477
|
_op(:gather, params, indices, validate_indices: validate_indices, name: name, axis: axis)
|
777
478
|
end
|
778
479
|
|
779
480
|
##
|
780
481
|
# Stacks a list of rank-R tensors into one rank-(R+1) tensor.
|
781
482
|
#
|
782
|
-
def stack(values, axis: 0, name:
|
483
|
+
def stack(values, axis: 0, name: "stack")
|
783
484
|
_op(:stack, *values, axis: axis, name: name)
|
784
485
|
end
|
785
486
|
|
786
487
|
##
|
787
488
|
# Unpacks the given dimension of a rank-R tensor into rank-(R-1) tensors.
|
788
489
|
#
|
789
|
-
def unstack(value, num: nil, axis: 0, name:
|
490
|
+
def unstack(value, num: nil, axis: 0, name: "unstack")
|
790
491
|
res = _op(:unstack, value, num: num, axis: axis, name: name)
|
791
492
|
|
792
493
|
num_vars = if value.shape.known?
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
494
|
+
new_shape = value.shape.shape.dup
|
495
|
+
rank = new_shape.size - 1
|
496
|
+
axis = rank + axis if axis < 0
|
497
|
+
rotated_shape = Array.new(axis + 1) { new_shape.shift }
|
498
|
+
new_shape = rotated_shape.rotate!(-1) + new_shape
|
499
|
+
new_shape[0]
|
500
|
+
else
|
501
|
+
raise TensorStream::ValueError, "num is unspecified and cannot be inferred." if num.nil?
|
502
|
+
|
503
|
+
num
|
504
|
+
end
|
804
505
|
|
805
506
|
return res[0] if num_vars == 1
|
806
507
|
|
@@ -811,14 +512,14 @@ module TensorStream
|
|
811
512
|
|
812
513
|
##
|
813
514
|
# Same as stack
|
814
|
-
def pack(values, axis: 0, name:
|
515
|
+
def pack(values, axis: 0, name: "pack")
|
815
516
|
_op(:stack, *values, axis: axis, name: name)
|
816
517
|
end
|
817
518
|
|
818
519
|
##
|
819
520
|
# Same as unstack
|
820
521
|
#
|
821
|
-
def unpack(value, num: nil, axis: 0, name:
|
522
|
+
def unpack(value, num: nil, axis: 0, name: "unpack")
|
822
523
|
unstack(value, num: num, axis: axis, name: name)
|
823
524
|
end
|
824
525
|
|
@@ -878,5 +579,15 @@ module TensorStream
|
|
878
579
|
def invert_permutation(x, name: nil)
|
879
580
|
_op(:invert_permutation, x, name: name)
|
880
581
|
end
|
582
|
+
|
583
|
+
def cast_axis(input, axis)
|
584
|
+
if !axis.nil?
|
585
|
+
axis
|
586
|
+
elsif input.shape.known?
|
587
|
+
(0...input.shape.ndims).to_a
|
588
|
+
else
|
589
|
+
range(0, rank(input))
|
590
|
+
end
|
591
|
+
end
|
881
592
|
end
|
882
593
|
end
|