tensor_stream 0.9.5 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/lib/tensor_stream/evaluator/ruby/images_ops.rb +30 -1
- data/lib/tensor_stream/evaluator/ruby/nn_ops.rb +108 -0
- data/lib/tensor_stream/evaluator/ruby_evaluator.rb +2 -2
- data/lib/tensor_stream/helpers/infer_shape.rb +7 -0
- data/lib/tensor_stream/images.rb +4 -4
- data/lib/tensor_stream/math_gradients.rb +30 -0
- data/lib/tensor_stream/monkey_patches/array.rb +36 -0
- data/lib/tensor_stream/monkey_patches/patch.rb +4 -0
- data/lib/tensor_stream/nn/nn_ops.rb +105 -99
- data/lib/tensor_stream/train/saver.rb +12 -7
- data/lib/tensor_stream/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4059c6bb82fc83c5aee32090e9c58231f9fd421afb3aa8bea1cbff4857edeb18
|
4
|
+
data.tar.gz: b7ceee8509455146402c3b3cdf9fa0a63eeec3dfee5512dd6e097221f1247481
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 329eb6875b1add417656537beac95d67c1c061fa3eba3b04031d3ac6f1a20f7e26bf12e66873b70ad575fe7d9f0482c02888f0b544405ba9d73d5b325070966f
|
7
|
+
data.tar.gz: 639a4d90dc1525e063bcdac3b30805a38697b009634d17cb745c99189b88b10b95ce49a9136d5c9c0617fbf3ca3ee1a74429a8579437b7896954ff6529952e79
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
6
|
|
7
|
+
## [0.9.5] - 2018-11-05
|
8
|
+
- [NEW OP] assert_equal, relu6
|
9
|
+
- [TRAINING] learning_rate_decay, dropout
|
10
|
+
- [BUG FIX] argmin, argmax now works properly
|
11
|
+
- [BUG FIX] shape inference fixes
|
12
|
+
|
7
13
|
## [0.9.2] - 2018-10-19
|
8
14
|
- Add profiling support
|
9
15
|
- Make sure sparse ruby arrays are caught
|
@@ -7,11 +7,25 @@ module TensorStream
|
|
7
7
|
register_op :decode_png do |_context, tensor, inputs|
|
8
8
|
content = inputs[0]
|
9
9
|
channels = tensor.options[:channels]
|
10
|
+
resample_new_shape = tensor.options[:new_shape]
|
11
|
+
resample_method = tensor.options[:resample_method] || :bilinear
|
10
12
|
channels = 4 if channels.zero?
|
11
13
|
|
12
14
|
image = ChunkyPNG::Image.from_blob(content)
|
13
15
|
|
14
16
|
image.grayscale! if channels == 1
|
17
|
+
|
18
|
+
if resample_new_shape
|
19
|
+
case resample_method
|
20
|
+
when :bilinear
|
21
|
+
image.resample_bilinear!(resample_new_shape[1], resample_new_shape[0]) # width, # height
|
22
|
+
when :nearest_neighbor
|
23
|
+
image.resample_nearest_neighbor!(resample_new_shape[1], resample_new_shape[0])
|
24
|
+
else
|
25
|
+
raise TensorStream::ValueError, "invalid resample method provided #{resample_method}. Available (:bilinear, :nearest_neighbor)"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
15
29
|
image_data = image.pixels.collect do |pixel|
|
16
30
|
color_values = if channels == 4
|
17
31
|
[ChunkyPNG::Color.r(pixel),
|
@@ -35,10 +49,13 @@ module TensorStream
|
|
35
49
|
TensorShape.reshape(image_data, [image.height, image.width, channels])
|
36
50
|
end
|
37
51
|
|
38
|
-
register_op :encode_png do |_context,
|
52
|
+
register_op :encode_png do |_context, tensor, inputs|
|
39
53
|
image_data = inputs[0]
|
40
54
|
height, width, channels = shape_eval(image_data)
|
41
55
|
|
56
|
+
resample_new_shape = tensor.options[:new_shape]
|
57
|
+
resample_method = tensor.options[:resample_method] || :bilinear
|
58
|
+
|
42
59
|
png = ChunkyPNG::Image.new(width, height)
|
43
60
|
image_data.each_with_index do |rows, h_index|
|
44
61
|
rows.each_with_index do |p_data, w_index|
|
@@ -51,6 +68,18 @@ module TensorStream
|
|
51
68
|
end
|
52
69
|
end
|
53
70
|
end
|
71
|
+
|
72
|
+
if resample_new_shape
|
73
|
+
case resample_method
|
74
|
+
when :bilinear
|
75
|
+
png.resample_bilinear!(resample_new_shape[1], resample_new_shape[0]) # width, # height
|
76
|
+
when :nearest_neighbor
|
77
|
+
png.resample_nearest_neighbor!(resample_new_shape[1], resample_new_shape[0])
|
78
|
+
else
|
79
|
+
raise TensorStream::ValueError, "invalid resample method provided #{resample_method}. Available (:bilinear, :nearest_neighbor)"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
54
83
|
png.to_s
|
55
84
|
end
|
56
85
|
end
|
@@ -211,6 +211,114 @@ module TensorStream
|
|
211
211
|
register_op :relu6 do |context, tensor, inputs|
|
212
212
|
call_vector_op(tensor, :relu6, inputs[0], inputs[1], context, ->(t, u) { [[t, 0].max, 6].min })
|
213
213
|
end
|
214
|
+
|
215
|
+
register_op :conv2d do |_context, tensor, inputs|
|
216
|
+
filter = inputs[1]
|
217
|
+
filter_shape = shape_eval(filter)
|
218
|
+
strides = tensor.options[:strides]
|
219
|
+
height_stride = strides[1]
|
220
|
+
width_stride = strides[2]
|
221
|
+
|
222
|
+
raise TensorStream::ValueError, " Current implementation does not yet support strides in the batch and depth dimensions." if strides[0] != 1 || strides[3] != 1
|
223
|
+
|
224
|
+
inputs[0].collect do |image|
|
225
|
+
height, width, _channels = shape_eval(image)
|
226
|
+
f_height, f_width, _input_channels, _output_channels = filter_shape
|
227
|
+
|
228
|
+
(0...height).step(height_stride).map do |y|
|
229
|
+
(0...width).step(width_stride).map do |x|
|
230
|
+
filter_result = (0...f_height).map do |f_y|
|
231
|
+
(0...f_width).map do |f_x|
|
232
|
+
f_element = filter[f_y][f_x]
|
233
|
+
|
234
|
+
next if x + f_x >= width
|
235
|
+
next if y + f_y >= height
|
236
|
+
|
237
|
+
image[y + f_y][x + f_x].zip(f_element).map do |image_channel, filter_channels|
|
238
|
+
filter_channels.map { |c| image_channel * c }
|
239
|
+
end
|
240
|
+
end.compact
|
241
|
+
end.flatten(2)
|
242
|
+
|
243
|
+
filter_result.transpose.map { |e| e.reduce(:+) }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
register_op :conv2d_backprop_input do |_context, tensor, inputs|
|
250
|
+
image_shape, filter, grad = inputs
|
251
|
+
|
252
|
+
strides = tensor.options[:strides]
|
253
|
+
|
254
|
+
height_stride = strides[1]
|
255
|
+
width_stride = strides[2]
|
256
|
+
|
257
|
+
filter_shape = shape_eval(filter)
|
258
|
+
|
259
|
+
f_height, f_width, _input_channels, output_channels = filter_shape
|
260
|
+
batch, height, width, channels = image_shape
|
261
|
+
|
262
|
+
Array.new(batch) do |b|
|
263
|
+
image_gradient = TensorShape.reshape(Array.new(height * width * channels) { 0.0 }, [height, width, channels])
|
264
|
+
|
265
|
+
(0...height).step(height_stride).each do |y|
|
266
|
+
(0...width).step(width_stride).each do |x|
|
267
|
+
(0...f_height).each do |f_y|
|
268
|
+
(0...f_width).each do |f_x|
|
269
|
+
next if x + f_x >= width
|
270
|
+
next if y + f_y >= height
|
271
|
+
|
272
|
+
channels.times.each do |c|
|
273
|
+
image_gradient[y + f_y][x + f_x][c] += Array.new(output_channels) do |o_c|
|
274
|
+
filter[f_y][f_x][c][o_c] * grad[b][(y/height_stride) + f_y][(x/width_stride) + f_x][o_c]
|
275
|
+
end.reduce(:+)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
image_gradient
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
register_op :conv2d_backprop_filter do |_context, tensor, inputs|
|
287
|
+
images, filter_shape, grad = inputs
|
288
|
+
|
289
|
+
strides = tensor.options[:strides]
|
290
|
+
height_stride = strides[1]
|
291
|
+
width_stride = strides[2]
|
292
|
+
|
293
|
+
filter_gradient_sum = Array.new(filter_shape.reduce(:*)) { 0.0 }
|
294
|
+
|
295
|
+
images.each_with_index.map do |image, index|
|
296
|
+
height, width, _channels = shape_eval(image)
|
297
|
+
f_height, f_width, input_channels, output_channels = filter_shape
|
298
|
+
|
299
|
+
(0...height).step(height_stride).each do |y|
|
300
|
+
(0...width).step(width_stride).each do |x|
|
301
|
+
filter_result = (0...f_height).map do |f_y|
|
302
|
+
(0...f_width).map do |f_x|
|
303
|
+
|
304
|
+
next Array.new(input_channels * output_channels) { 0.0 } if x + f_x >= width
|
305
|
+
next Array.new(input_channels * output_channels) { 0.0 } if y + f_y >= height
|
306
|
+
|
307
|
+
image[y + f_y][x + f_x].each_with_index.map do |image_channel, c_channel|
|
308
|
+
output_channels.times.map do |o_c|
|
309
|
+
image_channel * grad[index][(y/height_stride) + f_y][(x/width_stride) + f_x][o_c]
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end.flatten
|
314
|
+
|
315
|
+
filter_gradient_sum = multi_array_op(->(a, b) { a + b }, filter_gradient_sum, filter_result)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
TensorShape.reshape(filter_gradient_sum, filter_shape)
|
321
|
+
end
|
214
322
|
end
|
215
323
|
end
|
216
324
|
end
|
@@ -364,7 +364,7 @@ module TensorStream
|
|
364
364
|
|
365
365
|
def get_op_with_axis(a, target_axis, current_axis, op)
|
366
366
|
rank = get_rank(a)
|
367
|
-
return a.
|
367
|
+
return a.send(:"#{op}_index") if rank == 1
|
368
368
|
|
369
369
|
if current_axis == target_axis
|
370
370
|
compare_items = a.collect(&:flatten).transpose
|
@@ -372,7 +372,7 @@ module TensorStream
|
|
372
372
|
elsif a[0].is_a?(Array)
|
373
373
|
a.map { |item| get_op_with_axis(item, target_axis, current_axis + 1, op) }
|
374
374
|
else
|
375
|
-
return a.
|
375
|
+
return a.send(:"#{op}_index")
|
376
376
|
end
|
377
377
|
end
|
378
378
|
|
@@ -171,6 +171,13 @@ module TensorStream
|
|
171
171
|
axis = rank + axis if axis < 0
|
172
172
|
rotated_shape = Array.new(axis + 1) { new_shape.shift }
|
173
173
|
rotated_shape.rotate!(-1) + new_shape
|
174
|
+
when :conv2d
|
175
|
+
return nil unless tensor.inputs[0].shape.known?
|
176
|
+
return nil unless tensor.inputs[1].shape.known?
|
177
|
+
|
178
|
+
new_shape = tensor.inputs[0].shape.shape.dup
|
179
|
+
new_shape[3] = tensor.inputs[1].shape.shape[3]
|
180
|
+
new_shape
|
174
181
|
else
|
175
182
|
return nil if tensor.inputs[0].nil?
|
176
183
|
return tensor.inputs[0].shape.shape if tensor.inputs.size == 1
|
data/lib/tensor_stream/images.rb
CHANGED
@@ -3,14 +3,14 @@ module TensorStream
|
|
3
3
|
extend OpHelper
|
4
4
|
extend TensorStream::Utils
|
5
5
|
|
6
|
-
def self.decode_png(contents, channels: 0, dtype: :uint8, name: nil)
|
7
|
-
_op(:decode_png, contents, channels: channels, data_type: dtype, name: name)
|
6
|
+
def self.decode_png(contents, channels: 0, dtype: :uint8, name: nil, new_shape: nil)
|
7
|
+
_op(:decode_png, contents, channels: channels, data_type: dtype, name: name, new_shape: new_shape)
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.encode_png(contents, compression: -1, name: nil)
|
10
|
+
def self.encode_png(contents, compression: -1, name: nil, new_shape: nil, resample_method: nil)
|
11
11
|
check_allowed_types(contents, %i[uint8 uint16])
|
12
12
|
contents = convert_to_tensor(contents, dtype: :uint16)
|
13
|
-
_op(:encode_png, contents, compression: compression, name: name)
|
13
|
+
_op(:encode_png, contents, compression: compression, name: name, new_shape: new_shape, resample_method: resample_method)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -305,6 +305,8 @@ module TensorStream
|
|
305
305
|
Array.new(node.inputs.size) { |i| res[i] }
|
306
306
|
when :unstack
|
307
307
|
ts.stack(grad, axis: node.options[:axis])
|
308
|
+
when :conv2d
|
309
|
+
_Conv2DGrad(node, grad)
|
308
310
|
when :cast
|
309
311
|
t = %i[float16 float32 float64]
|
310
312
|
src_type = node.inputs[0].data_type
|
@@ -416,5 +418,33 @@ module TensorStream
|
|
416
418
|
out_grads = ts.split(grad, sizes, axis: non_neg_concat_dim, num: op.inputs.size - 1)
|
417
419
|
end_value_index <= dim_index ? out_grads + [nil] : [nil] + out_grads
|
418
420
|
end
|
421
|
+
|
422
|
+
def self._Conv2DGrad(op, grad)
|
423
|
+
# dilations = op.get_attr("dilations")
|
424
|
+
strides = op.options[:strides]
|
425
|
+
padding = op.options[:padding]
|
426
|
+
use_cudnn_on_gpu = op.options[:use_cudnn_on_gpu]
|
427
|
+
data_format = op.options[:data_format]
|
428
|
+
|
429
|
+
shape_0, shape_1 = ts.shape_n([op.inputs[0], op.inputs[1]])
|
430
|
+
[
|
431
|
+
_op(:conv2d_backprop_input,
|
432
|
+
shape_0,
|
433
|
+
op.inputs[1],
|
434
|
+
grad,
|
435
|
+
strides: strides,
|
436
|
+
padding: padding,
|
437
|
+
use_cudnn_on_gpu: use_cudnn_on_gpu,
|
438
|
+
data_format: data_format),
|
439
|
+
_op(:conv2d_backprop_filter,
|
440
|
+
op.inputs[0],
|
441
|
+
shape_1,
|
442
|
+
grad,
|
443
|
+
strides: strides,
|
444
|
+
padding: padding,
|
445
|
+
use_cudnn_on_gpu: use_cudnn_on_gpu,
|
446
|
+
data_format: data_format)
|
447
|
+
]
|
448
|
+
end
|
419
449
|
end
|
420
450
|
end
|
@@ -12,4 +12,40 @@ class Array
|
|
12
12
|
def **(other)
|
13
13
|
TensorStream.convert_to_tensor(self)**other
|
14
14
|
end
|
15
|
+
|
16
|
+
def max_index
|
17
|
+
if first.is_a?(Float)
|
18
|
+
highest = first
|
19
|
+
highest_index = 0
|
20
|
+
each_with_index do |item, index|
|
21
|
+
next if item.nan?
|
22
|
+
|
23
|
+
if item > highest
|
24
|
+
highest = item
|
25
|
+
highest_index = index
|
26
|
+
end
|
27
|
+
end
|
28
|
+
highest_index
|
29
|
+
else
|
30
|
+
index(max)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def min_index
|
35
|
+
if first.is_a?(Float)
|
36
|
+
highest = first
|
37
|
+
highest_index = 0
|
38
|
+
each_with_index do |item, index|
|
39
|
+
next if item.nan?
|
40
|
+
|
41
|
+
if item < highest
|
42
|
+
highest = item
|
43
|
+
highest_index = index
|
44
|
+
end
|
45
|
+
end
|
46
|
+
highest_index
|
47
|
+
else
|
48
|
+
index(min)
|
49
|
+
end
|
50
|
+
end
|
15
51
|
end
|
@@ -3,131 +3,137 @@ module TensorStream
|
|
3
3
|
class NN
|
4
4
|
extend TensorStream::OpHelper
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
class << self
|
7
|
+
def softmax(logits, axis: nil, name: nil)
|
8
|
+
_op(:softmax, logits, nil, axis: axis, name: name)
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def relu(features, name: nil)
|
12
|
+
TensorStream.max(features, 0, name: "relu_#{name}")
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def relu6(features, name: nil)
|
16
|
+
TensorStream.name_scope(name, "Relu6", values: [features]) do
|
17
|
+
features = TensorStream.convert_to_tensor(features, name: "features")
|
18
|
+
_op(:relu6, features, name: name)
|
19
|
+
end
|
18
20
|
end
|
19
|
-
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
##
|
23
|
+
# Computes dropout.
|
24
|
+
#
|
25
|
+
# With probability keep_prob, outputs the input element scaled up by 1 / keep_prob, otherwise outputs 0. The scaling is so that the expected sum is unchanged.
|
26
|
+
def dropout(x, keep_prob, noise_shape: nil, seed: nil, name: nil)
|
27
|
+
TensorStream.name_scope(name, "dropout", values: [x]) do
|
28
|
+
x = TensorStream.convert_to_tensor(x, name: "x")
|
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) && !(0 < keep_prob && keep_prob <= 1)
|
30
31
|
|
31
|
-
|
32
|
+
return x if keep_prob.is_a?(Float) && keep_prob.to_f == 1.0
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
keep_prob = TensorStream.convert_to_tensor(keep_prob, dtype: x.dtype, name: "keep_prob")
|
35
|
+
return x if keep_prob.value == 1.0
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
noise_shape = if noise_shape.nil?
|
38
|
+
TensorStream.shape(x)
|
39
|
+
else
|
40
|
+
noise_shape
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
43
|
+
random_tensor = keep_prob
|
44
|
+
random_tensor += TensorStream.random_uniform(noise_shape, seed: seed, dtype: x.dtype)
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
binary_tensor = TensorStream.floor(random_tensor)
|
47
|
+
TensorStream.div(x, keep_prob) * binary_tensor
|
48
|
+
end
|
47
49
|
end
|
48
|
-
end
|
49
50
|
|
50
|
-
|
51
|
-
|
52
|
-
|
51
|
+
def sigmoid(input, name: nil)
|
52
|
+
TensorStream.sigmoid(input, name: name)
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
def softmax_cross_entropy_with_logits(labels: nil, logits: nil, name: nil)
|
56
|
+
softmax_cross_entropy_with_logits_v2(labels: labels, logits: logits, name: name)
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
def softmax_cross_entropy_with_logits_v2(labels: nil, logits: nil, name: nil)
|
60
|
+
TensorStream.name_scope(name, default: 'softmax_cross_entropy_with_logits', values: [logits, labels]) do
|
61
|
+
ts = TensorStream
|
62
|
+
logits = ts.convert_to_tensor(logits, name: 'logits')
|
63
|
+
labels = ts.convert_to_tensor(labels, name: 'labels')
|
64
|
+
labels = ts.cast(labels, logits.dtype)
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
output = _op(:softmax_cross_entropy_with_logits_v2, logits, labels)
|
67
|
+
output[0]
|
68
|
+
end
|
67
69
|
end
|
68
|
-
end
|
69
70
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
71
|
+
def sparse_softmax_cross_entropy_with_logits(labels: nil, logits: nil, name: nil)
|
72
|
+
TensorStream.name_scope(name, default: "SparseSoftmaxCrossEntropyWithLogits", values: [logits, labels]) do
|
73
|
+
tf = TensorStream
|
74
|
+
labels = tf.convert_to_tensor(labels)
|
75
|
+
logits = tf.convert_to_tensor(logits)
|
76
|
+
precise_logits = logits.data_type == :float16 ? tf.cast(logits, :float32) : logits
|
77
|
+
|
78
|
+
labels_static_shape = labels.shape
|
79
|
+
labels_shape = tf.shape(labels)
|
80
|
+
static_shapes_fully_defined = labels_static_shape.known? && logits.shape.known?
|
81
|
+
|
82
|
+
raise TensorStream::ValueError, "Logits cannot be scalars - received shape #{logits.shape.shape}." if logits.shape.known? && logits.shape.scalar?
|
83
|
+
raise TensorStream::ValueError, "Rank mismatch: Rank of labels (received #{labels_static_shape.ndims}) " +
|
84
|
+
"should equal rank of logits minus 1 (received #{logits.shape.ndims})." if logits.shape.known? && (labels_static_shape.known? && labels_static_shape.ndims != logits.shape.ndims - 1)
|
85
|
+
if logits.shape.ndims == 2
|
86
|
+
cost = _op(:sparse_softmax_cross_entropy_with_logits,
|
87
|
+
precise_logits, labels, name: name)
|
88
|
+
if logits.data_type == :float16
|
89
|
+
return tf.cast(cost[0], :float16)
|
90
|
+
else
|
91
|
+
return cost[0]
|
92
|
+
end
|
91
93
|
end
|
92
|
-
end
|
93
94
|
|
94
|
-
|
95
|
+
shape_checks = []
|
95
96
|
|
96
|
-
|
97
|
+
shape_checks << tf.assert_equal(tf.rank(labels), tf.rank(logits) - 1) unless static_shapes_fully_defined
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
99
|
+
tf.control_dependencies(shape_checks) do
|
100
|
+
num_classes = tf.shape(logits)[tf.rank(logits) - 1]
|
101
|
+
precise_logits = tf.reshape(precise_logits, [-1, num_classes])
|
102
|
+
labels = tf.reshape(labels, [-1])
|
103
|
+
cost = _op(:sparse_softmax_cross_entropy_with_logits, precise_logits, labels, name: name)
|
104
|
+
cost = tf.reshape(cost[0], labels_shape)
|
104
105
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
106
|
+
if logits.data_type == :float16
|
107
|
+
tf.cast(cost, :float16)
|
108
|
+
else
|
109
|
+
cost
|
110
|
+
end
|
109
111
|
end
|
110
112
|
end
|
111
113
|
end
|
112
|
-
end
|
113
114
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
115
|
+
# Computes log softmax activations.
|
116
|
+
def log_softmax(logits, axis: -1, name: nil)
|
117
|
+
_op(:log_softmax, logits, axis: axis, name: name)
|
118
|
+
end
|
119
|
+
|
120
|
+
def sigmoid_cross_entropy_with_logits(labels: nil, logits: nil, name: nil)
|
121
|
+
TensorStream.name_scope(name, default: 'logistic_loss', values: [logits, labels]) do |_name|
|
122
|
+
tf = TensorStream
|
123
|
+
logits = tf.convert_to_tensor(logits, name: 'logits')
|
124
|
+
labels = tf.convert_to_tensor(labels, name: 'labels')
|
125
|
+
zeros = tf.zeros_like(logits, dtype: logits.dtype)
|
126
|
+
cond = (logits >= zeros)
|
127
|
+
relu_logits = tf.where(cond, logits, zeros)
|
128
|
+
neg_abs_logits = tf.where(cond, -logits, logits)
|
129
|
+
|
130
|
+
tf.add(relu_logits - logits * labels,
|
131
|
+
tf.log1p(tf.exp(neg_abs_logits)), name: name)
|
132
|
+
end
|
133
|
+
end
|
118
134
|
|
119
|
-
|
120
|
-
|
121
|
-
tf = TensorStream
|
122
|
-
logits = tf.convert_to_tensor(logits, name: 'logits')
|
123
|
-
labels = tf.convert_to_tensor(labels, name: 'labels')
|
124
|
-
zeros = tf.zeros_like(logits, dtype: logits.dtype)
|
125
|
-
cond = (logits >= zeros)
|
126
|
-
relu_logits = tf.where(cond, logits, zeros)
|
127
|
-
neg_abs_logits = tf.where(cond, -logits, logits)
|
128
|
-
|
129
|
-
tf.add(relu_logits - logits * labels,
|
130
|
-
tf.log1p(tf.exp(neg_abs_logits)), name: name)
|
135
|
+
def conv2d(input, filter, strides, padding, name: nil)
|
136
|
+
_op(:conv2d, input, filter, strides: strides, padding: padding, name: name)
|
131
137
|
end
|
132
138
|
end
|
133
139
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'json'
|
2
|
+
require "zlib"
|
2
3
|
|
3
4
|
module TensorStream
|
4
5
|
module Train
|
@@ -12,11 +13,12 @@ module TensorStream
|
|
12
13
|
write_meta_graph: true,
|
13
14
|
write_state: true,
|
14
15
|
strip_default_attrs: false)
|
15
|
-
|
16
|
+
graph = TensorStream::Graph.get_default_graph
|
17
|
+
vars = graph.get_collection(GraphKeys::GLOBAL_VARIABLES)
|
16
18
|
|
17
19
|
variables = {}
|
18
|
-
|
19
|
-
gs =
|
20
|
+
|
21
|
+
gs = eval_global_step(session, global_step)
|
20
22
|
output_dump = {
|
21
23
|
'variables' => variables,
|
22
24
|
'global_step' => gs
|
@@ -24,7 +26,7 @@ module TensorStream
|
|
24
26
|
|
25
27
|
vars.each do |variable|
|
26
28
|
val = variable.read_value
|
27
|
-
packed_data = TensorStream::Packer.pack(val, variable.data_type)
|
29
|
+
packed_data = Zlib::Deflate.deflate(TensorStream::Packer.pack(val, variable.data_type))
|
28
30
|
variables[variable.name] = {
|
29
31
|
'shape' => shape_eval(val),
|
30
32
|
'data' => Base64.strict_encode64(packed_data)
|
@@ -36,18 +38,21 @@ module TensorStream
|
|
36
38
|
|
37
39
|
new_filename = File.join(path, [basename, gs].compact.join('-'))
|
38
40
|
File.write(new_filename, output_dump.to_yaml)
|
39
|
-
|
41
|
+
if write_meta_graph
|
42
|
+
graph_filename = "#{basename}.pbtext"
|
43
|
+
TensorStream.train.write_graph(graph, path, graph_filename)
|
44
|
+
end
|
40
45
|
path
|
41
46
|
end
|
42
47
|
|
43
48
|
def restore(_session, inputfile)
|
44
|
-
input_dump = YAML.
|
49
|
+
input_dump = YAML.safe_load(File.read(inputfile))
|
45
50
|
|
46
51
|
vars = TensorStream::Graph.get_default_graph.get_collection(GraphKeys::GLOBAL_VARIABLES)
|
47
52
|
vars.each do |variable|
|
48
53
|
next unless input_dump['variables'].key?(variable.name)
|
49
54
|
|
50
|
-
data = TensorStream::Packer.unpack(Base64.decode64(input_dump['variables'][variable.name]['data']), variable.data_type)
|
55
|
+
data = TensorStream::Packer.unpack(Zlib::Inflate.inflate(Base64.decode64(input_dump['variables'][variable.name]['data'])), variable.data_type)
|
51
56
|
shape = input_dump['variables'][variable.name]['shape']
|
52
57
|
variable.buffer = nil
|
53
58
|
variable.value = TensorShape.reshape(data, shape)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tensor_stream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Emmanuel Dayo
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|