Add convnext mode and weights.
This commit is contained in:
256
Models/model_sk_convnext_v1.py
Normal file
256
Models/model_sk_convnext_v1.py
Normal file
@@ -0,0 +1,256 @@
|
||||
import tensorflow as tf
|
||||
from tensorflow.keras import layers, models, regularizers
|
||||
from tensorflow.keras.optimizers import Adam
|
||||
from tensorflow.keras.callbacks import TensorBoard, ModelCheckpoint, EarlyStopping, ReduceLROnPlateau
|
||||
from tensorflow.keras.applications import ConvNeXtTiny
|
||||
from tensorflow.keras.applications.convnext import preprocess_input
|
||||
from time import time
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# This is the new 2026 version
|
||||
# This model was trained with 13,185 images
|
||||
# See CNNImageProcessor solution for create the test images for training this model
|
||||
|
||||
|
||||
|
||||
# Figure out if we are training in CPU or GPU
|
||||
print("GPUs:", tf.config.list_physical_devices('GPU'))
|
||||
# -----------------------
|
||||
# ConvNeXt-Tiny Base Model
|
||||
# -----------------------
|
||||
modelname='convnext_20260228_90.h5.keras'
|
||||
|
||||
# convneXt was pretrained with 224 but our image data is 128 so we upscale our images to match the 224 requirements of the model
|
||||
actualImageDimension=224
|
||||
convneXtImageDimension=224
|
||||
|
||||
# Tensorboard
|
||||
log_dir = f'logs/convnext_{int(time())}'
|
||||
tensorboard = TensorBoard(log_dir=log_dir)
|
||||
|
||||
# -----------------------
|
||||
# Configuration
|
||||
# -----------------------
|
||||
shuffle_count=3000
|
||||
dataset_path = 'C:\\boneyard\\DeepLearning\\data'
|
||||
image_size = (actualImageDimension, actualImageDimension)
|
||||
batch_size = 16 # try 16 was 32
|
||||
image_size=(actualImageDimension, actualImageDimension)
|
||||
|
||||
|
||||
# -----------------------
|
||||
# Dataset Loading
|
||||
# -----------------------
|
||||
|
||||
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
|
||||
dataset_path,
|
||||
label_mode="binary",
|
||||
subset="training",
|
||||
validation_split=0.2,
|
||||
image_size=image_size,
|
||||
color_mode='rgb', # IMPORTANT for grayscale datasets
|
||||
batch_size=batch_size,
|
||||
seed=50
|
||||
)
|
||||
|
||||
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
|
||||
dataset_path,
|
||||
label_mode="binary",
|
||||
subset="validation",
|
||||
validation_split=0.2,
|
||||
image_size=image_size,
|
||||
color_mode='rgb',
|
||||
batch_size=batch_size,
|
||||
seed=50
|
||||
)
|
||||
|
||||
# -----------------------
|
||||
# Data Augmentation
|
||||
# -----------------------
|
||||
|
||||
# data_augmentation = tf.keras.Sequential([
|
||||
# layers.RandomFlip("horizontal"),
|
||||
# layers.RandomRotation(0.1)
|
||||
# ])
|
||||
#data_augmentation = tf.keras.Sequential([
|
||||
# layers.RandomFlip("horizontal"),
|
||||
# layers.RandomRotation(0.1),
|
||||
# layers.RandomRotation(0.1, fill_mode="nearest"),
|
||||
# layers.RandomZoom(0.1)
|
||||
#])
|
||||
|
||||
|
||||
# def preprocess_train(x, y):
|
||||
# x = data_augmentation(x, training=True)
|
||||
# return x, y
|
||||
|
||||
def preprocess_val(x, y):
|
||||
return x, y
|
||||
|
||||
val_ds = (
|
||||
val_ds
|
||||
.prefetch(tf.data.AUTOTUNE)
|
||||
)
|
||||
|
||||
train_ds = (
|
||||
train_ds
|
||||
.shuffle(3000)
|
||||
.prefetch(tf.data.AUTOTUNE)
|
||||
)
|
||||
|
||||
|
||||
# for images, labels in train_ds.take(1):
|
||||
|
||||
# plt.figure(figsize=(10,10))
|
||||
|
||||
# for i in range(12):
|
||||
# ax = plt.subplot(3,4,i+1)
|
||||
# plt.imshow(images[i].numpy().astype("uint8"))
|
||||
# plt.title(int(labels[i].numpy()))
|
||||
# plt.axis("off")
|
||||
|
||||
# plt.tight_layout()
|
||||
# plt.show()
|
||||
|
||||
|
||||
|
||||
|
||||
# -----------------------
|
||||
# ConvNeXt-Tiny Base Model
|
||||
# -----------------------
|
||||
|
||||
base_model = ConvNeXtTiny(
|
||||
weights='imagenet',
|
||||
include_top=False,
|
||||
input_shape=(convneXtImageDimension, convneXtImageDimension, 3)
|
||||
)
|
||||
|
||||
base_model.trainable = False # Freeze for initial training
|
||||
|
||||
# -----------------------
|
||||
# Build Full Model (Preprocessing Inside Model)
|
||||
# -----------------------
|
||||
inputs = tf.keras.Input(shape=(actualImageDimension, actualImageDimension, 3))
|
||||
|
||||
|
||||
|
||||
x = preprocess_input(inputs)
|
||||
x = base_model(x)
|
||||
# Dense Head
|
||||
# x = layers.GlobalAveragePooling2D()(x)
|
||||
# x = layers.BatchNormalization()(x)
|
||||
# x = layers.Dense(512, activation="relu")(x)
|
||||
# x = layers.Dropout(0.3)(x)
|
||||
# x = layers.Dense(128, activation="relu")(x)
|
||||
|
||||
x = layers.GlobalAveragePooling2D()(x)
|
||||
x = layers.BatchNormalization()(x)
|
||||
x = layers.Dense(256, activation="relu")(x)
|
||||
x = layers.Dropout(0.4)(x)
|
||||
|
||||
# End Dense Head
|
||||
outputs = layers.Dense(1, activation="sigmoid")(x)
|
||||
model = tf.keras.Model(inputs, outputs)
|
||||
|
||||
|
||||
model.compile(
|
||||
optimizer=Adam(learning_rate=1e-4),
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy']
|
||||
)
|
||||
|
||||
model.summary()
|
||||
|
||||
# -----------------------
|
||||
# Callbacks
|
||||
# -----------------------
|
||||
|
||||
|
||||
early_stopping = EarlyStopping(
|
||||
monitor='val_loss',
|
||||
patience=15,
|
||||
restore_best_weights=True,
|
||||
verbose=1
|
||||
)
|
||||
|
||||
checkpointer = ModelCheckpoint(
|
||||
filepath=modelname,
|
||||
monitor='val_accuracy',
|
||||
save_best_only=True,
|
||||
verbose=1
|
||||
)
|
||||
|
||||
lr_scheduler = ReduceLROnPlateau(
|
||||
monitor='val_loss',
|
||||
factor=0.5,
|
||||
patience=5,
|
||||
min_lr=1e-6,
|
||||
verbose=1
|
||||
)
|
||||
|
||||
# -----------------------
|
||||
# Initial Training
|
||||
# -----------------------
|
||||
|
||||
history = model.fit(
|
||||
train_ds,
|
||||
epochs=50,
|
||||
validation_data=val_ds,
|
||||
callbacks=[tensorboard, lr_scheduler, early_stopping, checkpointer]
|
||||
)
|
||||
|
||||
# -----------------------
|
||||
# Fine-Tuning
|
||||
# -----------------------
|
||||
|
||||
base_model.trainable = True
|
||||
|
||||
# Freeze early layers (recommended)
|
||||
for layer in base_model.layers[:-40]:
|
||||
layer.trainable = False
|
||||
|
||||
model.compile(
|
||||
optimizer=Adam(1e-5),
|
||||
loss='binary_crossentropy',
|
||||
metrics=['accuracy']
|
||||
)
|
||||
|
||||
history_fine = model.fit(
|
||||
train_ds,
|
||||
epochs=50,
|
||||
validation_data=val_ds,
|
||||
callbacks=[tensorboard, lr_scheduler, early_stopping, checkpointer]
|
||||
)
|
||||
|
||||
|
||||
# -----------------------
|
||||
# Plot Results
|
||||
# -----------------------
|
||||
|
||||
def plot_history(hist, title_prefix=""):
|
||||
plt.figure()
|
||||
plt.plot(hist.history['accuracy'], label='Train Accuracy')
|
||||
plt.plot(hist.history['val_accuracy'], label='Val Accuracy')
|
||||
plt.title(f'{title_prefix} Accuracy')
|
||||
plt.xlabel('Epochs')
|
||||
plt.ylabel('Accuracy')
|
||||
plt.legend()
|
||||
plt.show()
|
||||
|
||||
plt.figure()
|
||||
plt.plot(hist.history['loss'], label='Train Loss')
|
||||
plt.plot(hist.history['val_loss'], label='Val Loss')
|
||||
plt.title(f'{title_prefix} Loss')
|
||||
plt.xlabel('Epochs')
|
||||
plt.ylabel('Loss')
|
||||
plt.legend()
|
||||
plt.show()
|
||||
|
||||
plot_history(history, "Initial Training")
|
||||
plot_history(history_fine, "Fine-Tuning")
|
||||
|
||||
# -----------------------
|
||||
# Save Final Model
|
||||
# -----------------------
|
||||
|
||||
#model.save(modelname)
|
||||
Reference in New Issue
Block a user