Generative versus diskriminierende Berechnungen

Um die GANs zu verstehen, sollten Sie erkennen, wie generative Berechnungen funktionieren, und dafür ist es aufschlussreich, sie von diskriminierenden Berechnungen abzugrenzen. Diskriminierende Berechnungen versuchen, Eingabeinformationen zu charakterisieren, d.h., sie nehmen angesichts der Höhepunkte eines Informationsanlasses einen Namen oder eine Klasse vorweg, zu der diese Informationen einen Platz haben.

Wenn man beispielsweise jedes einzelne Wort in einer E-Mail (den Informationsfall) betrachtet, könnte eine diskriminierende Berechnung vorhersehen, ob es sich bei der Nachricht um Spam oder nicht-Spam handelt. Spam ist einer der Namen, und das aus der E-Mail angesammelte Wortpaket ist die Hervorhebung, aus der die Information besteht. An dem Punkt, an dem dieses Problem wissenschaftlich kommuniziert wird, wird der Name y und die Hervorhebungen x genannt. Die Definition p(y|x) wird verwendet, um “die Wahrscheinlichkeit von y bei x” zu bezeichnen, was für diese Situation “die Wahrscheinlichkeit, dass eine E-Mail bei den darin enthaltenen Wörtern ein Spam ist” bedeuten würde.

So werden durch diskriminierende Berechnungen Hervorhebungen auf Markierungen abgebildet. Sie befassen sich ausschließlich mit dieser Verbindung. Ein Ansatz, um generative Berechnungen zu berücksichtigen, ist, dass sie den umgekehrten Weg gehen. Anstatt eine Marke bei bestimmten Hervorhebungen zu antizipieren, versuchen sie, Hervorhebungen bei einem bestimmten Namen vorherzusehen.

Die Frage, die eine generative Berechnung zu beantworten versucht, ist: Die Erwartung dieser E-Mail ist Spam, wie wahrscheinlich sind diese Hervorhebungen? Während sich diskriminierende Modelle um die Verbindung zwischen y und x kümmern, geht es bei generativen Modellen um die Frage, “wie Sie x bekommen”. Sie ermöglichen es Ihnen, p(x|y), die Wahrscheinlichkeit von x bei gegebenem y oder die Wahrscheinlichkeit von Hervorhebungen bei gegebenem Namen oder Klasse zu erfassen. (Alles in allem können generative Berechnungen ebenfalls als Klassifikatoren verwendet werden. Aus irgendeinem merkwürdigen Grund können sie mehr als nur die Eingabeinformationen zu ordnen).

Ein anderer Ansatz, der in Betracht gezogen werden sollte, ist die Erkennung von diskriminierenden und generativen Berechnungen wie dieser:

Diskriminative Modelle machen sich mit der Grenze zwischen den Klassen vertraut

Generative Modelle modellieren die Ausbreitung einzelner Klassen

Wie GANs funktionieren

Eine neuronale Anordnung, Generator genannt, erzeugt neue Informationsvorkommen, während die andere, der Diskriminator, diese auf ihre Echtheit hin beurteilt; so wählt der Diskriminator beispielsweise aus, ob jedes von ihm erhobene Informationsvorkommen einen Platz im echten Vorbereitungsdatensatz hat oder nicht.

Angenommen, wir versuchen, etwas Alltäglicheres zu erreichen als die Mona Lisa zu kopieren. Wir erstellen manuell geschriebene Zahlen, wie sie im MNIST-Datensatz zu finden sind, der aus dieser gegenwärtigen Realität entnommen ist. Das Ziel des Diskriminators ist es, wenn er ein Vorkommnis aus dem echten MNIST-Datensatz anzeigt, diejenigen wahrzunehmen, die echt sind.

In der Zwischenzeit macht der Generator neue, konstruierte Bilder, die er an den Diskriminator weiterleitet. Er tut dies in der Erwartung, dass auch sie als gültig angesehen werden, obwohl sie gefälscht sind. Das Ziel des Generators ist es, erträgliche, mit Handzeichen geschriebene Bilder zu erzeugen: lügen, ohne dass man sie bekommt. Das Ziel des Diskriminators ist es, Bilder, die vom Generator stammen, als gefälscht zu erkennen.

Hier sind die Mittel, die eine GAN einsetzt:

Der Generator nimmt eine beliebige Zahl und gibt ein Bild zurück.

Dieses erzeugte Bild wird in den Diskriminator in der Nähe einer Flut von Bildern, die aus dem echten, der Grundwahrheit entsprechenden Datensatz stammen, eingeblendet.

