GAN,CGAN,DCGAN在MIST數據集上的源碼及訓練結果對比

    開始自學人工神經網絡的時候ANN,CNN,RNN都嘗試過了,包括後續的計算機視覺-目標檢測算法,聽覺-聲紋識別,強化學習-五子棋,都進行了編碼實驗,並且親手做了一個實際項目《憑證印章簽字檢查系統》用於銀行會計憑證批量檢查入庫,成功實施投入使用。

    但是對抗生成網絡一直沒有試過。近期找來了一些源碼進行了嘗試。寫出一些心得體會。並把使用的代碼和訓練結果給大家分享一下,歡迎評論和指正。

     後續對於一些好玩的實用的算法會繼續實驗,探索應用,下一步準備嘗試用蒙特卡洛樹加CNN實現一個簡單的alphago五子棋,希望難度能超過我(之前的僅用了強化學習,計算機走字有章法但是難度不夠高經常失誤)。希望各位大佬不吝賜教,交流加306128847。

先上圖:

訓練了三萬次 一批32張GAN,生成器和判別器都是使用了全連接:

圖片不是很清晰,有很多白點雜物,但基本上能看出數字。

CGAN只訓練了兩千次,CGAN和GAN用的網絡是一樣的,只是加入了標籤,大致能看出來數字是按照標籤的順序生成的,所以就停止了訓練,因爲後面的DC_GAN纔是最好玩的:

DCGAN網絡上的教程要求,所有的激活用leaky-relu,所有的上採樣用conv2dTranspose,所有的下采樣用conv2d,步長爲2,激活函數用tanh和sigmod:

第一次嘗試,都用relu,上採樣用unmaxpooling2D,下采樣用maxpooling2D,果然沒效果,生成的圖片都一樣而且看不出來是數字。分析原因,原因,可能是relu激活和pooling層會造成有些神經元反向傳播的時候不可導,而訓練生成器的時候卷積深度比較深,造成訓練困難,而判別器又因爲反覆學習正負樣本造成神經元死亡。

第二次嘗試,生成器用relu和unmaxpooling2D,生成器沒用激活函數。判別器用全連接。3萬次訓練效果如下:

效果還是挺好的!

第三次嘗試,按照教程的激活函數和上下采樣函數來,生成和判別器都用卷積網絡,3萬次訓練效果如下:

效果不太理想,可能我只是學到了方法,沒學到精髓。一些超參數出了問題。

第四次嘗試:生成器按照教程的網絡,判別器用全連接,訓練三萬次效果如下:

效果還可以。

總結:

1、對抗網絡對激活函數、超參數的要求較高,實驗容易失敗,需要反覆嘗試積累經驗。

2、對抗網絡穩定性不太好。

3、有大神指導會進步很快,希望各路大神不吝指教。

實驗源碼如下。

GAN:

from __future__ import print_function, division

from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
from tensorflow.keras.layers import LeakyReLU
from tensorflow.keras.layers import UpSampling2D, Conv2D
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.optimizers import Adam
import os
import matplotlib.pyplot as plt

import sys

import numpy as np


