<jupyter_start><jupyter_text>Defining Test and Train Paths<jupyter_code>import os.path

test_path = r'../data/test'
train_path = '../data/train/'<jupyter_output><empty_output><jupyter_text>Finding the height, width and channels of all training images<jupyter_code>import PIL.Image as Image

width = list()
height = list()

for category in os.listdir(train_path):

    if category.find('.') != 0:
        for img in os.listdir(os.path.join(train_path, category)):
            if img.find('.') != 0:
                img_path = os.path.join(train_path, category, img)
                img = Image.open(img_path)
                width.append(img.width)
                height.append(img.height)<jupyter_output><empty_output><jupyter_text>Deducing Image Shape<jupyter_code>import numpy as np

# Image shape will be an average of individual width/height of all training images
image_shape = (int(np.round(np.mean(width))), int(np.round(np.mean(height))), 3)
image_shape<jupyter_output><empty_output><jupyter_text>Using Image Data Generator<jupyter_code>from tensorflow.keras.preprocessing.image import ImageDataGenerator

image_generator = ImageDataGenerator(
    rotation_range=20,  # Rotate images randomly by 20 degrees
    width_shift_range=0.1,  # Shift width of the image by 10%
    height_shift_range=0.1,
    rescale=1 / 255,  # Normalize images
    shear_range=0.1,  # Cutting away 10% of the image
    zoom_range=0.1,  # Zoom in 10%
    horizontal_flip=True,
    fill_mode='nearest'  # Read documentation
)<jupyter_output><empty_output><jupyter_text>Making classes Known to the Generator<jupyter_code>image_generator.flow_from_directory(train_path)

image_generator.flow_from_directory(test_path)<jupyter_output>Found 7 images belonging to 3 classes.
Found 7 images belonging to 3 classes.<jupyter_text>Creating the Model<jupyter_code>from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, Flatten, Dropout

model = Sequential()

model.add(Conv2D(
    filters=32,
    kernel_size=(3, 3),
    input_shape=image_shape,
    activation='relu',
))
model.add(MaxPool2D(2, 2))

model.add(Conv2D(
    filters=64,
    kernel_size=(3, 3),
    input_shape=image_shape,
    activation='relu',
))

model.add(MaxPool2D(2, 2))

model.add(Conv2D(
    filters=64,
    kernel_size=(3, 3),
    input_shape=image_shape,
    activation='relu',
))
model.add(MaxPool2D(2, 2))

model.add(Flatten())

model.add(Dense(128, activation='relu'))

model.add(Dropout(0.5))

# Output layer
model.add(Dense(3, activation='softmax'))

model.compile('adam', 'categorical_crossentropy', metrics=['accuracy'])
model.summary()<jupyter_output>Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 776, 510, 32)      896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 388, 255, 32)      0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 386, 253, 64)      18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 193, 126, 64)      0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 191, 124, 64)      36928     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 95, 62, 64)        0         
________________________________________________________[...]<jupyter_text>Defining Batch Size<jupyter_code>batch_size = 3<jupyter_output><empty_output><jupyter_text>Test and Train Generators<jupyter_code>train_generator = image_generator.flow_from_directory(
    train_path,
    # All images will be resized to target height and width.
    target_size=image_shape[:2],
    batch_size=batch_size,
    color_mode='rgb',
    # Since we use categorical cross-entropy loss, we need categorical labels
    class_mode="categorical"
)
train_generator.class_indices
test_generator = image_generator.flow_from_directory(
    test_path,
    target_size=image_shape[:2],
    batch_size=batch_size,
    class_mode="categorical",
    shuffle=True
)<jupyter_output>Found 7 images belonging to 3 classes.<jupyter_text>Training the Model<jupyter_code>from tensorflow.keras.callbacks import EarlyStopping

early_stop = EarlyStopping(monitor='val_loss', patience=2)
results = model.fit_generator(
    train_generator,
    epochs=2,
    validation_data=test_generator,
    callbacks=[early_stop],
)<jupyter_output>Epoch 1/2
3/3 [==============================] - 87s 29s/step - loss: 12.2805 - accuracy: 0.2857 - val_loss: 12.5363 - val_accuracy: 0.2857
Epoch 2/2
3/3 [==============================] - 92s 31s/step - loss: 12.2805 - accuracy: 0.2857 - val_loss: 8.9545 - val_accuracy: 0.2857<jupyter_text>Saving Model's Weights<jupyter_code>from tensorflow.keras.models import save_model

save_model(model, '../models/resnet50_model.h5')<jupyter_output><empty_output><jupyter_text>Evaluating Model's Performance<jupyter_code>model.evaluate(test_generator)
# Make predictions
predictions = model.predict_generator(test_generator)
# SETTING CUT-OFF PROBABILITY
predictions = predictions > 0.5
predictions
test_generator.classes
one_hot_encoded_y_test = [
    [1, 0, 0],
    [1, 0, 0],
    [0, 1, 0],
    [0, 1, 0],
    [0, 1, 0],
    [0, 0, 1],
    [0, 0, 1],
]
from sklearn.metrics import classification_report, confusion_matrix

print(classification_report(one_hot_encoded_y_test, predictions, zero_division=0))
import jovian

jovian.commit()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12345893384268102, 'fraction_numerical': 0.04028477166174683, 'mean_word_length': 4.907692307692308, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '207237', 'license': 'MIT', 'n_tokens_mistral': 2009, 'n_tokens_neox': 1834, 'n_words': 376, 'path': 'notebooks/model-from-scratch.ipynb', 'repo_name': 'justVikram/ml-course-project', 'size': '5759'}