Introduzione e Implementazione delle Reti Siamesi

Introduzione e Implementazione Reti Siamesi

Introduzione

Le reti Siamesi offrono un approccio intrigante alla classificazione, consentendo una categorizzazione accurata delle immagini basata su un solo esempio. Queste reti utilizzano un concetto chiamato Contrastive Loss per valutare la similarità tra coppie di immagini all’interno di un dataset. A differenza dei metodi tradizionali che si concentrano sulla decodifica del contenuto delle immagini, le reti Siamesi si concentrano sulla comprensione delle variazioni e delle somiglianze tra le immagini. Questo metodo di apprendimento distintivo contribuisce alla loro resilienza in scenari di dati limitati, migliorando le prestazioni anche senza conoscenze specifiche di dominio.

Questo articolo approfondisce il fascinante campo della Verifica delle Firme attraverso l’ottica delle Reti Siamesi. Ti guideremo nella creazione di un modello funzionale utilizzando PyTorch, fornendo approfondimenti e passaggi pratici di implementazione lungo il percorso.

Obiettivi di Apprendimento

  • Comprendere il concetto di reti Siamesi e la loro architettura unica che coinvolge due sottoreti gemelle.
  • Differenziare le funzioni di perdita utilizzate nelle reti Siamesi, tra cui Binary Cross-Entropy Loss, Contrastive Loss e Triplet Loss.
  • Identificare e descrivere applicazioni reali in cui le reti Siamesi possono essere utilizzate in modo efficace, come il riconoscimento facciale, il riconoscimento delle impronte digitali e la valutazione della similarità del testo.
  • Riassumere i vantaggi e gli svantaggi delle reti Siamesi riguardo all’apprendimento in un solo passaggio, alla versatilità e alle prestazioni agnostiche del dominio.

Questo articolo è stato pubblicato come parte del Data Science Blogathon.

Cosa sono le Reti Siamesi?

Le Reti Siamesi appartengono a una categoria di reti che utilizzano due sottoreti identiche per la classificazione in un solo passaggio. Queste sottoreti condividono la stessa configurazione, parametri e pesi, pur accogliendo input diversi. Una Rete Siamese apprende una funzione di similarità, a differenza delle CNN convenzionali, che vengono addestrate su grandi quantità di dati per prevedere più classi. Questa funzione ci consente di distinguere tra classi utilizzando un minimo di dati, rendendole particolarmente efficaci per la classificazione in un solo passaggio. Questa capacità unica significa che, in molte situazioni, un singolo esempio è sufficiente affinché queste reti classifichino accuratamente le immagini.

Un’applicazione concreta delle Reti Siamesi è nel riconoscimento facciale e nella verifica delle firme. Immagina un’azienda che implementa un sistema di presenza basato sul riconoscimento facciale. Con un solo’immagine di ciascun dipendente disponibile, le CNN tradizionali avrebbero difficoltà a classificare con precisione migliaia di dipendenti. Entra in scena la rete Siamese, eccellendo proprio in questo tipo di scenario.

Esplorando il Few-Shot Learning

Nel few-shot learning, i modelli vengono addestrati per effettuare previsioni basate su un numero limitato di esempi. Questo si contrappone all’approccio tradizionale, che richiede un volume sostanziale di dati etichettati per scopi di addestramento. La significatività del few-shot learning emerge quando diventa difficile o costoso acquisire un ampio numero di dati etichettati.

L’architettura dei modelli few-shot sfrutta le sfumature tra un piccolo numero di campioni, consentendo loro di effettuare previsioni basate su pochi o addirittura un singolo esempio. Vari framework di progettazione come le Reti Siamesi, il Meta-learning e approcci simili facilitano questa capacità. Questi framework permettono al modello di estrarre rappresentazioni significative dei dati e utilizzarle per campioni nuovi e non visti in precedenza.

Un paio di esempi pratici in cui il few-shot learning brilla includono:

  1. Rilevamento Oggetti in Sorveglianza: Il few-shot learning può identificare in modo efficace gli oggetti all’interno delle immagini di sorveglianza, anche quando sono disponibili solo pochi esempi di tali oggetti. Dopo aver addestrato il modello su un modesto insieme di esempi etichettati, può successivamente rilevare questi oggetti in nuove immagini, anche se non li ha mai incontrati prima.

