tensor_stream 0.1.4 → 0.1.5

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.
@@ -11,7 +11,7 @@ module TensorStream
11
11
  @is_const = false
12
12
  @source = format_source(caller_locations)
13
13
 
14
- @name = options[:name] || build_name
14
+ @name = [@graph.get_name_scope, options[:name] || build_name].compact.join('/')
15
15
  @graph.add_node(self)
16
16
  end
17
17
 
@@ -1,10 +1,14 @@
1
1
  module TensorStream
2
2
  # TensorStream class that defines a session
3
3
  class Session
4
- attr_reader :last_session_context
4
+ attr_reader :last_session_context, :closed, :target
5
+ attr_accessor :randomizer
6
+
5
7
  def initialize(evaluator = :ruby_evaluator, thread_pool_class: Concurrent::ImmediateExecutor)
6
8
  @evaluator_class = Object.const_get("TensorStream::Evaluator::#{camelize(evaluator.to_s)}")
7
9
  @thread_pool = thread_pool_class.new
10
+ @closed = false
11
+ @randomizer = {}
8
12
  end
9
13
 
10
14
  def self.default_session
@@ -22,18 +26,32 @@ module TensorStream
22
26
  # scan for placeholders and assign value
23
27
  if options[:feed_dict]
24
28
  options[:feed_dict].keys.each do |k|
25
- context[k.name.to_sym] = options[:feed_dict][k] if k.is_a?(Placeholder)
29
+ if k.is_a?(Placeholder)
30
+ context[k.name.to_sym] = options[:feed_dict][k]
31
+ end
26
32
  end
27
33
  end
28
34
 
29
- evaluator = @evaluator_class.new(self, context.merge!(retain: options[:retain]), thread_pool: @thread_pool)
35
+ evaluator = @evaluator_class.new(self, context.merge!(retain: options[:retain]), thread_pool: @thread_pool, log_intermediates: options[:log_intermediates])
30
36
 
31
37
  execution_context = {}
32
- result = args.collect { |e| evaluator.run(e, execution_context) }
33
38
  @last_session_context = context
39
+ result = args.collect { |e| evaluator.run(e, execution_context) }
34
40
  result.size == 1 ? result.first : result
35
41
  end
36
42
 
43
+ def list_devices
44
+ [Device.new("cpu")]
45
+ end
46
+
47
+ def close
48
+ @closed = true
49
+ end
50
+
51
+ def closed?
52
+ @closed
53
+ end
54
+
37
55
  def dump_internal_ops(tensor)
38
56
  dump_ops(tensor, ->(_k, n) { n.is_a?(Tensor) && n.internal? })
39
57
  end
@@ -50,6 +68,10 @@ module TensorStream
50
68
  end.compact
51
69
  end
52
70
 
71
+ def graph_ml(tensor, filename)
72
+ TensorStream::Graphml.new(self).serialize(tensor, filename)
73
+ end
74
+
53
75
  private
54
76
 
55
77
  def camelize(string, uppercase_first_letter = true)
@@ -19,7 +19,7 @@ module TensorStream
19
19
  @is_const = options[:const] || false
20
20
  @internal = options[:internal]
21
21
  @graph = options[:graph] || TensorStream.get_default_graph
22
- @name = options[:name] || build_name
22
+ @name = [@graph.get_name_scope, options[:name] || build_name].compact.reject(&:empty?).join('/')
23
23
  @given_name = @name
24
24
 
25
25
  if options[:value]
@@ -55,7 +55,7 @@ module TensorStream
55
55
  end
56
56
 
57
57
  def +(other)
58
- TensorStream::Operation.new(:add, self, auto_wrap(other))
58
+ TensorStream::Operation.new(:add, self, TensorStream.convert_to_tensor(other, dtype: data_type))
59
59
  end
60
60
 
61
61
  def [](index)
@@ -63,19 +63,19 @@ module TensorStream
63
63
  end
64
64
 
65
65
  def *(other)
66
- TensorStream::Operation.new(:mul, self, auto_wrap(other))
66
+ TensorStream::Operation.new(:mul, self, TensorStream.convert_to_tensor(other, dtype: data_type))
67
67
  end
68
68
 
69
69
  def **(other)
70
- TensorStream::Operation.new(:pow, self, auto_wrap(other))
70
+ TensorStream::Operation.new(:pow, self, TensorStream.convert_to_tensor(other, dtype: data_type))
71
71
  end
72
72
 
73
73
  def /(other)
74
- TensorStream::Operation.new(:div, self, auto_wrap(other))
74
+ TensorStream::Operation.new(:div, self, TensorStream.convert_to_tensor(other, dtype: data_type))
75
75
  end
76
76
 
77
77
  def -(other)
78
- TensorStream::Operation.new(:sub, self, auto_wrap(other))
78
+ TensorStream::Operation.new(:sub, self, TensorStream.convert_to_tensor(other, dtype: data_type))
79
79
  end
80
80
 
81
81
  def -@
@@ -83,35 +83,40 @@ module TensorStream
83
83
  end
84
84
 
85
85
  def ==(other)
86
- op(:equal, self, other)
86
+ _op(:equal, self, other)
87
87
  end
88
88
 
89
89
  def <(other)
90
- op(:less, self, other)
90
+ _op(:less, self, other)
91
91
  end
92
92
 
93
93
  def !=(other)
94
- op(:not_equal, self, other)
94
+ _op(:not_equal, self, other)
95
95
  end
96
96
 
97
97
  def >(other)
98
- op(:greater, self, other)
98
+ _op(:greater, self, other)
99
99
  end
100
100
 
101
101
  def >=(other)
102
- op(:greater_equal, self, other)
102
+ _op(:greater_equal, self, other)
103
103
  end
104
104
 
105
105
  def <=(other)
106
- op(:less_equal, self, other)
106
+ _op(:less_equal, self, other)
107
107
  end
108
108
 
109
109
  def and(other)
110
- op(:logical_and, self, other)
110
+ _op(:logical_and, self, other)
111
111
  end
112
112
 
113
113
  def matmul(other)
114
- op(:matmul, self, other)
114
+ _op(:matmul, self, other)
115
+ end
116
+
117
+
118
+ def dot(other)
119
+ _op(:matmul, self, other)
115
120
  end
116
121
 
117
122
  def collect(&block)
@@ -122,6 +127,10 @@ module TensorStream
122
127
  @name
123
128
  end
124
129
 
130
+ def op
131
+ is_const ? _op(:const, self, nil, name: self.name) : _op(:variable, self, nil, name: self.name)
132
+ end
133
+
125
134
  def eval(options = {})
126
135
  Session.default_session.run(self, options)
127
136
  end
@@ -149,10 +158,10 @@ module TensorStream
149
158
  end
150
159
 
151
160
  def first
152
- op(:index, self, 0)
161
+ _op(:index, self, 0)
153
162
  end
154
163
 
155
- def to_math(name_only = false, max_depth = 99)
164
+ def to_math(name_only = false, max_depth = 99, _unused = 0)
156
165
  return @name if max_depth.zero? || name_only || @value.nil?
157
166
 
158
167
  if @value.is_a?(Array)
@@ -162,8 +171,8 @@ module TensorStream
162
171
  end
163
172
  end
164
173
 
165
- def auto_math(tensor, name_only = false, max_depth = 99)
166
- tensor.is_a?(Tensor) ? tensor.to_math(name_only, max_depth) : tensor
174
+ def auto_math(tensor, name_only = false, max_depth = 99, _cur_depth = 0)
175
+ tensor.is_a?(Tensor) ? tensor.to_math(name_only, max_depth, _cur_depth) : tensor
167
176
  end
168
177
 
169
178
  def self.detect_type(value)
@@ -181,6 +190,7 @@ module TensorStream
181
190
  end
182
191
 
183
192
  def self.cast_dtype(val, dtype)
193
+ return val if dtype.nil?
184
194
  return val if val.is_a?(Tensor)
185
195
 
186
196
  if val.is_a?(Array)
@@ -218,7 +228,7 @@ module TensorStream
218
228
  end
219
229
 
220
230
  def print!(message)
221
- op(:print, self, self, message: message)
231
+ _op(:print, self, self, message: message)
222
232
  end
223
233
 
224
234
  protected
@@ -232,10 +242,6 @@ module TensorStream
232
242
  add_consumer(consumer)
233
243
  end
234
244
 
235
- def format_source(trace)
236
- trace.reject { |c| c.to_s.include?(File.join('lib', 'tensor_stream')) }.first
237
- end
238
-
239
245
  def hashify_tensor(tensor)
240
246
  if tensor.is_a?(Tensor)
241
247
  tensor.to_h
@@ -264,16 +270,6 @@ module TensorStream
264
270
  end
265
271
  end
266
272
 
267
- def auto_wrap(operand)
268
- return auto_wrap(operand.call) if operand.is_a?(Proc)
269
-
270
- if !operand.is_a?(Tensor)
271
- i_cons(operand, dtype: @data_type || Tensor.detect_type(operand))
272
- else
273
- operand
274
- end
275
- end
276
-
277
273
  def build_name
