Compare commits

...

11 Commits

Author SHA1 Message Date
Lucas Oskorep 0d20122815 Add new file 2024-03-31 18:12:02 +00:00
Lucas Oskorep dc427837f6 feat: adding resnet and formatting updates 2023-04-06 00:37:59 -04:00
Lucas Oskorep ce5939d8a9 Update .gitlab-ci.yml file 2022-07-09 19:07:02 +00:00
Lucas Oskorep f70690efa8 merging to change repository base 2022-06-07 19:33:40 -04:00
Lucas 01703639ac adding todo 2022-06-03 15:59:18 -04:00
Lucas 6add80bd27 Removing unused import 2022-06-03 13:55:06 -04:00
Lucas d111cdae69 Updates to all parts of model building - moving to frozen transfer learning followed by slowed learning rate fine tuning using EfficientNets for final model. 2022-06-03 13:44:34 -04:00
Lucas 755fcde3a9 clean up imports. fix naming, force CPU to fill the cache faster with images using 20 workers. 2022-06-01 18:52:55 -04:00
Lucas 1b539d6945 renaming all files - moving training to be a single file for transfer vs not transfer learning. Made the testing file test all models. Needs to be updated to only update with new models. 2022-06-01 17:46:55 -04:00
Lucas ab0b7a0a4a Merge remote-tracking branch 'origin/master'
# Conflicts:
#	1 - ImageGatherer.py
#	3 - TestTrainSplit.py
#	4 - TransferLearningKeras.py
2022-05-25 19:59:11 -04:00
Lucas Oskorep 1dc7c2dee2 Updates....updates everywhere 2019-07-17 12:30:16 -05:00
967 changed files with 534 additions and 1438 deletions
+45
View File
@@ -0,0 +1,45 @@
# This file is a template, and might need editing before it works on your project.
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml
# This is a sample GitLab CI/CD configuration file that should run without any modifications.
# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts,
# it uses echo commands to simulate the pipeline execution.
#
# A pipeline is composed of independent jobs that run scripts, grouped into stages.
# Stages run in sequential order, but jobs within stages run in parallel.
#
# For more information, see: https://docs.gitlab.com/ee/ci/yaml/index.html#stages
stages: # List of stages for jobs, and their order of execution
- build
- test
- deploy
build-job: # This job runs in the build stage, which runs first.
stage: build
script:
- echo "Compiling the code..."
- echo "Compile complete."
unit-test-job: # This job runs in the test stage.
stage: test # It only starts when the job in the build stage completes successfully.
script:
- echo "Running unit tests... This will take about 60 seconds."
- sleep 60
- echo "Code coverage is 90%"
lint-test-job: # This job also runs in the test stage.
stage: test # It can run at the same time as unit-test-job (in parallel).
script:
- echo "Linting code... This will take about 10 seconds."
- sleep 10
- echo "No lint issues found."
deploy-job: # This job runs in the deploy stage.
stage: deploy # It only runs when *both* jobs in the test stage complete successfully.
script:
- echo "Deploying application..."
- echo "Application successfully deployed."
+17 -10
View File
@@ -5,6 +5,9 @@ import json
from pprint import pprint from pprint import pprint
from google_images_download import google_images_download from google_images_download import google_images_download
total_per = 10
form_increment = 1
def create_forms_dict(df): def create_forms_dict(df):
poke_dict = {} poke_dict = {}
@@ -39,22 +42,26 @@ def process_pokemon_names(df):
pprint(poke_dict) pprint(poke_dict)
pokes_to_limits = [] pokes_to_limits = []
for pokemon, form_list in poke_dict.items(): for pokemon, form_list in poke_dict.items():
if len(form_list) == 0:
print(pokemon) print(pokemon)
pokes_to_limits.append((pokemon, 200)) num_forms = len(form_list)
if num_forms == 0:
pokes_to_limits.append((pokemon, total_per))
elif len(form_list) == 1: elif num_forms == 1:
pokes_to_limits.append((pokemon, 150)) pokes_to_limits.append((pokemon, total_per - form_increment))
pokes_to_limits.append((search_term(form_list[0]), 50)) pokes_to_limits.append((search_term(form_list[0]), form_increment))
elif len(form_list) == 2: elif num_forms == 2:
pokes_to_limits.append((pokemon, 100)) pokes_to_limits.append((pokemon, total_per - form_increment * num_forms))
for form in form_list: for form in form_list:
pokes_to_limits.append((search_term(form), 50)) pokes_to_limits.append((search_term(form), form_increment))
elif len(form_list) >= 3: elif num_forms >= 3:
revised_increment = int(total_per / len(form_list))
for form in form_list: for form in form_list:
pokes_to_limits.append((search_term(form), int(200 / len(form_list)))) pokes_to_limits.append((pokemon, total_per - revised_increment * num_forms))
pokes_to_limits.append((search_term(form), revised_increment))
return pokes_to_limits return pokes_to_limits
-2
View File
@@ -7,9 +7,7 @@ import multiprocessing
import json import json
import shutil import shutil
from pathlib import Path
from PIL import Image from PIL import Image
from pprint import pprint
from random import randint from random import randint
from threading import Lock from threading import Lock
@@ -1,12 +1,13 @@
import os import os
from random import random from random import random
from shutil import copyfile, rmtree from shutil import rmtree
from pathlib import Path from pathlib import Path
import multiprocessing import multiprocessing
train_dir = "./data/train/" train_dir = "./data/train/"
test_dir = "./data/test/" test_dir = "./data/test/"
val_dir = "./data/val/" val_dir = "./data/val/"
train = .80 train = .80
test = .10 test = .10
val = .10 val = .10
-189
View File
@@ -1,189 +0,0 @@
import keras
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sn
from keras import optimizers
from keras.applications import inception_v3, mobilenet_v2, vgg16
from keras.applications.inception_v3 import preprocess_input
from keras.callbacks import ModelCheckpoint, EarlyStopping, TensorBoard
from keras.layers import Dense, Dropout, GlobalAveragePooling2D
from keras.models import Sequential
from keras.preprocessing.image import ImageDataGenerator
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from time import time
from PIL import ImageFile
# First we some globals that we want to use for this entire process
ImageFile.LOAD_TRUNCATED_IMAGES = True
input_shape = (224, 224, 3)
batch_size = 96
model_name = "mobilenet-fixed-data"
# Next we set up the Image Data Generators to feed into the training cycles.
# We need one for training, validation, and testing
train_idg = ImageDataGenerator(
horizontal_flip=True,
rotation_range=30,
width_shift_range=[-.1, .1],
height_shift_range=[-.1, .1],
preprocessing_function=preprocess_input
)
train_gen = train_idg.flow_from_directory(
'./data/train',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size
)
print(len(train_gen.classes))
val_idg = ImageDataGenerator(
horizontal_flip=True,
rotation_range=30,
width_shift_range=[-.1, .1],
height_shift_range=[-.1, .1],
preprocessing_function=preprocess_input
)
val_gen = val_idg.flow_from_directory(
'./data/val',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size
)
test_idg = ImageDataGenerator(
preprocessing_function=preprocess_input,
)
test_gen = test_idg.flow_from_directory(
'./data/test',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
shuffle=False
)
# Now we define the model we are going to use....to use something differnet just comment it out or add it here
# base_model = vgg16.VGG16(
# weights='imagenet',
# include_top=False,
# input_shape=input_shape
# )
# base_model = inception_v3.InceptionV3(
# weights='imagenet',
# include_top=False,
# input_shape=input_shape
# )
base_model = mobilenet_v2.MobileNetV2(
# weights='imagenet',
include_top=False,
input_shape=input_shape
)
# Create a new top for that model
add_model = Sequential()
add_model.add(base_model)
add_model.add(GlobalAveragePooling2D())
# add_model.add(Dense(4048, activation='relu'))
# add_model.add(Dropout(0.5))
add_model.add(Dense(2024, activation='relu'))
# Adding some dense layers in order to learn complex functions from the base model
add_model.add(Dropout(0.5))
add_model.add(Dense(512, activation='relu'))
add_model.add(Dense(len(train_gen.class_indices), activation='softmax')) # Decision layer
model = add_model
model.compile(loss='categorical_crossentropy',
# optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
optimizer=optimizers.Adam(lr=1e-4),
metrics=['accuracy'])
model.summary()
print(
model.output_shape
)
# Now that the model is created we can go ahead and train on it using the image generators we created earlier
file_path = model_name + ".hdf5"
checkpoint = ModelCheckpoint(file_path, monitor='val_acc', verbose=1, save_best_only=True, mode='max')
early = EarlyStopping(monitor="val_acc", mode="max", patience=15)
tensorboard = TensorBoard(
log_dir="logs/" + model_name + "{}".format(time()), histogram_freq=0, batch_size=batch_size,
write_graph=True,
write_grads=True,
write_images=True,
update_freq=batch_size
)
callbacks_list = [checkpoint, early, tensorboard] # early
history = model.fit_generator(
train_gen,
validation_data=val_gen,
steps_per_epoch=len(train_gen),
validation_steps=len(val_gen),
epochs=25,
shuffle=True,
verbose=True,
callbacks=callbacks_list
)
# Finally we are going to grab predictions from our model, save it, and then run some analysis on the results
predicts = model.predict_generator(test_gen, verbose=True, workers=1, steps=len(test_gen))
keras_file = model_name + 'finished.h5'
keras.models.save_model(model, keras_file)
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_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, [l for l in label_index.values()]))
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()
with open("labels.txt", "w") as f:
for label in label_index.values():
f.write(label + "\n")
-123
View File
@@ -1,123 +0,0 @@
from time import time
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
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 = 32
model_name = f"mobilenetv2-dense1024-l1l2-25drop-{time()}"
training_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
rotation_range=30,
width_shift_range=[-.1, .1],
height_shift_range=[-.1, .1],
)
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',
shuffle=True,
color_mode='rgb'
)
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]
history = model.fit(
train_gen,
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
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)
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
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)
+197
View File
@@ -0,0 +1,197 @@
from enum import Enum
import matplotlib.pyplot as plt
import numpy as np
from PIL import ImageFile
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from tensorflow import keras
from modeling_utils import ImageClassModelBuilder, ImageClassModels
ImageFile.LOAD_TRUNCATED_IMAGES = True
input_shape = (224, 224, 3)
batch_size = 32
training_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
rotation_range=30,
width_shift_range=[-.1, .1],
height_shift_range=[-.1, .1],
)
val_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
)
testing_idg = keras.preprocessing.image.ImageDataGenerator(
horizontal_flip=True,
)
class DatasetType(Enum):
TRAIN = 0
TEST = 1
VAL = 2
def get_gen(path, dataset_type: DatasetType = DatasetType.TRAIN):
idg = None
if dataset_type is DatasetType.TRAIN:
idg = training_idg
if dataset_type is DatasetType.TEST:
idg = testing_idg
if dataset_type is DatasetType.VAL:
idg = val_idg
return idg.flow_from_directory(
path,
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
class_mode='categorical',
shuffle=True,
color_mode='rgb'
)
def train_model(model, model_name, train_gen, val_gen, max_epochs):
print(model)
print(f"NOW TRAINING: {model_name}")
checkpoint = keras.callbacks.ModelCheckpoint(
f"./models/keras/{model_name}.hdf5",
monitor='val_categorical_crossentropy',
verbose=1,
save_best_only=True,
mode='min'
)
early = keras.callbacks.EarlyStopping(
monitor="val_categorical_crossentropy",
mode="auto",
patience=4,
restore_best_weights=True,
verbose=1,
)
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,
)
model.fit(
train_gen,
validation_data=val_gen,
epochs=max_epochs,
batch_size=batch_size,
shuffle=True,
verbose=True,
workers=20,
callbacks=[checkpoint, early, tensorboard],
max_queue_size=1000
)
return model
def test_model(model, test_gen):
predictions = model.predict(test_gen, verbose=True, workers=1, steps=len(test_gen))
print(predictions)
print(type(predictions))
print(predictions.shape)
# Process the predictions
predictions = np.argmax(predictions,
axis=1)
# test_gen.reset()
label_index = {v: k for k, v in test_gen.class_indices.items()}
predictions = [label_index[p] for p in predictions]
reals = [label_index[p] for p in test_gen.classes]
# Processed the saved results
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)
print("made dataframe")
plt.figure(figsize=(10, 7))
print("made plot")
print("showing plot")
plt.show()
if __name__ == "__main__":
model_builders = [
ImageClassModelBuilder(
input_shape=input_shape,
n_classes=807,
optimizer=keras.optimizers.Adam(learning_rate=.0001),
pre_trained=True,
freeze_layers=True,
freeze_batch_norm=True,
base_model_type=ImageClassModels.MOBILENET_V2,
dense_layer_neurons=1024,
dropout_rate=.5,
), ImageClassModelBuilder(
input_shape=input_shape,
n_classes=807,
optimizer=keras.optimizers.Adam(learning_rate=.0001),
pre_trained=True,
freeze_layers=True,
freeze_batch_norm=True,
base_model_type=ImageClassModels.INCEPTION_RESNET_V2,
dense_layer_neurons=1024,
dropout_rate=.5,
), ImageClassModelBuilder(
input_shape=input_shape,
n_classes=807,
optimizer=keras.optimizers.Adam(learning_rate=.0001),
pre_trained=True,
freeze_layers=True,
freeze_batch_norm=True,
base_model_type=ImageClassModels.INCEPTION_V3,
dense_layer_neurons=1024,
dropout_rate=.5,
), ImageClassModelBuilder(
input_shape=input_shape,
n_classes=807,
optimizer=keras.optimizers.Adam(learning_rate=.0001),
pre_trained=True,
freeze_layers=True,
freeze_batch_norm=True,
base_model_type=ImageClassModels.XCEPTION,
dense_layer_neurons=1024,
dropout_rate=.5,
), ImageClassModelBuilder(
input_shape=input_shape,
n_classes=807,
optimizer=keras.optimizers.Adam(learning_rate=.0001),
pre_trained=True,
freeze_layers=True,
freeze_batch_norm=True,
base_model_type=ImageClassModels.DENSENET201,
dense_layer_neurons=1024,
dropout_rate=.5,
)
]
for mb in model_builders:
model = mb.create_model()
model_name = mb.get_name()
train_gen = get_gen('./data/train', dataset_type=DatasetType.TRAIN)
val_gen = get_gen('./data/val', dataset_type=DatasetType.VAL)
test_gen = get_gen('./data/test', dataset_type=DatasetType.TEST)
model = train_model(model, model_name, train_gen, val_gen, 1)
# for layer in model.layers[2].layers:
# if not isinstance(layer, keras.layers.BatchNormalization):
# layer.trainable = True
# model.layers[2].trainable = True
# print(model)
# model.compile(
# optimizer=keras.optimizers.Adam(learning_rate=.00001),
# loss=keras.losses.CategoricalCrossentropy(),
# metrics=['accuracy', 'categorical_crossentropy']
# )
# model.summary()
# model = train_model(model, model_name + "-second_stage", train_gen, val_gen, 1)
# test_model(model, test_gen)
-78
View File
@@ -1,78 +0,0 @@
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sn
import numpy as np
from keras.applications.inception_v3 import preprocess_input
from keras.preprocessing.image import ImageDataGenerator
from keras.models import load_model
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
model = load_model("./Models/mobilenetv2-stock-all-fixed-v2/mobilenetv2.hdf5")
input_shape = (224, 224, 3)
batch_size = 96
test_idg = ImageDataGenerator(
preprocessing_function=preprocess_input,
)
test_gen = test_idg.flow_from_directory(
# './data/test',
'./SingleImageTestSet',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
shuffle=False
)
predictions = model.predict_generator(test_gen, verbose=True, workers=1, steps=len(test_gen))
print(predictions)
print(type(predictions))
print(predictions.shape)
# Process the predictions
predictions = np.argmax(predictions,
axis=1)
# test_gen.reset()
label_index = {v: k for k, v in test_gen.class_indices.items()}
predictions = [label_index[p] for p in predictions]
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'] = predictions
df["true_val"] = reals
df.to_csv("sub1_non_transfer.csv", index=False)
# Processed the saved results
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)
df_cm = pd.DataFrame(conf_mat, index=[i for i in list(set(reals))],
columns=[i for i in list(set(reals))])
print("made dataframe")
plt.figure(figsize=(10, 7))
print("made plot")
# sn.heatmap(df_cm, annot=True)
print("showing plot")
plt.show()
with open("labels.txt", "w") as f:
for label in label_index.values():
f.write(label + "\n")
+61
View File
@@ -0,0 +1,61 @@
from glob import glob
import matplotlib.pyplot as plt
import pandas as pd
from PIL import ImageFile
from keras.models import load_model
from keras.preprocessing.image import ImageDataGenerator
from modeling_utils import get_metrics
ImageFile.LOAD_TRUNCATED_IMAGES = True
accuracies = []
losses = []
filenames = []
input_shape = (224, 224, 3)
batch_size = 32
metrics_df = pd.read_csv("all_model_output.csv")
test_gen = ImageDataGenerator().flow_from_directory(
'./data/test',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
shuffle=False
)
single_gen = ImageDataGenerator().flow_from_directory(
'./single_image_test_set',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
shuffle=False
)
for file in glob("./models/keras/*.hdf5"):
print(file)
if file in metrics_df.values:
continue
model = load_model(file)
test_acc, test_ll = get_metrics(test_gen, model)
single_acc, single_ll = get_metrics(single_gen, model, file[:-5] + ".csv")
metrics_df = metrics_df.append({
"model": file,
"test_acc": test_acc,
"test_loss": test_ll,
"single_acc": single_acc,
"single_loss": single_ll,
}, ignore_index=True)
# Save the results
metrics_df.to_csv("all_model_output.csv", index=False)
print(metrics_df)
metrics_df = metrics_df.sort_values('single_acc')
metrics_df.plot.bar(y=["test_acc", "single_acc"], rot=90)
metrics_df = metrics_df.sort_values('test_acc')
metrics_df.plot.bar(y=["test_acc", "single_acc"], rot=90)
plt.tight_layout()
plt.show()
-11
View File
@@ -1,11 +0,0 @@
import tensorflow as tf
from tensorflow import keras
keras_file = "mobilenetv2.hdf5"
keras.models.load_model(keras_file)
h5_model = keras.models.load_model(keras_file)
converter = tf.lite.TFLiteConverter.from_keras_model_file(keras_file)
tflite_model = converter.convert()
with open('mobilenetv2.tflite', 'wb') as f:
f.write(tflite_model)
+43
View File
@@ -0,0 +1,43 @@
import os
from glob import glob
from pathlib import Path
import pandas as pd
import tensorflow as tf
from keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf
# TODO: Move these to a config for the project
input_shape = (224, 224, 3)
batch_size = 32
single_gen = ImageDataGenerator().flow_from_directory(
'./single_image_test_set',
target_size=(input_shape[0], input_shape[1]),
batch_size=batch_size,
shuffle=False
)
pd.DataFrame(sorted([f.name for f in os.scandir("./data/train") if f.is_dir()])).to_csv("./models/tflite/labels.txt",
index=False, header=False)
for file in glob("./models/keras/*.hdf5"):
path = Path(file)
tflite_file = f'./models/tflite/models/{path.name[:-5] + ".tflite"}'
if not Path(tflite_file).exists():
print(tflite_file)
keras_model = tf.keras.models.load_model(file)
keras_model.summary()
print(keras_model.input)
print(keras_model.layers)
converter = tf.lite.TFLiteConverter.from_keras_model(keras_model)
tflite_model = converter.convert()
with open(tflite_file, 'wb') as f:
f.write(tflite_model)
# TODO: Verify the model performance after converting to TFLITE
# interpreter = tf.lite.Interpreter(model_path=tflite_file)
# single_acc, single_ll = get_metrics(single_gen, keras_model)
# tf_single_acc, tf_single_ll = get_metrics(single_gen, tflite_model)
#
# print(single_acc, tf_single_acc)
# print(single_ll, tf_single_ll)
-4
View File
@@ -1,4 +0,0 @@
import pandas as pd
import os
pd.DataFrame(sorted([f.name for f in os.scandir("./data/train") if f.is_dir()])).to_csv("labels.txt", index=False, header=False)
+1
View File
@@ -0,0 +1 @@
Test readme file
Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

