Uwaga: Poniższy artykuł pomoże Ci w: Przewodnik po nauce metryk PyTorch: biblioteka do implementacji algorytmów uczenia się metryk
Uczenie się metryczne jest definiowane jako uczenie się funkcji odległości na wielu obiektach. PyTorch Metric Learning (PML) to biblioteka typu open source, która ułatwia żmudne i czasochłonne zadanie wdrażania różnych algorytmów głębokiego uczenia się metryk. Został wprowadzony przez Kevina Musgrave’a i Serge’a Belongie z Cornell Tech i Ser-Nam Lim z Facebook AI w sierpniu 2020 r. (artykuł badawczy).
Elastyczna i modułowa konstrukcja biblioteki PML umożliwia implementację różnych kombinacji algorytmów w istniejącym kodzie. Kilka algorytmów można również łączyć w celu uzyskania kompletnego przepływu pracy pociągu/testu.
Moduły nauki PyTorch Metric
- Straty – klasy do stosowania różnych funkcji stratDistances – obejmują klasy, które obliczają odległości parami lub podobieństwa między osadzaniami wejściowymiReducers – określają sposoby przejścia od kilku wartości strat do jednej wartości stratyRegularizers – stosowane do wag i osadzeń w celu regularyzacji.
PML zapewnia dwa rodzaje funkcji eksploracji:
- Podzbiór górników wsadowychTuple górników
- Samplery – są rozszerzeniami klasy torch.utils.data.Sampler. Określają, w jaki sposób powinny być tworzone partie próbek. Trainers – moduł Trainers zapewnia dostęp do algorytmów uczenia metryk, które oprócz funkcji utraty lub eksploracji wymagają rozszerzenia danych, dodatkowych sieci itp. Testerzy – przyjmują model i zbiór danych jako dane wejściowe i znajdź metryki dokładności oparte na najbliższym sąsiedztwie. (Korzystanie z testerów wymaga instalacji pakietu faiss)Utils
- Klasa AccuracyCalculator do obliczania kilku metryk dokładności na podstawie zapytania i osadzania referencji Modele wnioskowania: utils.inference zawiera klasy do znajdowania pasujących par w ramach partii lub z zestawu parLogging Presets – Moduł logging_presets zapewnia haczyki do logowania danych, wczesne zatrzymanie podczas szkolenia, sprawdzanie i zapisywanie modeli. Wymaga pakietów rejestratora i tablicy tensorowej, które należy zainstalować w następujący sposób:
pip zainstaluj tensorboard opiekuna rekordów
Poniższy rysunek przedstawia przegląd głównych modułów biblioteki PML:
Składowe funkcji straty:
Źródło obrazów: Artykuł badawczy
Wymagana wersja PyTorch do PyTorch Metric Learning
- pytorch-metric-learning >= v0.9.90 wymaga palnika >= 1.6pytorch-metric-learning = 1.2
Praktyczne wdrożenie PyTorch Metric Learning
Oto demonstracja użycia trenera TrainWithClassifier PML na zbiorze danych CIFAR100. Kod został zaimplementowany w Google colab z Pyton 3.7.10 I latarka 1.8.0 wersje. Wyjaśnienie kodu krok po kroku wygląda następująco:
- Zainstaluj wymagane pakiety
#Install PML !pip install -q pytorch-metric-learning[with-hooks]
#Install record keeper dla rejestrowania informacji !pip install record_keeper
- Zaimportuj wymagane biblioteki
%matplotlib inline z pytorch_metric_learning import loss, górnicy, samplery, trenerzy, testerzy z pytorch_metric_learning.utils import common_functions import pytorch_metric_learning.utils.logging_presets jako logging_presets import numpy jako np import torchvision z torchvision import zestawów danych, przekształca import latarka import torch.nn jako nn z Import PIL Import obrazu logging import matplotlib.pyplot as plt import umap from cycler import cycler import record_keeper import pytorch_metric_learning logging.getLogger().setLevel(logging.INFO) logging.info(“VERSION %s”%pytorch_metric_learning.__version__) Zdefiniuj model
3. Zdefiniuj model
class MLP(nn.Module): #wielowarstwowy model perceptronu # rozmiary[0] jest wymiarem wejściowych # rozmiarów[-1] jest wymiarem wyjścia def __init__(self, layerSizes, final_relu=False): #constructor method super().__init__() #refer to the base class list = [] #lista rozmiarów warstw modelu = [int(x) for x in sizes] #liczba neuronów w każdej warstwie num = len(sizes) – 1 #liczba warstw #warstwa wyjściowa final_relu_layer = num if final_relu else num – 1
dla i w zakresie (dł. (rozmiary) – 1): #dla każdej warstwy ip_size = rozmiary[i] #liczba cech wejściowych op_size = rozmiary[i + 1] #liczba cech wyjściowych if i 4. Określ urządzenie, do którego zostanie przydzielony torch.Tensor
urządzenie = torch.device(“cuda” jeśli torch.cuda.is_available() else “cpu”)
5. Ustaw model pnia i zastąp warstwę softmax funkcją tożsamości
Tutaj wykorzystaliśmy 18-warstwową głęboką sieć konwolucyjną (ResNet18)
trunk = torchvision.models.resnet18(pretrained=True) trunk_output_size = trunk.fc.in_features #liczba wejść dla warstwy liniowej trunk.fc = common_functions.Identity() #w pełni połączona warstwa trunk = torch.nn.DataParallel(trunk.to (urządzenie)) #torch.Tensor.to() wykonuje konwersję urządzenia
6. Ustaw model osadzania. Dane wyjściowe modelu pnia są podawane do niego jako dane wejściowe i wyprowadzane są 64-wymiarowe osadzenia.
emb = latarka.nn.DataParallel(MLP([trunk_output_size, 64]).do urządzenia))
7. Zestaw szkoleniowy w tym miejscu zawiera pierwsze 50 klas zestawu danych CIFAR100. Zdefiniuj klasyfikator, który przyjmie osadzenie jako dane wejściowe i wyprowadzi 50-wymiarowy wektor.
klasyfikator = latarka.nn.DataParallel(MLP([64, 50])).do urządzenia)
8. Zainicjuj optymalizatory
Zastosowaliśmy algorytm optymalizacyjny Adama
#optymalizuj model linii trunk_opt = torch.optim.Adam(trunk.parameters(), lr=00,00001, ubytek_wagi=0.0001)szybkość ning #’lr’ oznacza lear #optimize embedder embedder_opt = torch.optim.Adam(emb.parameters(), lr=00,0001, ubytek_wagi=0.0001) optymalizacja_klasyfikatora = latarka.optymalizacja.Adam(klasyfikator.parametry(), lr=00,0001, ubytek_wagi=00,0001)
9. Ustaw przekształcenia obrazu
#Dla treningu danych train_trf = transforms.Compose([transforms.Resize(64),
#compose man image transforms simultaneously
#crop the image to specified aspect ratio and size
transforms.RandomResizedCrop(scale=(0.16, 1), ratio=(0.75,
1.33),size=64),
#Randomly flip the images horizontally with 50% probability
transforms.RandomHorizontalFlip(0.5),
#Convert the images to tenors
transforms.ToTensor(),
#Normalize the tensor image with specified mean and standard deviation
transforms.Normalize(mean=[0.485, 0.456, 0.406]std=[0.229,
0.224, 0.225])]) #Powtórz podobny proces dla sprawdzania poprawności danych val_transform = transforms.Compose([transforms.Resize(64),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406]std=[0.229, 0.224, 0.225])])
10. Pobierz oryginalne zestawy danych uczących i sprawdzających
orig_train = datasets.CIFAR100(root=”CIFAR100_Dataset”, train=True, transform=None, download=True) orig_val = datasets.CIFAR100(root=”CIFAR100_Dataset”, train=False, transform=None, download=True)
11. Utwórz zbiory uczące i walidacyjne, które są rozłączne klasowo
class ClassDisjointCIFAR100(torch.utils.data.Dataset): def __init__(self, orig_train, orig_val, train, transform): #Utwórz regułę wyboru próbek należących do pierwszych 50 kategorii wyjściowych rule = (lambda x: x =50) #zaktualizuj zbiory treningowe i walidacyjne o wyżej zdefiniowaną regułę #indeks odpowiednich rekordów train_new = [i for i,x in enumerate(orig_train.targets) if rule(x)]
wartość_nowa = [i for i,x in enumerate(orig_val.targets) if rule(x)]
#dodaj zaktualizowane dane i odpowiednie etykiety self.data = np.concatenate([orig_train.data[train_new]orig_val.data[val_new]], oś=0) self.targets = np.concatenate([np.array(orig_train.targets)
[train_new],p.tablica(orig_val.cele)[val_new]], oś=0) self.transform = transform def __len__(self): #funkcja do pobrania długości zaktualizowanych danych return len(self.data) def __getitem__(self, index): #funkcja do wyodrębnienia obrazu i odpowiedniej etykiety img, target = self.data[index]własne.cele[index]
img = Image.fromarray(img) #tworzy pamięć obrazu z obiektu, jeśli self.transform nie ma wartości None: img = self.transform(img) #wykonaj transformację obrazu return img, target
12. Zainicjuj rozłączny zestaw uczący i sprawdzający poprawność klas
train_set = ClassDisjointCIFAR100(orig_train, origl_val, True, t rain_transform) val_set = ClassDisjointCIFAR100(orig_train, orig_val, False, val_transform) #debuguj kod, aby sprawdzić, czy klasy są rozłączne, używając słowa kluczowego assert assert set(train_set.targets).isdisjoint(set( val_set.targets))
13. Zainicjuj funkcję utraty
strata = straty.TripletMarginLoss(margin=0.1) #Utrata klasyfikacji clf_loss = torch.nn.CrossEntropyLoss()
14. Zainicjuj funkcję wyszukiwania
m = górnicy.MultiSimilarityMiner(epsilon=0.1)
Ustaw próbnik modułu ładującego dane; jeśli nie określono, stosuje się losowe pobieranie próbek
smpl = samplers.MPerClassSampler(train_dataset.targets, m=4length_before_new_iter=len(train_dataset))
Ustaw inne parametry treningu
rozmiar_wsadu = 32 epoki = 4 #liczba epok
15. Tworzyć słownik ww. modeli, optymalizatorów, funkcji straty i funkcji eksploracji
models = {“trunk”: trunk, “embedder”: embedder, “classifier”: klasyfikator} opt = {“trunk_optimizer”: optymalizator_trunk, “embedder_optimizer”: embedder_optimizer, “classifier_optimizer”: optymalizator_klasyfikatora} loss_f = {“metric_loss”: strata , “classifier_loss”: conversion_loss} mining_f = {“tuple_miner”: górnik} # Określ wagi strat loss_wts = {“metric_loss”: 1″utrata_klasyfikatora”: 0.5} #a słownik odwzorowujący nazwy strat na liczby
16. Stwórz hooki szkoleniowe i testowe za pomocą modułu logging_presets
record_keeper, _, _ = logging_presets.get_record_keeper(“logs”, “tensorboard”) hooks = logging_presets.get_hook_container(record_keeper) dataset_dictionary = {“zestaw walidacyjny”: val_set} model_folder = “zapisane_modele”
17. Zdefiniuj funkcję haka wizualizatora
def visualizer_hook(umapper, umap_embeddings, labels, split_name, keyname, *args): logging.info(“Wykres UMAP dla podziału {} i zestawu etykiet {}”.format(split_name, keyname)) #logging.info() logs komunikat z poziomem INFO na loggerze label_set = np.unique(labels) #unique labels num_classes = len(label_set) #ilość klas wyjściowych fig = plt.figure(figsize=(20,15)) plt.gca(). set_prop_cycle(cykler(“kolor”, [plt.cm.nipy_spectral(i) for i
in np.linspace(0, 0.9, num_classes)])) #matplotlib.pyplot.gca() użyty powyżej służy do pobierania bieżących osi, a matplotlib.axes.Axes.set_prop_cycle() ustawia cykl właściwości osi dla i w zakresie (liczba_klas): #get indeks rekordów mających i unikalny indeks etykiety = etykiety == zestaw_etykiet[i]
plt.plot(umap_embeddings[index, 0]umap_osadzenia[index, 1]„.”, rozmiar znacznika =1) plt.pokaż()
UMAP (Uniform Manifold Approximation and Projection) to technika redukcji wymiarów, którą można wykorzystać do wizualizacji.
18. Utwórz testera
test = testers.GlobalEmbeddingSpaceTester(end_of_testing_hook = hooks.end_of_testing_hook,visualizer = umap.UMAP(), visualizer_hook = visualizer_hook,dataloader_num_workers = 32)
testers.GlobalEmbeddingSpaceTester() znajduje najbliższych sąsiadów, biorąc pod uwagę wszystkie punkty w przestrzeni osadzania
19. Zainicjuj hak na koniec epoki. Wykonuje pewne operacje, takie jak rejestrowanie danych na końcu każdej epoki.
end_of_epoch = hooks.end_of_epoch_hook(tester, dataset_dictionay, model_folder, test_interval = 1cierpliwość = 1)
20. Wzorowy trener
Ponieważ mamy model magistrali -> model osadzania -> architektura klasyfikatora, użyliśmy trenera TrainWithClassifier. Stosuje stratę metryczną i stratę klasyfikacyjną odpowiednio do wyjścia sieci embedder i wyjścia sieci klasyfikatora.
trainer = trainers.TrainWithClassifier(models, Opt, #optimizers batch_size, loss_f, #loss function mining_f, #mining function train_set, sampler=smpl, dataloader_num_workers = 32, loss_weights = loss_wts, end_of_iteration_hook = hooks.end_of_iteration_hook, end_of_epoch_hook = end_of_epoch)
21. Szkolenie modelowe
trainer.train(num_epochs=epochs)
Przykładowe wykresy wyjściowe przez dwie epoki:
Bibliografia
Szczegółowe informacje na temat biblioteki PML można znaleźć w następujących źródłach: