TensorFlow で GAN を使用して画像を生成する

1. 説明

        この記事では、tensorflow での mnist データ収集に GAN を実装する方法について詳しく説明します。フレームワークの確立、データセットの読み取り、ジェネレーター、弁別器、コスト関数、最適化などの特定のステップのコード実装が含まれます。

2. GAN フレームワークの概要

  • ジェネレーター: このコンポーネントは、新しい画像を生成します。
  • Discriminator : このコンポーネントは、生成された画像の品質を評価します。

        GAN を使用して画像を生成するために開発する一般的なアーキテクチャを次の図に示します。次のセクションでは、データベースの読み取り方法、必要なアーキテクチャの作成方法、損失関数の計算方法、およびネットワークのトレーニング方法について簡単に説明します。さらに、ネットワークを検査し、新しいイメージを生成するためのコードが提供されます。

3. データセットを読み取る

        MNIST データセットはコンピューター ビジョンの分野で重要な位置を占めており、28 × 28 ピクセルの寸法を持つ多数の手書き数字が含まれています。このデータセットは、グレースケールのシングルチャネル画像形式であるため、GAN 実装に理想的であることがわかりました。

        以下のコード スニペットは、Tensorflow の組み込み関数を使用して MNIST データセットをロードする方法を示しています。読み込みが成功したら、画像を正規化して 3D 形式に再整形します。この変換により、GAN アーキテクチャにおける 2D 画像データの効率的な処理が可能になります。さらに、トレーニング データと検証データ用にメモリが割り当てられます。

        各画像の形状は 28x28x1 の行列として定義され、最後の次元は画像内のチャネル数を表します。MNIST データセットにはグレースケール画像が含まれているため、チャネルは 1 つだけです。

        この特定のインスタンスでは、潜在空間のサイズ (「zsize」で示される) を 100 に設定します。この値は、特定の要件や好みに基づいて調整できます。

from __future__ import print_function, division
from keras.datasets import mnist
from keras.layers import Input, Dense, Reshape, Flatten, Dropout
from keras.layers import BatchNormalization, Activation, ZeroPadding2D
from keras.layers import LeakyReLU
from keras.layers.convolutional import UpSampling2D, Conv2D
from keras.models import Sequential, Model
from keras.optimizers import Adam, SGD
import matplotlib.pyplot as plt
import sys
import numpy as np

num_rows = 28
num_cols = 28
num_channels = 1
input_shape = (num_rows, num_cols, num_channels)
z_size = 100

(train_ims, _), (_, _) = mnist.load_data()
train_ims = train_ims / 127.5 - 1.
train_ims = np.expand_dims(train_ims, axis=3)

valid = np.ones((batch_size, 1))
fake = np.zeros((batch_size, 1))

4. ジェネレーターを定義する

        ジェネレーター (D) は、ディスクリミネーターを騙すことができるリアルな画像を生成する役割を担うため、GAN において重要な役割を果たします。GAN における画像形成の主要なコンポーネントです。この研究では、完全接続 (FC) 層を含み、Leaky ReLU アクティベーションを採用するジェネレーターの特定のアーキテクチャを利用します。ただし、ジェネレーターの最後の層では LeakyReLU の代わりに TanH アクティベーションが使用されることに注意してください。この調整は、生成されたイメージが元の MNIST データベースと同じ間隔 (-1, 1) 内に存在するようにするために行われます。

def build_generator():
    gen_model = Sequential()
    gen_model.add(Dense(256, input_dim=z_size))
    gen_model.add(LeakyReLU(alpha=0.2))
    gen_model.add(BatchNormalization(momentum=0.8))
    gen_model.add(Dense(512))
    gen_model.add(LeakyReLU(alpha=0.2))
    gen_model.add(BatchNormalization(momentum=0.8))
    gen_model.add(Dense(1024))
    gen_model.add(LeakyReLU(alpha=0.2))
    gen_model.add(BatchNormalization(momentum=0.8))
    gen_model.add(Dense(np.prod(input_shape), activation='tanh'))
    gen_model.add(Reshape(input_shape))

    gen_noise = Input(shape=(z_size,))
    gen_img = gen_model(gen_noise)
    return Model(gen_noise, gen_img)