278
274
  @is_const ? "Const#{graph.get_const_counter}:#{@rank}" : "Variable#{graph.get_var_counter}:#{@rank}"
279
275
  end
@@ -3,9 +3,9 @@ module TensorStream
3
3
  class TensorShape
4
4
  attr_accessor :rank, :shape
5
5
 
6
- def initialize(shape, rank)
6
+ def initialize(shape, rank = nil)
7
7
  @shape = shape
8
- @rank = rank
8
+ @rank = rank.nil? && shape ? shape.size : rank
9
9
  end
10
10
 
11
11
  def to_s
@@ -22,5 +22,55 @@ module TensorStream
22
22
  def ndims
23
23
  shape.size
24
24
  end
25
+
26
+ def known?
27
+ return false if shape.nil?
28
+ shape.each { |s| return false if s.nil? }
29
+
30
+ true
31
+ end
32
+
33
+ def self.infer_shape(shape_a, shape_b)
34
+ return shape_a if shape_b.nil?
35
+ return shape_b if shape_a.nil?
36
+ return shape_a if shape_a == shape_b
37
+ return shape_b if shape_b.size > shape_a.size
38
+ return shape_a if shape_a.size > shape_b.size
39
+
40
+ reversed_a = shape_a.reverse
41
+ reversed_b = shape_b.reverse
42
+
43
+ reversed_a.each_with_index.collect do |s, index|
44
+ next s if index >= reversed_b.size
45
+ next nil if s.nil? || reversed_b[index].nil?
46
+ next nil if s.is_a?(Tensor) || reversed_b[index].is_a?(Tensor)
47
+ next reversed_b[index] if reversed_b[index] > s
48
+ s
49
+ end.reverse
50
+ end
51
+
52
+ def self.reshape(arr, new_shape)
53
+ return arr if new_shape.empty?
54
+
55
+ s = new_shape.shift
56
+
57
+ if new_shape.size.zero?
58
+ raise "reshape dimen mismatch #{arr.size} != #{s}" if arr.size != s
59
+ return arr
60
+ end
61
+
62
+ dim = (arr.size / s)
63
+ arr.each_slice(dim).collect do |slice|
64
+ reshape(slice, new_shape.dup)
65
+ end
66
+ end
67
+
68
+ def self.fix_inferred_elements(shape, total_size)
69
+ return shape if shape.empty?
70
+
71
+ current_size = shape.inject(1) { |product, n| n > 0 ? product * n : product }
72
+ inferred_size = total_size / current_size
73
+ shape.map { |s| s == -1 ? inferred_size : s }
74
+ end
25
75
  end
26
76
  end
@@ -9,10 +9,7 @@ module TensorStream
9
9
  end
10
10
 
11
11
  def minimize(cost)
12
- trainable_vars = TensorStream::Graph.get_default_graph
13
- .get_collection(GraphKeys::GLOBAL_VARIABLES)
14
- .select(&:trainable)
15
-
12
+ trainable_vars = TensorStream.trainable_variables
16
13
  derivatives = TensorStream.gradients(cost, trainable_vars)
17
14
  trainable_vars.each_with_index.collect do |var, index|
18
15
  var.assign_sub(derivatives[index] * @learning_rate)
@@ -7,19 +7,27 @@ module TensorStream
7
7
 
8
8
  @data_type = data_type
9
9
  @rank = rank
10
- @shape = TensorShape.new(shape, rank)
11
10
  @value = nil
12
11
  @source = format_source(caller_locations)
13
-
14
- @name = options[:name] || build_name
15
- @initalizer_tensor = options[:initializer] if options[:initializer]
12
+ @name = [TensorStream.get_variable_scope, options[:name] || build_name].compact.reject(&:empty?).join('/')
13
+ @initalizer_tensor = options[:initializer] ? options[:initializer] : _variable_scope.initializer || TensorStream.glorot_uniform_initializer
14
+ if shape.nil? && @initalizer_tensor && @initalizer_tensor.shape
15
+ shape = @initalizer_tensor.shape.shape
16
+ end
17
+ @shape = TensorShape.new(shape, rank)
16
18
  @trainable = options.fetch(:trainable, true)
17
19
  @graph.add_variable(self, options)
18
20
  end
19
21
 
22
+ def trainable?
23
+ @trainable
24
+ end
25
+
20
26
  def initializer
