pythontensorflowmachine-learningkerashandwriting-recognition

How to train new digits handwriting into exist keras model?


I'm having an existing model that trained to recognize handwritten digits. Then I have a new sample digit to train more into that model. Is there any way to do this?

  import os
  import cv2 as cv
  import numpy as np
  import matplotlib.pyplot as plt
  import tensorflow as tf

  ### train model ###
  mnist = tf.keras.datasets.mnist
  (x_train, y_train), (x_test, y_test) = mnist.load_data()
  x_train = x_train/255
  x_test = x_test/255

  model = tf.keras.models.Sequential()
  model.add(tf.keras.layers.Flatten(input_shape=(28,28)))
  model.add(tf.keras.layers.Dense(units=128,activation=tf.nn.relu))
  model.add(tf.keras.layers.Dense(units=10,activation=tf.nn.softmax))

  model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])

  model.fit(x_train, y_train, epochs=5)
  model.save('traineddata.model')

My new sample is number 1 like this: enter image description here


Solution

  • You could load image, convert to grayscale, resize to (28,28)
    and convert to train array with one example, and use it with fit()

    x_example = cv2.imread('image.png')
    x_example = cv2.cvtColor(x_example, cv2.COLOR_BGR2GRAY)
    x_example = cv2.resize(x_example, (28, 28))
    
    y_example = 1
    
    x_data = np.array( [ x_example ] )  # it has to be array with shape (1, 28, 28) instead of (28, 28)
    y_data = np.array( [ y_example ] )  # it has to be array with shape (1, 1) instead of (1,)
    
    model.fit(x_data, y_data, epochs=5)
    

    but it doesn't give good prediction for epochs=5.
    For epochs=10 it gives correct prediction for this image but I didn't check if it still gives correct predictions for other images.

    Maybe it would be better to add image to x_train, y_train and retrain all again.

    x_data = np.append(x_train, [x_example], axis=0)
    y_data = np.append(y_train, y_example)
    
    model.fit(x_data, y_data, epochs=5)
    

    It can be like in real life - when you learn new element then you better remeber it then older elements. When you learn again all elements with new element then you refresh all information and you remeber all of them.


    Minimal working code which I used for test.

    import warnings
    
    warnings.filterwarnings('ignore')  # hide/supress warnings
    
    import os
    import cv2
    import numpy as np
    import matplotlib.pyplot as plt
    import tensorflow as tf
    
    ### train model ###
    
    def build():
        print('-'*50)
        print('# Building model ')
        print('-'*50)
        
        model = tf.keras.models.Sequential()
        model.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
        model.add(tf.keras.layers.Dense(units=128, activation=tf.nn.relu))
        model.add(tf.keras.layers.Dense(units=10, activation=tf.nn.softmax))
        
        model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
    
        return model
        
    def train(model, x_train, y_train, epochs=5):
        print('-'*50)
        print('# Training model')
        print('-'*50)
        
        model.fit(x_train, y_train, epochs=epochs)
    
    def save(model):
        print('-'*50)
        print('# Saving model')
        print('-'*50)
    
        model.save('traineddata.model')
    
    def load():
        print('-'*50)
        print('# Loading model')
        print('-'*50)
        
        return tf.keras.models.load_model('traineddata.model')
    
    def test_one(model, x_example, y_example):
        print('-'*50)
        print('# Testing one element')
        print('-'*50)
        
        # create array with one or more images
        x_data = np.array( [ x_example ] )
        y_data = np.array( [ y_example ] )
    
        print('x_data shape:', x_data.shape)
        print('y_data shape:', y_data.shape)
        print(' expected:', y_data)
    
        # get list with one or more predictions
        y_results = model.predict(x_data)
    
        print('predicted:', y_results.argmax(axis=1))
    
    def retrain_one(model, x_example, y_example, epochs=5):
        print('-'*50)
        print('# Retraining one element')
        print('-'*50)
    
        # create array with one or more images
        x_data = np.array( [ x_example ] )
        y_data = np.array( [ y_example ] )
    
        print('x_data shape:', x_data.shape)
        print('y_data shape:', y_data.shape)
        print('y_data:', y_data)
    
        model.fit(x_data, y_data, epochs=epochs)
    
    def retrain_all(model, x_train, y_train, x_example, y_example, epochs=5):
        print('-'*50)
        print('# Retraining all elements')
        print('-'*50)
    
        # create array with all images
        x_data = np.append(x_train, [x_example], axis=0)
        y_data = np.append(y_train, y_example)
    
        print('x_data shape:', x_data.shape)
        print('y_data shape:', y_data.shape)
        print('y_data:', y_data)
    
        model.fit(x_data, y_data, epochs=epochs)
    
    # --- main ---
    
    # - load train/test images -
    
    print('>>> Loading train/test data ...')
    (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
    
    x_train = x_train/255
    x_test = x_test/255
    
    # - train + save or load -
    
    if not os.path.exists('traineddata.model'):
        print('>>> Building model ...')
        model = build()
    
        print('>>> Training model ...')
        train(model, x_train, y_train)
    
        print('>>> Saving model ...')
        save(model)
    else:
        print('>>> Loading model ...')
        model = load()
    
    #print(' - test on single example - ')
    #index = 0
    #test_one(model, x_train[index], y_train[index])
    
    print(' - image - ')
    
    x_example = cv2.imread('image.png')
    x_example = cv2.cvtColor(x_example, cv2.COLOR_BGR2GRAY)
    x_example = cv2.resize(x_example, (28, 28))
    
    y_example = 1
    
    print('>>> Predicting without training')
    
    test_one(model, x_example, y_example)
    
    print('>>> Predicting with training one element (epochs=10)')
    
    retrain_one(model, x_example, y_example, epochs=10)  # epochs=5 epochs=7
    test_one(model, x_example, y_example)
    
    print('>>> Predicting with retraining all elements')
    
    retrain_all(model, x_train, y_train, x_example, y_example)
    test_one(model, x_example, y_example)
    
    #print('>>> Saving new model')
    #model.save('traineddata.model')