Urban 8k Train running with newest Lightning and pytorch
This commit is contained in:
		| @@ -1,6 +1,6 @@ | |||||||
| from typing import Union | from typing import Union | ||||||
|  |  | ||||||
| import torch | import numpy as np | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     import librosa |     import librosa | ||||||
| @@ -53,7 +53,7 @@ class NormalizeLocal(object): | |||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return f'{self.__class__.__name__}({self.__dict__})' |         return f'{self.__class__.__name__}({self.__dict__})' | ||||||
|  |  | ||||||
|     def __call__(self, x: torch.Tensor): |     def __call__(self, x: np.ndarray): | ||||||
|         mean = x.mean() |         mean = x.mean() | ||||||
|         std = x.std() + 0.0001 |         std = x.std() + 0.0001 | ||||||
|  |  | ||||||
| @@ -62,8 +62,8 @@ class NormalizeLocal(object): | |||||||
|         # Numpy Version |         # Numpy Version | ||||||
|         x = (x - mean) / std |         x = (x - mean) / std | ||||||
|  |  | ||||||
|         x[torch.isnan(x)] = 0 |         x[np.isnan(x)] = 0 | ||||||
|         x[torch.isinf(x)] = 0 |         x[np.isinf(x)] = 0 | ||||||
|  |  | ||||||
|         return x |         return x | ||||||
|  |  | ||||||
| @@ -76,13 +76,13 @@ class NormalizeMelband(object): | |||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return f'{self.__class__.__name__}({self.__dict__})' |         return f'{self.__class__.__name__}({self.__dict__})' | ||||||
|  |  | ||||||
|     def __call__(self, x: torch.Tensor): |     def __call__(self, x: np.ndarray): | ||||||
|         mean = x.mean(-1).unsqueeze(-1) |         mean = x.mean(-1).unsqueeze(-1) | ||||||
|         std = x.std(-1).unsqueeze(-1) |         std = x.std(-1).unsqueeze(-1) | ||||||
|  |  | ||||||
|         x = x.__sub__(mean).__div__(std) |         x = x.__sub__(mean).__div__(std) | ||||||
|         x[torch.isnan(x)] = 0 |         x[np.isnan(x)] = 0 | ||||||
|         x[torch.isinf(x)] = 0 |         x[np.isinf(x)] = 0 | ||||||
|         return x |         return x | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -100,8 +100,6 @@ class LibrosaAudioToMel(object): | |||||||
|         self.power_to_db = power_to_db |         self.power_to_db = power_to_db | ||||||
|  |  | ||||||
|     def __call__(self, y): |     def __call__(self, y): | ||||||
|         import numpy as np |  | ||||||
|  |  | ||||||
|         mel = librosa.feature.melspectrogram(y, **self.mel_kwargs) |         mel = librosa.feature.melspectrogram(y, **self.mel_kwargs) | ||||||
|         if self.amplitude_to_db: |         if self.amplitude_to_db: | ||||||
|             mel = librosa.amplitude_to_db(mel, ref=np.max) |             mel = librosa.amplitude_to_db(mel, ref=np.max) | ||||||
| @@ -121,7 +119,6 @@ class PowerToDB(object): | |||||||
|         return f'{self.__class__.__name__}({self.__dict__})' |         return f'{self.__class__.__name__}({self.__dict__})' | ||||||
|  |  | ||||||
|     def __call__(self, x): |     def __call__(self, x): | ||||||
|         import numpy as np |  | ||||||
|         if self.running_max is not None: |         if self.running_max is not None: | ||||||
|             self.running_max = max(np.max(x), self.running_max) |             self.running_max = max(np.max(x), self.running_max) | ||||||
|             return librosa.power_to_db(x, ref=self.running_max) |             return librosa.power_to_db(x, ref=self.running_max) | ||||||
| @@ -148,11 +145,11 @@ class MelToImage(object): | |||||||
|  |  | ||||||
|     def __call__(self, x): |     def __call__(self, x): | ||||||
|         # Source to Solution: https://stackoverflow.com/a/57204349 |         # Source to Solution: https://stackoverflow.com/a/57204349 | ||||||
|         mels = torch.log(x + 1e-9)  # add small number to avoid log(0) |         mels = np.log(x + 1e-9)  # add small number to avoid log(0) | ||||||
|  |  | ||||||
|         # min-max scale to fit inside 8-bit range |         # min-max scale to fit inside 8-bit range | ||||||
|         img = scale_minmax(mels, 0, 255).int() |         img = scale_minmax(mels, 0, 255) | ||||||
|         img = torch.flip(img, dims=(0,))  # put low frequencies at the bottom in image |         img = np.flip(img)  # put low frequencies at the bottom in image | ||||||
|         img = torch.as_tensor(255) - img  # invert. make black==more energy |         img = 255 - img  # invert. make black==more energy | ||||||
|         img = img.float() |         img = img.astype(np.float) | ||||||
|         return img |         return img | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ class _AudioToMelDataset(Dataset, ABC): | |||||||
|         self.audio_augmentations = audio_augmentations |         self.audio_augmentations = audio_augmentations | ||||||
|  |  | ||||||
|         self.dataset = TorchMelDataset(self.mel_file_path, sample_segment_len, sample_hop_len, label, |         self.dataset = TorchMelDataset(self.mel_file_path, sample_segment_len, sample_hop_len, label, | ||||||
|                                        self.audio_file_duration, mel_kwargs['sample_rate'], mel_kwargs['hop_length'], |                                        self.audio_file_duration, mel_kwargs['sr'], mel_kwargs['hop_length'], | ||||||
|                                        mel_kwargs['n_mels'], transform=mel_augmentations) |                                        mel_kwargs['n_mels'], transform=mel_augmentations) | ||||||
|  |  | ||||||
|     def _build_mel(self): |     def _build_mel(self): | ||||||
| @@ -70,7 +70,7 @@ class LibrosaAudioToMelDataset(_AudioToMelDataset): | |||||||
|         audio_file_path = Path(audio_file_path) |         audio_file_path = Path(audio_file_path) | ||||||
|         # audio_file, sampling_rate = librosa.load(self.audio_path, sr=sampling_rate) |         # audio_file, sampling_rate = librosa.load(self.audio_path, sr=sampling_rate) | ||||||
|         mel_kwargs = kwargs.get('mel_kwargs', dict()) |         mel_kwargs = kwargs.get('mel_kwargs', dict()) | ||||||
|         mel_kwargs.update(sr=mel_kwargs.get('sr', None) or librosa.get_samplerate(self.audio_path)) |         mel_kwargs.update(sr=mel_kwargs.get('sr', None) or librosa.get_samplerate(audio_file_path)) | ||||||
|         kwargs.update(mel_kwargs=mel_kwargs) |         kwargs.update(mel_kwargs=mel_kwargs) | ||||||
|  |  | ||||||
|         super(LibrosaAudioToMelDataset, self).__init__(audio_file_path, *args, **kwargs) |         super(LibrosaAudioToMelDataset, self).__init__(audio_file_path, *args, **kwargs) | ||||||
| @@ -84,11 +84,14 @@ class LibrosaAudioToMelDataset(_AudioToMelDataset): | |||||||
|         if self.reset: |         if self.reset: | ||||||
|             self.mel_file_path.unlink(missing_ok=True) |             self.mel_file_path.unlink(missing_ok=True) | ||||||
|         if not self.mel_file_path.exists(): |         if not self.mel_file_path.exists(): | ||||||
|  |             lockfile = Path(str(self.mel_file_path).replace(self.mel_file_path.suffix, '.lock')) | ||||||
|             self.mel_file_path.parent.mkdir(parents=True, exist_ok=True) |             self.mel_file_path.parent.mkdir(parents=True, exist_ok=True) | ||||||
|  |             lockfile.touch(exist_ok=False) | ||||||
|             raw_sample, _ = librosa.core.load(self.audio_path, sr=self.sampling_rate) |             raw_sample, _ = librosa.core.load(self.audio_path, sr=self.sampling_rate) | ||||||
|             mel_sample = self._mel_transform(raw_sample) |             mel_sample = self._mel_transform(raw_sample) | ||||||
|             with self.mel_file_path.open('wb') as mel_file: |             with self.mel_file_path.open('wb') as mel_file: | ||||||
|                 pickle.dump(mel_sample, mel_file, protocol=pickle.HIGHEST_PROTOCOL) |                 pickle.dump(mel_sample, mel_file, protocol=pickle.HIGHEST_PROTOCOL) | ||||||
|  |             lockfile.unlink(missing_ok=False) | ||||||
|         else: |         else: | ||||||
|             pass |             pass | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ class TorchMelDataset(Dataset): | |||||||
|         super(TorchMelDataset, self).__init__() |         super(TorchMelDataset, self).__init__() | ||||||
|         self.sampling_rate = sampling_rate |         self.sampling_rate = sampling_rate | ||||||
|         self.audio_file_len = audio_file_len |         self.audio_file_len = audio_file_len | ||||||
|         self.padding = AutoPadToShape((1, n_mels , sub_segment_len)) if auto_pad_to_shape else None |         self.padding = AutoPadToShape((n_mels , sub_segment_len)) if auto_pad_to_shape else None | ||||||
|         self.path = Path(mel_path) |         self.path = Path(mel_path) | ||||||
|         self.sub_segment_len = sub_segment_len |         self.sub_segment_len = sub_segment_len | ||||||
|         self.mel_hop_len = mel_hop_len |         self.mel_hop_len = mel_hop_len | ||||||
| @@ -29,7 +29,7 @@ class TorchMelDataset(Dataset): | |||||||
|         with self.path.open('rb') as mel_file: |         with self.path.open('rb') as mel_file: | ||||||
|             mel_spec = pickle.load(mel_file, fix_imports=True) |             mel_spec = pickle.load(mel_file, fix_imports=True) | ||||||
|         start = self.offsets[item] |         start = self.offsets[item] | ||||||
|         snippet = mel_spec[:, : , start: start + self.sub_segment_len] |         snippet = mel_spec[: , start: start + self.sub_segment_len] | ||||||
|         if self.transform: |         if self.transform: | ||||||
|             snippet = self.transform(snippet) |             snippet = self.transform(snippet) | ||||||
|         if self.padding: |         if self.padding: | ||||||
|   | |||||||
							
								
								
									
										0
									
								
								metrics/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								metrics/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										13
									
								
								metrics/_base_score.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								metrics/_base_score.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | from abc import ABC | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class _BaseScores(ABC): | ||||||
