Problem in implementing a CNN with Tensorflow 2.0 for digit recognition

Viewed 99

I'm trying to implement a CNN in order to recognize single numbers coming from ttf files(RGB, in 3 channels). It does not learn and always stuck at some point. What I m doing wrong? Is the structure right? All examples I found are implemented with Keras or with Tensorflow 1.x. I tried multiples options for batchs, filters, learning rates...

# image
image_channels = 3
image_width = 30
image_height = 30
image_flatten = image_width * image_height
# batch
batch_size = 200
# Training parameters.
learning_rate = 0.005
training_epoch = 45000
display_step = 10
# Network parameters.
number_of_filters = 64
neurons_layer_1 = 1024
neurons_layer_2 = 512
neurons_output = 10
dropout_rate = 0.4

weights = {
    'W1': tf.Variable(tf.random.truncated_normal([3, 3, 3, number_of_filters], dtype=tf.float32, stddev=0.1),
                      name='Weights_1'),
    'W2': tf.Variable(tf.random.truncated_normal([14 * 14 * number_of_filters, neurons_layer_1], stddev=0.1),
                      name='Weights_2'),
    'W3': tf.Variable(tf.random.truncated_normal([neurons_layer_1, neurons_layer_2], stddev=0.1), name='Weights_3'),
    'W4': tf.Variable(tf.random.truncated_normal([neurons_layer_2, neurons_output], stddev=0.1), name='Weights_3')
}
biases = {
    'b1': tf.Variable(tf.constant(0.1, shape=[number_of_filters]), name='bias_1'),
    'b2': tf.Variable(tf.constant(0.1, shape=[neurons_layer_1]), name='bias_2'),
    'b3': tf.Variable(tf.constant(0.1, shape=[neurons_layer_2]), name='bias_2'),
    'b4': tf.Variable(tf.constant(0.1, shape=[neurons_output]), name='bias_3')
}

# Create model.
def neural_net(inputdata, debug=False):
    if debug:
        print("--------------- starting step:")
    # ## EXTRACTING FEATURES
    result_conv2d_1 = tf.nn.conv2d(inputdata, weights['W1'], strides=[1, 2, 2, 1], padding='VALID') + biases['b1']
    result_relu_1 = tf.nn.relu(result_conv2d_1)
    result_maxpool_1 = tf.nn.max_pool(result_relu_1, ksize=[1, 1, 1, 1], strides=[1, 1, 1, 1], padding='VALID')
    if debug:
        print("result_conv2d_1-->",result_conv2d_1.shape)
        print("result_relu_1  -->",result_relu_1.shape)
        print("maxpool1.shape --> ", result_maxpool_1.shape)

    # flat
    flatten = tf.reshape(result_maxpool_1, shape=(tf.shape(result_maxpool_1)[0], -1))
    if debug:
        print("flatten.shape  --> ", flatten.shape)

    # ## CLASIFFICATION
    # layer 1 - dense / fully connected
    layer1 = tf.nn.relu(tf.add(tf.matmul(flatten, weights['W2']), biases['b2']))
    # dropout
    #layer_drop = tf.nn.dropout(layer1, rate=dropout_rate)
    # layer 2 - dense / fully connected
    layer2 = tf.nn.relu(tf.add(tf.matmul(layer1, weights['W3']), biases['b3']))
    # layer 2 - dense / fully connected
    layer3 = tf.nn.relu(tf.add(tf.matmul(layer2, weights['W4']), biases['b4']))
    result = tf.nn.softmax(layer3)

    return result

# Cross-Entropy loss function.
def cross_entropy(predicted, desired):
    desired2 = tf.one_hot(desired, depth=neurons_output)
    cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=desired2, logits=predicted, name="cross_entropy")
    mean = tf.reduce_mean(cross_entropy, name="cross_entropy_mean")
    return mean


# Accuracy metric.
def accuracy(y_pred, y_true):
    # Predicted class is the index of highest score in prediction vector (i.e. argmax).
    correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64))
    return tf.reduce_mean(tf.cast(correct_prediction, tf.float32), axis=-1)


optimizer = tf.optimizers.Adam(learning_rate)

# Optimization process.
def run_optimization(inputdata, expected, debug=False):
    # Wrap computation inside a GradientTape for automatic differentiation.
    with tf.GradientTape() as g:
        predicted = neural_net(inputdata, debug)
        loss = cross_entropy(predicted, expected)
        #print(f'\r          loss: {loss}', end="")
    # Variables to update, i.e. train able variables.
    trainable_variables = list(weights.values()) + list(biases.values())
    # Compute gradients.
    gradients = g.gradient(loss, trainable_variables)
    # Update W and b following gradients.
    optimizer.apply_gradients(zip(gradients, trainable_variables))    


datafile = open("W:/machinelearning/dataset_ttf_single/ttf_single_full.p", "rb")
with datafile:
    for step in range(training_steps):
        # Run the optimization to update W and b values.
        batch_images, batch_labels = load_batch_dataset(datafile, batch_size)
        run_optimization(batch_images, batch_labels, False)
        if step % display_step == 0:
            predicted = neural_net(batch_images)
            loss = cross_entropy(predicted, batch_labels)
            acc = accuracy(predicted, batch_labels)
            print("\nstep: %i, loss: %f, accuracy: %f" % (step, loss, acc))
datafile.close()

The results are usually like this:

step: 330, loss: 2.341150, accuracy: 0.120000

step: 340, loss: 2.396150, accuracy: 0.065000

step: 350, loss: 2.361150, accuracy: 0.100000

step: 360, loss: 2.376150, accuracy: 0.085000

step: 370, loss: 2.371150, accuracy: 0.090000

step: 380, loss: 2.331150, accuracy: 0.130000

step: 390, loss: 2.326150, accuracy: 0.135000

It stacks between 0.10 and 0.15 usually. I followed an example of CNN MNIST in Tensorflow 2.0, it works but I'm not able to do it with different images not coming from MNIST. I'm sure the optimizers and the CNN are not perfect but I'm trying to start from the beginning creating a little piece of CNN and then improve it, I want to learn how it works, but something easy like this and very similar to MNIST, I'm stuck on it.

Someone can give me some clue about what is going on? Thanks!

1 Answers

It is not exactly apparent (especially if you haven't been burned in practice first!), but the value of stddev=0.1 you use in the initalization of your weights is actually a huge one.

Try with stddev=0.01.

Initializing the bias values with tf.constant(0) (instead of 0.1) would also be a good idea; in contrast with the weights, you can indeed initialize bias values to 0, and this is the most often used choice in practice.

Related