L’intorno della classe di un set di dati può essere appreso utilizzando la perdita morbida del vicino più vicino
In questo articolo, discutiamo come implementare la perdita soft del vicino più vicino di cui abbiamo anche parlato Qui.
RL’epresentation learning è il compito di apprendere le caratteristiche più salienti di un dato set di dati da parte di una rete neurale profonda. Di solito è un compito implicito svolto in un paradigma di apprendimento supervisionato ed è un fattore cruciale per il successo del deep learning (Križevskij et al., 2012; Lui et al., 2016; Simonyan et al., 2014). In altre parole, l’apprendimento delle rappresentazioni automatizza il processo di estrazione delle caratteristiche. Con questo, possiamo utilizzare le rappresentazioni apprese per compiti a valle come classificazione, regressione e sintesi.
Possiamo anche influenzare il modo in cui si formano le rappresentazioni apprese per soddisfare casi d’uso specifici. Nel caso della classificazione, le rappresentazioni sono predisposte per avere punti dati della stessa classe da raggruppare insieme, mentre per la generazione (ad esempio nei GAN), le rappresentazioni sono predisposte per avere punti di dati reali che si raggruppano con quelli sintetizzati.
Nello stesso senso, abbiamo apprezzato l’uso dell’analisi delle componenti principali (PCA) per codificare le funzionalità per le attività a valle. Tuttavia, non disponiamo di informazioni su classi o etichette nelle rappresentazioni codificate PCA, quindi le prestazioni sulle attività downstream potrebbero essere ulteriormente migliorate. Possiamo migliorare le rappresentazioni codificate approssimando le informazioni sulla classe o sull’etichetta in essa contenute apprendendo la struttura delle vicinanze del set di dati, ovvero quali caratteristiche sono raggruppate insieme, e tali cluster implicherebbero che le caratteristiche appartengono alla stessa classe secondo l’ipotesi di clustering in la letteratura sull’apprendimento semi-supervisionato (Chapelle et al., 2009).
Per integrare la struttura dell’intorno nelle rappresentazioni, sono state introdotte molteplici tecniche di apprendimento come gli embedding localmente lineari o LLE (Roweis e Saul, 2000), analisi delle componenti del quartiere o NCA (Hinton et al., 2004) e t-incorporamento stocastico dei vicini o t-SNE (Maaten e Hinton, 2008).
Tuttavia, le molteplici tecniche di apprendimento sopra menzionate presentano i loro inconvenienti. Ad esempio, sia LLE che NCA codificano incorporamenti lineari invece di incorporamenti non lineari. Nel frattempo, gli incorporamenti t-SNE risultano in strutture diverse a seconda degli iperparametri utilizzati.
Per evitare tali inconvenienti, possiamo utilizzare un algoritmo NCA migliorato che è il perdita morbida del vicino più vicino o SNNL (Salakhutdinov e Hinton, 2007; Frost et al., 2019). Il SNNL migliora l’algoritmo NCA introducendo la non linearità e viene calcolato per ogni strato nascosto di una rete neurale anziché esclusivamente sull’ultimo strato di codifica. Questa funzione di perdita viene utilizzata per ottimizzare il intreccio di punti in un set di dati.
In questo contesto, intreccio è definito come quanto i punti dati di classe simile sono vicini tra loro rispetto ai punti dati di classe diversa. Un basso entanglement significa che i punti dati di classi simili sono molto più vicini tra loro rispetto ai punti dati di classi diverse (vedere Figura 1). Avere un tale insieme di punti dati renderà le attività downstream molto più facili da realizzare con prestazioni ancora migliori. Frost et al. (2019) hanno ampliato l’obiettivo SNNL introducendo un fattore di temperatura T. Dandoci così la seguente funzione di perdita finale,
Dove D è una metrica della distanza sulle funzionalità di input grezze o sulle rappresentazioni di livelli nascosti di una rete neurale e T è il fattore di temperatura che è direttamente proporzionale alle distanze tra i punti dati in uno strato nascosto. Per questa implementazione, utilizziamo la distanza coseno come metrica della distanza per calcoli più stabili.
Lo scopo di questo articolo è aiutare i lettori a comprendere e implementare la perdita morbida del vicino più vicino, quindi analizzeremo la funzione di perdita per comprenderla meglio.
Metrica della distanza
La prima cosa che dovremmo calcolare sono le distanze tra i punti dati, che sono le caratteristiche di input grezze o le rappresentazioni dei livelli nascosti della rete.
Per la nostra implementazione, utilizziamo la metrica della distanza coseno (Figura 3) per calcoli più stabili. Per il momento ignoriamo i sottoinsiemi indicati ij E IO nella figura sopra e concentriamoci solo sul calcolo della distanza coseno tra i nostri punti dati di input. Realizziamo ciò attraverso il seguente codice PyTorch:
normalized_a = torch.nn.functional.normalize(features, dim=1, p=2)
normalized_b = torch.nn.functional.normalize(features, dim=1, p=2)
normalized_b = torch.conj(normalized_b).T
product = torch.matmul(normalized_a, normalized_b)
distance_matrix = torch.sub(torch.tensor(1.0), product)
Nel frammento di codice riportato sopra, normalizziamo innanzitutto le caratteristiche di input nelle righe 1 e 2 utilizzando la norma euclidea. Quindi, nella riga 3, otteniamo la trasposizione coniugata del secondo insieme di caratteristiche di input normalizzate. Calcoliamo la trasposizione coniugata a tenere conto di vettori complessi. Nelle righe 4 e 5 calcoliamo la somiglianza del coseno e la distanza delle caratteristiche di input.
Concretamente, considera il seguente insieme di funzionalità,
tensor((( 1.0999, -0.9438, 0.7996, -0.4247),
( 1.2150, -0.2953, 0.0417, -1.2913),
( 1.3218, 0.4214, -0.1541, 0.0961),
(-0.7253, 1.1685, -0.1070, 1.3683)))
Utilizzando la metrica della distanza che abbiamo definito sopra, otteniamo la seguente matrice di distanza,
tensor((( 0.0000e+00, 2.8502e-01, 6.2687e-01, 1.7732e+00),
( 2.8502e-01, 0.0000e+00, 4.6293e-01, 1.8581e+00),
( 6.2687e-01, 4.6293e-01, -1.1921e-07, 1.1171e+00),
( 1.7732e+00, 1.8581e+00, 1.1171e+00, -1.1921e-07)))
Probabilità di campionamento
Ora possiamo calcolare la matrice che rappresenta la probabilità di scegliere ciascuna caratteristica date le sue distanze a coppie da tutte le altre caratteristiche. Questa è semplicemente la probabilità di raccolta io punti in base alle distanze tra loro io E J O K punti.
Possiamo calcolarlo attraverso il seguente codice:
pairwise_distance_matrix = torch.exp(
-(distance_matrix / temperature)
) - torch.eye(features.shape(0)).to(model.device)
Il codice calcola innanzitutto l’esponenziale del negativo della matrice della distanza diviso per il fattore di temperatura, scalando i valori a valori positivi. Il fattore temperatura determina come controllare l’importanza data alle distanze tra coppie di punti, ad esempio, a basse temperature, la perdita è dominata da piccole distanze mentre le distanze effettive tra rappresentazioni ampiamente separate diventano meno rilevanti.
Prima della sottrazione di torch.eye(features.shape(0))
(aka matrice diagonale), il tensore era il seguente,
tensor(((1.0000, 0.7520, 0.5343, 0.1698),
(0.7520, 1.0000, 0.6294, 0.1560),
(0.5343, 0.6294, 1.0000, 0.3272),
(0.1698, 0.1560, 0.3272, 1.0000)))
Sottraiamo una matrice diagonale dalla matrice delle distanze per rimuovere tutti i termini di autosimilarità (cioè la distanza o la somiglianza di ciascun punto rispetto a se stesso).
Successivamente, possiamo calcolare la probabilità di campionamento per ciascuna coppia di punti dati tramite il seguente codice:
pick_probability = pairwise_distance_matrix / (
torch.sum(pairwise_distance_matrix, 1).view(-1, 1)
+ stability_epsilon
)
Probabilità del campionamento mascherato
Finora, la probabilità di campionamento che abbiamo calcolato non contiene alcuna informazione sull’etichetta. Integriamo le informazioni dell’etichetta nella probabilità di campionamento mascherandole con le etichette del set di dati.
Innanzitutto, dobbiamo derivare una matrice a coppie dai vettori delle etichette:
masking_matrix = torch.squeeze(
torch.eq(labels, labels.unsqueeze(1)).float()
)
Applichiamo la matrice di mascheramento per utilizzare le informazioni dell’etichetta per isolare le probabilità per i punti che appartengono alla stessa classe:
masked_pick_probability = pick_probability * masking_matrix
Successivamente, calcoliamo la probabilità somma per campionare una particolare caratteristica calcolando la somma della probabilità di campionamento mascherato per riga,
summed_masked_pick_probability = torch.sum(masked_pick_probability, dim=1)
Infine, possiamo calcolare il logaritmo della somma delle probabilità di campionamento per le caratteristiche per comodità computazionale con un’ulteriore variabile di stabilità computazionale e fare in modo che la media agisca come la perdita del vicino più vicino per la rete,
snnl = torch.mean(
-torch.log(summed_masked_pick_probability + stability_epsilon
)
Ora possiamo mettere insieme questi componenti in una funzione di passaggio in avanti per calcolare la perdita morbida del vicino più vicino su tutti gli strati di una rete neurale profonda,
def forward(
self,
model: torch.nn.Module,
features: torch.Tensor,
labels: torch.Tensor,
outputs: torch.Tensor,
epoch: int,
) -> Tuple:
if self.use_annealing:
self.temperature = 1.0 / ((1.0 + epoch) ** 0.55)primary_loss = self.primary_criterion(
outputs, features if self.unsupervised else labels
)
activations = self.compute_activations(model=model, features=features)
layers_snnl = ()
for key, value in activations.items():
value = value(:, : self.code_units)
distance_matrix = self.pairwise_cosine_distance(features=value)
pairwise_distance_matrix = self.normalize_distance_matrix(
features=value, distance_matrix=distance_matrix
)
pick_probability = self.compute_sampling_probability(
pairwise_distance_matrix
)
summed_masked_pick_probability = self.mask_sampling_probability(
labels, pick_probability
)
snnl = torch.mean(
-torch.log(self.stability_epsilon + summed_masked_pick_probability)
)
layers_snnl.append(snnl)
snn_loss = torch.stack(layers_snnl).sum()
train_loss = torch.add(primary_loss, torch.mul(self.factor, snn_loss))
return train_loss, primary_loss, snn_loss
Visualizzazione di rappresentazioni districate
Abbiamo addestrato un autocodificatore con la perdita morbida del vicino più vicino e visualizzato le sue rappresentazioni districate apprese. Il codificatore automatico aveva unità (x-500–500–2000-d-2000–500–500-x) ed è stato addestrato su un piccolo sottoinsieme etichettato dei set di dati MNIST, Fashion-MNIST ed EMNIST-Balanced. Questo per simulare la scarsità di esempi etichettati poiché si suppone che gli autocodificatori siano modelli non supervisionati.
Abbiamo visualizzato solo 10 cluster scelti arbitrariamente per una visualizzazione più semplice e pulita del set di dati EMNIST-Balanced. Possiamo vedere nella figura sopra che la rappresentazione del codice latente è diventata più favorevole al clustering avendo una serie di cluster ben definiti come indicato dalla dispersione dei cluster e assegnazioni corrette dei cluster come indicato dai colori dei cluster.
Commenti finali
In questo articolo, abbiamo analizzato la funzione di perdita del vicino più vicino morbido su come implementarla in PyTorch.
La perdita morbida del vicino più vicino è stata introdotta per la prima volta da Salakhutdinov e Hinton (2007) dove è stata utilizzata per calcolare la perdita sulla rappresentazione del codice latente (collo di bottiglia) di un codificatore automatico, e quindi detta rappresentazione è stata utilizzata per l’attività di classificazione kNN a valle.
Frosst, Papernot e Hinton (2019) quindi ampliato la perdita morbida del vicino più vicino introducendo un fattore di temperatura e calcolando la perdita su tutti gli strati di una rete neurale.
Infine, abbiamo utilizzato un fattore di temperatura di ricottura per la perdita morbida del vicino più vicino per migliorare ulteriormente le rappresentazioni districate apprese di una rete e anche accelerare il processo di districamento (Agarap e zucchero,).
L’implementazione completa del codice è disponibile in GitLab.
Riferimenti
- Agarap, Abien Fred e Arnulfo P. Azcarraga. “Migliorare le prestazioni del clustering k-means con rappresentazioni interne districate.” Conferenza congiunta internazionale 2020 sulle reti neurali (IJCNN). IEEE, 2020.
- Chapelle, Olivier, Bernhard Scholkopf e Alexander Zien. “Apprendimento semi-supervisionato (chapelle, o. et al., eds.; 2006) (recensioni di libri).” Transazioni IEEE su reti neurali 20.3 (2009): 542–542.
- Frosst, Nicholas, Nicolas Papernot e Geoffrey Hinton. “Analizzare e migliorare le rappresentazioni con la perdita morbida del vicino più vicino.” Conferenza internazionale sull’apprendimento automatico. PMLR, 2019.
- Goldberger, Jacob et al. “Analisi delle componenti del quartiere”. Progressi nei sistemi di elaborazione delle informazioni neurali. 2005.
- Lui, Kaiming et al. “Apprendimento residuo profondo per il riconoscimento delle immagini.” Atti della conferenza IEEE sulla visione artificiale e il riconoscimento di modelli. 2016.
- Hinton, G., et al. “Analisi dei componenti del quartiere.” Proc. NIPS. 2004.
- Krizhevskij, Alex, Ilya Sutskever e Geoffrey E. Hinton. “Classificazione Imagenet con reti neurali convoluzionali profonde.” Progressi nei sistemi di elaborazione delle informazioni neurali 25 (2012).
- Roweis, Sam T. e Lawrence K. Saul. “Riduzione dimensionalità non lineare, grazie all’integrazione a livello locale lineare.” scienza 290,5500 (2000): 2323–2326.
- Salakhutdinov, Ruslan e Geoff Hinton. “Imparare un inclusione non lineare preservando la struttura del vicinato di classe.” Intelligenza Artificiale e Statistica. 2007.
- Simonyan, Karen e Andrew Zisserman. “Reti convoluzionali molto profonde per il riconoscimento di immagini su larga scala.” arXiv prestampa arXiv:1409.1556 (2014).
- Van der Maaten, Laurens e Geoffrey Hinton. “Visualizzazione dei dati utilizzando t-SNE.” Giornale di ricerca sull’apprendimento automatico 9.11 (2008).
Fonte: towardsdatascience.com