<jupyter_start><jupyter_text>Training and validation data<jupyter_code>training_data = image_dataset_from_directory(
    directory=training_data_path,
    validation_split=validation_split,
    subset='training',
    labels='inferred',
    class_names=class_names,
    label_mode='int',
    batch_size=batch_size,
    image_size=(img_height, img_width),
    seed=seed,
    shuffle=True
)

validation_data = image_dataset_from_directory(
    directory=training_data_path,
    validation_split=validation_split,
    subset='validation',
    labels='inferred',
    class_names=class_names,
    label_mode='int',
    batch_size=batch_size,
    image_size=(img_height, img_width),
    seed=seed,
    shuffle=True
)<jupyter_output><empty_output><jupyter_text>VGG16 architecture<jupyter_code># VGG16 architecture
model = Sequential([
    # Rescaling layer
    Rescaling(
        scale=1. / 255,
        input_shape=(img_height, img_width, 3),
        name='rescale'
    ),
    
    # CONV -> CONV -> POOL
    Conv2D(
        filters=64,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_1_1'
    ),
    Conv2D(
        filters=64,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_1_2'
    ),
    MaxPooling2D(
        pool_size=(2, 2),
        strides=(2, 2),
        name='maxpool2d_1'
    ),
    Dropout(
        rate=0.2,
        name='dropout_1'
    ),
    
    # CONV -> CONV -> POOL
    Conv2D(
        filters=128,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_2_1'
    ),
    Conv2D(
        filters=128,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_2_2'
    ),
    MaxPooling2D(
        pool_size=(2, 2),
        strides=(2, 2),
        name='maxpool2d_2'
    ),
    Dropout(
        rate=0.2,
        name='dropout_2'
    ),
    
    # CONV -> CONV -> CONV -> POOL
    Conv2D(
        filters=256,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_3_1'
    ),
    Conv2D(
        filters=256,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_3_2'
    ),
    Conv2D(
        filters=256,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_3_3'
    ),
    MaxPooling2D(
        pool_size=(2, 2),
        strides=(2, 2),
        name='maxpool2d_3'
    ),
    Dropout(
        rate=0.2,
        name='dropout_3'
    ),

    # CONV -> CONV -> CONV -> POOL
    Conv2D(
        filters=512,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_4_1'
    ),
    Conv2D(
        filters=512,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_4_2'
    ),
    Conv2D(
        filters=512,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_4_3'
    ),
    MaxPooling2D(
        pool_size=(2, 2),
        strides=(2, 2),
        name='maxpool2d_4'
    ),
    Dropout(
        rate=0.2,
        name='dropout_4'
    ),
    
    # CONV -> CONV -> CONV -> POOL
    Conv2D(
        filters=512,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_5_1'
    ),
    Conv2D(
        filters=512,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_5_2'
    ),
    Conv2D(
        filters=512,
        kernel_size=(3, 3),
        padding='same',
        activation='relu',
        name='conv2d_5_3'
    ),
    MaxPooling2D(
        pool_size=(2, 2),
        strides=(2, 2),
        name='maxpool2d_5'
    ),
    Dropout(
        rate=0.2,
        name='dropout_5'
    ),

    # Flattening -> FC -> FC -> FC
    Flatten(
        name='flatten'
    ),
    Dense(
        units=4096, 
        activation='relu',
        name='fc_1'
    ),
    Dropout(
        rate=0.5,
        name='dropout_6'
    ),
    Dense(
        units=4096, 
        activation='relu',
        name='fc_2'
    ),
    Dropout(
        rate=0.5,
        name='dropout_7'
    ),
    Dense(
        units=len(class_names), # number of classes 
        activation='softmax',
        name='fc_output'
    )
])<jupyter_output><empty_output><jupyter_text>Compile model and see its summary<jupyter_code>model.compile(
    optimizer=SGD(learning_rate=0.001, momentum=0.9),
    loss=SparseCategoricalCrossentropy(),
    metrics=['accuracy']
)

plot_model(
    model, 
    to_file='vgg16_plot.png', 
    show_shapes=True,
    show_layer_names=True
)<jupyter_output><empty_output><jupyter_text>Define callbacks<jupyter_code>early_stopping_callback = EarlyStopping(
    monitor='val_loss', 
    mode='min', 
    verbose=1,
    patience=10,
    restore_best_weights=True
)

callbacks = [
    early_stopping_callback
]<jupyter_output><empty_output><jupyter_text>Fit and train<jupyter_code>history = model.fit(
    training_data,
    validation_data=validation_data,
    epochs=epochs,
    callbacks=callbacks,
    shuffle=True
)<jupyter_output><empty_output><jupyter_text>Save the model<jupyter_code>model.save(model_path)<jupyter_output><empty_output><jupyter_text>Load metrics to dataframe<jupyter_code>metrics_df = pd.DataFrame(history.history)<jupyter_output><empty_output><jupyter_text>Accuracy plot<jupyter_code>metrics_df[["accuracy", "val_accuracy"]].plot()
plt.title('Training and Validation Accuracy')
plt.savefig('accuracy.png')
plt.show()<jupyter_output><empty_output><jupyter_text>Loss plot<jupyter_code>metrics_df[["loss", "val_loss"]].plot()
plt.title('Training and Validation Loss')
plt.savefig('loss.png')
plt.show()<jupyter_output><empty_output><jupyter_text>Test the model  Define prediction function<jupyter_code>def predict_and_evaluate(images, labels, class_names):
    test_data_batch = np.array(images)
    print(test_data_batch.shape)
    
    predictions = model.predict(test_data_batch)
    predicted_labels = np.argmax(predictions, axis = 1)
    
    hits = 0

    for predicted_label, prediction, label in zip(predicted_labels, predictions, labels):        
        probability = np.max(prediction) * 100
        print(
            "{} with {:.2f}% probability (real class: {})".format(
                class_names[predicted_label],
                probability,
                class_names[label]
            )
        )
        
        hits = hits + 1 if label == predicted_label else hits      
        
    accuracy = (hits / len(labels)) * 100
    return accuracy, predicted_labels<jupyter_output><empty_output><jupyter_text>Load test data<jupyter_code>images = list()
labels = list()

for class_name in class_names:
    class_path = os.path.join(test_data_path, class_name)
    for image in os.listdir(class_path):
        image_path = os.path.join(class_path, image)
        image_data = load_img(
            image_path,
            target_size=(img_height, img_width),
            color_mode='rgb'
        )
        image_array = img_to_array(image_data)
        images.append(image_array)
        labels.append(class_names.index(class_name))<jupyter_output><empty_output><jupyter_text>Run prediction<jupyter_code>accuracy, predicted_labels = predict_and_evaluate(images, labels, class_names)
print("Accuracy is {:.2f}%".format(accuracy))
evaluation = model.evaluate(
    x=np.array(images),
    y=np.array(labels),
    batch_size=batch_size
)
print("Loss is {:.4f}".format(evaluation[0]))
print("Accuracy is {:.2f}%".format(100 * evaluation[1]))
print(classification_report(labels, predicted_labels, target_names=class_names))<jupyter_output><empty_output><jupyter_text>Confusion matrix<jupyter_code>matrix = confusion_matrix(labels, predicted_labels)

sns.heatmap(
    matrix,
    square=True,
    annot=True,
    cbar=False,
    cmap=plt.cm.Blues,
    xticklabels=class_names,
    yticklabels=class_names
)

plt.xlabel('Predicted Classes')
plt.ylabel('True Classes')
plt.title('Confusion Matrix')
plt.savefig('confusion_matrix.png')
plt.show();<jupyter_output><empty_output><jupyter_text>Download the model<jupyter_code>os.chdir('/kaggle/working')
os.getcwd()
FileLinks('./models')
FileLink('vgg16_plot.png')
FileLink('accuracy.png')
FileLink('loss.png')
FileLink('confusion_matrix.png')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12968917470525188, 'fraction_numerical': 0.02631892342503275, 'mean_word_length': 2.7811796488068437, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '367719', 'license': 'MIT', 'n_tokens_mistral': 3070, 'n_tokens_neox': 2933, 'n_words': 416, 'path': 'src/notebooks/vgg16.ipynb', 'repo_name': '2021-FIIT-Bc-projects/BP-Modroczky-Docker_CNN', 'size': '8397'}