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
+94 -160
View File
@@ -7,183 +7,117 @@ import seaborn as sn
from PIL import ImageFile from PIL import ImageFile
from tensorflow import keras from tensorflow import keras
from model_builders import ImageClassModelBuilder, ImageClassModels
ImageFile.LOAD_TRUNCATED_IMAGES = True ImageFile.LOAD_TRUNCATED_IMAGES = True
input_shape = (224, 224, 3) input_shape = (224, 224, 3)
batch_size = 64 batch_size = 32
model_name = "TF2_Mobilenet_V2_transfer" model_name = f"mobilenetv2-dense1024-l1l2-25drop-{time()}"
# preproc = keras.applications.inception_v3.preprocess_input training_idg = keras.preprocessing.image.ImageDataGenerator(
preproc = keras.applications.mobilenet_v2.preprocess_input
train_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True, horizontal_flip=True,
rescale=1. / 255, rotation_range=30,
# rotation_range=30, width_shift_range=[-.1, .1],
# width_shift_range=[-.1, .1], height_shift_range=[-.1, .1],
# height_shift_range=[-.1, .1],
# preprocessing_function=preproc
) )
train_gen = train_idg.flow_from_directory( testing_idg = keras.preprocessing.image.ImageDataGenerator(
'./downloads',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
color_mode='rgb'
)
val_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True, 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( def get_gen(path, test_set=False):
# weights='imagenet', idg = testing_idg if test_set else training_idg
# include_top=False, return idg.flow_from_directory(
# input_shape=input_shape path,
# ) target_size=(input_shape[0], input_shape[1]),
# base_model = keras.applications.InceptionV3( batch_size=batch_size,
# weights='imagenet', class_mode='categorical',
# include_top=False, shuffle=True,
# input_shape=input_shape color_mode='rgb'
# ) )
# 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) 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
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,
histogram_freq=1,
write_graph=True,
write_images=True,
update_freq=1,
profile_batch=2,
embeddings_freq=1,
)
callbacks_list = [checkpoint, early, tensorboard]
model.compile(optimizer=keras.optimizers.Adam(learning_rate=.0001), history = model.fit(
loss=keras.losses.CategoricalCrossentropy(), train_gen,
metrics=['accuracy']) validation_data=val_gen,
epochs=100,
batch_size=batch_size,
shuffle=True,
verbose=True,
workers=12,
callbacks=callbacks_list,
max_queue_size=1000
)
print(history)
return model
model.summary()
print(model.output_shape)
# Train the model def test_model(model, test_gen):
file_path = "weights.mobilenet.best.hdf5" 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)
checkpoint = keras.callbacks.ModelCheckpoint(file_path, monitor='val_loss', verbose=1, save_best_only=True, # Process the predictions
mode='min') predicts = np.argmax(predicts,
axis=1)
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]
early = keras.callbacks.EarlyStopping(monitor="loss", mode="min", patience=15) # Save the results
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()
tensorboard = keras.callbacks.TensorBoard(
log_dir="logs/" + model_name + "{}".format(time()),
histogram_freq=1,
write_graph=True,
write_images=True,
update_freq=1,
profile_batch=2,
embeddings_freq=1
)
callbacks_list = [checkpoint, early, tensorboard] # early if __name__ == "__main__":
train_gen = get_gen('./data/train')
history = model.fit( val_gen = get_gen('./data/val')
train_gen, test_gen = get_gen('./data/test', test_set=True)
validation_data=val_gen, model = train_model(train_gen, val_gen)
epochs=20, test_model(model, test_gen)
batch_size=batch_size,
shuffle=True,
verbose=True,
callbacks=callbacks_list
)
# 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))
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()}
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()
+11 -11
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(predictions)
print(type(predicts)) print(type(predictions))
print(predicts.shape) print(predictions.shape)
# Process the predictions # Process the predictions
predicts = np.argmax(predicts, predictions = np.argmax(predictions,
axis=1) axis=1)
# test_gen.reset() # test_gen.reset()
label_index = {v: k for k, v in test_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] predictions = [label_index[p] for p in predictions]
reals = [label_index[p] for p in test_gen.classes] reals = [label_index[p] for p in test_gen.classes]
# Save the results # Save the results
@@ -51,15 +51,15 @@ print(test_gen.classes.shape)
print(type(test_gen.classes)) print(type(test_gen.classes))
df = pd.DataFrame(columns=['fname', 'prediction', 'true_val']) df = pd.DataFrame(columns=['fname', 'prediction', 'true_val'])
df['fname'] = [x for x in test_gen.filenames] df['fname'] = [x for x in test_gen.filenames]
df['prediction'] = predicts df['prediction'] = predictions
df["true_val"] = reals df["true_val"] = reals
df.to_csv("sub1_non_transfer.csv", index=False) df.to_csv("sub1_non_transfer.csv", index=False)
# Processed the saved results # Processed the saved results
acc = accuracy_score(reals, predicts) acc = accuracy_score(reals, predictions)
conf_mat = confusion_matrix(reals, predicts) conf_mat = confusion_matrix(reals, predictions)
print(classification_report(reals, predicts, labels=[l for l in label_index.values()])) print(classification_report(reals, predictions, labels=[l for l in label_index.values()]))
print("Testing accuracy score is ", acc) print("Testing accuracy score is ", acc)
print("Confusion Matrix", conf_mat) 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