|
|
|
|
|
import numpy as np
|
|
from tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array
|
|
from tensorflow.keras.applications import MobileNetV2
|
|
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
|
|
from tensorflow.keras.models import Model
|
|
from tensorflow.keras.layers import AveragePooling2D, Dropout, Flatten, Dense, Input
|
|
from tensorflow.keras.optimizers import Adam
|
|
from tensorflow.keras.utils import to_categorical
|
|
from tensorflow.keras.regularizers import l2
|
|
from tensorflow.keras.callbacks import EarlyStopping
|
|
from sklearn.model_selection import train_test_split
|
|
import os
|
|
from PIL import UnidentifiedImageError
|
|
import keras_tuner as kt
|
|
|
|
|
|
data_dir = "dataset"
|
|
categories = ["with_mask", "without_mask"]
|
|
data = []
|
|
labels = []
|
|
|
|
print("Loading and preprocessing images for tuning...")
|
|
for category in categories:
|
|
path = os.path.join(data_dir, category)
|
|
for img_name in os.listdir(path):
|
|
img_path = os.path.join(path, img_name)
|
|
try:
|
|
image = load_img(img_path, target_size=(224, 224))
|
|
image = img_to_array(image)
|
|
image = preprocess_input(image)
|
|
data.append(image)
|
|
labels.append(0 if category == "with_mask" else 1)
|
|
except UnidentifiedImageError:
|
|
print(f"Skipped invalid image file: {img_path}")
|
|
except Exception as e:
|
|
print(f"Error loading image {img_path}: {e}")
|
|
print(f"Loaded {len(data)} images.")
|
|
|
|
data = np.array(data, dtype="float32")
|
|
labels = to_categorical(labels)
|
|
|
|
x_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.2, stratify=labels, random_state=42)
|
|
print(f"Training samples: {len(x_train)}, Validation samples: {len(x_test)}")
|
|
|
|
|
|
aug = ImageDataGenerator(
|
|
rotation_range=30,
|
|
zoom_range=0.2,
|
|
width_shift_range=0.2,
|
|
height_shift_range=0.2,
|
|
shear_range=0.2,
|
|
horizontal_flip=True,
|
|
brightness_range=[0.7, 1.3],
|
|
channel_shift_range=50,
|
|
fill_mode="nearest"
|
|
)
|
|
|
|
|
|
def build_model(hp):
|
|
base_model = MobileNetV2(weights="imagenet", include_top=False, input_tensor=Input(shape=(224, 224, 3)))
|
|
|
|
for layer in base_model.layers[:-20]:
|
|
layer.trainable = False
|
|
|
|
head_model = base_model.output
|
|
head_model = AveragePooling2D(pool_size=(7, 7))(head_model)
|
|
head_model = Flatten()(head_model)
|
|
|
|
|
|
hp_units = hp.Int('units', min_value=64, max_value=256, step=32, default=128)
|
|
hp_l2_reg = hp.Choice('l2_regularizer', values=[1e-4, 1e-3, 1e-2], default=1e-2)
|
|
hp_dropout = hp.Float('dropout_rate', min_value=0.2, max_value=0.6, step=0.1, default=0.5)
|
|
hp_learning_rate = hp.Choice('learning_rate', values=[1e-5, 5e-5, 1e-4], default=1e-5)
|
|
|
|
head_model = Dense(units=hp_units, activation="relu", kernel_regularizer=l2(hp_l2_reg))(head_model)
|
|
head_model = Dropout(hp_dropout)(head_model)
|
|
head_model = Dense(2, activation="softmax")(head_model)
|
|
|
|
model = Model(inputs=base_model.input, outputs=head_model)
|
|
|
|
model.compile(optimizer=Adam(learning_rate=hp_learning_rate),
|
|
loss="categorical_crossentropy",
|
|
metrics=["accuracy"])
|
|
return model
|
|
|
|
|
|
tuner = kt.Hyperband(
|
|
build_model,
|
|
objective='val_accuracy',
|
|
max_epochs=30,
|
|
factor=3,
|
|
directory='keras_tuner_dir',
|
|
project_name='mask_detector_tuning_run'
|
|
)
|
|
|
|
|
|
early_stopping_tuner = EarlyStopping(
|
|
monitor='val_loss',
|
|
patience=7,
|
|
restore_best_weights=True
|
|
)
|
|
|
|
print("\nStarting hyperparameter search. This may take a while...")
|
|
tuner.search(aug.flow(x_train, y_train, batch_size=32),
|
|
validation_data=(x_test, y_test),
|
|
steps_per_epoch=len(x_train) // 32,
|
|
epochs=30,
|
|
callbacks=[early_stopping_tuner])
|
|
|
|
print("\nHyperparameter search complete.")
|
|
|
|
|
|
best_hps = tuner.get_best_hyperparameters(num_trials=1)[0]
|
|
|
|
print(f"\n==========================================")
|
|
print(f" Best Hyperparameters Found:")
|
|
print(f" ------------------------------------------")
|
|
print(f" Units in Dense layer: {best_hps.get('units')}")
|
|
print(f" L2 Regularizer strength: {best_hps.get('l2_regularizer')}")
|
|
print(f" Dropout Rate: {best_hps.get('dropout_rate')}")
|
|
print(f" Learning Rate: {best_hps.get('learning_rate')}")
|
|
print(f"==========================================\n")
|
|
|
|
print("Please take note of these hyperparameters and use them to define your model in 'model.py'.") |