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à.
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.
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.
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
Offerto da
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 =100Offerto da
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.
defload_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)Offerto da
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 optimizerdefget_optimizer():return Adam(lr=0.0002, beta_1=0.5)defget_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
defget_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
Offerto da
È finalmente arrivato il momento di mettere insieme generatore e discriminatore!
defget_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
Offerto da
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 imagesdefplot_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 inrange(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)Offerto da
Hai ora programmato la maggior parte della tua rete. Non resta che addestrarla e dare un’occhiata alle immagini che hai creato.
deftrain(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 inxrange(1, epochs+1):print'-'*15,'Epoch %d'% e,'-'*15for _ 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 ==1or e %20==0:
plot_generated_images(e, generator)if __name__ =='__main__':
train(400,128)Offerto da
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
!
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.
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.
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à.
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.
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.
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
Kerase, 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
pipkerasmatplotlibtensorflowtqdmUserai
matplotlibper il plotting,tensorflowcome backend di Keras etqdmper 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.
Ora vuoi impostare alcune variabili:
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.
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.
È finalmente arrivato il momento di mettere insieme generatore e discriminatore!
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.
Hai ora programmato la maggior parte della tua rete. Non resta che addestrarla e dare un’occhiata alle immagini che hai creato.
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.
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.