5. 識別子の定義

        敵対的生成ネットワーク (GAN) では、ディスクリミネーター (D) が、信頼性と尤度を評価することによって、実際の画像と生成された画像を区別するという重要なタスクを実行します。このコンポーネントは、二値分類問題として見ることができます。このタスクを達成するために、完全接続層 (FC)、リーキー ReLU アクティベーション、およびドロップアウト層を含む簡素化されたネットワーク アーキテクチャを採用できます。ディスクリミネータの最後の層は FC 層とそれに続く Sigmoid 活性化で構成されていることは言及する価値があります。シグモイド活性化関数は、必要な分類確率を生成します。

def build_discriminator():
    disc_model = Sequential()
    disc_model.add(Flatten(input_shape=input_shape))
    disc_model.add(Dense(512))
    disc_model.add(LeakyReLU(alpha=0.2))
    disc_model.add(Dense(256))
    disc_model.add(LeakyReLU(alpha=0.2))
    disc_model.add(Dense(1, activation='sigmoid'))

    disc_img = Input(shape=input_shape)
    validity = disc_model(disc_img)
    return Model(disc_img, validity)

6. 損失関数を計算する

        GAN で適切な画像生成プロセスを保証するには、GAN のパフォーマンスを評価するための適切な指標を決定することが重要です。このパラメータは損失関数を介して定義します。

        識別器は、生成された画像を本物と偽物に分類し、本物である確率を与える責任があります。この違いを達成するために、弁別器は、実際の画像が提示された場合には関数 D(x) を最大化し、偽の画像が提示された場合には D(G(z)) を最小化することを目指します。

        一方、ジェネレーターは、誤解される可能性のあるリアルな画像を作成することで、識別者をだますことを目的としています。数学的には、これには D(G(z)) のスケーリングが含まれます。ただし、損失関数としてこのコンポーネントのみに依存すると、ネットワークが誤った結果を過信する可能性があります。この問題を解決するには、損失関数の対数 (D(G(z))) を使用します。

        GAN で生成された画像の全体的なコスト関数は、最小ゲームとして表すことができます。

min_G max_D V(D,G) = E(xp_data(x))(log(D(x))] + E(zp(z))(log(1 – D(G(z)))])

        この種の GAN トレーニングには優れたバランスが必要であり、2 人の対戦相手間の競争として機能する可能性があります。それぞれの側は、MinMax ゲームをプレイすることで、相手に影響を与え、相手を出し抜こうとします。

        バイナリのクロスエントロピー損失を使用してジェネレーターとディスクリミネーターを実装できます。

        ジェネレーターとディスクリミネーターの実装には、バイナリのクロスエントロピー損失を利用できます。

# discriminator
disc= build_discriminator()
disc.compile(loss='binary_crossentropy',
    optimizer='sgd',
    metrics=['accuracy'])

z = Input(shape=(z_size,))

# generator
img = generator(z)

disc.trainable = False

validity = disc(img)

# combined model
combined = Model(z, validity)
combined.compile(loss='binary_crossentropy', optimizer='sgd')

7. 損失の最適化

        ネットワークのトレーニングを促進するために、GAN が MinMax ゲームに参加できるようにすることを目指しています。この学習プロセスは、勾配降下法を使用したネットワークの重みの最適化を中心に展開します。学習プロセスを高速化し、次善の損失環境への収束を防ぐために、確率的勾配降下法 (SGD) が採用されています。

        弁別器と生成器の損失が異なる場合、単一の損失関数で両方のシステムを同時に最適化することはできません。したがって、システムごとに個別の損失関数が使用されます。

