import glob import random import tensorflow as tf import cv2 import os from keras.layers import Conv2D, Dense, MaxPool2D, Input, Flatten, BatchNormalization, Dropout from keras.models import Model, Sequential from keras.utils import plot_model from keras.metrics import Recall, Precision from keras.callbacks import EarlyStopping, ModelCheckpoint labels = sorted(os.listdir("./dataset/train")) char_to_int = dict((c, i) for i, c in enumerate(labels)) onehot_encoded = dict() os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2" def get_path_X(type_data): data_path = [] for label in labels: data_path.extend(glob.glob("./dataset/{}/{}/*".format(type_data, label))) random.shuffle(data_path) return data_path def get_Y(X_data): Y_data = [] for datum in X_data: Y_data.append(char_to_int[datum.split("/")[-2].strip()]) return Y_data def read_image(path): path = path.decode() x = cv2.imread(path, cv2.IMREAD_COLOR) x = cv2.resize(x, (224, 224)) x = x / 255.0 # (224, 224, 3) return x def tf_parse(x, y): def _parse(x, y): x = read_image(x) temp = [0] * len(labels) temp[y] = 1 y = temp return x, y x, y = tf.numpy_function(_parse, [x, y], [tf.float64, tf.int64]) x.set_shape([224, 224, 3]) y.set_shape([15]) return x, y def tf_dataset(x, y, batch=8): dataset = tf.data.Dataset.from_tensor_slices((x, y)) dataset = dataset.map(tf_parse) dataset = dataset.batch(batch) dataset = dataset.repeat() return dataset train_X_path = get_path_X("train") test_X_path = get_path_X("test") val_X_path = get_path_X("valid") train_Y = get_Y(train_X_path) test_Y = get_Y(test_X_path) val_Y = get_Y(val_X_path) train_ds = tf_dataset(train_X_path, train_Y) valid_ds = tf_dataset(val_X_path, val_Y) # for x, y in train_ds: # print(x.shape) # print(y.shape) # break def build_model(): size = 224 inputs = Input((size, size, 3)) x = inputs x = Conv2D(64, (3, 3), activation="relu")(x) x = MaxPool2D((2, 2), strides=2)(x) x = Conv2D(128, (3, 3), activation="relu")(x) x = MaxPool2D((2, 2), strides=2)(x) x = Dropout(0.3)(x) x = Flatten()(x) x = Dense(len(labels), activation="softmax")(x) return Model(inputs, x) def build_seq_model(): model = Sequential() # convolutional layer model.add( Conv2D(50, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu', input_shape=(224, 224, 3))) # convolutional layer model.add(Conv2D(75, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(MaxPool2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Conv2D(125, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(MaxPool2D(pool_size=(2, 2))) model.add(Dropout(0.25)) # flatten output of conv model.add(Flatten()) # hidden layer model.add(Dense(500, activation='relu')) model.add(Dropout(0.4)) model.add(Dense(250, activation='relu')) model.add(Dropout(0.3)) # output layer model.add(Dense(15, activation='softmax')) return model if __name__ == "__main__": batch = 8 lr = 1e-4 epochs = 50 cnn_model = Sequential() pretrained_model = tf.keras.applications.ResNet50(include_top=False, input_shape=(224, 224, 3), pooling='max', classes=15, weights='imagenet') for layer in pretrained_model.layers: layer.trainable = False cnn_model.add(pretrained_model) cnn_model.add(Flatten()) cnn_model.add(Dense(1024, activation='relu')) cnn_model.add(Dense(15, activation='softmax')) plot_model(cnn_model, "model.png", show_shapes=True) cnn_model.summary() metrics = ["acc", Recall(), Precision()] cnn_model.compile(loss="categorical_crossentropy", optimizer="adam", metrics=metrics) callbacks = [ ModelCheckpoint("files/model_new.h5"), EarlyStopping(monitor="val_loss", patience=10, restore_best_weights=False) ] train_steps = len(train_X_path) // batch valid_steps = len(val_X_path) // batch if len(train_X_path) % batch != 0: train_steps += 1 if len(val_X_path) % batch != 0: valid_steps += 1 cnn_model.fit( train_ds, validation_data=valid_ds, epochs=epochs, steps_per_epoch=train_steps, validation_steps=valid_steps, callbacks=callbacks, shuffle=False )