2. Assistenza Sanitaria Personalizzata: Nell’ambito dell’assistenza sanitaria personalizzata, i professionisti medici potrebbero disporre di un insieme limitato di cartelle cliniche di un paziente, comprendente poche scansioni TC o esami del sangue. Utilizzando un modello few-shot learning, queste istanze di addestramento ci consentono di prevedere il benessere prospettico del paziente. Questo potrebbe includere previsioni sull’insorgenza potenziale di una specifica malattia o sulla risposta probabile a un particolare approccio terapeutico.

L’Architettura delle Reti Siamesi

Il design della rete Siamese comprende due sottoreti identiche, ognuna delle quali elabora uno degli input. Inizialmente, gli input vengono elaborati attraverso una rete neurale convoluzionale (CNN), che estrae caratteristiche significative dalle immagini fornite. Queste sottoreti generano quindi output codificati, spesso attraverso uno strato completamente connesso, ottenendo una rappresentazione condensata dei dati di input.

La CNN è composta da due rami e da un componente di estrazione delle caratteristiche condiviso, composto da strati per la convoluzione, la normalizzazione batch e l’attivazione ReLU, seguiti da strati di max pooling e dropout. Il segmento finale coinvolge lo strato FC, che mappa le caratteristiche estratte nelle classificazioni finali. Una funzione delinea uno strato lineare seguito da una sequenza di attivazioni ReLU e una serie di operazioni consecutive (convoluzione, normalizzazione batch, attivazione ReLU, max pooling e dropout). La funzione forward guida gli input attraverso entrambi i rami della rete.

Lo strato di differenziazione serve a identificare somiglianze tra gli input e amplificare le distinzioni tra coppie diverse, utilizzando la funzione distanza euclidea:

Distanza(x₁, x₂) = ∥f(x₁) – f(x₂)∥₂

In questo contesto,

  • x₁, x₂ sono i due input.
  • f(x) rappresenta l’output della codifica.
  • Distanza indica la funzione distanza.

Questa proprietà consente alla rete di acquisire rappresentazioni efficaci dei dati e di applicarle a campioni nuovi e non visti in precedenza. Di conseguenza, la rete genera una codifica, spesso rappresentata come un punteggio di similarità, che aiuta nella differenziazione delle classi.

Rappresenta l’architettura della rete nella figura allegata. È importante notare che questa rete funziona come un classificatore one-shot, eliminando la necessità di molti esempi per classe.

Funzioni di Perdita Utilizzate nelle Reti Siamesi

Una funzione di perdita è uno strumento matematico per valutare la dissimilarità tra l’output previsto e l’output effettivo all’interno di un modello di machine learning, dato un input specifico. Durante l’addestramento di un modello, l’obiettivo è minimizzare questa funzione di perdita mediante l’aggiustamento dei parametri del modello.

Diverse funzioni di perdita si adattano a diversi tipi di problemi. Ad esempio, l’errore quadratico medio è adatto per sfide di regressione, mentre la perdita di entropia incrociata si adatta alle attività di classificazione.

Diversamente da molti altri tipi di reti, la Rete Siamese abbraccia diverse funzioni di perdita, descritte di seguito.

Perdita di Entropia Incrociata Binaria

La perdita di entropia incrociata binaria si rivela utile per attività di classificazione binaria, in cui l’obiettivo è prevedere tra due possibili risultati. Nel contesto di una rete Siamese, l’obiettivo è classificare un’immagine come “simile” o “diversa” da un’altra.

Questa funzione quantifica la disparità tra la probabilità prevista della classe positiva e l’output effettivo. All’interno della rete Siamese, la probabilità prevista si riferisce alla probabilità di similarità delle immagini, mentre l’output effettivo assume una forma binaria: 1 per la similarità delle immagini e 0 per la dissimilarità.

La formulazione della funzione coinvolge il logaritmo negativo della probabilità vera della classe, calcolato come:−(ylog(p)+(1−y)log(1−p))

Qui,

  • y indica l’etichetta vera.
  • p indica la probabilità prevista.

L’addestramento di un modello con perdita di entropia incrociata binaria si sforza di minimizzare questa funzione tramite l’aggiustamento dei parametri. Attraverso questa minimizzazione, il modello acquisisce competenza nella previsione accurata delle classi.

Perdita Contrastiva