def intialize_model():
    disc= build_discriminator()
    disc.compile(loss='binary_crossentropy',
        optimizer='sgd',
        metrics=['accuracy'])

    generator = build_generator()

    z = Input(shape=(z_size,))
    img = generator(z)

    disc.trainable = False

    validity = disc(img)

    combined = Model(z, validity)
    combined.compile(loss='binary_crossentropy', optimizer='sgd')
    return disc, Generator, and combined

        必要な機能をすべて指定したら、システムをトレーニングして損失を最適化できます。GAN をトレーニングして画像を生成する手順は次のとおりです。

  • 画像をロードし、ロードした画像と同じサイズのランダムなサウンドを生成します。
  • アップロードされた画像と生成された音声を区別し、信頼性の可能性を検討します。
  • 同じ振幅の別のランダム ノイズが生成され、ジェネレーターへの入力として使用されます。
  • 特定の期間ジェネレーターをトレーニングします。
  • 画像が満足できるまでこれらの手順を繰り返します。
def train(epochs, batch_size=128, sample_interval=50):
    # load images
    (train_ims, _), (_, _) = mnist.load_data()
    # preprocess
    train_ims = train_ims / 127.5 - 1.
    train_ims = np.expand_dims(train_ims, axis=3)

    valid = np.ones((batch_size, 1))
    fake = np.zeros((batch_size, 1))
    # training loop
    for epoch in range(epochs):

        batch_index = np.random.randint(0, train_ims.shape[0], batch_size)
        imgs = train_ims[batch_index]
    # create noise
        noise = np.random.normal(0, 1, (batch_size, z_size))
    # predict using a Generator
        gen_imgs = gen.predict(noise)
    # calculate loss functions
        real_disc_loss = disc.train_on_batch(imgs, valid)
        fake_disc_loss = disc.train_on_batch(gen_imgs, fake)
        disc_loss_total = 0.5 * np.add(real_disc_loss, fake_disc_loss)

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

        g_loss = full_model.train_on_batch(noise, valid)
   
    # save outputs every few epochs
        if epoch % sample_interval == 0:
            one_batch(epoch)

8. 手書きの数字を生成する

        MNIST データセットを使用すると、ジェネレーターを使用して一連の画像の予測を生成するユーティリティ関数を作成できます。この関数はランダムなサウンドを生成し、それをジェネレーターに供給し、それを実行して生成された画像を表示し、特別なフォルダーに保存します。ネットワークの進行状況を監視するには、このユーティリティ関数を定期的に (たとえば 200 サイクルごとに) 実行することをお勧めします。実装は次のとおりです。

def one_batch(epoch):
    r, c = 5, 5
    noise_model = np.random.normal(0, 1, (r * c, z_size))
    gen_images = gen.predict(noise_model)

    # Rescale images 0 - 1
    gen_images = gen_images*(0.5) + 0.5

    fig, axs = plt.subplots(r, c)
    cnt = 0
    for i in range(r):
        for j in range(c):
            axs[i,j].imshow(gen_images[cnt, :,:,0], cmap='gray')
            axs[i,j].axis('off')
            cnt += 1
    fig.savefig("images/%d.png" % epoch)
    plt.close()

        私たちの実験では、10,000 のバッチ サイズを使用して約 32 の GAN をトレーニングしました。トレーニングの進行状況を追跡するために、生成された画像を 200 エポックごとに保存し、「images」という名前の指定フォルダーに保存します。

disc, gen, full_model = intialize_model()
train(epochs=10000, batch_size=32, sample_interval=200)

        ここで、初期化、400 エポック、5000 エポック、および 10000 エポックの最終結果というさまざまな段階での GAN シミュレーション結果を確認してみましょう。

最初に、ジェネレータへの入力としてランダム ノイズから開始します。

        400 エポックのトレーニング後、生成された画像は依然として実際の数値とは大きく異なりますが、ある程度の進歩を観察できます。

        5000 エポックのトレーニング後、生成された数値が MNIST データセットに似始めていることがわかります。

        10,000 エポックのトレーニングをすべて完了すると、次の出力が得られます。

        これらの生成された画像は、ネットワークのトレーニングに使用される手書きの数字データに非常に似ています。これらの画像はトレーニング セットの一部ではなく、完全にネットワークによって生成されることに注意することが重要です。

