Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix linting in script and notebooks; add linting for notebooks by default #4

Merged
merged 5 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
python-version: "3.8"

- name: Install lint dependencies
run: pip install wheel setuptools black==22.3.0 isort==5.10.1 flake8==4.0.1
run: pip install wheel setuptools isort==5.10.1 flake8==4.0.1 black==22.3.0 "black[jupyter]"

- name: Lint the code
run: sh shell/lint.sh
25 changes: 15 additions & 10 deletions FindOptimumNumberOfClasses.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import os
import random

import numpy as np
import tensorflow as tf
from sklearn.metrics import silhouette_score
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.mobilenet_v2 import preprocess_input
from scipy.spatial.distance import cdist
from sklearn.metrics import silhouette_score
import random
from tensorflow.keras.preprocessing import image


class ImageProcessor:
def __init__(self, image_directory):
self.image_directory = image_directory
self.model = MobileNetV2(weights='imagenet', include_top=False, pooling='avg')
self.model = MobileNetV2(weights="imagenet", include_top=False, pooling="avg")

def load_and_preprocess_image(self, img_path):
img = image.load_img(img_path, target_size=(224, 224))
Expand All @@ -29,6 +29,7 @@ def extract_features(self):
filenames.append(filename)
return np.array(features), filenames


class GeneticAlgorithm:
def __init__(self, population_size, generations, mutation_rate, max_clusters):
self.population_size = population_size
Expand All @@ -37,7 +38,10 @@ def __init__(self, population_size, generations, mutation_rate, max_clusters):
self.max_clusters = max_clusters

def initialize_population(self, num_images):
return [np.random.randint(1, min(i + 2, self.max_clusters + 1), size=num_images) for i in range(self.population_size)]
return [
np.random.randint(1, min(i + 2, self.max_clusters + 1), size=num_images)
for i in range(self.population_size)
]

