Calcoli generativi contro calcoli discriminativi

Per comprendere i GAN, dovreste capire come funzionano i calcoli generativi, e per questo, distinguerli dai calcoli discriminanti è illuminante. I calcoli discriminanti tentano di caratterizzare le informazioni di input; cioè, dati i punti salienti di un’occasione di informazione, anticipano un nome o una classe a cui quell’informazione ha un posto.

Per esempio, date tutte le parole di un’e-mail (il caso delle informazioni), un calcolo discriminatorio potrebbe prevedere se il messaggio è spam o non_spam. spam è uno dei nomi, e il pacchetto di parole accumulato dall’e-mail è il risultato che comprende le informazioni informative. Nel momento in cui questo problema viene comunicato scientificamente, il nome viene chiamato y e i punti salienti vengono chiamati x. La definizione p(y|x) viene utilizzata per indicare “la probabilità di y data x”, che per questa situazione significherebbe “la probabilità che un’e-mail sia uno spam date le parole che contiene”.

Quindi la mappa dei calcoli discriminanti evidenzia ai segni. Essi si occupano esclusivamente di questo collegamento. Un approccio per considerare i calcoli generativi è che essi fanno l’inverso. Piuttosto che anticipare un marchio dato a certi punti salienti, cercano di prevedere i punti salienti con un nome specifico.

L’indagine a cui tenta di rispondere un calcolo generativo è: Aspettandosi che questa e-mail sia spam, quanto sono probabili questi punti salienti? Mentre i modelli discriminatori si preoccupano della connessione tra y e x, i modelli generativi si preoccupano di “come si ottiene x”. Essi permettono di catturare p(x|y), la probabilità di x dato y, o la probabilità di highlights dato un nome o una classe. (Tutto sommato, i calcoli generativi possono essere utilizzati anche come classificatori. Per qualche strana ragione possono realizzare più di un’informazione di input di ordine).

Un altro approccio da considerare è quello di riconoscere la discriminazione da quella generativa in questo modo:

I modelli discriminanti diventano familiari con il limite tra classi

I modelli generativi modellano la dispersione delle singole classi

Come funzionano le GAN

Un sistema neurale, chiamato generatore, crea nuove occorrenze di informazioni, mentre l’altro, il discriminatore, le valuta per la realtà; per esempio, il discriminatore sceglie se ogni occorrenza di informazioni che rileva ha o meno un posto con il vero set di dati di preparazione.

Supponiamo di tentare di realizzare qualcosa di più banale che copiare la Gioconda. Creeremo numeri scritti manualmente come quelli che si trovano nel dataset del MNIST, che è preso da questa realtà attuale. L’obiettivo del discriminatore, quando viene indicato un evento dal vero dataset MNIST, è quello di percepire quelli che sono in buona fede.

Nel frattempo, il generatore sta realizzando nuove immagini ingegnerizzate che vanno al discriminatore. Lo fa in quanto tale nelle aspettative che anche queste saranno ritenute valide, nonostante il fatto che siano false. L’obiettivo del generatore è quello di creare immagini tollerabili scritte a mano: mentire senza essere ottenuti. L’obiettivo del discriminatore è di riconoscere come false le immagini provenienti dal generatore.

Ecco i mezzi che un GAN prende:

Il generatore prende un numero arbitrario e restituisce un’immagine.

L’immagine creata viene inserita nel discriminatore vicino a un’ondata di immagini prese dal set di dati reali e di verità.

Il discriminatore prende sia le immagini reali che quelle contraffatte e restituisce le probabilità, un numero da qualche parte nell’intervallo 0 e 1, con 1 che parla di un’aspettativa di credibilità e 0 che parla di contraffazione.

In questo modo si ha un doppio cerchio di input:

Il discriminatore si trova in un cerchio di input con la verità di fondo delle immagini, che noi conosciamo.

Il generatore si trova in un cerchio di input con il discriminatore.

Schema GAN
Credito: O’Reilly

Si può pensare a un GAN come alla restrizione di un falsario e di un poliziotto in un giro di felini e topi, dove il falsario sta cercando di capire come passare le banconote false, e il poliziotto sta cercando di capire come riconoscerle. Entrambi sono dinamici; per esempio, anche il poliziotto si sta preparando (per allargare il rapporto, forse la banca nazionale sta salutando le accuse che sono passate di nascosto), e ogni lato viene a familiarizzare con le diverse tecniche in un’accelerazione costante.