|  |  | ||||||
|  |     def __init__(self, lightning_model): | ||||||
|  |         self.model = lightning_model | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |     def __call__(self, outputs): | ||||||
|  |         # summary_dict = dict() | ||||||
|  |         # return summary_dict | ||||||
|  |         raise NotImplementedError | ||||||
							
								
								
									
										56
									
								
								metrics/binary_class_classifictaion.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								metrics/binary_class_classifictaion.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | import numpy as np | ||||||
|  |  | ||||||
|  | import torch | ||||||
|  | from sklearn.ensemble import IsolationForest | ||||||
|  | from sklearn.metrics import recall_score, roc_auc_score, average_precision_score | ||||||
|  |  | ||||||
|  | from ml_lib.metrics._base_score import _BaseScores | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BinaryScores(_BaseScores): | ||||||
|  |  | ||||||
|  |     def __init__(self, *args): | ||||||
|  |         super(BinaryScores, self).__init__(*args) | ||||||
|  |  | ||||||
|  |     def __call__(self, outputs): | ||||||
|  |         summary_dict = dict() | ||||||
|  |  | ||||||
|  |         # Additional Score like the unweighted Average Recall: | ||||||
|  |         ######################### | ||||||
|  |         # UnweightedAverageRecall | ||||||
|  |         y_true = torch.cat([output['batch_y'] for output in outputs]) .cpu().numpy() | ||||||
|  |         y_pred = torch.cat([output['element_wise_recon_error'] for output in outputs]).squeeze().cpu().numpy() | ||||||
|  |  | ||||||
|  |         # How to apply a threshold manualy | ||||||
|  |         # y_pred = (y_pred >= 0.5).astype(np.float32) | ||||||
|  |  | ||||||
|  |         # How to apply a threshold by IF (Isolation Forest) | ||||||
|  |         clf = IsolationForest(random_state=self.model.seed) | ||||||
|  |         y_score = clf.fit_predict(y_pred.reshape(-1,1)) | ||||||
|  |         y_score = (np.asarray(y_score) == -1).astype(np.float32) | ||||||
|  |  | ||||||
|  |         uar_score = recall_score(y_true, y_score, labels=[0, 1], average='macro', | ||||||
|  |                                  sample_weight=None, zero_division='warn') | ||||||
|  |         summary_dict.update(dict(uar_score=uar_score)) | ||||||
|  |         ######################### | ||||||
|  |         # Precission | ||||||
|  |         precision_score = average_precision_score(y_true, y_score) | ||||||
|  |         summary_dict.update(dict(precision_score=precision_score)) | ||||||
|  |  | ||||||
|  |         ######################### | ||||||
|  |         # AUC | ||||||
|  |         try: | ||||||
|  |             auc_score = roc_auc_score(y_true=y_true, y_score=y_score) | ||||||
|  |             summary_dict.update(dict(auc_score=auc_score)) | ||||||
|  |         except ValueError: | ||||||
|  |             summary_dict.update(dict(auc_score=-1)) | ||||||
|  |  | ||||||
|  |         ######################### | ||||||
|  |         # pAUC | ||||||
|  |         try: | ||||||
|  |             pauc = roc_auc_score(y_true=y_true, y_score=y_score, max_fpr=0.15) | ||||||
|  |             summary_dict.update(dict(pauc_score=pauc)) | ||||||
|  |         except ValueError: | ||||||
|  |             summary_dict.update(dict(pauc_score=-1)) | ||||||
|  |  | ||||||
|  |         return summary_dict | ||||||
							
								
								
									
										129
									
								
								metrics/multi_class_classification.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								metrics/multi_class_classification.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | |||||||