La perdita contrastiva analizza la differenziazione delle coppie di immagini mediante l’uso della distanza come misura di similarità. Questa funzione si rivela vantaggiosa quando il numero di istanze di addestramento per classe è limitato. È importante notare che la perdita contrastiva richiede coppie di campioni di addestramento negativi e positivi. Una visualizzazione di questa perdita è fornita nella figura allegata.

L’equazione della perdita contrastiva può essere:

(1 – Y) * 0.5 * D^2 + Y * 0.5 * max(0, m – D^2)

Ecco la scomposizione:

  • Y rappresenta un parametro di input.
  • D sta per la distanza euclidea.
  • Quando Y è uguale a 0, gli input appartengono alla stessa classe. D’altra parte, un valore di Y pari a 1 indica che provengono da classi diverse.
  • Il parametro ‘m’ definisce un margine per la funzione di distanza, aiutando a identificare le coppie che contribuiscono alla perdita. È importante notare che il valore di ‘m’ è sempre maggiore di 0.

Triplet Loss

La triplet loss utilizza triple di dati. L’immagine sotto illustra queste triple.

La funzione di triplet loss mira ad aumentare la separazione tra l’ancora e i campioni negativi, riducendo al contempo la distanza tra l’ancora e i campioni positivi.

Matematicamente, la funzione di triplet loss si definisce come la differenza massima tra la distanza dall’ancora al positivo (d(a,p)) e la distanza dall’ancora al negativo (d(a,n)), sottratta da un valore di margine. Quando questa differenza è positiva, il valore calcolato diventa la perdita; altrimenti, viene impostato a zero.

Ecco una scomposizione dei componenti:

  • d indica la distanza euclidea.
  • a rappresenta l’input dell’ancora.
  • p indica l’input positivo.
  • n sta per l’input negativo.

Il obiettivo principale è garantire che l’input positivo sia più vicino all’input dell’ancora rispetto all’input negativo, mantenendo una separazione minima.

Costruire un modello basato su una rete Siamese per la verifica delle firme

La verifica della firma consiste nel distinguere le firme contraffatte da una collezione di firme autentiche. In questo scenario, un modello deve comprendere le sfumature tra numerose firme. Deve quindi distinguere tra firme autentiche e false quando gliene viene presentata una qualsiasi. Raggiungere questo obiettivo di verifica rappresenta una sfida considerevole per le CNN convenzionali a causa delle variazioni intricate e delle istanze di allenamento limitate. A complicare la difficoltà, spesso esiste solo una firma singola per individuo, richiedendo l’efficienza del modello nella verifica di migliaia di firme di individui. Le sezioni seguenti approfondiscono la creazione di un modello basato su PyTorch per affrontare questo compito intricato.

Dataset

Il dataset che utilizzeremo riguarda la validazione delle firme ed è ICDAR 2011. Questa collezione comprende firme olandesi, che includono sia firme autentiche che contraffatte. Un campione dei dati è qui per riferimento. Link per il dataset.

Descrizione del problema

Questo articolo approfondisce il compito di rilevare firme contraffatte all’interno di un contesto di verifica delle firme. Il nostro obiettivo consiste nel sfruttare un dataset di firme e utilizzare una rete Siamese per prevedere l’autenticità delle firme di test, distinguendo quelle genuine da quelle false. Per raggiungere questo obiettivo, dobbiamo stabilire un processo passo dopo passo. Ciò comporta l’acquisizione dei dati dal dataset, la creazione di coppie di immagini e il loro successivo elaborazione attraverso la rete Siamese. Dopo aver allenato la rete utilizzando il dataset fornito, sviluppiamo quindi funzioni di predizione.

Importazione delle librerie essenziali

La costruzione della rete Siamese richiede l’inclusione di diverse librerie chiave. Introduciamo la libreria Pillow (PIL) per la manipolazione delle immagini, matplotlib per la visualizzazione, numpy per le operazioni numeriche e tqdm per una barra di avanzamento. Inoltre, sfruttiamo il potere di PyTorch e torchvision per facilitare l’allenamento e la costruzione della rete.

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
import torchvision.utils as tv_utils
from torch.autograd import Variable
from torch.utils.data import DataLoader, Dataset
import PIL.Image as Image
import matplotlib.pyplot as plt
import numpy as np
import os
import pandas as pd
import torch.utils.data as custom_data
from tqdm import tqdm

Funzioni di utilità

Per visualizzare gli output della rete, creare una funzione di utilità. Questa funzione accetta immagini e le rispettive etichette corrispondenti come input e le organizza in una griglia per una visualizzazione conveniente.

