Obliczenia generatywne a obliczenia dyskryminacyjne

Aby zrozumieć GAN-y, należy zdać sobie sprawę, jak działają obliczenia generatywne, a do tego wyróżnienie ich od obliczeń dyskryminacyjnych jest oświecające. Obliczenia dyskryminacyjne starają się scharakteryzować informacje wejściowe, to znaczy, biorąc pod uwagę szczególne cechy danej informacji, antycypują nazwę lub klasę, dla której ta informacja ma miejsce.

Na przykład, biorąc pod uwagę każde słowo w emailu (przypadek informacyjny), obliczenia dyskryminacyjne mogą przewidzieć, czy wiadomość jest spamem, czy nie_spamem. Spam jest jedną z nazw, a pakiet słów zgromadzonych w emailu jest wyróżnieniem, które składa się na informacje informacyjne. W momencie naukowego przekazania tej kwestii, nazwa nazywa się y, a wyróżnione słowa x. Definicja p(y|x) jest używana do określenia “prawdopodobieństwa y podanego x”, co w tej sytuacji oznaczałoby “prawdopodobieństwo, że wiadomość e-mail jest spamem, biorąc pod uwagę słowa, które zawiera”.

Tak więc mapa obliczeń dyskryminacyjnych zaznacza do znaków. Dotyczą one wyłącznie tego połączenia. Jednym z podejść do obliczeń generatywnych jest to, że robią one odwrotnie. Zamiast antycypować znak, który ma być wyróżniony, starają się przewidzieć wyróżnienia, które mają określoną nazwę.

Badanie, na które próbuje się odpowiedzieć w ramach obliczeń generatywnych, jest następujące: Spodziewając się, że ten e-mail jest spamem, jak prawdopodobne są te wyróżnione punkty? Podczas gdy modelom dyskryminacyjnym zależy na związku między y a x, modelom generatywnym zależy na tym, “jak otrzymasz x”. Umożliwiają one wyłapanie p(x|y), prawdopodobieństwa otrzymania x podanego y, lub prawdopodobieństwa otrzymania podkreślenia podanego imienia lub klasy. (Biorąc pod uwagę wszystkie te czynniki, obliczenia generatywne mogą być również wykorzystywane jako klasyfikatory. Z jakiegoś dziwnego powodu mogą one osiągnąć więcej, niż tylko zamówić informacje wejściowe).

Innym podejściem, które należy wziąć pod uwagę, jest rozpoznanie rozróżnienia od takiego generatywnego:

Modele dyskryminacyjne zapoznają się z granicą pomiędzy klasami

Modele generatywne modelują rozproszenie poszczególnych klas

Jak działają GAN-y

Jeden układ neuronowy, zwany generatorem, tworzy nowe zdarzenia informacyjne, podczas gdy drugi, dyskryminator, ocenia je pod kątem realności; na przykład, dyskryminator wybiera, czy każde wystąpienie informacji, które bada, ma miejsce z prawdziwie przygotowywanym zestawem danych, czy też nie.

Przypuśćmy, że staramy się osiągnąć coś bardziej powszechnego niż kopiowanie Mona Lisy. Stworzymy ręcznie pisane cyfry, takie jak te, które znajdują się w zbiorze danych MNIST, który jest zaczerpnięty z tej obecnej rzeczywistości. Celem dyskryminatora, gdy wskaże on zdarzenie z prawdziwego zbioru danych MNIST, jest dostrzeżenie tych, które są w dobrej wierze.

W międzyczasie, generator tworzy nowe, zaprojektowane obrazy, które trafiają do dyskryminatora. Czyni to w ten sposób w oczekiwaniu, że one również będą cenione, mimo że są fałszywe. Celem generatora jest stworzenie tolerowanych, pisanych odręcznie cyfr: kłamać, nie dając się złapać. Celem dyskryminatora jest rozpoznanie obrazów pochodzących z generatora jako fałszywych.

