-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Transform model fine-tuning code to Python package
Transform the model fine-tuning code in the Jupyter notebook files into a Python package named `deeptune` to help people fine-tune and train models of siamese architecture. * **Package Structure:** - Create `deeptune` package with subdirectories: `data`, `models`, `training`, `evaluation`, `utils`, and `cli`. - Add `__init__.py` files to each subdirectory to make them sub-packages. - Add `config.py` for configuration settings. - Add `requirements.txt` to list dependencies. * **CLI Support:** - Create `cli.py` in `cli` subdirectory to allow users to interact with the package through the command line. - Implement `evaluate_model` command to evaluate models. * **Loss Functions:** - Implement Triplet Loss, ArcFace Loss, and Contrastive Loss in `training/losses.py`. * **Data Generators:** - Implement `TripletGenerator` in `training/data_generators.py` to generate triplets for the triplet loss function. * **Evaluation:** - Move `Model-Training/eval-mark-I.py` to `evaluation/eval_mark_I.py` and update imports. - Move `Model-Training/Evaluate_model_1.ipynb` to `evaluation/evaluate_model_1.ipynb` and update imports. * **Documentation:** - Update `README.md` to include instructions for using the new Python package, CLI usage, and example code. --- For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/Devasy23/FaceRec?shareId=XXXX-XXXX-XXXX-XXXX).
- Loading branch information
Showing
14 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# deeptune package initialization |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# This file makes `cli` a sub-package |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import click | ||
import os | ||
from deeptune.evaluation.eval_mark_I import ( | ||
load_and_preprocess_image, | ||
generate_embeddings, | ||
calculate_intra_cluster_distances, | ||
) | ||
from keras.models import load_model | ||
import numpy as np | ||
|
||
|
||
@click.group() | ||
def cli(): | ||
pass | ||
|
||
|
||
@click.command() | ||
@click.argument("model_path") | ||
@click.argument("dataset_path") | ||
def evaluate_model(model_path, dataset_path): | ||
"""Evaluate the model with the given dataset.""" | ||
model = load_model(model_path) | ||
embeddings, labels = generate_embeddings(model, dataset_path) | ||
intra_distances = calculate_intra_cluster_distances(embeddings, labels) | ||
print(f"Intra-Cluster Distances: {intra_distances}") | ||
print(f"Mean Distance: {np.mean(intra_distances)}") | ||
|
||
|
||
cli.add_command(evaluate_model) | ||
|
||
if __name__ == "__main__": | ||
cli() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from __future__ import annotations | ||
|
||
import os | ||
|
||
basedir = os.path.abspath(os.path.dirname(__file__)) | ||
|
||
|
||
class Config: | ||
SECRET_KEY = os.environ.get("SECRET_KEY") | ||
DEBUG = True | ||
upload_image_path = os.path.join(basedir, "static/Images/uploads") | ||
ALLOWED_EXTENSIONS = ["jpg", "jpeg", "png", "jfif"] | ||
image_data_file = os.path.join(basedir, "static/Images/image_data.json") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# deeptune data sub-package initialization |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# deeptune evaluation sub-package initialization |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# deeptune models sub-package initialization |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
deepface==0.0.92 | ||
fastapi==0.115.0 | ||
keras==2.15.0 | ||
matplotlib>=3.8.2 | ||
numpy==1.26.0 | ||
Pillow==10.4.0 | ||
pydantic==2.9.2 | ||
pymongo==4.6.3 | ||
python-dotenv==1.0.1 | ||
tensorflow==2.15.0 | ||
uvicorn==0.31.0 | ||
pytest==7.4.4 | ||
httpx | ||
sphinx | ||
sphinx-rtd-theme | ||
myst-parser | ||
mypy-extensions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# deeptune training sub-package initialization |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import os | ||
import random | ||
import numpy as np | ||
from keras.preprocessing import image | ||
|
||
class TripletGenerator: | ||
def __init__(self, dataset_path, batch_size=32, target_size=(160, 160)): | ||
self.dataset_path = dataset_path | ||
self.batch_size = batch_size | ||
self.target_size = target_size | ||
self.classes = os.listdir(dataset_path) | ||
self.class_indices = {cls: i for i, cls in enumerate(self.classes)} | ||
self.image_paths = {cls: [os.path.join(dataset_path, cls, img) for img in os.listdir(os.path.join(dataset_path, cls))] for cls in self.classes} | ||
|
||
def __len__(self): | ||
return len(self.classes) | ||
|
||
def __getitem__(self, idx): | ||
cls = self.classes[idx] | ||
positive_images = random.sample(self.image_paths[cls], 2) | ||
negative_cls = random.choice([c for c in self.classes if c != cls]) | ||
negative_image = random.choice(self.image_paths[negative_cls]) | ||
|
||
anchor = self.load_and_preprocess_image(positive_images[0]) | ||
positive = self.load_and_preprocess_image(positive_images[1]) | ||
negative = self.load_and_preprocess_image(negative_image) | ||
|
||
return np.array([anchor, positive, negative]), np.array([1, 0]) | ||
|
||
def load_and_preprocess_image(self, img_path): | ||
img = image.load_img(img_path, target_size=self.target_size) | ||
img_array = image.img_to_array(img) | ||
img_array = np.expand_dims(img_array, axis=0) | ||
img_array /= 255.0 | ||
return img_array | ||
|
||
def generate(self): | ||
while True: | ||
for i in range(len(self)): | ||
yield self[i] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import tensorflow as tf | ||
import tensorflow.keras.backend as K | ||
from tensorflow.keras.losses import Loss | ||
import numpy as np | ||
|
||
|
||
class TripletLoss(Loss): | ||
def __init__(self, margin=1.0, **kwargs): | ||
super().__init__(**kwargs) | ||
self.margin = margin | ||
|
||
def call(self, y_true, y_pred): | ||
anchor, positive, negative = y_pred[:, 0], y_pred[:, 1], y_pred[:, 2] | ||
pos_dist = K.sum(K.square(anchor - positive), axis=-1) | ||
neg_dist = K.sum(K.square(anchor - negative), axis=-1) | ||
loss = K.maximum(pos_dist - neg_dist + self.margin, 0.0) | ||
return K.mean(loss) | ||
|
||
|
||
class ContrastiveLoss(Loss): | ||
def __init__(self, margin=1.0, **kwargs): | ||
super().__init__(**kwargs) | ||
self.margin = margin | ||
|
||
def call(self, y_true, y_pred): | ||
y_true = K.cast(y_true, y_pred.dtype) | ||
pos_dist = K.sum(K.square(y_pred[:, 0] - y_pred[:, 1]), axis=-1) | ||
neg_dist = K.sum(K.square(y_pred[:, 0] - y_pred[:, 2]), axis=-1) | ||
loss = y_true * pos_dist + (1 - y_true) * K.maximum(self.margin - neg_dist, 0.0) | ||
return K.mean(loss) | ||
|
||
|
||
class ArcFaceLoss(Loss): | ||
def __init__(self, scale=64.0, margin=0.5, **kwargs): | ||
super().__init__(**kwargs) | ||
self.scale = scale | ||
self.margin = margin | ||
|
||
def call(self, y_true, y_pred): | ||
y_true = K.cast(y_true, y_pred.dtype) | ||
cosine = K.clip(y_pred, -1.0, 1.0) | ||
theta = tf.acos(cosine) | ||
target_logits = tf.cos(theta + self.margin) | ||
logits = y_true * target_logits + (1 - y_true) * cosine | ||
logits *= self.scale | ||
return tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=logits) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# deeptune utils sub-package initialization |