import numpy as np
import matplotlib.pyplot as plt

def display_image(img, caption=None, save=False):
    image_array = img.numpy()
    plt.axis("off")
    
    if caption:
        plt.text(
            75,
            8,
            caption,
            style="italic",
            fontweight="bold",
            bbox={"facecolor": "white", "alpha": 0.8, "pad": 10},
        )
    
    plt.imshow(np.transpose(image_array, (1, 2, 0)))
    plt.show()

Preelaborazione dei dati

La struttura dei dati utilizzata dalla rete Siamese differisce notevolmente dalle reti di classificazione delle immagini convenzionali. A differenza di fornire una singola coppia immagine-etichetta, il Generatore di dataset per la rete Siamese richiede la fornitura di coppie di immagini. Queste coppie vengono sottoposte a un processo di trasformazione che prevede la conversione in bianco e nero, il ridimensionamento successivo e la conversione finale in Tensori. Due categorie distinte di coppie sono coppie positive, caratterizzate da immagini di input identiche, e coppie negative, con immagini diverse. Inoltre, una funzione fornisce la dimensione del dataset quando viene invocata.

import os
import pandas as pd
import torch
import torch.utils.data as data
from PIL import Image
import numpy as np

class PairedDataset(data.Dataset):
    def __init__(self, df_path=None, data_dir=None, transform=None, subset=None):
        self.df = pd.read_csv(df_path)
        if subset is not None:
            self.df = self.df[:subset]
        self.df.columns = ["image1", "image2", "label"]
        self.data_dir = data_dir
        self.transform = transform

    def __getitem__(self, index):
        pair1_path = os.path.join(self.data_dir, self.df.iat[index, 0])
        pair2_path = os.path.join(self.data_dir, self.df.iat[index, 1])

        pair1 = Image.open(pair1_path).convert("L")
        pair2 = Image.open(pair2_path).convert("L")

        if self.transform:
            pair1 = self.transform(pair1)
            pair2 = self.transform(pair2)

        label = torch.tensor([int(self.df.iat[index, 2])], dtype=torch.float32)

        return pair1, pair2, label

    def __len__(self):
        return len(self.df)

Panoramica Concisa delle Funzionalità

Gli input della rete consistono in immagini che compongono coppie di dati positivi e negativi. Rappresentiamo queste coppie come dati di immagine e le trasformiamo in formato Tensor, incorporando efficacemente le informazioni sottostanti dell’immagine. Le etichette associate alla rete Siamese sono categoriche.

Processo di Standardizzazione delle Funzionalità

Un passaggio cruciale consiste nella standardizzazione delle funzionalità e nella conversione delle immagini in bianco e nero. Inoltre, ridimensioniamo uniformemente tutte le immagini in un formato quadrato (105×105), poiché la rete Siamese richiede questa dimensione. Successivamente, convertiamo tutte le immagini in Tensori, il che migliora l’efficienza computazionale e consente l’utilizzo della GPU.

data_transform = transforms.Compose([
    transforms.Resize((105, 105)),
    transforms.ToTensor()
])

Divisione del Dataset

Dividiamo il dataset in segmenti distinti di addestramento e test per facilitare sia l’addestramento che il test del modello. Per facilità di illustrazione, ci concentriamo sui primi 1000 punti dati. Optare per un valore di funzione ‘load_subset’ pari a None implicherebbe l’utilizzo dell’intero dataset, sebbene a discapito di un tempo di elaborazione prolungato. Considerare l’aumento dei dati come approccio per migliorare le prestazioni a lungo termine della rete.

train_dataset = PairedDataset(
    df_train,
    dir_train,
    transform=transforms.Compose([
        transforms.Resize((105, 105)),
        transforms.ToTensor()
    ]),
    subset=1000
)

evaluation_dataset = PairedDataset(
    df_val,
    dir_val,
    transform=transforms.Compose([
        transforms.Resize((105, 105)),
        transforms.ToTensor()
    ]),
    subset=1000
)

Architettura della Rete Neurale

La costruzione dell’architettura descritta comporta una serie di passaggi. Inizialmente, stabiliamo una funzione che costruisce insiemi di livelli di Convoluzione, Normalizzazione Batch e ReLU, offrendo la flessibilità di includere o escludere un livello Dropout alla fine. Un’altra funzione è stata ideata per generare sequenze di livelli Fully Connected (FC), completate da successivi livelli ReLU. Una volta che la componente CNN è costruita tramite le funzioni sopra menzionate, l’attenzione si sposta sulla formazione del segmento FC della rete. Nella rete sono implementate dimensioni di padding e di kernel distinte.

