|
import os
|
|
import shutil
|
|
import random
|
|
import numpy as np
|
|
import json
|
|
from sklearn.model_selection import train_test_split
|
|
import tensorflow as tf
|
|
from tensorflow.keras.preprocessing.image import ImageDataGenerator
|
|
|
|
SOURCE_DIR = r"E:\Dog_Breed_Classification_model\dataset"
|
|
TARGET_DIR = r"E:\Dog_Breed_Classification_model\dataset_split"
|
|
IMG_SIZE = (224, 224)
|
|
BATCH_SIZE = 16
|
|
EPOCHS = 20
|
|
SEED = 42
|
|
|
|
def split_dataset():
|
|
random.seed(SEED)
|
|
for split in ['train', 'val']:
|
|
os.makedirs(os.path.join(TARGET_DIR, split), exist_ok=True)
|
|
|
|
for breed in os.listdir(SOURCE_DIR):
|
|
class_path = os.path.join(SOURCE_DIR, breed)
|
|
if not os.path.isdir(class_path):
|
|
continue
|
|
images = [img for img in os.listdir(class_path) if img.lower().endswith(('.jpg', '.jpeg', '.png'))]
|
|
train_imgs, val_imgs = train_test_split(images, test_size=0.2, random_state=SEED)
|
|
|
|
for split, img_list in zip(['train', 'val'], [train_imgs, val_imgs]):
|
|
split_dir = os.path.join(TARGET_DIR, split, breed)
|
|
os.makedirs(split_dir, exist_ok=True)
|
|
for img in img_list:
|
|
shutil.copy2(os.path.join(class_path, img), os.path.join(split_dir, img))
|
|
|
|
def create_generators():
|
|
train_gen = ImageDataGenerator(rescale=1./255, rotation_range=15, width_shift_range=0.1,
|
|
height_shift_range=0.1, horizontal_flip=True)
|
|
val_gen = ImageDataGenerator(rescale=1./255)
|
|
|
|
train_data = train_gen.flow_from_directory(os.path.join(TARGET_DIR, 'train'),
|
|
target_size=IMG_SIZE, batch_size=BATCH_SIZE,
|
|
class_mode='categorical')
|
|
|
|
val_data = val_gen.flow_from_directory(os.path.join(TARGET_DIR, 'val'),
|
|
target_size=IMG_SIZE, batch_size=BATCH_SIZE,
|
|
class_mode='categorical')
|
|
return train_data, val_data
|
|
|
|
def build_model(num_classes):
|
|
base_model = tf.keras.applications.MobileNetV2(input_shape=(*IMG_SIZE, 3), include_top=False, weights='imagenet')
|
|
base_model.trainable = False
|
|
model = tf.keras.Sequential([
|
|
base_model,
|
|
tf.keras.layers.GlobalAveragePooling2D(),
|
|
tf.keras.layers.Dense(128, activation='relu'),
|
|
tf.keras.layers.Dropout(0.3),
|
|
tf.keras.layers.Dense(num_classes, activation='softmax')
|
|
])
|
|
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
|
|
return model
|
|
|
|
def save_model(model, class_indices):
|
|
model.save("dog_breed_classifier.h5")
|
|
with open("class_indices.json", "w") as f:
|
|
json.dump(class_indices, f)
|
|
|
|
if __name__ == "__main__":
|
|
split_dataset()
|
|
train_data, val_data = create_generators()
|
|
model = build_model(num_classes=len(train_data.class_indices))
|
|
model.fit(train_data, validation_data=val_data, epochs=EPOCHS)
|
|
save_model(model, train_data.class_indices) |