class GAN(object):
    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)
        self.latent_dim = 100

        optimizer = Adam(0.0002, 0.5)

        # 構建和編譯判別器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
                                   optimizer=optimizer,
                                   metrics=['accuracy'])

        # 構建生成器
        self.generator = self.build_generator()

        # 生成器輸入噪聲,生成假圖片
        z = Input(shape=(self.latent_dim,))
        img = self.generator(z)

        # 爲了組合模型,只訓練生成器
        self.discriminator.trainable = False

        # 判別器將生成的圖片作爲輸入並確定有效性
        validity = self.discriminator(img)

        # The combined model  (stacked generator and discriminator)
        # 訓練生成器騙過判別器
        self.combined = Model(z, validity)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)

    def build_generator(self):

        model = Sequential()

        model.add(Dense(256, input_dim=self.latent_dim))
        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))

        # np.prod(self.img_shape)=28x28x1
        model.add(Dense(np.prod(self.img_shape), activation='tanh'))
        model.add(Reshape(self.img_shape))

        model.summary()

        noise = Input(shape=(self.latent_dim,))
        img = model(noise)

        # 輸入噪音輸出圖片
        return Model(noise, img)

    def build_discriminator(self):

        model = Sequential()

        model.add(Flatten(input_shape=self.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.summary()

        img = Input(shape=self.img_shape)
        validity = model(img)

        return Model(img, validity)

    def train(self, epochs, batch_size=128, sample_interval=50):
        dataPath = 'C:/Users/lenovo/Desktop/MinstGan/mnist.npz'
        # 加載數據集
        (x_train, _), (_, _) = mnist.load_data(path=dataPath)

        # 歸一化到-1到1
        x_train = x_train / 127.5 - 1.
        print(x_train.shape)
        x_train = np.expand_dims(x_train, axis=3)
        print(x_train.shape)

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # ---------------------
            # 訓練判別器
            # ---------------------

            # X_train.shape[0]Ϊ爲數據集的數量,隨機生成batch_size個數量的隨機數,作爲數據的索引
            idx = np.random.randint(0, x_train.shape[0], batch_size)

            # 從數據集隨機挑選batch_size個數據,作爲一個批次訓練
            imgs = x_train[idx]

            # 噪聲維度(batch_size,100)
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # 由生成器根據噪音生成假的圖片
            gen_imgs = self.generator.predict(noise)

            # 訓練判別器,判別器希望真實的圖片,打上標籤1,假的圖片打上標籤0
            d_loss_real = self.discriminator.train_on_batch(imgs, valid)
            d_loss_fake = self.discriminator.train_on_batch(gen_imgs, fake)
            d_loss = 0.5 * np.add(d_loss_real, d_loss_fake)

            # ---------------------
            #  訓練生成器
            # ---------------------

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

            # Train the generator (to have the discriminator label samples as valid)
            g_loss = self.combined.train_on_batch(noise, valid)

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

            # 每sample_interval個epoch保存一次生成圖片
            if epoch % sample_interval == 0:
                self.sample_images(epoch)
                if not os.path.exists("keras_model"):
                    os.makedirs("keras_model")
                self.generator.save_weights("keras_model/G_model%d.hdf5" % epoch, True)
                self.discriminator.save_weights("keras_model/D_model%d.hdf5" % epoch, True)

    def sample_images(self, epoch):
        r, c = 5, 5
        # 重新生成一批噪音,維度爲(25,100)
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        gen_imgs = self.generator.predict(noise)

        # 將生成的圖片重新規整0-1之間
        gen_imgs = 0.5 * gen_imgs + 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_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].axis('off')
                cnt += 1
        if not os.path.exists("keras_imgs"):
            os.makedirs("keras_imgs")
        fig.savefig("keras_imgs/%d.png" % epoch)
        plt.close()

    def test(self, gen_nums=100):
        self.generator.load_weights("keras_model/G_model15000.hdf5", by_name=True)
        self.discriminator.load_weights("keras_model/D_model15000.hdf5", by_name=True)
        noise = np.random.normal(0, 1, (gen_nums, self.latent_dim))
        gen = self.generator.predict(noise)
        print(gen.shape)
        # 重整圖片到0-1
        gen = 0.5 * gen + 0.5
        for i in range(0, len(gen)):
            plt.figure(figsize=(128, 128), dpi=1)
            plt.imshow(gen[i, :, :, 0], cmap="gray")
            plt.axis("off")
            if not os.path.exists("keras_gen"):
                os.makedirs("keras_gen")
            plt.savefig("keras_gen" + os.sep + str(i) + '.jpg', dpi=1)
            plt.close()


if __name__ == '__main__':
    gan = GAN()
    gan.train(epochs=30000, batch_size=32, sample_interval=1000)
    gan.test()

 

CGAN:

from tensorflow.keras.datasets import mnist
import tensorflow.keras.backend as K
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
from tensorflow.keras.layers import LeakyReLU,Embedding
from tensorflow.keras.layers import UpSampling2D, Conv2D
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.optimizers import Adam
import os
import matplotlib.pyplot as plt

import sys

import numpy as np


class GAN(object):
    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)
        self.latent_dim = 100

        optimizer = Adam(0.0002, 0.5)

        # 構建和編譯判別器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
                                   optimizer=optimizer,
                                   metrics=['accuracy'])
        # self.discriminator.compile(loss='sparse_categorical_crossentropy',
        #                            optimizer=optimizer,
        #                            metrics=['accuracy'])

        # 構建生成器
        self.generator = self.build_generator()

        # 生成器輸入噪聲,生成假圖片
        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,))
        img = self.generator([noise, label])

        # 爲了組合模型,只訓練生成器
        self.discriminator.trainable = False

        # 判別器將生成的圖片作爲輸入並確定有效性
        validity = self.discriminator([img, label])

        # The combined model  (stacked generator and discriminator)
        # 訓練生成器騙過判別器
        self.combined = Model([noise, label], validity)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)

    def build_generator(self):

        model = Sequential()

        model.add(Dense(256, input_dim=self.latent_dim + 10))
        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))

        # np.prod(self.img_shape)=28x28x1
        model.add(Dense(np.prod(self.img_shape), activation='tanh'))
        model.add(Reshape(self.img_shape))

        model.summary()

        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, 10)(label))
        model_input = K.concatenate([noise, label_embedding], axis=1)
        img = model(model_input)

        # 輸入噪音輸出圖片
        return Model([noise, label], img)

    def build_discriminator(self):

        model = Sequential()

        model.add(Flatten(input_shape=(28,28,2)))
        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.summary()
        img = Input(shape=self.img_shape)  # 輸入 (28,28,1)
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, np.prod(self.img_shape))(label))
        flat_img = Flatten()(img)
        model_input = K.concatenate([flat_img, label_embedding], axis = -1)
        validity = model(model_input)

        return Model([img, label], validity)

    def train(self, epochs, batch_size=128, sample_interval=50):
        dataPath = 'C:/Users/lenovo/Desktop/MinstGan/mnist.npz'
        # 加載數據集
        (x_train, y_train), (_, _) = mnist.load_data(path=dataPath)

        # 歸一化到-1到1
        x_train = x_train / 127.5 - 1.
        print(x_train.shape)
        x_train = np.expand_dims(x_train, axis=3)
        print(x_train.shape)
        y_train = np.expand_dims(y_train, axis=1)
        print(y_train.shape)#60000,1

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # ---------------------
            # 訓練判別器
            # ---------------------

            # X_train.shape[0]Ϊ爲數據集的數量,隨機生成batch_size個數量的隨機數,作爲數據的索引
            idx = np.random.randint(0, x_train.shape[0], batch_size)

            # 從數據集隨機挑選batch_size個數據,作爲一個批次訓練
            imgs = x_train[idx]
            labels = y_train[idx]

            # 噪聲維度(batch_size,100)
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # 由生成器根據噪音生成假的圖片
            gen_imgs = self.generator.predict([noise, labels])
            # 訓練判別器,判別器希望真實的圖片,打上標籤1,假的圖片打上標籤0
            d_loss_real = self.discriminator.train_on_batch([imgs, labels], valid)
            d_loss_fake2 = self.discriminator.train_on_batch([gen_imgs, labels], fake)
            d_loss = d_loss_real + d_loss_fake2

            # ---------------------
            #  訓練生成器
            # ---------------------
            # Train the generator (to have the discriminator label samples as valid)
            g_loss = self.combined.train_on_batch([noise, labels], valid)


            # 每sample_interval個epoch保存一次生成圖片
            if epoch % sample_interval == 0:
                # 打印loss
                print("%d [D loss: %f, acc.: %.2f%%] [G loss: %f]" % (epoch, d_loss[0], 100 * d_loss[1], g_loss))
                self.sample_images(epoch)
                if not os.path.exists("keras_model"):
                    os.makedirs("keras_model")
                self.generator.save_weights("keras_model/G_model%d.hdf5" % epoch, True)
                self.discriminator.save_weights("keras_model/D_model%d.hdf5" % epoch, True)

    def sample_images(self, epoch):
        r, c = 4, 5
        # 重新生成一批噪音,維度爲(25,100)
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        sampled_labels = np.concatenate([np.arange(0, 10).reshape(-1, 1), np.arange(0, 10).reshape(-1, 1)])
        gen_imgs = self.generator.predict([noise, sampled_labels])

        # 將生成的圖片重新規整0-1之間
        gen_imgs = 0.5 * gen_imgs + 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_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].axis('off')
                cnt += 1
        if not os.path.exists("keras_imgs"):
            os.makedirs("keras_imgs")
        fig.savefig("keras_imgs/%d.png" % epoch)
        plt.close()

    def retore(self, epoch):
        self.generator.load_weights("keras_model/G_model%d.hdf5" % epoch)
        self.discriminator.load_weights("keras_model/D_model%d.hdf5" % epoch)