Oto środki, które podejmuje GAN:

Generator bierze dowolny numer i zwraca zdjęcie.

Stworzone zdjęcie jest wkręcane do dyskryminatora w pobliżu fali zdjęć wykonanych z prawdziwego, naziemnego zbioru danych.

Dyskryminator robi zarówno oryginalne jak i podrobione zdjęcia i zwraca prawdopodobieństwo, liczba gdzieś w zakresie od 0 do 1, z czego 1 mówi do oczekiwania wiarygodności, a 0 do podróbki.

Masz więc podwójne koło wejściowe:

Dyskryminator znajduje się w okręgu wejściowym z podstawową prawdą obrazów, którą znamy.

Generator znajduje się w kole wejściowym z dyskryminatorem.

Schemat GAN
Kredyt: O’Reilly

Możesz myśleć o GAN-ie jako o ograniczeniu fałszerz i gliniarz w rundzie z kotem i myszką, gdzie fałszerz zastanawia się, jak przekazać fałszywe notatki, a gliniarz zastanawia się, jak je rozpoznać. Oba są dynamiczne; na przykład, gliniarz jest w przygotowaniu, jak również (w celu poszerzenia relacji, być może krajowy bank jest wywoływanie opłat, które zakradły się w przeszłości), a każda strona przychodzi do zapoznania się z różnymi technikami w stałym przyspieszeniu.

Dla MNIST, organizacja dyskryminacyjna jest standardową organizacją konwolucyjną, która może klasyfikować zdjęcia przyklejone do niej, dwumianowy klasyfikator oznaczający zdjęcia jako prawdziwe lub fałszywe. Można powiedzieć, że generator jest odwróconym układem falistym: Podczas gdy klasyfikator standardowy robi zdjęcie i zmniejsza jego próbkowanie, aby zapewnić prawdopodobieństwo, generator bierze wektor nieregularnego zamieszania i zwiększa jego próbkowanie do zdjęcia. Główny odrzuca informacje poprzez strategie zmniejszania próbkowania, takie jak maxpooling, a drugi generuje nowe informacje.

Obie siatki próbują usprawnić naprzemienną i sprzeczną pojemność docelową, lub nieszczęśliwą pracę, w grze o sumie zerowej. Jest to w zasadzie model punditu postaci na ekranie. Tak jak dyskryminator zmienia swoje zachowanie, tak i generator, i na odwrót. Ich nieszczęścia naciskają na siebie nawzajem.

GANy
GAN-y, Autoenkodery i VAE-y

Cenne może być kontrastowanie generatywnych układów źle rozmieszczonych z innymi układami neuronowymi, na przykład z autokoderami i autokoderami zmiennymi.

Autoenkodery kodują informacje wejściowe jako wektory. Tworzą one zakryte lub zagęszczone przedstawienie surowych informacji. Są one pomocne w zmniejszaniu wymiarowości, tzn. wypełnienie wektorowe jako ukryty portret pakuje surową informację w mniej niezwykłych wymiarach. Autoenkodery mogą być połączone z rzekomym dekoderem, który umożliwia odtworzenie informacji wejściowych w zależności od ich ukrytej prezentacji, tak samo jak w przypadku ograniczonej maszyny Boltzmanna.

schemat autenkodera
Wskazówki dotyczące przygotowania GAN-u

W momencie, gdy trenujesz dyskryminator, utrzymuj stały szacunek dla generatora; a w momencie, gdy trenujesz generator, utrzymuj go na stałym poziomie. Każdy z nich powinien przygotować się przeciwko statycznemu wrogowi. Na przykład, daje to generatorowi lepszy odczyt na zboczu, przez które musi się uczyć.

W podobny sposób, zanim zaczniesz przygotowywać generator, przetrenowanie dyskryminatora z MNISTem spowoduje ustawienie bardziej wyraźnego nachylenia.