Per l’MNIST, il discriminatore organizza è una disposizione standard convoluzionale che può classificare le immagini che gli sono state affiancate, un classificatore binomiale che contrassegna le immagini come autentiche o false. Il generatore è una disposizione convoluzionale inversa, si potrebbe dire: Mentre un classificatore convoluzionale standard prende un’immagine e la ridimensiona per fornire una probabilità, il generatore prende un vettore di confusione irregolare e la ridimensiona in un’immagine. Il principale scarta le informazioni attraverso strategie di downsampling come il maxpooling, e il secondo produce nuove informazioni.

Le due reti stanno cercando di razionalizzare una capacità alternativa e contraddittoria del bersaglio, o lavoro di sfortuna, in un gioco a zero zero. Si tratta fondamentalmente di un modello di pundit dei personaggi sullo schermo. Come il discriminatore cambia il suo comportamento, così fa il generatore, e viceversa. Le loro sventure si spingono l’una contro l’altra.

GAN
GAN, Autoencoder e VAE

Potrebbe essere utile per contrastare i sistemi generativi mal posizionati con altri sistemi neurali, per esempio gli autoencoder e gli autoencoder variazionali.

Gli autoencoder codificano le informazioni in ingresso come vettori. Essi creano una rappresentazione nascosta, o compattata, delle informazioni grezze. Sono utili per la riduzione della dimensionalità; cioè, il riempimento vettoriale come rappresentazione nascosta racchiude l’informazione grezza in meno misure notevoli. Gli autoencoder possono essere combinati con un presunto decoder, che permette di ricreare le informazioni di input dipendenti dalla sua rappresentazione nascosta, proprio come si farebbe con una macchina Boltzmann limitata.

schema dell’autoencoder
Consigli per la preparazione di un GAN

Nel momento in cui si addestra il discriminatore, mantenere costante la stima del generatore; e quando si addestra il generatore, mantenere costante il discriminatore. Ognuno dovrebbe prepararsi contro un nemico statico. Per esempio, questo dà al generatore una lettura superiore sul pendio da cui deve imparare.

In modo simile, preallenando il discriminatore contro il MNIST prima di iniziare a preparare il generatore, si imposterà un’inclinazione più chiara.

Ogni lato del GAN può sopraffare l’altro. Nel caso in cui il discriminatore sia eccessivamente grande, restituirà delle stime così vicine a 0 o 1 che il generatore si batterà per valutare l’inclinazione. Nella remota possibilità che il generatore sia eccessivamente grande, si avventurerà tenacemente in difetti del discriminatore che portano a falsi negativi. Questo potrebbe essere moderato dai tassi di apprendimento individuale delle reti. I due sistemi neurali devono avere un “livello attitudinale” comparabile. 1

Le GAN hanno messo da parte un lungo sforzo per prepararsi. Su una GPU solitaria un GAN può richiedere ore e su una CPU solitaria più di un giorno. Anche se difficili da sintonizzare e quindi da utilizzare, le GAN hanno rinvigorito una tonnellata di affascinanti esplorazioni e composizioni.

Ecco un esempio di GAN codificato in Keras, da cui è possibile importare modelli in Deeplearning4j.

classe GAN():

def __init__(self):

    self.img_rows = 28

    self.img_cols = 28

    auto.channels = 1

    self.img_shape = (self.img_rows, self.img_cols, self.channels)

    ottimizzatore = Adam(0.0002, 0.5)

    # Costruisci e compila il discriminatore

    self.discriminator = auto.build_discriminator()

    self.discriminator.compile(loss='binary_crossentropy',

        optimizer=ottimizzatore,

        metrica=['accuratezza']))

    # Costruisci e compila il generatore

    auto.generator = auto.build_generator()

    self.generator.compile(loss='binary_crossentropy', optimizer=ottimizzatore)

    # Il generatore prende il rumore come input e genera imgs

    z = Ingresso(forma=(100,))

    img = autogeneratore(z)

    # Per il modello combinato addestreremo solo il generatore

    auto-discriminatore.addestrabile = Falso

    # Il valido prende le immagini generate come input e determina la validità

    valido = auto-discriminatore(img)

    # Il modello combinato (generatore e discriminatore impilato) prende

    # rumore come ingresso => genera immagini => determina la validità

    self.combined = Modello(z, valido)

    self.combined.compile(loss='binario_crossentropia', ottimizzatore=ottimizzatore)

