import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
import pandas as pd
import scipy as sp
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras.preprocessing.image import ImageDataGenerator
train_df = pd.read_csv('train.csv')
val_df = pd.read_csv('val.csv')
test_df = pd.read_csv('test.csv')
submission_df = pd.read_csv('sample_submission.csv')
print(train_df)
batch_size = 32
img_height = 64
img_width = 64
trainimg_dir = 'train_images'
valimg_dir = 'val_images'
testimg_dir = 'test_images'
checkpoint_filepath = 'best_model.h5'
early_stopping_callback = tf.keras.callbacks.EarlyStopping(
patience=5, # Number of epochs with no improvement after which training will be stopped
restore_best_weights=True # Restores the weights of the best-performing epoch
)
checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
'best_model.h5', # Filepath to save the best model
monitor='val_accuracy', # Metric to monitor for saving the best model
save_best_only=True, # Save only the best model
mode='max' # Mode for monitoring ('max' for accuracy)
)
def preprocess_image(file_path):
img = tf.io.read_file(file_path)
img = tf.image.decode_png(img, channels=3)
img = tf.image.resize(img, [img_height, img_width])
return img
train_images = []
train_labels = []
for index, row in train_df.iterrows():
image_path = trainimg_dir + '/' + row['Image']
train_images.append(preprocess_image(image_path))
train_labels.append(row['Class'])
train_images = np.array(train_images)
train_labels = np.array(train_labels)
class_names = np.unique(train_labels)
train_ds = tf.data.Dataset.from_tensor_slices((train_images, train_labels))
train_ds = train_ds.batch(batch_size)
# Verify the number of images and labels
num_images = len(train_images)
num_labels = len(train_labels)
print("Number of images: ", num_images)
print("Number of labels: ", num_labels)
plt.figure(figsize=(10,10))
for images, labels in train_ds.take(1):
for i in range(9):
ax = plt.subplot(3,3,i+1)
plt.imshow(images[i].numpy().astype("uint8"))
plt.title(class_names[labels[i]])
plt.axis("off")
plt.show()
for image_batch, labels_batch in train_ds:
print(image_batch.shape)
print(labels_batch.shape)
break
validation_images = []
validation_labels = []
for index, row in val_df.iterrows():
image_path = valimg_dir + '/' + row['Image']
validation_images.append(preprocess_image(image_path))
validation_labels.append(row['Class'])
validation_images = np.array(validation_images)
validation_labels = np.array(validation_labels)
val_ds = tf.data.Dataset.from_tensor_slices((validation_images, validation_labels))
val_ds = val_ds.batch(batch_size)
plt.figure(figsize=(10,10))
for images, labels in val_ds.take(1):
for i in range(9):
ax = plt.subplot(3,3,i+1)
plt.imshow(images[i].numpy().astype("uint8"))
plt.title(class_names[labels[i]])
plt.axis("off")
plt.show()
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
normalization_layer = layers.Rescaling(1./255)
normalized_train_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
normalized_val_ds = val_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch_train, labels_batch_train = next(iter(normalized_train_ds))
first_image_train = image_batch_train[0]
print("Train - Min", np.min(first_image_train), "Max: ", np.max(first_image_train))
image_batch_val, labels_batch_val = next(iter(normalized_val_ds))
first_image_val = image_batch_val[0]
print("Val - Min", np.min(first_image_val), "Max: ", np.max(first_image_val))
num_classes = len(class_names)
print(num_classes)
model = Sequential([
layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Conv2D(128, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(128, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Conv2D(256, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(256, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Conv2D(512, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(512, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Flatten(),
layers.Dropout(0.5),
layers.Dense(1024, activation='relu'),
layers.BatchNormalization(),
layers.Dense(num_classes)
])
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
)
model.summary()
def learning_rate_schedule(epoch):
if epoch < 10:
return 0.001
else:
return 0.001 * tf.math.exp(0.1 * (10 - epoch))
lr_schedule_callback = tf.keras.callbacks.LearningRateScheduler(learning_rate_schedule)
epochs=100
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs,
callbacks=[early_stopping_callback, checkpoint_callback, lr_schedule_callback]
)
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(len(acc))
plt.figure(figsize=(20, 10))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
# Custom function for Random Erasing
def random_erasing(img):
p = 0.5 # Probability of applying Random Erasing
s_l = 0.02 # Minimum erasing area
s_h = 0.4 # Maximum erasing area
r_1 = 0.3 # Minimum aspect ratio of erasing area
mean = np.mean(img)
if np.random.rand() > p:
return img
h, w, _ = img.shape
s = h * w
while True:
se = np.random.uniform(s_l, s_h) * s
re = np.random.uniform(r_1, 1 / r_1)
he = int(np.sqrt(se * re))
we = int(np.sqrt(se / re))
xe = np.random.randint(0, w)
ye = np.random.randint(0, h)
if xe + we <= w and ye + he <= h:
img[ye:ye + he, xe:xe + we, :] = mean
return img
data_generator = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
brightness_range=[0.8, 1.2],
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
vertical_flip=True,
preprocessing_function=random_erasing
)
plt.figure(figsize=(10, 10))
for images, _ in train_ds.take(1):
for i in range(9):
augmented_images = next(data_generator.flow(images, shuffle=False))
ax = plt.subplot(3, 3, i + 1)
plt.imshow(augmented_images[0].astype("uint8"))
plt.axis("off")
plt.show()
augmented_train_ds = data_generator.flow(train_images, train_labels, batch_size=batch_size, shuffle=False)
augmented_train_images = np.concatenate([train_images, augmented_train_ds[0][0]])
augmented_train_labels = np.concatenate([train_labels, augmented_train_ds[0][1]])
print(augmented_train_images.shape)
print(augmented_train_labels.shape)
augmented_train_ds = tf.data.Dataset.from_tensor_slices((augmented_train_images, augmented_train_labels))
augmented_train_ds = augmented_train_ds.shuffle(buffer_size=10000).batch(batch_size)
num_classes = len(class_names)
print(num_classes)
model = Sequential([
layers.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
layers.Conv2D(128, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(128, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Conv2D(256, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(256, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Conv2D(512, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(512, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.Conv2D(1024, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.Conv2D(1024, 3, padding='same', activation='relu'),
layers.BatchNormalization(),
layers.MaxPooling2D(),
layers.GlobalAveragePooling2D(), # Change to Global Average Pooling
layers.Dropout(0.5), # Reduce the dropout rate to 0.5
layers.Dense(128, activation='relu'),
layers.BatchNormalization(), # Add Batch Normalization after Dense layer
layers.Dropout(0.5), # Add dropout after Dense layer
layers.Dense(num_classes, activation='softmax')
])
# Use a higher learning rate
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
model.compile(
optimizer=optimizer,
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy']
)
model.summary()
epochs = 200
# Define a custom learning rate schedule
def learning_rate_schedule(epoch):
initial_learning_rate = 0.1
decay_per_epoch = 0.99
lrate = initial_learning_rate * (decay_per_epoch ** epoch)
return lrate
lr_schedule_callback = tf.keras.callbacks.LearningRateScheduler(learning_rate_schedule)
history = model.fit(
augmented_train_ds,
validation_data=val_ds,
epochs=epochs,
callbacks=[early_stopping_callback, checkpoint_callback, lr_schedule_callback]
)
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(len(acc))
plt.figure(figsize=(15, 15))
plt.subplot(2, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(2, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
test_labels = []
for img in test_df['Image']:
img = preprocess_image(testimg_dir + '/' + img)
img = tf.keras.preprocessing.image.img_to_array(img)
img = tf.expand_dims(img, 0)
prediction = model.predict(img)
score = tf.nn.softmax(prediction[0])
print("This image most likely belongs to {} with a {:.2f} percent confidence."
.format(class_names[np.argmax(score)], 100 * np.max(score)))
test_labels.append(class_names[np.argmax(score)])
submission_df['Class'] = test_labels
submission_df.to_csv('gorkalarrucea.csv', index=False)