Vai al contenuto principale

Demistificare le Generative Adversarial Nets (GAN)

Scopri cosa sono le Generative Adversarial Networks senza entrare nei dettagli matematici e scrivi il codice di una semplice GAN che può creare cifre!
Aggiornato 29 set 2026  · 9 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

In questo tutorial scoprirai cosa sono le Generative Adversarial Networks (GAN) senza entrare nei dettagli matematici. Poi imparerai a scrivere il codice di una semplice GAN in grado di creare cifre!

Analogia

Il modo più semplice per capire cosa sono le GAN è attraverso una semplice analogia:

Supponiamo che ci sia un negozio che compra dai clienti alcuni tipi di vino che poi rivenderà.

analogy

Tuttavia, ci sono clienti malintenzionati che vendono vino contraffatto per ottenere denaro. In questo caso, il proprietario del negozio deve essere in grado di distinguere tra vini falsi e autentici.

analogy

Puoi immaginare che all’inizio il falsario possa commettere molti errori quando cerca di vendere il vino contraffatto, e per il proprietario del negozio sarà facile identificare che il vino non è autentico. A causa di questi fallimenti, il falsario continuerà a provare tecniche diverse per simulare i vini autentici e alcune alla fine avranno successo. Ora che il falsario sa che certe tecniche hanno superato i controlli del negoziante, può iniziare a migliorare ulteriormente i vini falsi basandosi su quelle tecniche.

Allo stesso tempo, probabilmente la proprietaria del negozio riceverà feedback da altri negozianti o esperti di vino sul fatto che alcuni dei vini che possiede non sono originali. Questo significa che la proprietaria dovrà migliorare il modo in cui determina se un vino è falso o autentico. L’obiettivo del falsario è creare vini indistinguibili da quelli autentici, e l’obiettivo della proprietaria è riconoscere con precisione se un vino è vero o no.

Questa competizione a botta e risposta è l’idea principale alla base delle GAN.

Componenti di una Generative Adversarial Network

Usando l’esempio sopra, possiamo ricavare l’architettura di una GAN.

gan

Nelle GAN ci sono due componenti principali: il generatore e il discriminatore. La proprietaria del negozio nell’esempio è nota come rete discriminatrice ed è di solito una rete neurale convoluzionale (dato che le GAN sono usate soprattutto per compiti di visione) che assegna una probabilità che l’immagine sia reale.

Il falsario è noto come rete generativa ed è anch’essa tipicamente una rete neurale convoluzionale (con strati di deconvoluzione). Questa rete prende un vettore di rumore e produce un’immagine. Durante l’addestramento della rete generativa, questa impara quali parti dell’immagine migliorare/modificare in modo che al discriminatore risulti più difficile distinguere le immagini generate da quelle reali.

La rete generativa continua a produrre immagini sempre più simili a quelle reali, mentre la rete discriminatrice cerca di determinare le differenze tra immagini reali e false. L’obiettivo finale è ottenere una rete generativa capace di produrre immagini indistinguibili da quelle reali.

Una semplice Generative Adversarial Network con Keras

Ora che hai capito cosa sono le GAN e i loro componenti principali, possiamo iniziare a scriverne una molto semplice. Userai Keras e, se non conosci questa libreria Python, dovresti leggere questo tutorial prima di continuare. Questo tutorial si basa sulla GAN sviluppata qui.

La prima cosa da fare è installare i seguenti pacchetti tramite pip

  • keras
  • matplotlib
  • tensorflow
  • tqdm

Userai matplotlib per il plotting, tensorflow come backend di Keras e tqdm per mostrare una comoda barra di avanzamento per ogni epoca (iterazione).

Il passo successivo è creare uno script Python. In questo script, per prima cosa importerai tutti i moduli e le funzioni che utilizzerai. Man mano che verranno usati, ne verrà data una spiegazione.

import os
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm


from keras.layers import Input
from keras.models import Model, Sequential
from keras.layers.core import Dense, Dropout
from keras.layers.advanced_activations import LeakyReLU
from keras.datasets import mnist
from keras.optimizers import Adam
from keras import initializers

Ora vuoi impostare alcune variabili:

# Let Keras know that we are using tensorflow as our backend engine
os.environ["KERAS_BACKEND"] = "tensorflow"

# To make sure that we can reproduce the experiment and get the same results
np.random.seed(10)

# The dimension of our random noise vector.
random_dim = 100

Prima di iniziare a costruire il discriminatore e il generatore, dovresti prima raccogliere e pre-processare i dati. Userai il popolare dataset MNIST, che contiene un insieme di immagini di singole cifre da 0 a 9.

mnist dataset

def load_minst_data():
    # load the data
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    # normalize our inputs to be in the range[-1, 1]
    x_train = (x_train.astype(np.float32) - 127.5)/127.5
    # convert x_train with a shape of (60000, 28, 28) to (60000, 784) so we have
    # 784 columns per row
    x_train = x_train.reshape(60000, 784)
    return (x_train, y_train, x_test, y_test)

Nota che mnist.load_data() fa parte di Keras e ti permette di importare facilmente il dataset MNIST nel tuo workspace.

Ora puoi creare le reti del generatore e del discriminatore. Userai l’ottimizzatore Adam per entrambe le reti. Per generatore e discriminatore, creerai una rete neurale con tre livelli nascosti con funzione di attivazione Leaky ReLU. Dovresti anche aggiungere strati di dropout al discriminatore per migliorarne la robustezza su immagini mai viste.

# You will use the Adam optimizer
def get_optimizer():
    return Adam(lr=0.0002, beta_1=0.5)