def fitness(self, individual, features):
try:
Expand All @@ -62,7 +66,7 @@ def evolve(self, features):
for generation in range(self.generations):
fitness_scores = [self.fitness(ind, features) for ind in population]
sorted_indices = np.argsort(fitness_scores)
best_individuals = [population[idx] for idx in sorted_indices[-(self.population_size // 2):]]
best_individuals = [population[idx] for idx in sorted_indices[-(self.population_size // 2) :]]

next_generation = best_individuals[:]
while len(next_generation) < self.population_size:
Expand All @@ -77,6 +81,7 @@ def evolve(self, features):

return max(population, key=lambda ind: self.fitness(ind, features))


class ImageClassifier:
def __init__(self, image_directory, output_file):
self.processor = ImageProcessor(image_directory)
Expand All @@ -89,11 +94,11 @@ def run(self):
self.output_classification(optimal_classes, filenames)

def output_classification(self, classes, filenames):
with open(self.output_file, 'w') as file:
with open(self.output_file, "w") as file:
for filename, cluster in zip(filenames, classes):
file.write(f"{filename}, {cluster}\n")


if __name__ == "__main__":
classifier = ImageClassifier('path_to_images', 'output.txt')
classifier = ImageClassifier("path_to_images", "output.txt")
classifier.run()
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pip install -r requirements.txt
First install linting dependencies:

```
pip install black==22.3.0 isort==5.10.1 flake8==4.0.1
pip install isort==5.10.1 flake8==4.0.1 black==22.3.0 "black[jupyter]"
```

Then run linting test by:
Expand Down
109 changes: 50 additions & 59 deletions notebooks/ManyShotTransferLearning.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"from tensorflow.keras.callbacks import Callback, EarlyStopping, ModelCheckpoint\n",
"from MLD import multi_lens_distortion\n",
"\n",
"os.environ['TF_FORCE_GPU_ALLOW_GROWTH'] = 'true' \n",
"os.environ[\"TF_FORCE_GPU_ALLOW_GROWTH\"] = \"true\"\n",
"os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"1\" # Select GPU"
]
},
Expand All @@ -33,10 +33,11 @@
"IMG_SIZE = (224, 224)\n",
"IMG_SHAPE = IMG_SIZE + (3,)\n",
"\n",
"\n",
"def network_1():\n",
" # Load pre-trained DenseNet201 and ResNet101V2 models\n",
" dense_net_full = tf.keras.applications.DenseNet201(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')\n",
" res_net_full = tf.keras.applications.ResNet101V2(input_shape=IMG_SHAPE, include_top=False, weights='imagenet')\n",
" dense_net_full = tf.keras.applications.DenseNet201(input_shape=IMG_SHAPE, include_top=False, weights=\"imagenet\")\n",
" res_net_full = tf.keras.applications.ResNet101V2(input_shape=IMG_SHAPE, include_top=False, weights=\"imagenet\")\n",
"\n",
" # Create a new model with only the first 54 layers of DenseNet201\n",
" dense_net = tf.keras.Model(inputs=dense_net_full.input, outputs=dense_net_full.layers[178].output)\n",
Expand All @@ -60,18 +61,19 @@
"\n",
" # Dense layers for classification\n",
" z = layers.Dropout(0.4)(concatenated)\n",
" z = layers.Dense(512, activation='relu')(z)\n",
" z = layers.Dense(512, activation=\"relu\")(z)\n",
" # z = layers.Dropout(0.2)(z)\n",
" z = layers.Dense(2, activation='softmax')(z)\n",
" z = layers.Dense(2, activation=\"softmax\")(z)\n",
"\n",
" # Final model\n",
" model = Model(inputs=input, outputs=z)\n",
" model.compile(optimizer=optimizers.Adam(1e-4), loss=\"CategoricalCrossentropy\", metrics=['accuracy'])\n",
" model.compile(optimizer=optimizers.Adam(1e-4), loss=\"CategoricalCrossentropy\", metrics=[\"accuracy\"])\n",
"\n",
" model.summary()\n",
" return model\n",
"\n",
"model = network_1()\n"
"\n",
"model = network_1()"
]
},
{
Expand All @@ -81,8 +83,9 @@
"outputs": [],
"source": [
"from os import walk\n",
"filenames = next(walk('./NLCB/Data3/'), (None, None, []))[2] # [] if no file\n",
"filenames_val = next(walk('./NLCB/Data3/Validation/'), (None, None, []))[2] # [] if no file"
"\n",
"filenames = next(walk(\"./NLCB/Data3/\"), (None, None, []))[2] # [] if no file\n",
"filenames_val = next(walk(\"./NLCB/Data3/Validation/\"), (None, None, []))[2] # [] if no file"
]
},
{
Expand All @@ -92,21 +95,20 @@
"outputs": [],
"source": [
"def custom_data_generator(directory):\n",
" for filepath in glob.glob(os.path.join(directory, '*.png')): # assuming jpeg images\n",
" for filepath in glob.glob(os.path.join(directory, \"*.png\")): # assuming jpeg images\n",
" image = tf.io.read_file(filepath)\n",
" image = tf.image.decode_jpeg(image, channels=3)\n",
" label = []\n",
" label[0] = 1 if filepath[4] == 'n' else 0 # Check the 5th character from the end for 'n'\n",
" label[1] = 0 if filepath[4] != 'n' else 1\n",
" label[0] = 1 if filepath[4] == \"n\" else 0 # Check the 5th character from the end for 'n'\n",
" label[1] = 0 if filepath[4] != \"n\" else 1\n",
" yield image, label\n",
"\n",
"\n",
"\n",
"def custom_preprocessing_function(img):\n",
"\n",
" if tf.random.uniform((), minval= 0, maxval=1) > 0.5:\n",
" if tf.random.uniform((), minval=0, maxval=1) > 0.5:\n",
" nbr_rot = tf.random.uniform(shape=[], minval=1, maxval=4, dtype=tf.int32)\n",
" img =tf.image.rot90(img, k=nbr_rot)\n",
" img = tf.image.rot90(img, k=nbr_rot)\n",
"\n",
" img = tf.image.random_hue(img, 0.08)\n",
" img = tf.image.random_contrast(img, 0.7, 1.3)\n",
Expand All @@ -117,20 +119,18 @@
" # print(img.shape)\n",
" # img = tf.image.random_crop(img, (int(img.shape[0]/2),int(img.shape[1]/2), 3))\n",
" img = tf.image.random_crop(img, (224, 224, 3))\n",
" img = img/255.\n",
" img = tf.image.resize(img,(224,224))\n",
" img = tf.numpy_function(\n",
" multi_lens_distortion, \n",
" [img, 4, (80, 110), (-0.4, 0.4)], \n",
" tf.uint8\n",
" )\n",
" img = img / 255.0\n",
" img = tf.image.resize(img, (224, 224))\n",
" img = tf.numpy_function(multi_lens_distortion, [img, 4, (80, 110), (-0.4, 0.4)], tf.uint8)\n",
"\n",
" return img\n",
"\n",
"\n",
"def validation_preprocessing_function(img):\n",
" # img = tf.image.random_crop(img, (224, 224, 3))\n",
" img = img/255.\n",
" img = tf.image.resize(img,(224,224))\n",
" img = img / 255.0\n",
" img = tf.image.resize(img, (224, 224))\n",
"\n",
"\n",
"# Paths\n",
"train_data_dir = \"./NLCB/Data3/Training/\"\n",
Expand All @@ -142,29 +142,20 @@
" shear_range=0.2,\n",
" zoom_range=0.2,\n",
" horizontal_flip=True,\n",
" preprocessing_function=custom_preprocessing_function # Add more augmentations here\n",
" preprocessing_function=custom_preprocessing_function, # Add more augmentations here\n",
")\n",
"\n",
"# Create a data generator for validation data\n",
"validation_datagen = ImageDataGenerator(preprocessing_function=validation_preprocessing_function)\n",
"\n",
"# Use custom data generator for training and validation datasets\n",
"train_generator = train_datagen.flow_from_directory(\n",
" train_data_dir,\n",
" target_size=(224, 224),\n",
" batch_size=16,\n",
" class_mode='categorical',\n",
" shuffle=True\n",
" train_data_dir, target_size=(224, 224), batch_size=16, class_mode=\"categorical\", shuffle=True\n",
")\n",
"\n",
"validation_generator = validation_datagen.flow_from_directory(\n",
" validation_data_dir,\n",
" target_size=(224, 224),\n",
" batch_size=16,\n",
" class_mode='categorical',\n",
" shuffle=False\n",
")\n",
"\n"
" validation_data_dir, target_size=(224, 224), batch_size=16, class_mode=\"categorical\", shuffle=False\n",
")"
]
},
{
Expand All @@ -173,7 +164,7 @@
"metadata": {},
"outputs": [],
"source": [
"model.compile(optimizer=optimizers.Adamax(1e-4), loss=\"CategoricalCrossentropy\", metrics=['accuracy'])\n",
"model.compile(optimizer=optimizers.Adamax(1e-4), loss=\"CategoricalCrossentropy\", metrics=[\"accuracy\"])\n",
"\n",
"# # considering you want to monitor accuracy:\n",
"# acc_thresh = 0.95\n",
Expand Down Expand Up @@ -204,19 +195,19 @@
"\n",
"# Setting up callbacks for early stopping on minimum validation loss and saving the best model\n",
"early_stopping_callback = EarlyStopping(\n",
" monitor='val_loss',\n",
" monitor=\"val_loss\",\n",
" patience=patience,\n",
" verbose=1,\n",
" mode='min',\n",
" restore_best_weights=True # Restores model weights from the epoch with the best value of the monitored quantity.\n",
" mode=\"min\",\n",
" restore_best_weights=True, # Restores model weights from the epoch with the best value of the monitored quantity.\n",
")\n",
"\n",
"model_checkpoint_callback = ModelCheckpoint(\n",
" './PWCModel/best_model.h5', # Path where the model will be saved\n",
" monitor='val_loss',\n",
" \"./PWCModel/best_model.h5\", # Path where the model will be saved\n",
" monitor=\"val_loss\",\n",
" save_best_only=True, # Only the best model according to the validation loss is saved\n",
" mode='min',\n",
" verbose=1\n",
" mode=\"min\",\n",
" verbose=1,\n",
")\n",
"\n",
"history = model.fit(\n",
Expand All @@ -225,11 +216,11 @@
" validation_data=validation_generator,\n",
" validation_steps=len(validation_generator),\n",
" epochs=200,\n",
" callbacks=[early_stopping_callback, model_checkpoint_callback]\n",
" callbacks=[early_stopping_callback, model_checkpoint_callback],\n",
")\n",
"\n",
"# Save the overall model after training (optional, as the best model is already saved)\n",
"model.save('./PWCModel/best_PWC_model.h5')\n"
"model.save(\"./PWCModel/best_PWC_model.h5\")"
]
},
{
Expand All @@ -252,20 +243,20 @@
"outputs": [],
"source": [
"# summarize history for accuracy\n",
"plt.plot(history.history['accuracy'])\n",
"plt.plot(history.history['val_accuracy'])\n",
"plt.title('model accuracy')\n",
"plt.ylabel('accuracy')\n",
"plt.xlabel('epoch')\n",
"plt.legend(['Training', 'Validation'], loc='upper left')\n",
"plt.plot(history.history[\"accuracy\"])\n",
"plt.plot(history.history[\"val_accuracy\"])\n",
"plt.title(\"model accuracy\")\n",
"plt.ylabel(\"accuracy\")\n",
"plt.xlabel(\"epoch\")\n",
"plt.legend([\"Training\", \"Validation\"], loc=\"upper left\")\n",
"plt.show()\n",
"# summarize history for loss\n",
"plt.plot(history.history['loss'])\n",
"plt.plot(history.history['val_loss'])\n",
"plt.title('model loss')\n",
"plt.ylabel('loss')\n",
"plt.xlabel('epoch')\n",
"plt.legend(['Training', 'Validation'], loc='upper left')\n",
"plt.plot(history.history[\"loss\"])\n",
"plt.plot(history.history[\"val_loss\"])\n",
"plt.title(\"model loss\")\n",
"plt.ylabel(\"loss\")\n",
"plt.xlabel(\"epoch\")\n",
"plt.legend([\"Training\", \"Validation\"], loc=\"upper left\")\n",
"plt.show()"
]
}
Expand Down
Loading
Loading