Der Diskriminator nimmt sowohl echte als auch gefälschte Bilder auf und gibt Wahrscheinlichkeiten zurück, eine Zahl irgendwo zwischen 0 und 1, wobei 1 für die Erwartung der Glaubwürdigkeit und 0 für die Fälschung spricht.

Sie haben also einen zweifachen Eingabekreis:

Der Diskriminator befindet sich in einem Eingabekreis mit der Grundwahrheit der Bilder, die wir kennen.

Der Generator befindet sich in einem Eingabekreis mit dem Diskriminator.

GAN-Schema
Kredit: O’Reilly

Man kann sich eine GAN als die Einschränkung eines Fälschers und eines Bullen in einer Runde von Katze und Maus vorstellen, wobei der Fälscher herausfindet, wie man gefälschte Scheine weitergibt, und der Bulle herausfindet, wie er sie erkennen kann. Beide sind dynamisch; zum Beispiel ist der Polizist auch in der Vorbereitung (um die Beziehung zu erweitern, möglicherweise hagelt die Nationalbank Gebühren, die sich vorbeigeschlichen haben), und jede Seite macht sich mit den verschiedenen Techniken in einer konsistenten Beschleunigung vertraut.

Für das MNIST ist der Diskriminator Organizer ein Standard-Faltungsarrangement, das die darauf gestützten Bilder klassifizieren kann, ein Binomialklassifikator, der Bilder als echt oder gefälscht markiert. Der Generator ist eine umgekehrte Faltungsanordnung, könnte man sagen: Während ein Standardfaltungs-Klassifikator ein Bild aufnimmt und es herunterrechnet, um eine Wahrscheinlichkeit zu liefern, nimmt der Generator einen Vektor unregelmäßiger Bewegung auf und rechnet ihn zu einem Bild hoch. Der Hauptgenerator verwirft Informationen durch Downsampling-Strategien wie Maxpooling, und der zweite erzeugt neue Informationen.

Die beiden Netze versuchen, eine alternative und widersprüchliche Zielkapazität oder Unglücksarbeit in einem Null-Zum-Spiel zu rationalisieren. Es handelt sich im Grunde genommen um ein On-Screen-Charakter-Pandit-Modell. Wenn der Diskriminator sein Verhalten ändert, ändert auch der Generator sein Verhalten und umgekehrt. Ihr Unglück drängt sich gegeneinander.

GANs
GANs, Autoencoder und VAEs

Es könnte wertvoll sein, generative, schlecht disponierte Systeme mit anderen neuronalen Systemen, z.B. Autoencodern und Variations-Autoencodern, zu vergleichen.

Autoencoder kodieren Eingangsinformationen als Vektoren. Sie stellen eine verdeckte oder verdichtete Darstellung der Rohinformation dar. Sie sind hilfreich bei der Verringerung der Dimensionalität, d.h. die Vektorfüllung als verdeckte Darstellung verpackt die Rohinformation in weniger bemerkenswerte Messungen. Autoencoder können mit einem vermeintlichen Decoder kombiniert werden, der es Ihnen ermöglicht, Eingabeinformationen in Abhängigkeit von ihrer verdeckten Darstellung wiederzugeben, ähnlich wie bei einer begrenzten Boltzmann-Maschine.

Autokodierer-Schema
Tipps zur Vorbereitung einer GAN

Wenn Sie den Diskriminator trainieren, halten Sie die Wertschätzung des Generators konstant; und wenn Sie den Generator trainieren, halten Sie den Diskriminator stabil. Jeder sollte sich auf einen statischen Gegner vorbereiten. Dadurch erhält der Generator beispielsweise eine bessere Ablesung der Steigung, an der er lernen muss.

Ähnlich verhält es sich, wenn Sie den Diskriminator gegen MNIST vor der Vorbereitung des Generators trainieren, um eine deutlichere Neigung zu erreichen.

Jede Seite der GAN kann die andere überwältigen. Falls der Diskriminator übermäßig groß ist, wird er die Wertschätzung so nahe an 0 oder 1 zurückgeben, dass der Generator darum kämpfen wird, die Neigung zu durchschauen. Für den Fall, dass der Generator übermäßig groß ist, wird er hartnäckig Unzulänglichkeiten im Diskriminator ausprobieren, die zu gefälschten Negativen führen. Dies könnte durch die individuellen Lernraten der Netze abgeschwächt werden. Die beiden neuronalen Systeme müssen ein vergleichbares “Eignungsniveau” haben. 1

Die GANs haben eine lange Vorbereitungsphase hinter sich. Auf einer Einzelplatz-GPU kann ein GAN Stunden und auf einer Einzelplatz-CPU über einen Tag dauern. Obwohl sie schwer zu stimmen und daher schwer zu nutzen sind, haben GANs eine Menge faszinierender Erkundungen und Kompositionen belebt.

