itzbhav's picture
Upload 8 files
3fde58f verified
# ------------------------------------------------------
# 1. Import Libraries
# ------------------------------------------------------
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import cv2
import tensorflow as tf
from sklearn.model_selection import train_test_split
from keras.preprocessing.image import ImageDataGenerator
from keras.utils import to_categorical
from keras.applications import MobileNetV2
from keras.layers import Dense, GlobalAveragePooling2D, Dropout
from keras.models import Model, load_model
from keras.preprocessing import image
from keras.applications.mobilenet_v2 import preprocess_input
from keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint
# ------------------------------------------------------
# 2. Load Dataset
# ------------------------------------------------------
data_dir = 'dataset' # <-- Replace with your dataset folder
categories = os.listdir(data_dir)
data = []
for category in categories:
category_path = os.path.join(data_dir, category)
for img_name in os.listdir(category_path):
img_path = os.path.join(category_path, img_name)
data.append((img_path, category))
data = pd.DataFrame(data, columns=['Filepath', 'Label'])
print(f"Total samples: {len(data)}")
print(data.head())
# ------------------------------------------------------
# 3. Exploratory Data Analysis (EDA)
# ------------------------------------------------------
# Class distribution
plt.figure(figsize=(8,6))
sns.countplot(x='Label', data=data)
plt.title('Blood Group Class Distribution')
plt.xticks(rotation=45)
plt.show()
# Display few images
plt.figure(figsize=(12,8))
for i in range(9):
sample = data.sample(n=1).iloc[0]
img = cv2.imread(sample['Filepath'])
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.subplot(3,3,i+1)
plt.imshow(img)
plt.title(sample['Label'])
plt.axis('off')
plt.tight_layout()
plt.show()
# ------------------------------------------------------
# 4. Train-Validation-Test Split
# ------------------------------------------------------
train, temp = train_test_split(data, test_size=0.3, random_state=42, stratify=data['Label'])
valid, test = train_test_split(temp, test_size=0.5, random_state=42, stratify=temp['Label'])
print(f"Training samples: {len(train)}")
print(f"Validation samples: {len(valid)}")
print(f"Testing samples: {len(test)}")
# ------------------------------------------------------
# 5. Preprocessing (Image Augmentation + Scaling)
# ------------------------------------------------------
train_datagen = ImageDataGenerator(
preprocessing_function=preprocess_input,
rotation_range=20,
zoom_range=0.2,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
horizontal_flip=True
)
valid_datagen = ImageDataGenerator(preprocessing_function=preprocess_input)
target_size = (224, 224)
train_gen = train_datagen.flow_from_dataframe(
dataframe=train,
x_col='Filepath',
y_col='Label',
target_size=target_size,
class_mode='categorical',
batch_size=32,
shuffle=True,
seed=42
)
valid_gen = valid_datagen.flow_from_dataframe(
dataframe=valid,
x_col='Filepath',
y_col='Label',
target_size=target_size,
class_mode='categorical',
batch_size=32,
shuffle=False
)
# ------------------------------------------------------
# 6. Load MobileNetV2 Base Model
# ------------------------------------------------------
base_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224,224,3))
# ------------------------------------------------------
# 7. Freeze Base Layers
# ------------------------------------------------------
for layer in base_model.layers:
layer.trainable = False
# ------------------------------------------------------
# 8. Define Function to Build Model (for tuning)
# ------------------------------------------------------
def build_model(dropout_rate=0.3, learning_rate=0.001):
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dropout(dropout_rate)(x)
x = Dense(128, activation='relu')(x)
x = Dropout(dropout_rate)(x)
predictions = Dense(len(categories), activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
return model
# ------------------------------------------------------
# 9. Hyperparameter Tuning (Manual)
# ------------------------------------------------------
dropout_rates = [0.3, 0.4]
learning_rates = [0.001, 0.0005]
best_val_accuracy = 0
best_model = None
best_params = {}
for dr in dropout_rates:
for lr in learning_rates:
print(f"\nTraining with Dropout: {dr}, Learning Rate: {lr}")
model = build_model(dropout_rate=dr, learning_rate=lr)
callbacks = [
EarlyStopping(monitor='val_accuracy', patience=5, restore_best_weights=True),
ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, verbose=1),
ModelCheckpoint('best_model.h5', monitor='val_accuracy', save_best_only=True, verbose=1)
]
history = model.fit(
train_gen,
validation_data=valid_gen,
epochs=20,
callbacks=callbacks,
verbose=1
)
val_acc = max(history.history['val_accuracy'])
print(f"Validation Accuracy: {val_acc:.4f}")
if val_acc > best_val_accuracy:
best_val_accuracy = val_acc
best_model = model
best_params = {'dropout_rate': dr, 'learning_rate': lr}
print("\nBest Parameters:", best_params)
print(f"Best Validation Accuracy: {best_val_accuracy:.4f}")
# ------------------------------------------------------
# 10. Fine-tuning (Unfreeze some base layers)
# ------------------------------------------------------
# Unfreeze last 30 layers for fine-tuning
for layer in base_model.layers[-30:]:
layer.trainable = True
# Recompile
optimizer = tf.keras.optimizers.Adam(learning_rate=best_params['learning_rate'] / 10)
best_model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
# Train again
history_finetune = best_model.fit(
train_gen,
validation_data=valid_gen,
epochs=10,
callbacks=[
EarlyStopping(monitor='val_accuracy', patience=5, restore_best_weights=True),
ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, verbose=1)
],
verbose=1
)
# ------------------------------------------------------
# 11. Save the Final Model
# ------------------------------------------------------
best_model.save('bloodgroup_mobilenet_finetuned.h5')
print("Fine-tuned model saved as bloodgroup_mobilenet_finetuned.h5")
# ------------------------------------------------------
# 12. Evaluate the Final Model
# ------------------------------------------------------
# Accuracy and Loss plots
plt.figure(figsize=(14,5))
plt.subplot(1,2,1)
plt.plot(history_finetune.history['accuracy'], label='Fine-tuned Train Accuracy')
plt.plot(history_finetune.history['val_accuracy'], label='Fine-tuned Validation Accuracy')
plt.title('Fine-tuned Model Accuracy')
plt.legend()
plt.subplot(1,2,2)
plt.plot(history_finetune.history['loss'], label='Fine-tuned Train Loss')
plt.plot(history_finetune.history['val_loss'], label='Fine-tuned Validation Loss')
plt.title('Fine-tuned Model Loss')
plt.legend()
plt.show()
# ------------------------------------------------------
# 13. Prediction on Single Image (User Input)
# ------------------------------------------------------
# Load the fine-tuned model
model = load_model('bloodgroup_mobilenet_finetuned.h5')
# Define the class labels
labels = {'A+': 0, 'A-': 1, 'AB+': 2, 'AB-': 3, 'B+': 4, 'B-': 5, 'O+': 6, 'O-': 7}
labels = dict((v, k) for k, v in labels.items())
# Example: Single image prediction
img_path = 'dataset/AB+/augmented_cluster_4_4.BMP'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
result = model.predict(x)
predicted_class = np.argmax(result)
predicted_label = labels[predicted_class]
confidence = result[0][predicted_class] * 100
plt.imshow(image.array_to_img(image.img_to_array(img)/255.0))
plt.axis('off')
plt.title(f"Prediction: {predicted_label} with confidence {confidence:.2f}%")
plt.show()