9. 次のステップ

        GAN による画像生成で良好な結果が得られたので、さらに改善する方法はたくさんあります。この議論の範囲内で、さまざまなパラメーターを試すことを検討できます。以下にいくつかの提案を示します。

  • 潜在空間変数 z_size のさまざまな値を調べて、効率が向上するかどうかを確認します。
  • トレーニング エポックの数を 10,000 を超えて増やします。トレーニング時間を 2 倍または 3 倍にすると、結果が改善または低下する可能性があります。
  • ファッション MNIST やモバイル MNIST などの別のデータセットを使用してみてください。これらのデータセットは MNIST と同じ構造を持っているため、既存のコードを適応させます。
  • CycleGun、DCGAN などの代替アーキテクチャを試してみることを検討してください。これらのモデルを調査するには、ジェネレーター関数とディスクリミネーター関数を変更するだけで十分な場合があります。

        これらの変更を実装することで、GAN の機能をさらに強化し、画像生成の新たな可能性を探ることができます。

        これらの生成された画像は、ネットワークのトレーニングに使用される手書きの数字データに非常に似ています。これらの画像はトレーニング セットの一部ではなく、完全にネットワークによって生成されます。

10. 結論

        要約すると、GAN は、既存のデータベースに基づいて新しい画像を生成できる強力な機械学習モデルです。このチュートリアルでは、例として Tensorflow ライブラリと MNIST データベースを使用して、単純な GAN を設計およびトレーニングする方法を示します。

        重要なポイント

  • GAN は 2 つの重要なコンポーネントで構成されています。ランダムな入力から新しい画像を生成するジェネレーターと、本物の画像と偽の画像を区別するように設計されたディスクリミネーターです。
  • 学習プロセスを通じて、サンプル画像に示すように、手書きの数字によく似た一連の画像を作成することができました。
  • GAN のパフォーマンスを最適化するために、本物の画像と偽の画像を区別するのに役立つマッチング インジケーターと損失関数を提供します。目に見えないデータで GAN を評価し、ジェネレーターを使用することで、これまでに見たことのない新しい画像を生成できます。
  • 全体として、GAN は画像生成において興味深い可能性を提供し、機械学習やコンピューター ビジョンなどのさまざまなアプリケーションにおいて大きな可能性を秘めています。

11. よくある質問

        質問 1. 敵対的生成ネットワーク (GAN) とは何ですか?

        回答: 敵対的生成ネットワーク (GAN) は、特定のトレーニング セットに類似した統計を含む新しいデータを生成する機械学習フレームワークです。画像、ビデオ、テキストなどのさまざまな種類のデータで GAN を使用します。

        質問 2. クリエイティブ モデルとは何ですか?

        1つ。生成モデルは、一連の入力データに基づいて新しいデータを生成する機械学習アルゴリズムです。これらのモデルは、画像生成、テキスト生成、その他の形式のデータ合成などのタスクに使用します。

        質問 3. 損失​​関数とは何ですか?

        1つ。損失関数は、2 つのデータ セット間の差を測定する数学関数です。GAN のコンテキストでは、モデル ジェネレーターは、通常はクラス レコードと注釈付き画像を使用して、生成データとトレーニング データの差を定義する損失関数を最適化することによってトレーニングされます。

        質問 4. CNN と Gan の違いは何ですか?

        回答: CNN (畳み込みニューラル ネットワーク) と GAN (敵対的生成ネットワーク) はどちらも深層学習アーキテクチャですが、目的が異なります。GAN は、特定のトレーニング セットと同様の新しいデータを生成するように設計された生成モデルですが、CNN は分類と認識タスクに使用されます。CNN は可変オートエンコーダー (VAE) として構成することで生成モデルとして使用できますが、CNN は識別トレーニングで優れたパフォーマンスを発揮し、コンピューター ビジョンでの画像分類タスクでより効果的です。

おすすめ

転載: blog.csdn.net/gongdiwudu/article/details/131563850