Skip to content

Commit 7bbfc98

Browse files
committed
Update quantized tutorial
1 parent 2ca7fd1 commit 7bbfc98

11 files changed

+1048
-1197
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
#! /usr/bin/python
2+
# -*- coding: utf-8 -*-
3+
"""
4+
5+
- 1. This model has 1,068,298 paramters and Dorefa compression strategy(weight:1 bit, active: 1 bit),
6+
after 500 epoches' training with GPU,accurcy of 41.1% was found.
7+
8+
- 2. For simplified CNN layers see "Convolutional layer (Simplified)"
9+
in read the docs website.
10+
11+
- 3. Data augmentation without TFRecord see `tutorial_image_preprocess.py` !!
12+
13+
Links
14+
-------
15+
.. https://www.tensorflow.org/versions/r0.9/tutorials/deep_cnn/index.html
16+
.. https://github.com/tensorflow/tensorflow/tree/r0.9/tensorflow/models/image/cifar10
17+
18+
Note
19+
------
20+
The optimizers between official code and this code are different.
21+
22+
Description
23+
-----------
24+
The images are processed as follows:
25+
.. They are cropped to 24 x 24 pixels, centrally for evaluation or randomly for training.
26+
.. They are approximately whitened to make the model insensitive to dynamic range.
27+
28+
For training, we additionally apply a series of random distortions to
29+
artificially increase the data set size:
30+
.. Randomly flip the image from left to right.
31+
.. Randomly distort the image brightness.
32+
.. Randomly distort the image contrast.
33+
34+
Speed Up
35+
--------
36+
Reading images from disk and distorting them can use a non-trivial amount
37+
of processing time. To prevent these operations from slowing down training,
38+
we run them inside 16 separate threads which continuously fill a TensorFlow queue.
39+
40+
"""
41+
42+
import time
43+
import numpy as np
44+
import multiprocessing
45+
import tensorflow as tf
46+
import tensorlayer as tl
47+
from tensorlayer.models import Model
48+
from tensorlayer.layers import (Input, Conv2d, Sign, MaxPool2d, LocalResponseNorm, BinaryConv2d, BinaryDense, Flatten, Dense)
49+
50+
51+
tl.logging.set_verbosity(tl.logging.DEBUG)
52+
53+
# Download data, and convert to TFRecord format, see ```tutorial_tfrecord.py```
54+
# prepare cifar10 data
55+
X_train, y_train, X_test, y_test = tl.files.load_cifar10_dataset(shape=(-1, 32, 32, 3), plotable=False)
56+
57+
58+
def binary_model(input_shape, n_classes):
59+
in_net = Input(shape=input_shape, name='input')
60+
61+
net = Conv2d(64, (5, 5), (1, 1), act='relu', padding='SAME', name='conv1')(in_net)
62+
net = Sign(name='sign1')(net)
63+
64+
net = MaxPool2d((3, 3), (2, 2), padding='SAME', name='pool1')(net)
65+
net = LocalResponseNorm(4, 1.0, 0.001 / 9.0, 0.75, name='norm1')(net)
66+
net = BinaryConv2d(64, (5, 5), (1, 1), act='relu', padding='SAME', name='bconv1')(net)
67+
68+
net = LocalResponseNorm(4, 1.0, 0.001 / 9.0, 0.75, name='norm2')(net)
69+
net = MaxPool2d((3, 3), (2, 2), padding='SAME', name='pool2')(net)
70+
net = Flatten(name='flatten')(net)
71+
net = Sign(name='sign2')(net)
72+
net = BinaryDense(384, act='relu', name='d1relu')(net)
73+
net = Sign(name='sign3')(net)
74+
net = BinaryDense(192, act='relu', name='d2relu')(net)
75+
net = Dense(n_classes, act=None, name='output')(net)
76+
net = Model(inputs=in_net, outputs=net, name='binarynet')
77+
return net
78+
79+
# training settings
80+
net = binary_model([None, 24, 24, 3], n_classes=10)
81+
batch_size = 128
82+
n_epoch = 50000
83+
learning_rate = 0.0001
84+
print_freq = 5
85+
n_step_epoch = int(len(y_train) / batch_size)
86+
n_step = n_epoch * n_step_epoch
87+
shuffle_buffer_size = 128
88+
89+
train_weights = net.trainable_weights
90+
optimizer = tf.optimizers.Adam(learning_rate)
91+
cost = tl.cost.cross_entropy
92+
93+
def generator_train():
94+
inputs = X_train
95+
targets = y_train
96+
if len(inputs) != len(targets):
97+
raise AssertionError("The length of inputs and targets should be equal")
98+
for _input, _target in zip(inputs, targets):
99+
# yield _input.encode('utf-8'), _target.encode('utf-8')
100+
yield _input, _target
101+
102+
103+
def generator_test():
104+
inputs = X_test
105+
targets = y_test
106+
if len(inputs) != len(targets):
107+
raise AssertionError("The length of inputs and targets should be equal")
108+
for _input, _target in zip(inputs, targets):
109+
# yield _input.encode('utf-8'), _target.encode('utf-8')
110+
yield _input, _target
111+
112+
113+
def _map_fn_train(img, target):
114+
# 1. Randomly crop a [height, width] section of the image.
115+
img = tf.image.random_crop(img, [24, 24, 3])
116+
# 2. Randomly flip the image horizontally.
117+
img = tf.image.random_flip_left_right(img)
118+
# 3. Randomly change brightness.
119+
img = tf.image.random_brightness(img, max_delta=63)
120+
# 4. Randomly change contrast.
121+
img = tf.image.random_contrast(img, lower=0.2, upper=1.8)
122+
# 5. Subtract off the mean and divide by the variance of the pixels.
123+
img = tf.image.per_image_standardization(img)
124+
target = tf.reshape(target, ())
125+
return img, target
126+
127+
128+
def _map_fn_test(img, target):
129+
# 1. Crop the central [height, width] of the image.
130+
img = tf.image.resize_with_pad(img, 24, 24)
131+
# 2. Subtract off the mean and divide by the variance of the pixels.
132+
img = tf.image.per_image_standardization(img)
133+
img = tf.reshape(img, (24, 24, 3))
134+
target = tf.reshape(target, ())
135+
return img, target
136+
137+
138+
139+
def _train_step(network, X_batch, y_batch, cost, train_op=tf.optimizers.Adam(learning_rate=0.0001), acc=None):
140+
with tf.GradientTape() as tape:
141+
y_pred = network(X_batch)
142+
_loss = cost(y_pred, y_batch)
143+
grad = tape.gradient(_loss, network.trainable_weights)
144+
train_op.apply_gradients(zip(grad, network.trainable_weights))
145+
if acc is not None:
146+
_acc = acc(y_pred, y_batch)
147+
return _loss, _acc
148+
else:
149+
return _loss, None
150+
151+
def accuracy(_logits, y_batch):
152+
return np.mean(np.equal(np.argmax(_logits, 1), y_batch))
153+
154+
# dataset API and augmentation
155+
train_ds = tf.data.Dataset.from_generator(
156+
generator_train, output_types=(tf.float32, tf.int32)
157+
) # , output_shapes=((24, 24, 3), (1)))
158+
train_ds = train_ds.map(_map_fn_train, num_parallel_calls=multiprocessing.cpu_count())
159+
# train_ds = train_ds.repeat(n_epoch)
160+
train_ds = train_ds.shuffle(shuffle_buffer_size)
161+
train_ds = train_ds.prefetch(buffer_size=4096)
162+
train_ds = train_ds.batch(batch_size)
163+
# value = train_ds.make_one_shot_iterator().get_next()
164+
165+
test_ds = tf.data.Dataset.from_generator(
166+
generator_test, output_types=(tf.float32, tf.int32)
167+
) # , output_shapes=((24, 24, 3), (1)))
168+
# test_ds = test_ds.shuffle(shuffle_buffer_size)
169+
test_ds = test_ds.map(_map_fn_test, num_parallel_calls=multiprocessing.cpu_count())
170+
# test_ds = test_ds.repeat(n_epoch)
171+
test_ds = test_ds.prefetch(buffer_size=4096)
172+
test_ds = test_ds.batch(batch_size)
173+
# value_test = test_ds.make_one_shot_iterator().get_next()
174+
175+
for epoch in range(n_epoch):
176+
start_time = time.time()
177+
178+
train_loss, train_acc, n_iter = 0, 0, 0
179+
for X_batch, y_batch in train_ds:
180+
net.train()
181+
_loss, acc = _train_step(net, X_batch, y_batch, cost=cost, train_op=optimizer, acc=accuracy)
182+
183+
train_loss += _loss
184+
train_acc += acc
185+
n_iter += 1
186+
187+
print("Epoch {} of {} took {}".format(epoch + 1, n_epoch, time.time() - start_time))
188+
print(" train loss: {}".format(train_loss / n_iter))
189+
print(" train acc: {}".format(train_acc / n_iter))
190+
191+
# use training and evaluation sets to evaluate the model every print_freq epoch
192+
if epoch + 1 == 1 or (epoch + 1) % print_freq == 0:
193+
net.eval()
194+
val_loss, val_acc, n_val_iter = 0, 0, 0
195+
for X_batch, y_batch in test_ds:
196+
_logits = net(X_batch) # is_train=False, disable dropout
197+
val_loss += tl.cost.cross_entropy(_logits, y_batch, name='eval_loss')
198+
val_acc += np.mean(np.equal(np.argmax(_logits, 1), y_batch))
199+
n_val_iter += 1
200+
print(" val loss: {}".format(val_loss / n_val_iter))
201+
print(" val acc: {}".format(val_acc / n_val_iter))
202+
203+
# use testing data to evaluate the model
204+
net.eval()
205+
test_loss, test_acc, n_iter = 0, 0, 0
206+
for X_batch, y_batch in test_ds:
207+
_logits = net(X_batch)
208+
test_loss += tl.cost.cross_entropy(_logits, y_batch, name='test_loss')
209+
test_acc += np.mean(np.equal(np.argmax(_logits, 1), y_batch))
210+
n_iter += 1
211+
print(" test loss: {}".format(test_loss / n_iter))
212+
print(" test acc: {}".format(test_acc / n_iter))

0 commit comments

Comments
 (0)