Die Zahl von dem, was ich tat, ist leicht zu verstehen. Kurz gesagt, der Codierer komprimiert die Informationen, indem er die Dimension der Bilddaten verringert, und der Decodierer rekonstruiert das Bild unter Verwendung der komprimierten Informationen. Berechnen und optimieren Sie den Abstand MAE zwischen den Pixeln des Eingabebildes und des Ausgabebildes. Lernen ohne Lehrer.
Wie erzeugen Sie nun mit diesem Auto-Encoder ein Bild? Trainieren Sie zunächst den Auto-Encoder anhand von Bildern. Optimieren Sie so, dass die Parameter der beiden Netzwerke, des Codierers und des Decodierers, angemessen sind. Dann können Sie ein grobes Gefühl dafür bekommen, wie das Eingabebild im latenten Raum ausgedrückt wird. Bei Verwendung dieses Modells als Generierungsmodell wird grundsätzlich nicht der Codiererteil verwendet, sondern nur der latente Raum und der Decodierer.
Während gewöhnliche Auto-Encoder versuchen, den latenten Raum als Array zu lernen, versuchen variable Encoder, geeignete Parameter zu finden, die die Verteilung des latenten Raums definieren. Dann wird das Bild rekonstruiert, indem der Wert aus dieser latenten Verteilung abgetastet wird, um einen bestimmten Wert zu erhalten, und in den Decodierer eingegeben wird.
Der linke ist ein normaler Auto-Encoder und der rechte ist ein variabler Encoder.
Für Details ist dieser Artikel sehr einfach zu verstehen.
GAN
Weitere Informationen zu GAN finden Sie in anderen Artikeln. Hier werden die charakteristischen Eigenschaften von GAN beschrieben. In der GAN-Architektur werden sowohl der Generator als auch der Diskriminator durch die Verlustfunktion des Diskriminators trainiert. Das eigene Training des Diskriminators versucht, den Diskriminatorverlust für alle Trainingsdaten zu minimieren. Der Generator versucht andererseits, den Verlust des Klassifikators für die gefälschten Proben, die er macht, zu maximieren. Mit anderen Worten, das Training gewöhnlicher neuronaler Netze ist ein Optimierungsproblem, während das Training von GAN ein Spiel ist, bei dem Generatoren und Klassifikatoren eher konkurrieren als optimieren. Es stabilisiert sich, wenn das Nash-Gleichgewicht erreicht ist.
Der GAN-Trainingsalgorithmus kann wie folgt zusammengefasst werden.
Jeder iterative Schritt im Training:
1.Diskriminatorentraining
a.Wählen Sie zufällig Stichproben aus realen Daten aus, um Mini-Batch X zu erstellen
b.Machen Sie einen Mini-Batch z eines Zufallszahlenvektors und machen Sie einen Mini-Batch G, der aus gefälschten Proben besteht(Z)=X`machen
c. D(x)Und D.(x`)Berechnen Sie den Diskriminanzverlust für die Aktualisierungsparameter und aktualisieren Sie sie, indem Sie den Gesamtfehler zurückgeben
2.Generatortraining
a.Machen Sie einen Mini-Batch z eines Zufallszahlenvektors und machen Sie einen Mini-Batch G, der aus gefälschten Proben besteht(z)=X`machen
b.D(x`)Der Unterscheidungsfehler wird maximiert, indem der Unterscheidungsverlust für ihn berechnet und zurückpropagiert wird, um die Generatorparameter zu aktualisieren.
Beachten Sie, dass die Generatorparameter beim Training des Klassifikators in Schritt 1 nicht aktualisiert werden! Beachten Sie, dass die Klassifikatorparameter beim Training des Generators in Schritt 2 nicht aktualisiert werden!
Implementieren Sie GAN mit den bisherigen Grundkenntnissen von GAN so einfach wie möglich. (Eine praktischere Implementierung wird in einem nachfolgenden Artikel gegeben.)
Dieses Mal werden wir den Code implementieren, um ein Bild aus MNIST-Daten mit Keras 'Sequential API zu generieren.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from keras.datasets import mnist
from keras.layers import Dense, Flatten, Reshape
from keras.layers.advanced_activations import LeakyReLU
from keras.models import Sequential
from keras.optimizers import Adam
#Einstellung der Eingabedimension
img_rows = 28
img_cols = 28
channels = 1
img_shape = (img_rows, img_cols, channels)
#Dimension des Eingangsrauschens zum Generator
z_dim = 100
#Generator
def build_generator(img_shape, z_dim):
model = Sequential()
model.add(Dense(128, input_dim=z_dim))
model.add(LeakyReLU(alpha=0.01))
model.add(Dense(28*28*1, activation='tanh'))
model.add(Reshape(img_shape))
return model
#Identifikator
def build_discriminator(image_shape):
model = Sequential()
model.add(Flatten(input_shape=img_shape))
model.add(Dense(128))
model.add(LeakyReLU(alpha=0.01))
model.add(Dense(1, activation='sigmoid'))
return model
#kompilieren!
def build_gan(generator, discriminator):
model = Sequential()
model.add(generator)
model.add(discriminator)
return model
#Klassifikator erstellen und kompilieren
discriminator = build_discriminator(img_shape)
discriminator.compile(loss='binary_crossentropy',
optimizer=Adam(),
metrics=["accuracy"])
#Generator bauen
generator = build_generator(img_shape, z_dim)
#Die Identifikatorparameter werden während des Generatoraufbaus festgelegt
discriminator.trainable = False
#Erstellen und kompilieren Sie das GAN-Modell
gan = build_gan(generator, discriminator)
gan.compile(loss="binary_crossentropy",optimizer=Adam())
#Ausbildung!
losses = []
accuracies = []
iteration_checkpoints = []
def train(iterations, batch_size, sample_interval):
(X_train, Y_train), (X_test, Y_test) = mnist.load_data() #X_train.shape=(60000, 28, 28)
X_train = X_train /127.5 - 1.0
X_train = np.expand_dims(X_train, axis=3)
real = np.ones((batch_size, 1))
fake = np.zeros((batch_size,1))
for iteration in range(iterations):
#Machen Sie eine zufällig ausgewählte Charge aus einem realen Bild
idx = np.random.randint(0, X_train.shape[0],batch_size)
imgs = X_train[idx]
#Erstellen Sie einen Stapel gefälschter Bilder
z = np.random.normal(0, 1, (batch_size, 100))
gen_imgs = generator.predict(z)
#Diskriminatorentraining
d_loss_real = discriminator.train_on_batch(imgs, real)
d_loss_fake = discriminator.train_on_batch(gen_imgs, fake)
d_loss, accuracy = 0.5 * np.add(d_loss_real, d_loss_fake)
#Erstellen Sie einen Stapel gefälschter Bilder
z = np.random.normal(0, 1, (batch_size, 100))
ge_images = generator.predict(z)
#Generatortraining
g_loss = gan.train_on_batch(z, real)
if (iteration+1) % sample_interval == 0:
#Iteration Notieren Sie den Verlustwert und den Übereinstimmungswert
losses.append((d_loss, g_loss))
accuracies.append(100 * accuracy)
iteration_checkpoints.append(iteration+1)
print("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" %
(iteration + 1, d_loss, 100.0 * accuracy, g_loss))
sample_images(generator)
def sample_images(generator, image_grid_rows=4, image_grid_columns=4):
#Zufällige Rauschabtastung
z = np.random.normal(0, 1, (image_grid_rows * image_grid_columns, z_dim))
gen_imgs = generator.predict(z)
#Pixelwertskala
gen_imgs = 0.5 * gen_imgs + 0.5
fig, axs = plt.subplots(image_grid_rows,
image_grid_columns,
figsize=(4, 4),
sharey=True,
sharex=True)
cnt = 0
for i in range(image_grid_rows):
for j in range(image_grid_columns):
# Output a grid of images
axs[i, j].imshow(gen_imgs[cnt, :, :, 0], cmap='gray')
axs[i, j].axis('off')
cnt += 1
iterations = 20000
batch_size = 128
sample_interval = 1000
train(iterations, batch_size, sample_interval)
1000 [D loss: 0.129656, acc.: 96.09%] [G loss: 3.387729]
2000 [D loss: 0.079047, acc.: 97.66%] [G loss: 3.964481]
3000 [D loss: 0.071152, acc.: 97.27%] [G loss: 5.072118]
4000 [D loss: 0.217956, acc.: 91.02%] [G loss: 3.993687]
5000 [D loss: 0.380112, acc.: 86.72%] [G loss: 3.941338]
6000 [D loss: 0.292950, acc.: 89.45%] [G loss: 4.491636]
7000 [D loss: 0.345073, acc.: 85.55%] [G loss: 4.056399]
8000 [D loss: 0.396545, acc.: 86.33%] [G loss: 3.101150]
9000 [D loss: 0.744731, acc.: 70.70%] [G loss: 2.761991]
10000 [D loss: 0.444913, acc.: 80.86%] [G loss: 3.474383]
11000 [D loss: 0.362310, acc.: 82.81%] [G loss: 3.101751]
12000 [D loss: 0.383188, acc.: 84.38%] [G loss: 3.111648]
13000 [D loss: 0.283140, acc.: 89.06%] [G loss: 3.082010]
14000 [D loss: 0.411019, acc.: 81.64%] [G loss: 2.747284]
15000 [D loss: 0.386751, acc.: 82.03%] [G loss: 2.795580]
16000 [D loss: 0.475734, acc.: 80.86%] [G loss: 2.436490]
17000 [D loss: 0.285364, acc.: 89.45%] [G loss: 2.764011]
18000 [D loss: 0.202013, acc.: 91.80%] [G loss: 4.058733]
19000 [D loss: 0.285773, acc.: 86.72%] [G loss: 3.038511]
20000 [D loss: 0.354960, acc.: 81.64%] [G loss: 2.719907]
↓1000iteration ↓2000iteration ↓10000iteration ↓20000iteration
Zu Beginn des Lernens war das Bild wie Rauschen, aber am Ende scheint es, dass sogar ein einfacher Zweischichtgenerator relativ realistische handgeschriebene Zeichen erzeugen kann. Auf dem Hintergrund des handschriftlichen Bildes, das durch einfaches GAN erzeugt wurde, erscheinen jedoch weiße Punkte, und es fällt sofort auf, dass es nicht handgeschrieben ist. Um diese Schwäche zu verbessern, möchte ich DCGAN beim nächsten Mal mithilfe der Faltung implementieren!