|  | from itertools import cycle | ||||||
|  |  | ||||||
|  | import numpy as np | ||||||
|  | import torch | ||||||
|  | from sklearn.metrics import f1_score, roc_curve, auc, roc_auc_score, ConfusionMatrixDisplay, confusion_matrix | ||||||
|  |  | ||||||
|  | from ml_lib.metrics._base_score import _BaseScores | ||||||
|  | from ml_lib.utils.tools import to_one_hot | ||||||
|  |  | ||||||
|  | from matplotlib import pyplot as plt | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class MultiClassScores(_BaseScores): | ||||||
|  |  | ||||||
|  |     def __init__(self, *args): | ||||||
|  |         super(MultiClassScores, self).__init__(*args) | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |     def __call__(self, outputs): | ||||||
|  |         summary_dict = dict() | ||||||
|  |         ####################################################################################### | ||||||
|  |         # Additional Score  -  UAR  -  ROC  -  Conf. Matrix  -  F1 | ||||||
|  |         ####################################################################################### | ||||||
|  |         # | ||||||
|  |         # INIT | ||||||
|  |         y_true = torch.cat([output['batch_y'] for output in outputs]).cpu().numpy() | ||||||
|  |         y_true_one_hot = to_one_hot(y_true, self.model.n_classes) | ||||||
|  |  | ||||||
|  |         y_pred = torch.cat([output['y'] for output in outputs]).squeeze().cpu().float().numpy() | ||||||
|  |         y_pred_max = np.argmax(y_pred, axis=1) | ||||||
|  |  | ||||||
|  |         class_names = {val: key for key, val in self.model.dataset.test_dataset.classes.items()} | ||||||
|  |         ###################################################################################### | ||||||
|  |         # | ||||||
|  |         # F1 SCORE | ||||||
|  |         micro_f1_score = f1_score(y_true, y_pred_max, labels=None, pos_label=1, average='micro', sample_weight=None, | ||||||
|  |                                   zero_division=True) | ||||||
|  |         macro_f1_score = f1_score(y_true, y_pred_max, labels=None, pos_label=1, average='macro', sample_weight=None, | ||||||
|  |                                   zero_division=True) | ||||||
|  |         summary_dict.update(dict(micro_f1_score=micro_f1_score, macro_f1_score=macro_f1_score)) | ||||||
|  |  | ||||||
|  |         ####################################################################################### | ||||||
|  |         # | ||||||
|  |         # ROC Curve | ||||||
|  |  | ||||||
|  |         # Compute ROC curve and ROC area for each class | ||||||
|  |         fpr = dict() | ||||||
|  |         tpr = dict() | ||||||
|  |         roc_auc = dict() | ||||||
|  |         for i in range(self.model.n_classes): | ||||||
|  |             fpr[i], tpr[i], _ = roc_curve(y_true_one_hot[:, i], y_pred[:, i]) | ||||||
|  |             roc_auc[i] = auc(fpr[i], tpr[i]) | ||||||
|  |  | ||||||
|  |         # Compute micro-average ROC curve and ROC area | ||||||
|  |         fpr["micro"], tpr["micro"], _ = roc_curve(y_true_one_hot.ravel(), y_pred.ravel()) | ||||||
|  |         roc_auc["micro"] = auc(fpr["micro"], tpr["micro"]) | ||||||
|  |  | ||||||
|  |         # First aggregate all false positive rates | ||||||
|  |         all_fpr = np.unique(np.concatenate([fpr[i] for i in range(self.model.n_classes)])) | ||||||
|  |  | ||||||
|  |         # Then interpolate all ROC curves at this points | ||||||
|  |         mean_tpr = np.zeros_like(all_fpr) | ||||||
|  |         for i in range(self.model.n_classes): | ||||||
|  |             mean_tpr += np.interp(all_fpr, fpr[i], tpr[i]) | ||||||
|  |  | ||||||
|  |         # Finally average it and compute AUC | ||||||
|  |         mean_tpr /= self.model.n_classes | ||||||
|  |  | ||||||
|  |         fpr["macro"] = all_fpr | ||||||
|  |         tpr["macro"] = mean_tpr | ||||||
|  |         roc_auc["macro"] = auc(fpr["macro"], tpr["macro"]) | ||||||
|  |  | ||||||
|  |         # Plot all ROC curves | ||||||
|  |         plt.figure() | ||||||
|  |         plt.plot(fpr["micro"], tpr["micro"], | ||||||
|  |                  label=f'micro ROC ({round(roc_auc["micro"], 2)})', | ||||||
|  |                  color='deeppink', linestyle=':', linewidth=4) | ||||||
|  |  | ||||||
|  |         plt.plot(fpr["macro"], tpr["macro"], | ||||||
|  |                  label=f'macro ROC({round(roc_auc["macro"], 2)})', | ||||||
|  |                  color='navy', linestyle=':', linewidth=4) | ||||||
|  |  | ||||||
|  |         colors = cycle(['firebrick', 'orangered', 'gold', 'olive', 'limegreen', 'aqua', | ||||||
|  |                         'dodgerblue', 'slategrey', 'royalblue', 'indigo', 'fuchsia'], ) | ||||||
|  |  | ||||||
|  |         for i, color in zip(range(self.model.n_classes), colors): | ||||||
|  |             plt.plot(fpr[i], tpr[i], color=color, lw=2, label=f'{class_names[i]} ({round(roc_auc[i], 2)})') | ||||||
|  |  | ||||||
|  |         plt.plot([0, 1], [0, 1], 'k--', lw=2) | ||||||
|  |         plt.xlim([0.0, 1.0]) | ||||||
|  |         plt.ylim([0.0, 1.05]) | ||||||
|  |         plt.xlabel('False Positive Rate') | ||||||
|  |         plt.ylabel('True Positive Rate') | ||||||
|  |         plt.legend(loc="lower right") | ||||||
|  |  | ||||||
|  |         self.model.logger.log_image('ROC', image=plt.gcf(), step=self.model.current_epoch) | ||||||
|  |         # self.model.logger.log_image('ROC', image=plt.gcf(), step=self.model.current_epoch, ext='pdf') | ||||||
|  |         plt.clf() | ||||||
|  |  | ||||||
|  |         ####################################################################################### | ||||||
|  |         # | ||||||
|  |         # ROC AUC SCORE | ||||||
|  |  | ||||||
|  |         try: | ||||||
|  |             macro_roc_auc_ovr = roc_auc_score(y_true_one_hot, y_pred, multi_class="ovr", | ||||||
|  |                                               average="macro") | ||||||
|  |             summary_dict.update(macro_roc_auc_ovr=macro_roc_auc_ovr) | ||||||
|  |         except ValueError: | ||||||
|  |             micro_roc_auc_ovr = roc_auc_score(y_true_one_hot, y_pred, multi_class="ovr", | ||||||
|  |                                               average="micro") | ||||||
|  |             summary_dict.update(micro_roc_auc_ovr=micro_roc_auc_ovr) | ||||||
|  |  | ||||||
|  |         ####################################################################################### | ||||||
|  |         # | ||||||
|  |         # Confusion matrix | ||||||
|  |  | ||||||
|  |         cm = confusion_matrix([class_names[x] for x in y_true], [class_names[x] for x in y_pred_max], | ||||||
|  |                               labels=[class_names[key] for key in class_names.keys()], | ||||||
|  |                               normalize='all') | ||||||
|  |         disp = ConfusionMatrixDisplay(confusion_matrix=cm, | ||||||
|  |                                       display_labels=[class_names[i] for i in range(self.model.n_classes)] | ||||||
|  |                                       ) | ||||||
|  |         disp.plot(include_values=True) | ||||||
|  |  | ||||||
|  |         self.model.logger.log_image('Confusion_Matrix', image=disp.figure_, step=self.model.current_epoch) | ||||||
|  |         # self.model.logger.log_image('Confusion_Matrix', image=disp.figure_, step=self.model.current_epoch, ext='pdf') | ||||||
|  |  | ||||||
|  |         plt.close('all') | ||||||
|  |         return summary_dict | ||||||
		Reference in New Issue
	
	Block a user
	 Si11ium
					Si11ium