if __name__ == '__main__':
    gan = GAN()
    # gan.retore(11000)
    gan.train(epochs=30000, batch_size=32, sample_interval=500)

 

DCGAN1:

from tensorflow.keras.datasets import mnist
import tensorflow.keras.backend as K
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
from tensorflow.keras.layers import LeakyReLU,Embedding
from tensorflow.keras.layers import UpSampling2D, Conv2D
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.optimizers import Adam
import os
import matplotlib.pyplot as plt

import sys

import numpy as np


class GAN(object):
    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)
        self.latent_dim = 100

        optimizer = Adam(0.0002, 0.5)

        # 構建和編譯判別器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
                                   optimizer=optimizer,
                                   metrics=['accuracy'])
        # self.discriminator.compile(loss='sparse_categorical_crossentropy',
        #                            optimizer=optimizer,
        #                            metrics=['accuracy'])

        # 構建生成器
        self.generator = self.build_generator()

        # 生成器輸入噪聲,生成假圖片
        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,))
        img = self.generator([noise, label])

        # 爲了組合模型,只訓練生成器
        self.discriminator.trainable = False

        # 判別器將生成的圖片作爲輸入並確定有效性
        validity = self.discriminator([img, label])

        # The combined model  (stacked generator and discriminator)
        # 訓練生成器騙過判別器
        self.combined = Model([noise, label], validity)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)

    def build_generator(self):

        model = Sequential()

        model.add(Dense(128, activation='relu', input_dim=110))
        model.add(Dense(196, activation='relu'))
        model.add(Reshape((7, 7, 4)))
        model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
        model.add(UpSampling2D(size=(2,2)))
        model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
        model.add(UpSampling2D(size=(2,2)))
        model.add(Conv2D(16, (3, 3), activation='relu', padding='same'))
        model.add(Conv2D(1, (3, 3), padding='same'))

        model.summary()

        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, 10)(label))
        model_input = K.concatenate([noise, label_embedding], axis=1)
        img = model(model_input)

        # 輸入噪音輸出圖片
        return Model([noise, label], img)

    def build_discriminator(self):

        model = Sequential()

        model.add(Flatten(input_shape=(28,28,2)))
        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.summary()
        img = Input(shape=self.img_shape)  # 輸入 (28,28,1)
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, np.prod(self.img_shape))(label))
        flat_img = Flatten()(img)
        model_input = K.concatenate([flat_img, label_embedding], axis = -1)
        validity = model(model_input)

        return Model([img, label], validity)

    def train(self, epochs, batch_size=128, sample_interval=50):
        dataPath = 'C:/Users/lenovo/Desktop/MinstGan/mnist.npz'
        # 加載數據集
        (x_train, y_train), (_, _) = mnist.load_data(path=dataPath)

        # 歸一化到-1到1
        x_train = x_train / 127.5 - 1.
        print(x_train.shape)
        x_train = np.expand_dims(x_train, axis=3)
        print(x_train.shape)
        y_train = np.expand_dims(y_train, axis=1)
        print(y_train.shape)#60000,1

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # ---------------------
            # 訓練判別器
            # ---------------------

            # X_train.shape[0]Ϊ爲數據集的數量,隨機生成batch_size個數量的隨機數,作爲數據的索引
            idx = np.random.randint(0, x_train.shape[0], batch_size)

            # 從數據集隨機挑選batch_size個數據,作爲一個批次訓練
            imgs = x_train[idx]
            labels = y_train[idx]

            # 噪聲維度(batch_size,100)
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # 由生成器根據噪音生成假的圖片
            gen_imgs = self.generator.predict([noise, labels])
            # 訓練判別器,判別器希望真實的圖片,打上標籤1,假的圖片打上標籤0
            d_loss_real = self.discriminator.train_on_batch([imgs, labels], valid)
            d_loss_fake2 = self.discriminator.train_on_batch([gen_imgs, labels], fake)
            d_loss = d_loss_real + d_loss_fake2

            # ---------------------
            #  訓練生成器
            # ---------------------
            # Train the generator (to have the discriminator label samples as valid)
            g_loss = self.combined.train_on_batch([noise, labels], valid)

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

            # 每sample_interval個epoch保存一次生成圖片
            if epoch % sample_interval == 0:
                self.sample_images(epoch)
                if not os.path.exists("keras_model"):
                    os.makedirs("keras_model")
                self.generator.save_weights("keras_model/G_model%d.hdf5" % epoch, True)
                self.discriminator.save_weights("keras_model/D_model%d.hdf5" % epoch, True)

    def sample_images(self, epoch):
        r, c = 4, 5
        # 重新生成一批噪音,維度爲(25,100)
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        sampled_labels = np.concatenate([np.arange(0, 10).reshape(-1, 1), np.arange(0, 10).reshape(-1, 1)])
        gen_imgs = self.generator.predict([noise, sampled_labels])

        # 將生成的圖片重新規整0-1之間
        gen_imgs = 0.5 * gen_imgs + 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_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].axis('off')
                cnt += 1
        if not os.path.exists("keras_imgs"):
            os.makedirs("keras_imgs")
        fig.savefig("keras_imgs/%d.png" % epoch)
        plt.close()

    def retore(self, epoch):
        self.generator.load_weights("keras_model/G_model%d.hdf5" % epoch)
        self.discriminator.load_weights("keras_model/D_model%d.hdf5" % epoch)