def get_generator(optimizer):
    generator = Sequential()
    generator.add(Dense(256, input_dim=random_dim, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(512))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(1024))
    generator.add(LeakyReLU(0.2))

    generator.add(Dense(784, activation='tanh'))
    generator.compile(loss='binary_crossentropy', optimizer=optimizer)
    return generator

def get_discriminator(optimizer):
    discriminator = Sequential()
    discriminator.add(Dense(1024, input_dim=784, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(512))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(256))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))

    discriminator.add(Dense(1, activation='sigmoid'))
    discriminator.compile(loss='binary_crossentropy', optimizer=optimizer)
    return discriminator

È finalmente arrivato il momento di mettere insieme generatore e discriminatore!

def get_gan_network(discriminator, random_dim, generator, optimizer):
    # We initially set trainable to False since we only want to train either the
    # generator or discriminator at a time
    discriminator.trainable = False
    # gan input (noise) will be 100-dimensional vectors
    gan_input = Input(shape=(random_dim,))
    # the output of the generator (an image)
    x = generator(gan_input)
    # get the output of the discriminator (probability if the image is real or not)
    gan_output = discriminator(x)
    gan = Model(inputs=gan_input, outputs=gan_output)
    gan.compile(loss='binary_crossentropy', optimizer=optimizer)
    return gan

Per completezza, puoi creare una funzione che salvi le immagini generate ogni 20 epoche. Dato che non è al centro di questa lezione, non è necessario capirla a fondo.

# Create a wall of generated MNIST images
def plot_generated_images(epoch, generator, examples=100, dim=(10, 10), figsize=(10, 10)):
    noise = np.random.normal(0, 1, size=[examples, random_dim])
    generated_images = generator.predict(noise)
    generated_images = generated_images.reshape(examples, 28, 28)

    plt.figure(figsize=figsize)
    for i in range(generated_images.shape[0]):
        plt.subplot(dim[0], dim[1], i+1)
        plt.imshow(generated_images[i], interpolation='nearest', cmap='gray_r')
        plt.axis('off')
    plt.tight_layout()
    plt.savefig('gan_generated_image_epoch_%d.png' % epoch)

Hai ora programmato la maggior parte della tua rete. Non resta che addestrarla e dare un’occhiata alle immagini che hai creato.

def train(epochs=1, batch_size=128):
    # Get the training and testing data
    x_train, y_train, x_test, y_test = load_minst_data()
    # Split the training data into batches of size 128
    batch_count = x_train.shape[0] / batch_size

    # Build our GAN netowrk
    adam = get_optimizer()
    generator = get_generator(adam)
    discriminator = get_discriminator(adam)
    gan = get_gan_network(discriminator, random_dim, generator, adam)

    for e in xrange(1, epochs+1):
        print '-'*15, 'Epoch %d' % e, '-'*15
        for _ in tqdm(xrange(batch_count)):
            # Get a random set of input noise and images
            noise = np.random.normal(0, 1, size=[batch_size, random_dim])
            image_batch = x_train[np.random.randint(0, x_train.shape[0], size=batch_size)]

            # Generate fake MNIST images
            generated_images = generator.predict(noise)
            X = np.concatenate([image_batch, generated_images])

            # Labels for generated and real data
            y_dis = np.zeros(2*batch_size)
            # One-sided label smoothing
            y_dis[:batch_size] = 0.9

            # Train discriminator
            discriminator.trainable = True
            discriminator.train_on_batch(X, y_dis)

            # Train generator
            noise = np.random.normal(0, 1, size=[batch_size, random_dim])
            y_gen = np.ones(batch_size)
            discriminator.trainable = False
            gan.train_on_batch(noise, y_gen)

        if e == 1 or e % 20 == 0:
            plot_generated_images(e, generator)

if __name__ == '__main__':
    train(400, 128)

Dopo l’addestramento per 400 epoche, puoi visualizzare le immagini generate. Guardando le immagini prodotte dopo la prima epoca, si vede che non hanno alcuna struttura reale; osservando l’immagine dopo 40 epoche, le cifre iniziano a prendere forma e, infine, le immagini prodotte dopo 400 epoche mostrano cifre chiare anche se un paio sono ancora irriconoscibili.

Risultati dopo 1 epoca Risultati dopo 40 epoche Risultati dopo 400 epoche
!images1 images2 images3

Questo codice impiega circa 2 minuti per epoca su una CPU ed è il motivo principale per cui è stato scelto. Puoi fare esperimenti usando più epoche e aggiungendo più (e diversi) strati sia al generatore che al discriminatore. Tieni però presente che, usando architetture più complesse e profonde, il tempo di esecuzione aumenterà se utilizzi solo una CPU. Tuttavia, non lasciare che questo ti fermi dallo sperimentare!

Conclusione

Complimenti, sei arrivato alla fine di questo tutorial, in cui hai imparato in modo intuitivo le basi delle Generative Adversarial Networks (GAN)! Inoltre, hai implementato il tuo primo modello con l’aiuto della libreria Keras. Se vuoi saperne di più sul deep learning con Python, prendi in considerazione il corso di DataCamp Deep Learning in Python.

Argomenti
Deep Learning
Intelligenza artificiale
Machine Learning

Scopri di più su Python e il Deep Learning

{count, plural, one {Corso} other {Corsi}}

Introduzione al Deep Learning in Python

{hours} ore
264.7K
Impara le basi delle reti neurali e come creare modelli di deep learning usando Keras 2.0 in Python.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

{count, plural, one {blog} other {blogs}}

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

{count, plural, one {blog} other {blogs}}

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

{count, plural, one {blog} other {blogs}}

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

Mostra AltroMostra Altro