Hier ist ein Beispiel für ein in Keras kodiertes GAN, von dem Modelle in Deeplearning4j importiert werden können.

Klasse GAN() importiert werden können:

def __init__(self):

    self.img_rows = 28

    self.img_cols = 28

    self.channels = 1

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

    Optimierer = Adam(0.0002, 0.5)

    # Bauen und kompilieren Sie den Diskriminator

    selbst.diskriminator = selbst.build_diskriminator()

    self.discriminator.compile(verlust='binäre_kreuzentropie',

        optimizer=Optimierer,

        Metriken=['Genauigkeit'])

    # Bauen und kompilieren Sie den Generator

    self.generator = self.build_generator()

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

    # Der Generator nimmt das Rauschen als Eingabe und die erzeugten Bilder

    z = Eingabe(Form=(100,))

    img = selbst.generator(z)

    # Für das kombinierte Modell werden wir nur den Generator trainieren.

    selbst.diskriminator.trainierbar = Falsch

    # Der Valid Valid nimmt die generierten Bilder als Eingabe und bestimmt die Gültigkeit

    gültig = Selbstdiskriminator(img)

    # Das kombinierte Modell (gestapelter Generator und Diskriminator) nimmt

    # Rauschen als Eingabe => erzeugt Bilder => bestimmt die Gültigkeit

    self.combined = Modell(z, gültig)

    self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)

def build_generator(self):

    noise_shape = (100,)

    Modell = Sequentiell()

    model.add(Dicht(256, input_shape=noise_shape))

    modell.add(LeckageReLU(alpha=0.2))

    modell.add(BatchNormalisierung(momentum=0.8))

    model.add(Dicht(512))

    modell.add(LeckageReLU(alpha=0.2))

    modell.add(BatchNormalisierung(momentum=0.8))

    model.add(Dicht(1024))

    modell.add(LeckageReLU(alpha=0.2))

    modell.add(BatchNormalisierung(momentum=0.8))

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

    model.add(Umgestaltung(selbst.img_form))

    modell.zusammenfassung()

    Rauschen = Eingabe(Form=Rausch_Form)

    img = Modell(lärm)

    Rückgabemodell(Rauschen, img)

def build_discriminator(selbst):

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

    Modell = Sequentiell()

    model.add(Abflachen(input_shape=img_shape))

    model.add(Dicht(512))

    modell.add(LeckageReLU(alpha=0.2))

    model.add(Dicht(256))

    modell.add(LeckageReLU(alpha=0.2))

    model.add(Dicht(1, Aktivierung='sigmoid'))

    modell.zusammenfassung()

    img = Eingabe(form=img_form)

    Gültigkeit = Modell(img)

    Rückgabemodell(img, Gültigkeit)

def train(self, epoches, batch_size=128, save_interval=50):

    # Laden Sie den Datensatz

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

    # Neuskalierung -1 bis 1
  X_Zug = (X_Zug.astype(np.float32) - 127,5) / 127,5

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

        halbe_Batch = int(batch_size / 2)

        für Epoche in Reichweite (Epochen):

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

            # Zug-Diskriminator

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

            # Wählen Sie einen zufälligen halben Stapel von Bildern aus

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

            imgs = X_Zug[idx]

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

            # Einen halben Stapel neuer Bilder erzeugen

            gen_imgs = self.generator.predict(rausch)

            ~ Train the discriminator ~

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

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

            d_loss = 0,5 * np.add(d_loss_real, d_loss_fake)

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

            # Zug-Generator

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

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

            # Der Generator möchte, dass der Diskriminator die generierten Samples kennzeichnet

            # als gültig (Einsen)

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

            # Den Generator trainieren

            g_verlust = selbst.kombinierter.Zug_auf_Batch(Rauschen, gültig_y)

            ~ Plot the progress ~

            Druck ("%d [D-Verlust: %f, gem.: %.2f%%] [G-Verlust: %f]" % (Epoche, d_Verlust[0], 100*d_Verlust[1], g_Verlust))

            # Wenn im Speicherintervall => erzeugte Bildmuster speichern

            wenn Epoche % save_interval == 0:

                self.save_imgs(epoche)

    def save_imgs(selbst, epoche):

        r, c = 5, 5

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

        gen_imgs = self.generator.predict(rausch)

        # Bilder neu skalieren 0 - 1

        gen_imgs = 0,5 * gen_imgs + 0,5

        Abbildung, axs = plt.subplots(r, c)

        cnt = 0

        für i im Bereich(r):

            für j im Bereich(c):

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

                axs[i,j].axis('aus')

                cnt += 1

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

        plt.close()

wenn __Name__ == '__Hauptname__':

    gan = GAN()

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