tensor_stream 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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