Hi !
I’m using DIGITS to train my tensorflow models, currently a LeNet network with gray[28x28] input using my own classified images.
I prepare a dataset with two labels, 0 and 1 that stands for :
- 0 => not a ball (~ 6000 images)
- 1 => a ball (~ 1000 images)
When I train it using DIGITS, I get a model with an accuracy of ~94% and a loss of 0.27.
When I classify one image using DIGITS, it classifies it well, as you can see below :
External Media
Very well, so now I want to use this model in one of my Python script. So I define the model, derived from the network.py provided with DIGITS :
class LeNetModel():
# A placeholder version, allowing to load an image from a numpy array (OpenCV in my case)
def placeholder_gray28(self, nclasses):
x = tf.placeholder(tf.float32, shape=[28, 28, 1], name="x")
return x, self.gray28(x, nclasses)
def gray28(self, x, nclasses, is_training=False):
rs = tf.reshape(x, shape=[-1, 28, 28, 1])
# scale (divide by MNIST std)
rs = rs * 0.0125
with slim.arg_scope([slim.conv2d, slim.fully_connected],
weights_initializer=tf.contrib.layers.xavier_initializer(),
weights_regularizer=slim.l2_regularizer(0.0005)):
model = slim.conv2d(rs, 20, [5, 5], padding='VALID', scope='conv1')
model = slim.max_pool2d(model, [2, 2], padding='VALID', scope='pool1')
model = slim.conv2d(model, 50, [5, 5], padding='VALID', scope='conv2')
model = slim.max_pool2d(model, [2, 2], padding='VALID', scope='pool2')
model = slim.flatten(model)
model = slim.fully_connected(model, 500, scope='fc1')
model = slim.dropout(model, 0.5, is_training=is_training, scope='do1')
model = slim.fully_connected(model, nclasses, activation_fn=None, scope='fc2')
# I only append this softmax, that changes output tensor values but doesn't change the classification
model = tf.nn.softmax(model)
return model
Except the latest softmax, this is the same network as the one that has been trained by DIGITS.
I use this model by shaping and providing a Tensor obtained from the same JPG image as I use in DIGITS :
def name_in_checkpoint(var):
return 'model/' + var.op.name
TF_INTRA_OP_THREADS = 0
TF_INTER_OP_THREADS = 0
MIN_LOGS_PER_TRAIN_EPOCH = 8 # torch default: 8
FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_boolean('log_device_placement', False, """Whether to log device placement.""")
tf.app.flags.DEFINE_boolean('serving_export', False, """Flag for exporting an Tensorflow Serving model""")
if __name__ == '__main__':
filename_queue = tf.train.string_input_producer(tf.train.match_filenames_once("img-535.jpg"))
image_reader = tf.WholeFileReader()
key, image_file = image_reader.read(filename_queue)
ball = tf.image.decode_jpeg(image_file)
ball = tf.to_float(ball)
ball = tf.image.resize_bicubic([ball],(28,28))
ball = tf.image.rgb_to_grayscale([ball])
ball = tf.divide(ball, 255)
single_batch = [key, ball]
inference_op = LeNetModel().gray28(ball,2,False)
sess = tf.Session(config=tf.ConfigProto(
allow_soft_placement=True,
inter_op_parallelism_threads=TF_INTER_OP_THREADS,
intra_op_parallelism_threads=TF_INTRA_OP_THREADS,
log_device_placement=FLAGS.log_device_placement))
variables_to_restore = slim.get_variables_to_restore(exclude=["is_training"])
variables_to_restore = {name_in_checkpoint(var):var for var in variables_to_restore}
saver = tf.train.Saver(variables_to_restore)
# Initialize variables
init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
sess.run(init_op)
saver.restore(sess, "snapshot_30.ckpt")
tf.train.start_queue_runners(sess)
print sess.run(inference_op * 100)
sess.close()
exit(0)
And I am not able to have the same results. Executing this script, I get this result :
[[ 82.83679962 17.16320229]]
Neither the score nor the classification are right. But I can’t understand what I am doing wrong. I take a look at the DIGITS source code and I can’t find significant differences with my code. Does anybody encounter this problem ?
You can download the full use case here : http://vps166675.ovh.net/digits-issue.tar.gz
Thank you in advance.
Damien.