import json import torch import numpy as np from sklearn.preprocessing import minmax_scale, StandardScaler from anonymization import DemoPoolAnonymizer, DemoRandomAnonymizer TAGS_TO_MODELS = { 'pool': 'pool_minmax_ecapa+xvector', 'random': 'random_in-scale_ecapa+xvector', 'pool raw': 'pool_raw_ecapa+xvector' } ANON_MODELS = { 'pool': DemoPoolAnonymizer, 'random': DemoRandomAnonymizer } class DemoAnonymizer: def __init__(self, model_path, model_tag, device): self.device = device self.scaling = None self.std_scaler = None self.model_tag = model_tag self.dim_ranges = self._load_dim_ranges(model_path / TAGS_TO_MODELS[model_tag]) self.anonymizer = self._load_anonymizer(model_path / TAGS_TO_MODELS[model_tag]) def anonymize_embedding(self, audio, sr): anon_embedding = self.anonymizer.anonymize_embedding(audio, sr) if self.dim_ranges: anon_embedding = self._scale_embedding(anon_embedding) return anon_embedding def _load_dim_ranges(self, model_dir): if (model_dir / 'stats_per_dim.json').exists(): with open(model_dir / 'stats_per_dim.json') as f: dim_ranges = json.load(f) return [(v['min'], v['max']) for k, v in sorted(dim_ranges.items(), key=lambda x: int(x[0]))] def _load_anonymizer(self, model_dir): model_name = model_dir.name.lower() if 'pool' in model_name: model_type = 'pool' else: model_type = 'random' print(f'Model type of anonymizer: {model_type}') model = ANON_MODELS[model_type](device=self.device, vec_type='ecapa+xvector') model.load_parameters(model_dir) if 'minmax' in model_name: # self.scaling = 'minmax' #elif 'std_scale' in model_name and model_type == 'pool': self.scaling = 'std' self.std_scaler = StandardScaler() self.std_scaler.fit(model.pool_embeddings.cpu().numpy()) return model def _scale_embedding(self, vector): if self.scaling == 'minmax': vector = vector.cpu().numpy() scaled_dims = [] for i in range(len(self.dim_ranges)): scaled_dims.append(minmax_scale(np.array([vector[i]]), self.dim_ranges[i])[0]) vector = torch.tensor(scaled_dims).to(self.device) elif self.scaling == 'std': vector = vector.unsqueeze(0).cpu().numpy() vector = torch.tensor(self.std_scaler.transform(vector)[0]) return vector