+7
View File
@@ -0,0 +1,7 @@
model,test_acc,test_loss,single_acc,single_loss
./models/keras\pt-fl-fbn-efficientnet_v2b0-d1024-do0.5-l11.e-04-l21.e-04-5224-second_stage.hdf5,0.6720150708068079,1.7423864365349095,0.9893048128342246,0.4364729183409372
./models/keras\pt-fl-fbn-efficientnet_v2b0-d1024-do0.5-l11.e-04-l21.e-04-5224.hdf5,0.410029881772119,3.346152696366266,0.986096256684492,0.3234976000776315
./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-8105-second_stage.hdf5,0.6850721060153306,1.675868156533777,0.9967914438502674,0.3373779159304851
./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-8105.hdf5,0.3755359230869169,3.5500588697038067,0.9540106951871656,0.4727042578503783
./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-9317-second_stage.hdf5,0.6121780461172843,2.197206965588216,0.9946581196581196,0.2974041509252359
./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-9317.hdf5,0.3702228787976106,3.601324427207316,0.9594017094017094,0.4877960320956891
1 model test_acc test_loss single_acc single_loss
2 ./models/keras\pt-fl-fbn-efficientnet_v2b0-d1024-do0.5-l11.e-04-l21.e-04-5224-second_stage.hdf5 0.6720150708068079 1.7423864365349095 0.9893048128342246 0.4364729183409372
3 ./models/keras\pt-fl-fbn-efficientnet_v2b0-d1024-do0.5-l11.e-04-l21.e-04-5224.hdf5 0.410029881772119 3.346152696366266 0.986096256684492 0.3234976000776315
4 ./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-8105-second_stage.hdf5 0.6850721060153306 1.675868156533777 0.9967914438502674 0.3373779159304851
5 ./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-8105.hdf5 0.3755359230869169 3.5500588697038067 0.9540106951871656 0.4727042578503783
6 ./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-9317-second_stage.hdf5 0.6121780461172843 2.197206965588216 0.9946581196581196 0.2974041509252359
7 ./models/keras\pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-9317.hdf5 0.3702228787976106 3.601324427207316 0.9594017094017094 0.4877960320956891
-76
View File
@@ -1,76 +0,0 @@
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
@@ -1 +1,2 @@
from .image_class_builder import ImageClassModelBuilder, ImageClassModels from .image_class_builder import ImageClassModelBuilder, ImageClassModels
from .model_testing import get_metrics
+125
View File
@@ -0,0 +1,125 @@
import random
from enum import Enum
from typing import Tuple
import numpy as np
import tensorflow as tf
from tensorflow import keras
from .model_wrapper import ModelWrapper
class ImageClassModels(Enum):
INCEPTION_V3 = ModelWrapper(
keras.applications.inception_v3.InceptionV3,
keras.applications.inception_v3.preprocess_input,
"inception_v3"
)
INCEPTION_RESNET_V2 = ModelWrapper(
keras.applications.inception_resnet_v2.InceptionResNetV2,
keras.applications.inception_resnet_v2.preprocess_input,
"inception_resnet_v2"
)
XCEPTION = ModelWrapper(
keras.applications.xception.Xception,
keras.applications.xception.preprocess_input,
"xception"
)
DENSENET201 = ModelWrapper(
keras.applications.densenet.DenseNet201,
keras.applications.densenet.preprocess_input,
"densenet201"
)
MOBILENET_V2 = ModelWrapper(
keras.applications.mobilenet_v2.MobileNetV2,
keras.applications.mobilenet_v2.preprocess_input,
"mobilenet_v2"
)
EFFICIENTNET_V2S = ModelWrapper(
keras.applications.efficientnet_v2.EfficientNetV2S,
tf.keras.applications.efficientnet_v2.preprocess_input,
"efficientnet_v2s"
)
EFFICIENTNET_V2B0 = ModelWrapper(
keras.applications.efficientnet_v2.EfficientNetV2B0,
tf.keras.applications.efficientnet_v2.preprocess_input,
"efficientnet_v2b0"
)
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,
freeze_batch_norm: bool = False,
freeze_layers: bool = False,
base_model_type: ImageClassModels = ImageClassModels.MOBILENET_V2,
dense_layer_neurons: int = 1024,
dropout_rate: float = .5,
l1: float = 1e-4,
l2: float = 1e-4):
self.input_shape = input_shape
self.n_classes = n_classes
self.optimizer = optimizer
self.pre_trained = pre_trained
self.freeze_layers = freeze_layers
self.freeze_batch_norm = freeze_batch_norm
self.dense_layer_neurons = dense_layer_neurons
self.dropout_rate = dropout_rate
self.l1 = l1
self.l2 = l2
self.set_base_model(base_model_type)
def set_base_model(self, base_model_type: ImageClassModels):
self.base_model_type = base_model_type
self.base_model = self.base_model_type.value.model_func(
weights='imagenet' if self.pre_trained else None,
input_shape=self.input_shape,
include_top=False
)
def create_model(self):
if self.freeze_layers:
self.base_model.trainable = False
if self.freeze_batch_norm:
for layer in self.base_model.layers:
if isinstance(layer, keras.layers.BatchNormalization):
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_type.value.model_preprocessor(x)
x = self.base_model(x)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dense(self.dense_layer_neurons, activation='relu',
kernel_regularizer=keras.regularizers.L1L2(l1=self.l1, l2=self.l2))(x)
x = keras.layers.Dropout(self.dropout_rate)(x)
output = keras.layers.Dense(self.n_classes, activation='softmax')(x)
self.model = keras.Model(inputs=i, outputs=output)
self.model.compile(
optimizer=self.optimizer,
loss=keras.losses.CategoricalCrossentropy(),
metrics=['accuracy', 'categorical_crossentropy']
)
self.model.summary()
return self.model
def get_fine_tuning(self):
print("self.model is found")
self.base_model.trainable = True
self.model.compile(
optimizer=self.optimizer,
loss=keras.losses.CategoricalCrossentropy(),
metrics=['accuracy', 'categorical_crossentropy']
)
self.model.summary()
return self.model
def get_name(self):
return f"{'pt-' if self.pre_trained else ''}{'fl-' if self.freeze_layers else ''}{'fbn-' if self.freeze_batch_norm else ''}" \
f"{self.base_model_type.value.name}-d{self.dense_layer_neurons}-do{self.dropout_rate}" \
f"{'-l1' + np.format_float_scientific(self.l1) if self.l1 > 0 else ''}{'-l2' + np.format_float_scientific(self.l2) if self.l2 > 0 else ''}" \
f"-{random.randint(1111, 9999)}"
+24
View File
@@ -0,0 +1,24 @@
import numpy as np
import pandas as pd
from sklearn.metrics import accuracy_score, confusion_matrix, log_loss
def get_metrics(gen, model, save_predictions_file=None):
model_output = model.predict(gen, verbose=True, workers=12)
prediction_indices = np.argmax(model_output, axis=1)
label_index = {v: k for k, v in gen.class_indices.items()}
predictions = [label_index[p] for p in prediction_indices]
reals = [label_index[p] for p in gen.classes]
acc = accuracy_score(reals, predictions)
ll = log_loss(gen.classes, model_output, labels=[l for l in label_index.keys()])
conf_mat = confusion_matrix(reals, predictions, 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("Confusion Matrix", conf_mat)
if save_predictions_file:
df = pd.DataFrame(columns=['fname', 'prediction', 'true_val'])
df['fname'] = [x for x in gen.filenames]
df['prediction'] = predictions
df["true_val"] = reals
df.to_csv(save_predictions_file, index=False)
return acc, ll
@@ -1,7 +1,7 @@
from collections import Callable from typing import Callable
class ModelWrapper(object): class ModelWrapper(object):
def __init__(self, model_func:Callable, model_preprocessor:Callable): def __init__(self, model_func:Callable, model_preprocessor:Callable, name:str):
self.model_func = model_func self.model_func = model_func
self.model_preprocessor = model_preprocessor self.model_preprocessor = model_preprocessor
self.name = name
+5
View File
@@ -0,0 +1,5 @@
import pandas as pd
df = pd.read_csv("models/keras/pt-fl-fbn-efficientnet_v2s-d1024-do0.5-l11.e-04-l21.e-04-8105-second_stage.csv")
print(df.loc[df["prediction"] != df["true_val"]])
+1
View File
@@ -0,0 +1 @@
tensorboard --logdir_spec=local:./logs,remote:Z:/MachineLearning/Tensorboard/Tensordex/Logs --bind_all
@@ -19,7 +19,6 @@ for index, row in df2.iterrows():
incorrect = df[df["prediction"]!= df["true_val"]] incorrect = df[df["prediction"]!= df["true_val"]]
total_same_fam = 0 total_same_fam = 0
# TODO: Add in support for figuring out if the pokemon are related/evolutions of one another
for index, row in incorrect.iterrows(): for index, row in incorrect.iterrows():
img = mpimg.imread("./SingleImageTestSet/" + row['fname']) img = mpimg.imread("./SingleImageTestSet/" + row['fname'])
imgplot = plt.imshow(img) imgplot = plt.imshow(img)

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Before

Width:  |  Height:  |  Size: 159 KiB

After

Width:  |  Height:  |  Size: 159 KiB

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 185 KiB

Before

Width:  |  Height:  |  Size: 501 KiB

After

Width:  |  Height:  |  Size: 501 KiB

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Before

Width:  |  Height:  |  Size: 830 KiB

After

Width:  |  Height:  |  Size: 830 KiB

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Before

Width:  |  Height:  |  Size: 517 KiB

After

Width:  |  Height:  |  Size: 517 KiB

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Before

Width:  |  Height:  |  Size: 666 KiB

After

Width:  |  Height:  |  Size: 666 KiB

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 171 KiB

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Before

Width:  |  Height:  |  Size: 695 KiB

After

Width:  |  Height:  |  Size: 695 KiB

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Before

Width:  |  Height:  |  Size: 381 KiB

After

Width:  |  Height:  |  Size: 381 KiB

Before

Width:  |  Height:  |  Size: 600 KiB

After

Width:  |  Height:  |  Size: 600 KiB

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 274 KiB

Before

Width:  |  Height:  |  Size: 549 KiB

After

Width:  |  Height:  |  Size: 549 KiB

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Before

Width:  |  Height:  |  Size: 2.0 MiB

After

Width:  |  Height:  |  Size: 2.0 MiB

Before

Width:  |  Height:  |  Size: 332 KiB

After

Width:  |  Height:  |  Size: 332 KiB

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Before

Width:  |  Height:  |  Size: 485 KiB

After

Width:  |  Height:  |  Size: 485 KiB

Before

Width:  |  Height:  |  Size: 705 KiB

After

Width:  |  Height:  |  Size: 705 KiB

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Some files were not shown because too many files have changed in this diff Show More