La porzione FC è composta da blocchi che comprendono livelli Lineari seguiti da attivazioni ReLU. Con l’architettura definita, eseguiamo un passaggio in avanti per elaborare i dati forniti attraverso la rete. Un aspetto importante da sottolineare è la funzione “view”, che riconfigura l’output del blocco precedente appiattendo le dimensioni. Una volta stabilito questo meccanismo, siamo pronti per addestrare la rete Siamese utilizzando i dati forniti.

class SiameseNetwork(nn.Module):
    def __init__(self):
        super(SiameseNetwork, self).__init__()

        self.cnn1 = nn.Sequential(
            self.create_conv_block(1, 96, 11, 1, False),
            self.create_conv_block(96, 256, 5, 2, True),
            nn.Conv2d(256, 384, kernel_size=3, stride=1, padding=1),
            nn.BatchNorm2d(384),
            nn.ReLU(inplace=True),
            self.create_conv_block(384, 256, 3, 1, True),
        )

        self.fc1 = nn.Sequential(
            self.create_linear_relu(30976, 1024),
            nn.Dropout2d(p=0.5),
            self.create_linear_relu(1024, 128),
            nn.Linear(128, 2)
        )

    def create_linear_relu(self, input_channels, output_channels):
        return nn.Sequential(nn.Linear(input_channels, output_channels),
        nn.ReLU(inplace=True))

    def create_conv_block(self, input_channels, output_channels, kernel_size,
    padding, dropout=True):
        if dropout:
            return nn.Sequential(
                nn.Conv2d(input_channels, output_channels, kernel_size=kernel_size,
                stride=1, padding=padding),
                nn.BatchNorm2d(output_channels),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(3, stride=2),
                nn.Dropout2d(p=0.3)
            )
        else:
            return nn.Sequential(
                nn.Conv2d(input_channels, output_channels, kernel_size=kernel_size,
                stride=1),
                nn.BatchNorm2d(output_channels),
                nn.ReLU(inplace=True),
                nn.MaxPool2d(3, stride=2)
            )

    def forward_once(self, x):
        output = self.cnn1(x)
        output = output.view(output.size()[0], -1)
        output = self.fc1(output)
        return output

    def forward(self, input1, input2):
        out1 = self.forward_once(input1)
        out2 = self.forward_once(input2)
        return out1, out2

Funzione di Perdita

La funzione di perdita contrastiva serve come funzione di perdita fondamentale per la Rete Siamese. Definire questa perdita comporta l’utilizzo delle equazioni chiarite in precedenza nell’articolo. Per migliorare l’efficienza del codice, anziché definire la perdita come una funzione diretta, un approccio alternativo prevede l’ereditarietà dalla classe nn.Module. Ciò consente la creazione di una classe personalizzata che fornisce gli output della funzione. Un tale wrapper consente a PyTorch di ottimizzare l’esecuzione del codice, migliorando così le prestazioni complessive.

class ContrastiveLoss(nn.Module):
    def __init__(self, margin=2.0):
        super(ContrastiveLoss, self).__init__()
        self.margin = margin

    def forward(self, output1, output2, label):
        distanza_euclidea = F.pairwise_distance(output1, output2)
        perdita_positiva = (1 - label) * torch.pow(distanza_euclidea, 2)
        perdita_negativa = label * torch.pow(torch.clamp(self.margin - distanza_euclidea, min=0.0), 2)
        perdita_totale = torch.mean(perdita_positiva + perdita_negativa)
        return perdita_totale

Allenamento della Rete Siamese

Con i dati caricati e preelaborati, sono pronti per iniziare l’allenamento della rete Siamese. Per avviare questo processo, iniziamo stabilendo i caricatori di dati sia per l’allenamento che per il test. In particolare, il DataLoader di valutazione è configurato con una dimensione del batch pari a 1 per facilitare le valutazioni individuali. Successivamente, il modello viene distribuito sulla GPU e vengono definiti componenti fondamentali come la funzione di perdita contrastiva e l’ottimizzatore Adam.

train_loader = DataLoader(train_dataset,
                        shuffle=True,
                        num_workers=8,
                        batch_size=bs) 