if __name__ == '__main__':
    gan = GAN()
    # gan.retore(500)
    gan.train(epochs=30000, batch_size=32, sample_interval=300)

 

DCGAN2:

from tensorflow.keras.datasets import mnist
import tensorflow.keras.backend as K
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
from tensorflow.keras.layers import LeakyReLU,Embedding
from tensorflow.keras.layers import UpSampling2D, Conv2D, MaxPooling2D, Conv2DTranspose
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.optimizers import Adam
import os
import matplotlib.pyplot as plt

import sys

import numpy as np


class GAN(object):
    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)
        self.latent_dim = 100
        self.dropout = 0.2
        optimizer = Adam(0.0001, 0.9)

        # 構建和編譯判別器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
                                   optimizer=optimizer,
                                   metrics=['accuracy'])
        # self.discriminator.compile(loss='sparse_categorical_crossentropy',
        #                            optimizer=optimizer,
        #                            metrics=['accuracy'])

        # 構建生成器
        self.generator = self.build_generator()

        # 生成器輸入噪聲,生成假圖片
        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,))
        img = self.generator([noise, label])

        # 爲了組合模型,只訓練生成器
        self.discriminator.trainable = False

        # 判別器將生成的圖片作爲輸入並確定有效性
        validity = self.discriminator([img, label])

        # The combined model  (stacked generator and discriminator)
        # 訓練生成器騙過判別器
        self.combined = Model([noise, label], validity)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer,
                                   metrics=['accuracy'])

    def build_generator(self):

        model = Sequential()

        model.add(Dense(64 * 7 * 7,  input_dim=110))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Reshape((7, 7, 64)))
        model.add(Conv2DTranspose(64, kernel_size = 3, strides = 2, padding='same'))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Conv2DTranspose(32,  kernel_size = 3, strides = 2, padding='same'))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Conv2D(16,  kernel_size = 3, padding='same'))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Conv2D(1, (3, 3), padding='same', activation='tanh'))

        # model.add(Dense(128, activation='relu', input_dim=110))
        # model.add(Dense(16 * 7 * 7, activation='relu'))
        # model.add(Reshape((7, 7, 16)))
        # model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
        # model.add(UpSampling2D(size=(2,2)))
        # model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
        # model.add(UpSampling2D(size=(2,2)))
        # model.add(Conv2D(16, (3, 3), activation='relu', padding='same'))
        # model.add(Conv2D(1, (3, 3), padding='same'))

        model.summary()

        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, 10)(label))
        model_input = K.concatenate([noise, label_embedding], axis=1)
        img = model(model_input)

        # 輸入噪音輸出圖片
        return Model([noise, label], img)

    def build_discriminator(self):

        model = Sequential()

        model.add(Conv2D(64, (3, 3), strides=(2,2), input_shape = (28, 28, 2)))
        model.add(LeakyReLU(alpha=0.2))#判別器不能用relu  徵造反覆標記 成神經元死亡
        model.add(Dropout(self.dropout))
        model.add(Conv2D(128, (3, 3), strides=(2,2)))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(self.dropout))
        model.add(Conv2D(128, (3, 3), strides=(2,2)))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dropout(self.dropout))
        model.add(Flatten())
        model.add(Dense(64))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Dense(1, activation='sigmoid'))

        model.summary()
        img = Input(shape=self.img_shape)  # 輸入 (28,28,1)
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, np.prod(self.img_shape))(label))
        # flat_img = Flatten()(img)
        label_embedding = Reshape(self.img_shape)(label_embedding)
        model_input = K.concatenate([img, label_embedding], axis = -1)
        print(model_input.shape)
        validity = model(model_input)

        return Model([img, label], validity)

    def train(self, epochs, batch_size=128, sample_interval=50):
        dataPath = 'C:/Users/lenovo/Desktop/MinstGan/mnist.npz'
        # 加載數據集
        (x_train, y_train), (_, _) = mnist.load_data(path=dataPath)

        # 歸一化到-1到1
        x_train = x_train / 127.5 - 1.
        print(x_train.shape)
        x_train = np.expand_dims(x_train, axis=3)
        print(x_train.shape)
        y_train = np.expand_dims(y_train, axis=1)
        print(y_train.shape)#60000,1

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # ---------------------
            # 訓練判別器
            # ---------------------

            # X_train.shape[0]Ϊ爲數據集的數量,隨機生成batch_size個數量的隨機數,作爲數據的索引
            idx = np.random.randint(0, x_train.shape[0], batch_size)

            # 從數據集隨機挑選batch_size個數據,作爲一個批次訓練
            imgs = x_train[idx]
            labels = y_train[idx]

            # 噪聲維度(batch_size,100)
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # 由生成器根據噪音生成假的圖片
            gen_imgs = self.generator.predict([noise, labels])
            # 訓練判別器,判別器希望真實的圖片,打上標籤1,假的圖片打上標籤0
            d_loss_real = self.discriminator.train_on_batch([imgs, labels], valid)
            d_loss_fake = self.discriminator.train_on_batch([gen_imgs, labels], fake)

            # ---------------------
            #  訓練生成器
            # ---------------------
            # Train the generator (to have the discriminator label samples as valid)
            g_loss = self.combined.train_on_batch([noise, labels], valid)

            # 打印loss 真圖識別率 假圖識別率  誘騙成功率
            print("%d [D realloss: %f, realacc: %.2f%%, fakeloss: %f, fakeacc: %.2f%%] [G loss: %f, acc = %.2f%%]" %
                  (epoch, d_loss_real[0], 100 * d_loss_real[1], d_loss_fake[0], 100 * d_loss_fake[1], g_loss[0], 100 * g_loss[1]))

            # 每sample_interval個epoch保存一次生成圖片
            if epoch % sample_interval == 0:
                self.sample_images(epoch)
                if not os.path.exists("keras_model"):
                    os.makedirs("keras_model")
                self.generator.save_weights("keras_model/G_model%d.hdf5" % epoch, True)
                self.discriminator.save_weights("keras_model/D_model%d.hdf5" % epoch, True)

    def sample_images(self, epoch):
        r, c = 4, 5
        # 重新生成一批噪音,維度爲(25,100)
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        sampled_labels = np.concatenate([np.arange(0, 10).reshape(-1, 1), np.arange(0, 10).reshape(-1, 1)])
        gen_imgs = self.generator.predict([noise, sampled_labels])

        # 將生成的圖片重新規整0-1之間
        gen_imgs = 0.5 * gen_imgs + 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_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].axis('off')
                cnt += 1
        if not os.path.exists("keras_imgs"):
            os.makedirs("keras_imgs")
        fig.savefig("keras_imgs/%d.png" % epoch)
        plt.close()

    def retore(self, epoch):
        self.generator.load_weights("keras_model/G_model%d.hdf5" % epoch)
        self.discriminator.load_weights("keras_model/D_model%d.hdf5" % epoch)

