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:
+94
-160
@@ -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
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
from .image_class_builder import ImageClassModelBuilder, ImageClassModels
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user