def build_generator(self):

    noise_shape = (100,)

    modello = sequenziale()

    model.add(Dense(256, input_shape=rumore_shape))

    model.add(LeakyReLU(alpha=0.2))

    model.add(BatchNormalization(momentum=0.8))

    model.add(Dense(512))

    model.add(LeakyReLU(alpha=0.2))

    model.add(BatchNormalization(momentum=0.8))

    model.add(Dense(1024))

    model.add(LeakyReLU(alpha=0.2))

    model.add(BatchNormalization(momentum=0.8))

    model.add(Dense(np.prod(np.prod(self.img_shape), activation='tanh')))

    model.add(Reshape(self.img_shape))

    modello.sommario()

    rumore = Ingresso(forma=rumore_forma_di_rumore)

    img = modello(rumore)

    Modello di ritorno (rumore, img)

def build_discriminator(self):

    img_shape = (self.img_rows, self.img_cols, self.channels)

    modello = sequenziale()

    model.add(Flatten(Flatten(input_shape=img_shape))

    model.add(Dense(512))

    model.add(LeakyReLU(alpha=0.2))

    model.add(Dense(256))

    model.add(LeakyReLU(alpha=0.2))

    model.add(Dense(1, attivazione='sigmoid'))

    modello.sommario()

    img = Ingresso(forma=img_shape)

    validità = modello(img)

    Modello di ritorno(img, validità)

def treno(auto, epoche, batch_size=128, save_interval=50):

    # Carica il dataset

    (X_train, _), (_, _) = mnist.load_data()

    # Ridimensionamento da -1 a 1

        X_train = (X_train.astype(np.float32) - 127.5) / 127.5

        X_train = np.expand_dims(X_train, axis=3)

        half_batch = int(batch_size / 2)

        per le epoche a portata di mano (epoche):

            # ---------------------

            # Discriminatore del treno

            # ---------------------

            # Selezionare un mezzo gruppo casuale di immagini

            idx = np.random.randint(0, X_train.shape[0], half_batch)

            imgs = X_train[idx]

            rumore = np.random.normal(0, 1, (half_batch, 100))

            # Genera un mezzo lotto di nuove immagini

            gen_imgs = auto.generator.predict(noise)

            # Addestrare il discriminatore

            d_loss_real = auto.discriminator.train_on_batch(imgs, np.ones((half_batch, 1)))

            d_loss_fake = auto.discriminator.train_on_batch(gen_imgs, np.zeros((half_batch, 1)))

            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

            # ---------------------

            # Generatore di treni

            # ---------------------

            rumore = np.random.normal(0, 1, (batch_size, 100))

            # Il generatore vuole che il discriminatore etichetti i campioni generati

            # come validi (uno)

            valid_y = np.array([1] * batch_size)

            # Allena il generatore #

            g_loss = auto.combinato.treno_su_batch(rumore, valido_y)

            # Trama il progresso

            stampa ("%d [D loss: %f, acc.: %.2f%%%] [G loss: %f]" % (epoca, d_loss[0], 100*d_loss[1], g_loss))

            # Se ad intervallo di salvataggio => salva i campioni di immagine generati

            se epoca % save_interval == 0:

                self.save_imgs(epoch)

    def save_imgs(self, epoch):

        r, c = 5, 5

        rumore = np.random.normal(0, 1, (r * c, 100))

        gen_imgs = auto.generator.predict(noise)

        # Ridimensionamento immagini 0 - 1

        gen_imgs = 0,5 * gen_imgs + 0,5

        fico, assi = plt.sottoparcelle(r, c)

        cnt = 0

        per i nel raggio d'azione(r):

            per j nella gamma(c):

                axs[i,j].imshow(gen_imgs[cnt, :, :,:,0], cmap='gray')

                assi[i,j].asse('off')

                cnt += 1

        fig.savefig("gan/images/mnist_%d.png" % epoch)

        plt.close()

se __name__ == '__main__':

    gan = GAN()

    gan.train(epochs=30000, batch_size=32, save_interval=200)