creating model builder for faster model tweaking and iteration. Increased threads for training to better feed the GPU images from the image generator.

This commit is contained in:
Lucas
2022-05-25 19:47:30 -04:00
parent 5990351a47
commit 616c99c7f5
12 changed files with 189 additions and 171 deletions
+51 -117
View File
@@ -7,26 +7,30 @@ import seaborn as sn
from PIL import ImageFile
from tensorflow import keras
from model_builders import ImageClassModelBuilder, ImageClassModels
ImageFile.LOAD_TRUNCATED_IMAGES = True
input_shape = (224, 224, 3)
batch_size = 64
model_name = "TF2_Mobilenet_V2_transfer"
batch_size = 32
model_name = f"mobilenetv2-dense1024-l1l2-25drop-{time()}"
# preproc = keras.applications.inception_v3.preprocess_input
preproc = keras.applications.mobilenet_v2.preprocess_input
train_idg = keras.preprocessing.image.ImageDataGenerator(
training_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
rescale=1. / 255,
# rotation_range=30,
# width_shift_range=[-.1, .1],
# height_shift_range=[-.1, .1],
# preprocessing_function=preproc
rotation_range=30,
width_shift_range=[-.1, .1],
height_shift_range=[-.1, .1],
)
train_gen = train_idg.flow_from_directory(
'./downloads',
testing_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
)
def get_gen(path, test_set=False):
idg = testing_idg if test_set else training_idg
return idg.flow_from_directory(
path,
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
class_mode='categorical',
@@ -34,156 +38,86 @@ train_gen = train_idg.flow_from_directory(
color_mode='rgb'
)
val_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
rescale=1. / 255,
# rotation_range=30,
# width_shift_range=[-.1, .1],
# height_shift_range=[-.1, .1],
# preprocessing_function=keras.applications.mobilenet_v2.preprocess_input
)
val_gen = val_idg.flow_from_directory(
'./data/val',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
)
print((val_gen.classes))
nclass = len(train_gen.class_indices)
print(nclass)
# for _ in range(5):
# img, label = train_gen.next()
# print(img.shape) # (1,256,256,3)
# plt.imshow(img[0])
# plt.show()
# plt.imshow(
# base_model = vgg16.VGG16(
# weights='imagenet',
# include_top=False,
# input_shape=input_shape
# )
# base_model = keras.applications.InceptionV3(
# weights='imagenet',
# include_top=False,
# input_shape=input_shape
# )
# base_model = keras.applications.xception.Xception(
# weights='imagenet',
# include_top=False,
# input_shape=input_shape
# )
base_model = keras.applications.mobilenet_v2.MobileNetV2(
weights='imagenet',
include_top=False,
input_shape=input_shape
)
base_model.trainable = False
# i = keras.layers.Input([input_shape[0], input_shape[1], input_shape[2]])
i = base_model.input
# x = preproc(i)
# x = base_model
x = keras.layers.GlobalAveragePooling2D()(base_model.output)
x = keras.layers.Dense(1024, activation='relu')(x)
x = keras.layers.Dropout(0.5)(x)
output = keras.layers.Dense(nclass, activation='softmax')(x)
model = keras.Model(inputs=i, outputs=output)
model.compile(optimizer=keras.optimizers.Adam(learning_rate=.0001),
loss=keras.losses.CategoricalCrossentropy(),
metrics=['accuracy'])
model.summary()
print(model.output_shape)
def train_model(train_gen, val_gen):
model = ImageClassModelBuilder(
input_shape=input_shape,
n_classes=807,
optimizer=keras.optimizers.Adam(learning_rate=.0001),
pre_trained=True,
fine_tune=0,
base_model=ImageClassModels.MOBILENET_V2
).create_model()
# Train the model
file_path = "weights.mobilenet.best.hdf5"
checkpoint = keras.callbacks.ModelCheckpoint(file_path, monitor='val_loss', verbose=1, save_best_only=True,
checkpoint = keras.callbacks.ModelCheckpoint(f"./Models/keras/{model_name}.hdf5", monitor='val_loss', verbose=1,
save_best_only=True,
mode='min')
early = keras.callbacks.EarlyStopping(monitor="loss", mode="min", patience=15)
tensorboard = keras.callbacks.TensorBoard(
log_dir="logs/" + model_name + "{}".format(time()),
log_dir="logs/" + model_name,
histogram_freq=1,
write_graph=True,
write_images=True,
update_freq=1,
profile_batch=2,
embeddings_freq=1
embeddings_freq=1,
)
callbacks_list = [checkpoint, early, tensorboard] # early
callbacks_list = [checkpoint, early, tensorboard]
history = model.fit(
train_gen,
validation_data=val_gen,
epochs=20,
epochs=100,
batch_size=batch_size,
shuffle=True,
verbose=True,
callbacks=callbacks_list
workers=12,
callbacks=callbacks_list,
max_queue_size=1000
)
print(history)
return model
# Create Test generator
test_idg = keras.preprocessing.image.ImageDataGenerator(
rescale=1. / 255,
)
test_gen = test_idg.flow_from_directory(
'./data/test',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
shuffle=False
)
len(test_gen.filenames)
score = model.evaluate_generator(test_gen, workers=1, steps=len(test_gen))
# predicts
predicts = model.predict_generator(test_gen, verbose=True, workers=1, steps=len(test_gen))
def test_model(model, test_gen):
print(len(test_gen.filenames))
score = model.evaluate(test_gen, workers=8, steps=len(test_gen))
predicts = model.predict(test_gen, verbose=True, workers=8, steps=len(test_gen))
print("Loss: ", score[0], "Accuracy: ", score[1])
print(score)
print(predicts)
print(type(predicts))
print(predicts.shape)
# Process the predictions
predicts = np.argmax(predicts,
axis=1)
# test_gen.reset()
label_index = {v: k for k, v in train_gen.class_indices.items()}
label_index = {v: k for k, v in test_gen.class_indices.items()}
predicts = [label_index[p] for p in predicts]
reals = [label_index[p] for p in test_gen.classes]
# Save the results
print(label_index)
print(test_gen.classes)
print(test_gen.classes.shape)
print(type(test_gen.classes))
df = pd.DataFrame(columns=['fname', 'prediction', 'true_val'])
df['fname'] = [x for x in test_gen.filenames]
df['prediction'] = predicts
df["true_val"] = reals
df.to_csv("sub1.csv", index=False)
# Processed the saved results
from sklearn.metrics import accuracy_score, confusion_matrix
acc = accuracy_score(reals, predicts)
conf_mat = confusion_matrix(reals, predicts)
print("Testing accuracy score is ", acc)
print("Confusion Matrix", conf_mat)
df_cm = pd.DataFrame(conf_mat, index=[i for i in list(set(reals))],
columns=[i for i in list(set(reals))])
plt.figure(figsize=(10, 7))
sn.heatmap(df_cm, annot=True)
plt.show()
if __name__ == "__main__":
train_gen = get_gen('./data/train')
val_gen = get_gen('./data/val')
test_gen = get_gen('./data/test', test_set=True)
model = train_model(train_gen, val_gen)
test_model(model, test_gen)
+10 -10
View File
@@ -31,17 +31,17 @@ test_gen = test_idg.flow_from_directory(
)
predicts = model.predict_generator(test_gen, verbose=True, workers=1, steps=len(test_gen))
predictions = model.predict_generator(test_gen, verbose=True, workers=1, steps=len(test_gen))
print(predicts)
print(type(predicts))
print(predicts.shape)
print(predictions)
print(type(predictions))
print(predictions.shape)
# Process the predictions
predicts = np.argmax(predicts,
predictions = np.argmax(predictions,
axis=1)
# test_gen.reset()
label_index = {v: k for k, v in test_gen.class_indices.items()}
predicts = [label_index[p] for p in predicts]
predictions = [label_index[p] for p in predictions]
reals = [label_index[p] for p in test_gen.classes]
# Save the results
@@ -51,15 +51,15 @@ print(test_gen.classes.shape)
print(type(test_gen.classes))
df = pd.DataFrame(columns=['fname', 'prediction', 'true_val'])
df['fname'] = [x for x in test_gen.filenames]
df['prediction'] = predicts
df['prediction'] = predictions
df["true_val"] = reals
df.to_csv("sub1_non_transfer.csv", index=False)
# Processed the saved results
acc = accuracy_score(reals, predicts)
conf_mat = confusion_matrix(reals, predicts)
print(classification_report(reals, predicts, labels=[l for l in label_index.values()]))
acc = accuracy_score(reals, predictions)
conf_mat = confusion_matrix(reals, predictions)
print(classification_report(reals, predictions, labels=[l for l in label_index.values()]))
print("Testing accuracy score is ", acc)
print("Confusion Matrix", conf_mat)
+1
View File
@@ -0,0 +1 @@
from .image_class_builder import ImageClassModelBuilder, ImageClassModels
+76
View File
@@ -0,0 +1,76 @@
from enum import Enum
from typing import Tuple
import tensorflow as tf
from tensorflow import keras
from .modelwrapper import ModelWrapper
class ImageClassModels(Enum):
INCEPTION_V3 = ModelWrapper(
keras.applications.InceptionV3,
keras.applications.inception_v3.preprocess_input
)
XCEPTION = ModelWrapper(
keras.applications.xception.Xception,
keras.applications.inception_v3.preprocess_input
)
MOBILENET_V2 = ModelWrapper(
keras.applications.mobilenet_v2.MobileNetV2,
keras.applications.mobilenet_v2.preprocess_input
)
class ImageClassModelBuilder(object):
def __init__(self,
input_shape: Tuple[int, int, int],
n_classes: int,
optimizer: tf.keras.optimizers.Optimizer = keras.optimizers.Adam(
learning_rate=.0001),
pre_trained: bool = True,
fine_tune: int = 0,
base_model: ImageClassModels = ImageClassModels.MOBILENET_V2):
self.input_shape = input_shape
self.n_classes = n_classes
self.optimizer = optimizer
self.pre_trained = pre_trained
self.fine_tune = fine_tune
self.base_model = base_model
def set_base_model(self, base_model: ImageClassModels):
self.base_model = base_model
def create_model(self):
base_model = self.base_model.value.model_func(
weights='imagenet' if self.pre_trained else None,
include_top=False
)
if self.pre_trained:
if self.fine_tune > 0:
for layer in base_model.layers[:-self.fine_tune]:
layer.trainable = False
else:
for layer in base_model.layers:
layer.trainable = False
i = tf.keras.layers.Input([self.input_shape[0], self.input_shape[1], self.input_shape[2]], dtype=tf.float32)
x = tf.cast(i, tf.float32)
x = self.base_model.value.model_preprocessor(x)
x = base_model(x)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(1024, activation='relu', kernel_regularizer=keras.regularizers.L1L2(l1=1e-5, l2=1e-5))(x)
x = keras.layers.Dropout(0.25)(x)
output = keras.layers.Dense(self.n_classes, activation='softmax')(x)
model = keras.Model(inputs=i, outputs=output)
model.compile(optimizer=self.optimizer,
loss=keras.losses.CategoricalCrossentropy(),
metrics=[
'accuracy',
# 'mse'
])
model.summary()
return model
+7
View File
@@ -0,0 +1,7 @@
from collections import Callable
class ModelWrapper(object):
def __init__(self, model_func:Callable, model_preprocessor:Callable):
self.model_func = model_func
self.model_preprocessor = model_preprocessor