if __name__ == '__main__':
    gan = GAN()
    # gan.retore(4500)
    gan.train(epochs=30000, batch_size=32, sample_interval=300)

 

DC_GAN3:

from tensorflow.keras.datasets import mnist
import tensorflow.keras.backend as K
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, ZeroPadding2D
from tensorflow.keras.layers import LeakyReLU,Embedding,Conv2DTranspose
from tensorflow.keras.layers import UpSampling2D, Conv2D
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.optimizers import Adam
import os
import matplotlib.pyplot as plt

import sys

import numpy as np


class GAN(object):
    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)
        self.latent_dim = 100

        optimizer = Adam(0.0002, 0.5)

        # 構建和編譯判別器
        self.discriminator = self.build_discriminator()
        self.discriminator.compile(loss='binary_crossentropy',
                                   optimizer=optimizer,
                                   metrics=['accuracy'])
        # self.discriminator.compile(loss='sparse_categorical_crossentropy',
        #                            optimizer=optimizer,
        #                            metrics=['accuracy'])

        # 構建生成器
        self.generator = self.build_generator()

        # 生成器輸入噪聲,生成假圖片
        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,))
        img = self.generator([noise, label])

        # 爲了組合模型,只訓練生成器
        self.discriminator.trainable = False

        # 判別器將生成的圖片作爲輸入並確定有效性
        validity = self.discriminator([img, label])

        # The combined model  (stacked generator and discriminator)
        # 訓練生成器騙過判別器
        self.combined = Model([noise, label], validity)
        self.combined.compile(loss='binary_crossentropy', optimizer=optimizer)

    def build_generator(self):

        model = Sequential()

        # model.add(Dense(128, activation='relu', input_dim=110))
        # model.add(Dense(196, activation='relu'))
        # model.add(Reshape((7, 7, 4)))
        # model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
        # model.add(UpSampling2D(size=(2,2)))
        # model.add(Conv2D(32, (3, 3), activation='relu', padding='same'))
        # model.add(UpSampling2D(size=(2,2)))
        # model.add(Conv2D(16, (3, 3), activation='relu', padding='same'))
        # model.add(Conv2D(1, (3, 3), padding='same'))

        model.add(Dense(64 * 7 * 7,  input_dim=110))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Reshape((7, 7, 64)))
        model.add(Conv2DTranspose(64, kernel_size = 3, strides = 2, padding='same'))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Conv2DTranspose(32,  kernel_size = 3, strides = 2, padding='same'))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Conv2D(16,  kernel_size = 3, padding='same'))
        model.add(BatchNormalization(momentum=0.9))
        model.add(LeakyReLU(alpha=0.2))
        model.add(Conv2D(1, (3, 3), padding='same', activation='tanh'))

        model.summary()

        noise = Input(shape=(self.latent_dim,))
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, 10)(label))
        model_input = K.concatenate([noise, label_embedding], axis=1)
        img = model(model_input)

        # 輸入噪音輸出圖片
        return Model([noise, label], img)

    def build_discriminator(self):

        model = Sequential()

        model.add(Flatten(input_shape=(28,28,2)))
        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.summary()
        img = Input(shape=self.img_shape)  # 輸入 (28,28,1)
        label = Input(shape=(1,), dtype='int32')
        label_embedding = Flatten()(Embedding(10, np.prod(self.img_shape))(label))
        flat_img = Flatten()(img)
        model_input = K.concatenate([flat_img, label_embedding], axis = -1)
        validity = model(model_input)

        return Model([img, label], validity)

    def train(self, epochs, batch_size=128, sample_interval=50):
        dataPath = 'C:/Users/lenovo/Desktop/MinstGan/mnist.npz'
        # 加載數據集
        (x_train, y_train), (_, _) = mnist.load_data(path=dataPath)

        # 歸一化到-1到1
        x_train = x_train / 127.5 - 1.
        print(x_train.shape)
        x_train = np.expand_dims(x_train, axis=3)
        print(x_train.shape)
        y_train = np.expand_dims(y_train, axis=1)
        print(y_train.shape)#60000,1

        # Adversarial ground truths
        valid = np.ones((batch_size, 1))
        fake = np.zeros((batch_size, 1))

        for epoch in range(epochs):

            # ---------------------
            # 訓練判別器
            # ---------------------

            # X_train.shape[0]Ϊ爲數據集的數量,隨機生成batch_size個數量的隨機數,作爲數據的索引
            idx = np.random.randint(0, x_train.shape[0], batch_size)

            # 從數據集隨機挑選batch_size個數據,作爲一個批次訓練
            imgs = x_train[idx]
            labels = y_train[idx]

            # 噪聲維度(batch_size,100)
            noise = np.random.normal(0, 1, (batch_size, self.latent_dim))

            # 由生成器根據噪音生成假的圖片
            gen_imgs = self.generator.predict([noise, labels])
            # 訓練判別器,判別器希望真實的圖片,打上標籤1,假的圖片打上標籤0
            d_loss_real = self.discriminator.train_on_batch([imgs, labels], valid)
            d_loss_fake2 = self.discriminator.train_on_batch([gen_imgs, labels], fake)
            d_loss = d_loss_real + d_loss_fake2

            # ---------------------
            #  訓練生成器
            # ---------------------
            # Train the generator (to have the discriminator label samples as valid)
            g_loss = self.combined.train_on_batch([noise, labels], valid)

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

            # 每sample_interval個epoch保存一次生成圖片
            if epoch % sample_interval == 0:
                self.sample_images(epoch)
                if not os.path.exists("keras_model"):
                    os.makedirs("keras_model")
                self.generator.save_weights("keras_model/G_model%d.hdf5" % epoch, True)
                self.discriminator.save_weights("keras_model/D_model%d.hdf5" % epoch, True)

    def sample_images(self, epoch):
        r, c = 4, 5
        # 重新生成一批噪音,維度爲(25,100)
        noise = np.random.normal(0, 1, (r * c, self.latent_dim))
        sampled_labels = np.concatenate([np.arange(0, 10).reshape(-1, 1), np.arange(0, 10).reshape(-1, 1)])
        gen_imgs = self.generator.predict([noise, sampled_labels])

        # 將生成的圖片重新規整0-1之間
        gen_imgs = 0.5 * gen_imgs + 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_imgs[cnt, :, :, 0], cmap='gray')
                axs[i, j].axis('off')
                cnt += 1
        if not os.path.exists("keras_imgs"):
            os.makedirs("keras_imgs")
        fig.savefig("keras_imgs/%d.png" % epoch)
        plt.close()

    def retore(self, epoch):
        self.generator.load_weights("keras_model/G_model%d.hdf5" % epoch)
        self.discriminator.load_weights("keras_model/D_model%d.hdf5" % epoch)

if __name__ == '__main__':
    gan = GAN()
    # gan.retore(500)
    gan.train(epochs=30000, batch_size=32, sample_interval=300)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章