21
- @initalizer_tensor.shape = @shape
22
- assign(@initalizer_tensor)
27
+ init_op = @initalizer_tensor.op
28
+ init_op.shape = @shape || init_op.shape
29
+ init_op.data_type = @data_type || init_op.data_type
30
+ assign(init_op)
23
31
  end
24
32
 
25
33
  def assign(value)
@@ -34,7 +42,7 @@ module TensorStream
34
42
  Operation.new(:assign_add, self, value)
35
43
  end
36
44
 
37
- def to_math(_tensor, _name_only = false, _max_depth = 99)
45
+ def to_math(_tensor, _name_only = false, _max_depth = 99, _unused = 0)
38
46
  @name
39
47
  end
40
48
 
@@ -49,5 +57,13 @@ module TensorStream
49
57
  def self.global_variables_initializer
50
58
  variables_initializer(TensorStream::GraphKeys::GLOBAL_VARIABLES)
51
59
  end
60
+
61
+ private
62
+
63
+ def _variable_scope
64
+ return OpenStruct.new(name: '', reuse: false, initializer: nil) if Thread.current[:tensor_stream_variable_scope].nil? || Thread.current[:tensor_stream_variable_scope].empty?
65
+ scope = Thread.current[:tensor_stream_variable_scope].last
66
+ scope
67
+ end
52
68
  end
53
69
  end
@@ -1,5 +1,5 @@
1
1
  module TensorStream
2
- VERSION = '0.1.4'.freeze
2
+ VERSION = '0.1.5'.freeze
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -0,0 +1,76 @@
1
+ require "bundler/setup"
2
+ require 'tensor_stream'
3
+ require 'pry-byebug'
4
+
5
+ tf = TensorStream
6
+
7
+ rows = File.readlines(File.join("samples","iris.data")).map {|l| l.chomp.split(',') }
8
+
9
+ iris = rows[0...100].shuffle!
10
+
11
+ transformed_data = iris.collect do |row|
12
+ row[0, 4].map(&:to_f)
13
+ end
14
+
15
+ columns = (0..3).map do |i|
16
+ transformed_data.map { |row| row[i] }
17
+ end
18
+
19
+ # Normalize data values before feeding into network
20
+ normalize = -> (val, high, low) { (val - low) / (high - low) } # maps input to float between 0 and 1
21
+
22
+ transformed_data.map! do |row|
23
+ row.map.with_index do |val, j|
24
+ max, min = columns[j].max, columns[j].min
25
+ normalize.(val, max, min)
26
+ end
27
+ end
28
+
29
+
30
+ srand(5)
31
+ seed = 5
32
+ tf.set_random_seed(seed)
33
+
34
+ train_x = transformed_data[0..50].map { |x| x[0..3].map(&:to_f) }
35
+ train_y = iris[0..50].map { |x| x[4] == 'Iris-setosa' ? 0.0 : 1.0 }
36
+
37
+ test_x = transformed_data[51..100].map { |x| x[0..3].map(&:to_f) }
38
+ test_y = iris[51..100].map { |x| x[4] == 'Iris-setosa' ? 0.0 : 1.0 }
39
+
40
+
41
+ A = tf.variable(tf.random_normal([4, 1]))
42
+ b = tf.variable(tf.random_normal([1, 1]))
43
+
44
+ init = tf.global_variables_initializer
45
+ sess = tf.session
46
+ sess.run(init)
47
+
48
+ data = tf.placeholder(:float32, shape: [nil, 4])
49
+ target = tf.placeholder(:float32, shape: [nil, 1])
50
+
51
+ mod = data.dot(A) + b
52
+
53
+ loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits: mod, labels: target))
54
+
55
+ learning_rate = 0.003
56
+ batch_size = 30
57
+ iter_num = 1500
58
+
59
+ optimizer = TensorStream::Train::GradientDescentOptimizer.new(learning_rate)
60
+ goal = optimizer.minimize(loss)
61
+ prediction = tf.round(tf.sigmoid(mod))
62
+ # Bool into float32 type
63
+ correct = tf.cast(tf.equal(prediction, target), dtype: :float32)
64
+ # Average
65
+ accuracy = tf.reduce_mean(correct)
66
+
67
+ loss_trace = []
68
+ train_acc = []
69
+ test_acc = []
70
+
71
+ (0..iter_num).each do |epoch|
72
+ batch_train_X = train_x
73
+ batch_train_y = [train_y].transpose
74
+ sess.run(goal, feed_dict: { data => batch_train_X, target => batch_train_y })
75
+ temp_loss = sess.run(loss, feed_dict: {data => batch_train_X, target => batch_train_y})
76
+ end