tensor_stream-opencl 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/tensor_stream/opencl/opencl_evaluator.rb +58 -11
- data/lib/tensor_stream/opencl/version.rb +1 -1
- data/mnist_model.yml +379860 -0
- data/samples/build_mnist_model.rb +130 -0
- data/samples/classify.rb +12 -0
- data/samples/mnist_data_3.0.rb +0 -1
- metadata +3 -2
- data/samples/image_sort.rb +0 -9
@@ -0,0 +1,130 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# builds a frozen mnist image recognition model from scratch
|
4
|
+
# based on mnist_data_3.0.rb
|
5
|
+
|
6
|
+
require "bundler/setup"
|
7
|
+
require 'tensor_stream'
|
8
|
+
require 'mnist-learn'
|
9
|
+
require 'csv'
|
10
|
+
|
11
|
+
# Enable OpenCL hardware accelerated computation, not using OpenCL can be very slow
|
12
|
+
require 'tensor_stream/opencl'
|
13
|
+
require 'tensor_stream/utils/freezer'
|
14
|
+
|
15
|
+
epochs = (ARGV[0] || 2000).to_i
|
16
|
+
|
17
|
+
tf = TensorStream
|
18
|
+
puts "Tensorstream version #{tf.__version__} with OpenCL lib #{TensorStream::Opencl::VERSION}"
|
19
|
+
|
20
|
+
# Import MNIST data
|
21
|
+
puts "downloading minst data"
|
22
|
+
# Download images and labels into mnist.test (10K images+labels) and mnist.train (60K images+labels)
|
23
|
+
mnist = Mnist.read_data_sets('/tmp/data', one_hot: true)
|
24
|
+
|
25
|
+
puts "downloading finished"
|
26
|
+
|
27
|
+
x = tf.placeholder(:float32, shape: [nil, 28, 28, 1])
|
28
|
+
y_ = tf.placeholder(:float32, shape: [nil, 10])
|
29
|
+
step = tf.placeholder(:int32)
|
30
|
+
pkeep = tf.placeholder(tf.float32)
|
31
|
+
|
32
|
+
# Network parameters
|
33
|
+
K = 4 # first convolutional layer output depth
|
34
|
+
L = 8 # second convolutional layer output depth
|
35
|
+
M = 12 # third convolutional layer
|
36
|
+
N = 200 # fully connected layer
|
37
|
+
|
38
|
+
|
39
|
+
w1 = tf.variable(tf.truncated_normal([6, 6, 1, K], stddev: 0.1))
|
40
|
+
b1 = tf.variable(tf.ones([K])/10)
|
41
|
+
|
42
|
+
w2 = tf.variable(tf.truncated_normal([5, 5, K, L], stddev: 0.1))
|
43
|
+
b2 = tf.variable(tf.ones([L])/10)
|
44
|
+
|
45
|
+
w3 = tf.variable(tf.truncated_normal([4, 4, L, M], stddev: 0.1))
|
46
|
+
b3 = tf.variable(tf.ones([M])/10)
|
47
|
+
|
48
|
+
w4 = tf.variable(tf.truncated_normal([7 * 7 * M, N], stddev: 0.1))
|
49
|
+
b4 = tf.variable(tf.ones([N])/10)
|
50
|
+
|
51
|
+
w5 = tf.variable(tf.truncated_normal([N, 10], stddev: 0.1))
|
52
|
+
b5 = tf.variable(tf.ones([10])/10)
|
53
|
+
|
54
|
+
# The model
|
55
|
+
stride = 1 # output is 28x28
|
56
|
+
y1 = tf.nn.relu(tf.nn.conv2d(tf.reshape(x, [-1, 28, 28, 1]), w1, [1, stride, stride, 1], 'SAME') + b1)
|
57
|
+
stride = 2 # output is 14x14
|
58
|
+
y2 = tf.nn.relu(tf.nn.conv2d(y1, w2, [1, stride, stride, 1], 'SAME') + b2)
|
59
|
+
stride = 2 # output is 7x7
|
60
|
+
y3 = tf.nn.relu(tf.nn.conv2d(y2, w3, [1, stride, stride, 1], 'SAME') + b3)
|
61
|
+
|
62
|
+
# reshape the output from the third convolution for the fully connected layer
|
63
|
+
yy = tf.reshape(y3, [-1, 7 * 7 * M])
|
64
|
+
y4 = tf.nn.relu(tf.matmul(yy, w4) + b4)
|
65
|
+
|
66
|
+
ylogits = tf.matmul(y4, w5) + b5
|
67
|
+
|
68
|
+
# model
|
69
|
+
y = tf.nn.softmax(ylogits, name: 'out')
|
70
|
+
|
71
|
+
# cross-entropy loss function (= -sum(Y_i * log(Yi)) ), normalised for batches of 100 images
|
72
|
+
# TensorFlow provides the softmax_cross_entropy_with_logits function to avoid numerical stability
|
73
|
+
# problems with log(0) which is NaN
|
74
|
+
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits: ylogits, labels: y_)
|
75
|
+
cross_entropy = tf.reduce_mean(cross_entropy)*100
|
76
|
+
|
77
|
+
is_correct = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
|
78
|
+
accuracy = tf.reduce_mean(tf.cast(is_correct, :float32))
|
79
|
+
|
80
|
+
# training step, learning rate = 0.003
|
81
|
+
lr = 0.0001.t + tf.train.exponential_decay(0.003, step, 2000, 1/Math::E)
|
82
|
+
train_step = TensorStream::Train::AdamOptimizer.new(lr).minimize(cross_entropy)
|
83
|
+
|
84
|
+
sess = tf.session
|
85
|
+
# Add ops to save and restore all the variables.
|
86
|
+
|
87
|
+
init = tf.global_variables_initializer
|
88
|
+
|
89
|
+
sess.run(init)
|
90
|
+
|
91
|
+
#Setup save and restore
|
92
|
+
model_save_path = "test_models/mnist_data_3.0"
|
93
|
+
saver = tf::Train::Saver.new
|
94
|
+
saver.restore(sess, model_save_path)
|
95
|
+
|
96
|
+
mnist_train = mnist.train
|
97
|
+
test_data = { x => mnist.test.images, y_ => mnist.test.labels, pkeep => 1.0 }
|
98
|
+
|
99
|
+
puts "training #{epochs} epochs"
|
100
|
+
(0..epochs).each do |i|
|
101
|
+
# load batch of images and correct answers
|
102
|
+
batch_x, batch_y = mnist_train.next_batch(100)
|
103
|
+
train_data = { x => batch_x, y_ => batch_y, step => i, pkeep => 0.75 }
|
104
|
+
|
105
|
+
# train
|
106
|
+
sess.run(train_step, feed_dict: train_data)
|
107
|
+
|
108
|
+
if (i % 10 == 0)
|
109
|
+
|
110
|
+
a_train, c_train, l = sess.run([accuracy, cross_entropy, lr], feed_dict: { x => batch_x, y_ => batch_y, step => i, pkeep => 1.0})
|
111
|
+
puts "#{i}: accuracy:#{a_train} loss:#{c_train} (lr:#{l})"
|
112
|
+
end
|
113
|
+
|
114
|
+
if (i % 100 == 0)
|
115
|
+
# success on test data?
|
116
|
+
a_test, c_test = sess.run([accuracy, cross_entropy], feed_dict: test_data, pkeep => 1.0)
|
117
|
+
puts("#{i}: ******** test accuracy: #{a_test} test loss: #{c_test}")
|
118
|
+
|
119
|
+
# save current state of the model
|
120
|
+
save_path = saver.save(sess, model_save_path)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Freezing removes variables and turns them into constants
|
125
|
+
puts "saving frozen model"
|
126
|
+
freezer = TensorStream::Freezer.new
|
127
|
+
freezer.convert(sess, model_save_path, 'mnist_model.yml')
|
128
|
+
puts "done. model written at mnist_model.yml"
|
129
|
+
|
130
|
+
|
data/samples/classify.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# This script reads a grayscale PNG and predicts what digit it is
|
4
|
+
# Note: You can use the dump_mnist.rb script to get those images
|
5
|
+
#
|
6
|
+
# This also requires an existing model:
|
7
|
+
#
|
8
|
+
# You can run
|
9
|
+
#
|
10
|
+
# ruby samples/build_mnist_model.rb
|
11
|
+
#
|
12
|
+
# to build a model that you can use
|
13
|
+
|
3
14
|
require "bundler/setup"
|
4
15
|
require "tensor_stream"
|
5
16
|
require 'mnist-learn'
|
@@ -14,6 +25,7 @@ input = target_graph['Placeholder']
|
|
14
25
|
output = TensorStream.argmax(target_graph['out'], 1)
|
15
26
|
sess = TensorStream.session
|
16
27
|
|
28
|
+
# invert since model was trained on a white on black png image
|
17
29
|
reshaped_image = 255.0.t - decoded_image.reshape([1, 28, 28, 1]).cast(:float32)
|
18
30
|
result = sess.run(output, feed_dict: { input => reshaped_image})
|
19
31
|
|
data/samples/mnist_data_3.0.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tensor_stream-opencl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Dayo
|
@@ -246,9 +246,10 @@ files:
|
|
246
246
|
- lib/tensor_stream/opencl/opencl_evaluator.rb
|
247
247
|
- lib/tensor_stream/opencl/opencl_template_helper.rb
|
248
248
|
- lib/tensor_stream/opencl/version.rb
|
249
|
+
- mnist_model.yml
|
250
|
+
- samples/build_mnist_model.rb
|
249
251
|
- samples/classify.rb
|
250
252
|
- samples/dump_mnist.rb
|
251
|
-
- samples/image_sort.rb
|
252
253
|
- samples/iris.data
|
253
254
|
- samples/iris.rb
|
254
255
|
- samples/logistic_regression.rb
|