Każda ze stron GAN może przytłoczyć drugą. W przypadku, gdy dyskryminator jest zbyt duży, zwróci szacunek tak blisko 0 lub 1, że generator będzie walczył o wykorzystanie pochylenia. W przypadku, gdy generator jest zbyt duży, będzie uporczywie przygrywał z wadami dyskryminatora, które prowadzą do fałszywych negatywów. Może to być moderowane przez indywidualne wskaźniki uczenia się sieci. Te dwa systemy neuronowe muszą mieć porównywalny “poziom predyspozycji”. 1

GAN-y odłożyły długi wysiłek na przygotowanie. W przypadku samotnej jednostki GPU przygotowanie GAN-a może trwać kilka godzin, a w przypadku samotnej jednostki CPU – ponad jeden dzień. Choć trudne do dostrojenia, a co za tym idzie – do wykorzystania, GAN-y ożywiły tonę fascynujących poszukiwań i kompozycji.

Oto przykład zakodowanego w Kerze GAN-a, z którego modele mogą być importowane do Deeplearning4j.

klasa GAN():

def __init__(ja):

    self.img_rows = 28

    self.img_cols = 28

    self.channels = 1

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

    optymalizator = Adam(0.0002, 0.5)

    # Zbuduj i skompiluj dyskryminator

    self.discriminator = self.build_discriminator()

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

        optymalizator=optymalizator,

        metryka=["dokładność"])

    # Zbuduj i skompiluj generator

    self.generator = self.build_generator()

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

    # Generator bierze hałas jako wejście i generuje imgi

    z = Input(shape=(100,))

    img = self.generator(z)

    # Dla modelu kombinowanego będziemy trenować tylko generator

    Samo-wyróżniający się.szkolny = Fałszywy

    # valid takes generated images as input and determines validity

    ważne = self.discriminator(img)

    # The combined model (stacked generator and discriminator) takes

    # noise as input => generates images => determines validity

    self.combined = Model(z, ważny)

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

def build_generator(self):

    noise_shape = (100,)

    model = sekwencyjny()

    model.add(Dense(256, input_shape=noise_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(self.img_shape), activation='tanh'))

    model.add(Reshape(self.img_shape))

    model.streszczenie()

    noise = Input(shape=noise_shape)

    img = model(hałas)

    powrót Model (hałas, img)

def build_discriminator(ja):

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

    model = sekwencyjny()

    model.add(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, activation='sigmoid'))

    model.streszczenie()

    img = Input(shape=img_shape)

    ważność = model(img)

    powrót Model (img, ważność)

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

    # Load the dataset

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

    # Rescale -1 do 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)

        dla epoki w zakresie (epokach):

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

            # Train Discriminator

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

            # Wybierz losowo pół partii obrazów

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

            imgs = X_train[idx]

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

            # Generowanie pół partii nowych obrazów

            gen_imgs = self.generator.predict(hałas)

            # Pociągnij dyskryminatora

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

            d_loss_fake = self.discriminator.train_on_batch(gen_imgs, np.zera((half_batch, 1)))

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

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

            # Generator pociągu

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

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

            # Generator chce, aby dyskryminator oznaczył wygenerowane próbki

            # as valid (ones)

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

            # Pociągnij generator

            g_loss = self.combined.train_on_batch(hałas, ważne_y)

            # Plotuj postępy

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

            # If at save interval => save generated image samples

            if epoch % save_interval == 0:

                self.save_imgs(epoka)

    def save_imgs(ja, epoka):

        r, c = 5, 5

        hałas = np.random.normal(0, 1, (r * c, 100))

        gen_imgs = self.generator.predict(hałas)

        # Obrazy w skali od 0 do 1

        gen_imgs = 0,5 * gen_imgs + 0,5

        fig, osie = plt.podpowierzchnie(r, c)

        cnt = 0

        dla i w zakresie(r):

            dla j w zakresie(c):

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

                axs[i,j].axis("off")

                cnt += 1

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

        plt.close()

if __name__ == "__main__":

    gan = GAN()

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