eval_loader = DataLoader(evaluation_dataset,
                        shuffle=True,
                        num_workers=8,
                        batch_size=1) 

siamese_net = SiameseNetwork().cuda()
loss_function = ContrastiveLoss()
optimizer = torch.optim.Adam(siamese_net.parameters(), lr=1e-3, weight_decay=0.0005)

In seguito, viene creata una funzione che accetta il DataLoader di allenamento come input. All’interno di questa funzione, viene mantenuto un array in corso per tenere traccia della perdita, insieme a un contatore per facilitare i futuri tentativi di tracciamento. Il processo iterativo successivo naviga attraverso i punti dati all’interno del DataLoader. Per ogni punto, le coppie di immagini vengono trasferite alla GPU, sottoposte a elaborazione da parte della rete e viene calcolata la perdita contrastiva. I passaggi successivi comprendono l’esecuzione di un passaggio indietro, che culmina nella fornitura della perdita netta relativa a un batch di dati.

def train(train_loader, model, optimizer, loss_function):
    perdita_totale = 0.0
    num_batches = len(train_loader)

    model.train()

    for batch_idx, (pair_left, pair_right, label) in
    enumerate(tqdm(train_loader, total=num_batches)):
        pair_left, pair_right, label = pair_left.cuda(),
        pair_right.cuda(), label.cuda()

        optimizer.zero_grad()
        output1, output2 = model(pair_left, pair_right)

        perdita_contrastiva = loss_function(output1, output2, label)
        perdita_contrastiva.backward()
        optimizer.step()

        perdita_totale += perdita_contrastiva.item()

    perdita_media = perdita_totale / num_batches

    return perdita_media

Il modello può essere addestrato su più epoche utilizzando la nostra funzione creata. In questa dimostrazione, l’articolo copre solo un numero limitato di epoche. Se la perdita di valutazione ottenuta durante l’allenamento rappresenta la migliore performance osservata durante la durata dell’allenamento, il modello viene conservato per l’inferenza successiva in quella particolare epoca.

best_eval_loss = float('inf')

for epoch in tqdm(range(1, num_epoch)):
    train_loss = train(train_loader)
    eval_loss = evaluate(eval_loader)

    print(f"Epoca: {epoch}")
    print(f"Perdita di allenamento: {train_loss}")
    print(f"Perdita di valutazione: {eval_loss}")

    if eval_loss < best_eval_loss:
        best_eval_loss = eval_loss
        print(f"Perdita di valutazione migliore: {best_eval_loss}")
        torch.save(siamese_net.state_dict(), "model.pth")
        print("Modello salvato con successo")

Test del Modello

Segue una fase di valutazione dopo l’addestramento del modello, che ci consente di valutarne le prestazioni e condurre l’inferenza per singoli punti dati. Analogamente alla funzione di allenamento, viene creata una funzione di valutazione che prende il caricatore di dati di test come input. Il caricatore di dati viene iterato, elaborando un’istanza alla volta. Successivamente, vengono estratte le coppie di immagini per il test. Queste coppie vengono quindi inviate alla GPU, consentendo l’esecuzione del modello. Gli output risultanti dal modello vengono utilizzati per calcolare la perdita contrastiva, che viene successivamente memorizzata in una lista designata.

def valuta(eval_loader):
    loss_list = []
    counter_list = []
    numero_iterazioni = 0

    for i, dati in tqdm(enumerate(eval_loader, 0), total=len(eval_loader)):
        coppia_sinistra, coppia_destra, etichetta = dati
        coppia_sinistra, coppia_destra, etichetta = coppia_sinistra.cuda(), coppia_destra.cuda(), etichetta.cuda()
        
        output1, output2 = siamese_net(coppia_sinistra, coppia_destra)
        contrastive_loss = loss_function(output1, output2, etichetta)
        loss_list.append(contrastive_loss.item())
    
    loss_array = np.array(loss_list)
    media_loss = loss_array.mean() / len(eval_loader)
    
    return media_loss

Possiamo eseguire il codice per effettuare una singola valutazione su tutti i punti dati di test. Per valutare le prestazioni in modo visivo, genereremo dei grafici che rappresentino le immagini e visualizzeremo le distanze tra i punti dati identificate dal modello. Presenta questi risultati sotto forma di griglia.

