From ab6c67dfed60c26a1bb82b168f5aaf9d5b188476 Mon Sep 17 00:00:00 2001 From: KatrionaGoldmann Date: Wed, 3 Apr 2024 17:05:58 +0100 Subject: [PATCH 1/6] Add model option --- .gitignore | 4 ++++ trapdata/ml/models/classification.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitignore b/.gitignore index 935b6dbd..b95e30db 100644 --- a/.gitignore +++ b/.gitignore @@ -138,3 +138,7 @@ trapdata.ini # Docker volumes db_data/ + + +# Test files +sample_images \ No newline at end of file diff --git a/trapdata/ml/models/classification.py b/trapdata/ml/models/classification.py index d213fef5..6e8c83d1 100644 --- a/trapdata/ml/models/classification.py +++ b/trapdata/ml/models/classification.py @@ -261,6 +261,20 @@ class QuebecVermontMothSpeciesClassifierMixedResolution( "quebec-vermont_moth-category-map_19Jan2023.json" ) +class CostaRicaSpeciesClassifier( + SpeciesClassifier, Resnet50ClassifierLowRes +): + name = "Costa Rica Species Classifier" + description = ( + "Trained on ___ by Turing" + ) + weights_path = ( + "/Users/kgoldmann/Downloads/turing-singapore_v02_resnet50_2023-12-19-14-04.pt" + ) + labels_path = ( + "/Users/kgoldmann/Downloads/01_singapore_species_name_indices.json" + ) + class UKDenmarkMothSpeciesClassifierMixedResolution( SpeciesClassifier, Resnet50ClassifierLowRes From 8f1273e146358ed3e7debbeb0b097f4d676d20b5 Mon Sep 17 00:00:00 2001 From: KatrionaGoldmann Date: Thu, 11 Apr 2024 10:53:16 +0100 Subject: [PATCH 2/6] Add CR model --- README.md | 15 ++++++++ trapdata/ml/models/classification.py | 57 ++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index aa8df02c..7d5cf950 100644 --- a/README.md +++ b/README.md @@ -146,3 +146,18 @@ docker stop ami-db && docker remove ami-db A script is available in the repo source to run the commands above. `./scrips/start_db_container.sh` + + + +## KG: Notes to self + +- To clear the cache: + + ``` + rm /Users/kgoldmann/Library/Application Support/trapdata/trapdata.db + ``` + +- To add new models, save the pt and json files to: +``` +/Users/kgoldmann/Library/Application Support/trapdata/models +``` \ No newline at end of file diff --git a/trapdata/ml/models/classification.py b/trapdata/ml/models/classification.py index 6e8c83d1..c163d0be 100644 --- a/trapdata/ml/models/classification.py +++ b/trapdata/ml/models/classification.py @@ -105,6 +105,57 @@ def forward(self, x): return x +class Resnet50Classifier_KG(InferenceBaseClass): + # function to run the Turing models + logger.info("KG: Resnet50Classifier_KG") + input_size = 300 + + def get_model(self): + num_classes = len(self.category_map) + logger.info(f"KG: num_classes {num_classes}") + + model = Resnet50(num_classes=num_classes) + model = model.to(self.device) + + logger.info("KG: check A") + # logger.info(f"KG: check {self.weights}") + + # # state_dict = torch.hub.load_state_dict_from_url(weights_url) + checkpoint = torch.load(self.weights, map_location=self.device) + logger.info("KG: check B") + + # # The model state dict is nested in some checkpoints, and not in others + state_dict = checkpoint.get("model_state_dict") or checkpoint + logger.info("KG: check C") + + model.load_state_dict(state_dict) + # model.load_state_dict(state_dict) + logger.info("KG: check D") + model.eval() + print("KG: model eval complete") + return model + + def get_transforms(self): + mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] + return torchvision.transforms.Compose( + [ + torchvision.transforms.Resize((self.input_size, self.input_size)), + torchvision.transforms.ToTensor(), + torchvision.transforms.Normalize(mean, std), + ] + ) + + def post_process_batch(self, output): + predictions = torch.nn.functional.softmax(output, dim=1) + predictions = predictions.cpu().numpy() + + categories = predictions.argmax(axis=1) + labels = [self.category_map[cat] for cat in categories] + scores = predictions.max(axis=1).astype(float) + + result = list(zip(labels, scores)) + logger.debug(f"Post-processing result batch: {result}") + return result class Resnet50Classifier(InferenceBaseClass): input_size = 300 @@ -262,17 +313,17 @@ class QuebecVermontMothSpeciesClassifierMixedResolution( ) class CostaRicaSpeciesClassifier( - SpeciesClassifier, Resnet50ClassifierLowRes + SpeciesClassifier, Resnet50Classifier ): name = "Costa Rica Species Classifier" description = ( "Trained on ___ by Turing" ) weights_path = ( - "/Users/kgoldmann/Downloads/turing-singapore_v02_resnet50_2023-12-19-14-04.pt" + "turing-costarica_v02_state_resnet50_2024-01-08-11-14.pt" ) labels_path = ( - "/Users/kgoldmann/Downloads/01_singapore_species_name_indices.json" + "01_costarica_species_name_indices.json" ) From 7c4d96c9180e752bd01d0879c917eb47b515f2f6 Mon Sep 17 00:00:00 2001 From: KatrionaGoldmann Date: Thu, 11 Apr 2024 10:55:51 +0100 Subject: [PATCH 3/6] Update readme --- README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7d5cf950..bba14658 100644 --- a/README.md +++ b/README.md @@ -149,15 +149,17 @@ A script is available in the repo source to run the commands above. -## KG: Notes to self - -- To clear the cache: +## KG Notes for adding new models +- To add new models, save the pt and json files to: ``` - rm /Users/kgoldmann/Library/Application Support/trapdata/trapdata.db + ~/Library/Application Support/trapdata/models ``` + or wherever you set the appropriate dir in settings. + The json file is simply a dict of species name and index. -- To add new models, save the pt and json files to: -``` -/Users/kgoldmann/Library/Application Support/trapdata/models -``` \ No newline at end of file +- To clear the cache: + + ``` + rm ~/Library/Application Support/trapdata/trapdata.db + ``` \ No newline at end of file From 4a21861087384e535840fa54b3490d8a42ee39eb Mon Sep 17 00:00:00 2001 From: KatrionaGoldmann Date: Thu, 6 Jun 2024 16:09:13 +0100 Subject: [PATCH 4/6] add CR resnet class --- trapdata/ml/models/classification.py | 31 +++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/trapdata/ml/models/classification.py b/trapdata/ml/models/classification.py index c163d0be..755bf8af 100644 --- a/trapdata/ml/models/classification.py +++ b/trapdata/ml/models/classification.py @@ -118,7 +118,6 @@ def get_model(self): model = model.to(self.device) logger.info("KG: check A") - # logger.info(f"KG: check {self.weights}") # # state_dict = torch.hub.load_state_dict_from_url(weights_url) checkpoint = torch.load(self.weights, map_location=self.device) @@ -136,7 +135,7 @@ def get_model(self): return model def get_transforms(self): - mean, std = [0.485, 0.456, 0.406], [0.229, 0.224, 0.225] + mean, std = [0.5, 0.5, 0.5], [0.5, 0.5, 0.5] return torchvision.transforms.Compose( [ torchvision.transforms.Resize((self.input_size, self.input_size)), @@ -312,19 +311,35 @@ class QuebecVermontMothSpeciesClassifierMixedResolution( "quebec-vermont_moth-category-map_19Jan2023.json" ) -class CostaRicaSpeciesClassifier( - SpeciesClassifier, Resnet50Classifier +class TuringCostaRicaSpeciesClassifier( + SpeciesClassifier, Resnet50Classifier_KG ): - name = "Costa Rica Species Classifier" + name = "Turing Costa Rica Species Classifier" description = ( - "Trained on ___ by Turing" + "Trained on 13th May 2024 by Turing team using Resnet50 model." ) weights_path = ( - "turing-costarica_v02_state_resnet50_2024-01-08-11-14.pt" + "turing-costarica_v03_resnet50_2024-06-04-16-17_state.pt" ) labels_path = ( - "01_costarica_species_name_indices.json" + "03_costarica_data_category_map.json" + ) + + +class TuringUKSpeciesClassifier( + SpeciesClassifier, Resnet50Classifier_KG +): + name = "Turing UK Species Classifier" + description = ( + "Trained on 13th May 2024 by Turing team using Resnet50 model." ) + weights_path = ( + "turing-uk_v03_resnet50_2024-05-13-10-03_state.pt" + ) + labels_path = ( + "03_uk_data_category_map.json" + ) + class UKDenmarkMothSpeciesClassifierMixedResolution( From 913a5e484f36ac872672aa197afa32f2f38cacea Mon Sep 17 00:00:00 2001 From: KatrionaGoldmann Date: Thu, 6 Jun 2024 16:12:13 +0100 Subject: [PATCH 5/6] tidy --- README.md | 4 +++- trapdata/ml/models/classification.py | 6 ------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index bba14658..72728cdd 100644 --- a/README.md +++ b/README.md @@ -158,8 +158,10 @@ A script is available in the repo source to run the commands above. or wherever you set the appropriate dir in settings. The json file is simply a dict of species name and index. + Then you need to create a class in `trapdata/ml/models/classification.py` or `trapdata/ml/models/localization.py` and add the model details. + - To clear the cache: ``` - rm ~/Library/Application Support/trapdata/trapdata.db + rm ~/Library/Application\ Support/trapdata/trapdata.db ``` \ No newline at end of file diff --git a/trapdata/ml/models/classification.py b/trapdata/ml/models/classification.py index 755bf8af..48b37b24 100644 --- a/trapdata/ml/models/classification.py +++ b/trapdata/ml/models/classification.py @@ -117,21 +117,15 @@ def get_model(self): model = Resnet50(num_classes=num_classes) model = model.to(self.device) - logger.info("KG: check A") - # # state_dict = torch.hub.load_state_dict_from_url(weights_url) checkpoint = torch.load(self.weights, map_location=self.device) - logger.info("KG: check B") # # The model state dict is nested in some checkpoints, and not in others state_dict = checkpoint.get("model_state_dict") or checkpoint - logger.info("KG: check C") model.load_state_dict(state_dict) # model.load_state_dict(state_dict) - logger.info("KG: check D") model.eval() - print("KG: model eval complete") return model def get_transforms(self): From 7d2f4f6952cd85a786c8170fc2e613da6809da3f Mon Sep 17 00:00:00 2001 From: KatrionaGoldmann Date: Fri, 7 Jun 2024 10:08:47 +0100 Subject: [PATCH 6/6] update model description --- trapdata/ml/models/classification.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/trapdata/ml/models/classification.py b/trapdata/ml/models/classification.py index 48b37b24..5ae43613 100644 --- a/trapdata/ml/models/classification.py +++ b/trapdata/ml/models/classification.py @@ -105,26 +105,20 @@ def forward(self, x): return x -class Resnet50Classifier_KG(InferenceBaseClass): +class Resnet50Classifier_Turing(InferenceBaseClass): # function to run the Turing models - logger.info("KG: Resnet50Classifier_KG") + logger.info("KG: Resnet50Classifier_Turing") input_size = 300 def get_model(self): num_classes = len(self.category_map) - logger.info(f"KG: num_classes {num_classes}") - model = Resnet50(num_classes=num_classes) model = model.to(self.device) - - # # state_dict = torch.hub.load_state_dict_from_url(weights_url) checkpoint = torch.load(self.weights, map_location=self.device) - - # # The model state dict is nested in some checkpoints, and not in others + # The model state dict is nested in some checkpoints, and not in others state_dict = checkpoint.get("model_state_dict") or checkpoint model.load_state_dict(state_dict) - # model.load_state_dict(state_dict) model.eval() return model @@ -306,11 +300,11 @@ class QuebecVermontMothSpeciesClassifierMixedResolution( ) class TuringCostaRicaSpeciesClassifier( - SpeciesClassifier, Resnet50Classifier_KG + SpeciesClassifier, Resnet50Classifier_Turing ): name = "Turing Costa Rica Species Classifier" description = ( - "Trained on 13th May 2024 by Turing team using Resnet50 model." + "Trained on 4th June 2024 by Turing team using Resnet50 model." ) weights_path = ( "turing-costarica_v03_resnet50_2024-06-04-16-17_state.pt" @@ -321,7 +315,7 @@ class TuringCostaRicaSpeciesClassifier( class TuringUKSpeciesClassifier( - SpeciesClassifier, Resnet50Classifier_KG + SpeciesClassifier, Resnet50Classifier_Turing ): name = "Turing UK Species Classifier" description = (