for i, dati in enumerate(dl_eval, 0):
    x0, x1, etichetta = dati
    immagini_concatenate = torch.cat((x0, x1), 0)
    out1, out2 = siamese_net(x0.to('cuda'), x1.to('cuda'))

    distanza_euclidea = F.pairwise_distance(out1, out2)
    print(etichetta)
    if etichetta == torch.FloatTensor([[0]]):
        testo_etichetta = "Coppia Originale di Firma"
    else:
        testo_etichetta = "Coppia Falsificata di Firma"

    display_images(torchvision.utils.make_grid(immagini_concatenate))
    print("Distanza Euclidea Predetta:", distanza_euclidea.item())
    print("Etichetta Effettiva:", testo_etichetta)
    if i == 4:
        break

Output

Vantaggi e Svantaggi delle Reti Siamesi

Svantaggi

  • Un notevole svantaggio delle reti Siamesi è la loro uscita, che fornisce un punteggio di similarità anziché una distribuzione di probabilità che somma a 1. Questa caratteristica può presentare sfide in determinate applicazioni in cui le uscite basate su probabilità sono preferibili.

Vantaggi

  • Le reti Siamesi mostrano resilienza nel trattare con un numero variabile di esempi all’interno di diverse classi. Questa adattabilità deriva dalla capacità della rete di funzionare in modo efficace con informazioni di classe limitate.
  • Le prestazioni di classificazione della rete non dipendono dalla fornitura di informazioni specifiche del dominio, contribuendo alla sua versatilità.
  • Le reti Siamesi possono fare previsioni anche con un’unica immagine per classe.

Applicazioni delle Reti Siamesi

Le reti Siamesi trovano utilità in diverse applicazioni, alcune delle quali sono descritte di seguito.

Riconoscimento Facciale: Le reti Siamesi si dimostrano vantaggiose nelle attività di riconoscimento facciale con un’unica immagine. Utilizzando la loss contrastiva, queste reti distinguono volti simili da volti diversi, consentendo un’identificazione facciale efficace con un numero minimo di campioni di dati.

Riconoscimento delle Impronte Digitali: Sfrutta le reti Siamesi per il riconoscimento delle impronte digitali. Fornendo coppie di impronte digitali pre-elaborate alla rete, impara a differenziare tra impronte valide e non valide, migliorando l’accuratezza dell’autenticazione basata sulle impronte digitali.

Verifica delle Firme: Questo articolo si è principalmente concentrato sull’implementazione della Verifica delle Firme tramite reti Siamesi. Come dimostrato, la rete elabora coppie di firme per determinare l’autenticità delle firme, distinguendo tra firme genuine e contraffatte.

Somiglianza di Testo: Le reti Siamesi trovano rilevanza anche nella valutazione della somiglianza di testo. Attraverso l’input accoppiato, la rete può individuare somiglianze tra diversi frammenti di testo. Le applicazioni pratiche includono l’identificazione di domande analoghe all’interno di una banca dati di domande o il recupero di documenti simili da un repository di testo.

Conclusion

Una rete neurale siamese, spesso abbreviata come SNN, rientra nella categoria di progetti di reti neurali che incorporano due o più sub-reti che condividono una struttura identica. In questo contesto, “identica” implica avere configurazioni, parametri e pesi corrispondenti. La sincronizzazione degli aggiornamenti dei parametri tra queste sub-reti determina le somiglianze tra gli input attraverso il confronto di vettori di caratteristiche.

Punti chiave

  • Le reti siamesi eccellono nella classificazione di set di dati con un numero limitato di esempi per classe, rendendole preziose per scenari con pochi dati di addestramento.
  • Attraverso questa esplorazione, abbiamo acquisito una comprensione dei principi fondamentali che sottostanno alle reti siamesi, comprendendo la loro architettura, le funzioni di perdita impiegate e il processo di addestramento di tali reti.
  • Il nostro percorso ha compreso l’applicazione pratica delle reti siamesi nel contesto della verifica delle firme, utilizzando il dataset ICDAR 2011. Ciò ha coinvolto la creazione di un modello in grado di rilevare firme contraffatte.
  • La pipeline di addestramento e test per le reti siamesi è diventata chiara, offrendo una comprensione completa di come queste reti operano. Ci siamo addentrati nella rappresentazione dei dati accoppiati, un aspetto cruciale della loro efficacia.

Domande frequenti

I media mostrati in questo articolo non sono di proprietà di Analytics Vidhya e sono utilizzati a discrezione dell’autore.