學(xué)習(xí)筆記TF051:生成式對(duì)抗網(wǎng)絡(luò)

生成式對(duì)抗網(wǎng)絡(luò)(gennerative adversarial network,GAN)吻贿,谷歌2014年提出網(wǎng)絡(luò)模型串结。靈感自二人博弈的零和博弈,目前最火的非監(jiān)督深度學(xué)習(xí)舅列。GAN之父肌割,Ian J.Goodfellow,公認(rèn)人工智能頂級(jí)專家帐要。

原理把敞。
生成式對(duì)搞網(wǎng)絡(luò)包含一個(gè)生成模型(generative model,G)和一個(gè)判別模型(discriminative model,D)。Ian J.Goodfellow榨惠、Jean Pouget-Abadie奋早、Mehdi Mirza、Bing Xu赠橙、David Warde-Farley耽装、Sherjil Ozair、Aaron Courville期揪、Yoshua Bengio論文掉奄,《Generative Adversarial Network》,https://arxiv.org/abs/1406.2661 横侦。
生成式對(duì)抗網(wǎng)絡(luò)結(jié)構(gòu):
噪聲數(shù)據(jù)->生成模型->假圖片---|
|->判別模型->真/假
打亂訓(xùn)練數(shù)據(jù)->訓(xùn)練集->真圖片-|
生成式對(duì)抗網(wǎng)絡(luò)主要解決如何從訓(xùn)練樣本中學(xué)習(xí)出新樣本挥萌。生成模型負(fù)責(zé)訓(xùn)練出樣本的分布,如果訓(xùn)練樣本是圖片就生成相似的圖片枉侧,如果訓(xùn)練樣本是文章名子就生成相似的文章名子引瀑。判別模型是一個(gè)二分類器,用來判斷輸入樣本是真實(shí)數(shù)據(jù)還是訓(xùn)練生成的樣本榨馁。
生成式對(duì)抗網(wǎng)絡(luò)優(yōu)化憨栽,是一個(gè)二元極小極大博弈(minimax two-player game)問題。使生成模型輸出在輸入給判別模型時(shí),判斷模型秀難判斷是真實(shí)數(shù)據(jù)還是虛似數(shù)據(jù)屑柔。訓(xùn)練好的生成模型屡萤,能把一個(gè)噪聲向量轉(zhuǎn)化成和訓(xùn)練集類似的樣本。Argustus Odena掸宛、Christopher Olah死陆、Jonathon Shlens論文《Coditional Image Synthesis with Auxiliary Classifier GANs》。
輔助分類器生成式對(duì)抗網(wǎng)絡(luò)(auxiliary classifier GAN唧瘾,AC-GAN)實(shí)現(xiàn)措译。

生成式對(duì)抗網(wǎng)絡(luò)應(yīng)用。生成數(shù)字饰序,生成人臉圖像领虹。

生成式對(duì)抗網(wǎng)絡(luò)實(shí)現(xiàn)。https://github.com/fchollet/keras/blob/master/examples/mnist_acgan.py 求豫。
Augustus Odena塌衰、Chistopher Olah和Jonathon Shlens 論文《Conditional Image Synthesis With Auxiliary Classifier GANs》。
通過噪聲蝠嘉,讓生成模型G生成虛假數(shù)據(jù)最疆,和真實(shí)數(shù)據(jù)一起送到判別模型D,判別模型一方面輸出數(shù)據(jù)真/假,一方面輸出圖片分類是晨。
首先定義生成模型肚菠,目的是生成一對(duì)(z,L)數(shù)據(jù)舔箭,z是噪聲向量罩缴,L是(1,28,28)的圖像空間。

def build_generator(latent_size):
    cnn = Sequential()
    cnn.add(Dense(1024, input_dim=latent_size, activation='relu'))
    cnn.add(Dense(128 * 7 * 7, activation='relu'))
    cnn.add(Reshape((128, 7, 7)))
    #上采樣层扶,圖你尺寸變?yōu)?14X14
    cnn.add(UpSampling2D(size=(2,2)))
    cnn.add(Convolution2D(256, 5, 5, border_mode='same', activation='relu', init='glorot_normal'))
    #上采樣箫章,圖像尺寸變?yōu)?8X28
    cnn.add(UpSampling2D(size=(2,2)))
    cnn.add(Convolution2D(128, 5, 5, border_mode='same', activation='relu', init='glorot_normal'))
    #規(guī)約到1個(gè)通道
    cnn.add(Convolution2D(1, 2, 2, border_mode='same', activation='tanh', init='glorot_normal'))
    #生成模型輸入層,特征向量
    latent = Input(shape=(latent_size, ))
    #生成模型輸入層,標(biāo)記
    image_class = Input(shape=(1,), dtype='int32')
    cls = Flatten()(Embedding(10, latent_size, init='glorot_normal')(image_class))
    h = merge([latent, cls], mode='mul')
    fake_image = cnn(h) #輸出虛假圖片
    return Model(input=[latent, image_class], output=fake_image)

定義判別模型镜会,輸入(1,28,28)圖片檬寂,輸出兩個(gè)值,一個(gè)是判別模型認(rèn)為這張圖片是否是虛假圖片戳表,另一個(gè)是判別模型認(rèn)為這第圖片所屬分類桶至。

def build_discriminator();
    #采用激活函數(shù)Leaky ReLU來替換標(biāo)準(zhǔn)的卷積神經(jīng)網(wǎng)絡(luò)中的激活函數(shù)
    cnn = Wequential()
    cnn.add(Convolution2D(32, 3, 3, border_mode='same', subsample=(2, 2), input_shape=(1, 28, 28)))
    cnn.add(LeakyReLU())
    cnn.add(Dropout(0.3))
    cnn.add(Convolution2D(64, 3, 3, border_mode='same', subsample=(1, 1)))
    cnn.add(LeakyReLU())
    cnn.add(Dropout(0.3))
    cnn.add(Convolution2D(128, 3, 3, border_mode='same', subsample=(1, 1)))
    cnn.add(LeakyReLU())
    cnn.add(Dropout(0.3))
    cnn.add(Convolution2D(256, 3, 3, border_mode='same', subsample=(1, 1)))
    cnn.add(LeakyReLU())
    cnn.add(Dropout(0.3))
    cnn.add(Flatten())
    image = Input(shape=(1, 28, 28))
    features = cnn(image)
    #有兩個(gè)輸出
    #輸出真假值,范圍在0~1
    fake = Dense(1, activation='sigmoid',name='generation')(features)
    #輔助分類器匾旭,輸出圖片分類
   aux = Dense(10, activation='softmax', name='auxiliary')(features)
    return Model(input=image, output=[fake, aux])

訓(xùn)練過程镣屹,50輪(epoch),把權(quán)重保存,每輪把虛假數(shù)據(jù)生成圖處保存价涝,觀察虛假數(shù)據(jù)演化過程女蜈。

if __name__ =='__main__':
    #定義超參數(shù)
    nb_epochs = 50
    batch_size = 100
    latent_size = 100
    #優(yōu)化器學(xué)習(xí)率
    adam_lr = 0.0002
    adam_beta_l = 0.5
    #構(gòu)建判別網(wǎng)絡(luò)
    discriminator = build_discriminator()
    discriminator.compile(optimizer=adam(lr=adam_lr, beta_l=adam_beta_l), loss='binary_crossentropy')
    latent = Input(shape=(lastent_size, ))
    image_class = Input(shape-(1, ), dtype='int32')
    #生成組合模型
    discriminator.trainable = False
    fake, aux = discriminator(fake)
    combined = Model(input=[latent, image_class], output=[fake, aux])
    combined.compile(optimizer=Adam(lr=adam_lr, beta_l=adam_beta_1), loss=['binary_crossentropy', 'sparse_categorical_crossentropy'])
    #將mnist數(shù)據(jù)轉(zhuǎn)化為(...,1,28,28)維度,取值范圍為[-1,1]
    (X_train,y_train),(X_test,y_test) = mnist.load_data()
    X_train = (X_train.astype(np.float32) - 127.5) / 127.5
    X_train = np.expand_dims(X_train, axis=1)
    X_test = (X_test.astype(np.float32) - 127.5) / 127.5
    X_test = np.expand_dims(X_test, axis=1)
    num_train, num_test = X_train.shape[0], X_test.shape[0]
    train_history = defaultdict(list)
    test_history = defaultdict(list)
    for epoch in range(epochs):
        print('Epoch {} of {}'.format(epoch + 1, epochs))
        num_batches = int(X_train.shape[0] / batch_size)
        progress_bar = Progbar(target=num_batches)
        epoch_gen_loss = []
        epoch_disc_loss = []
        for index in range(num_batches):
            progress_bar.update(index)
            #產(chǎn)生一個(gè)批次的噪聲數(shù)據(jù)
            noise = np.random.uniform(-1, 1, (batch_size, latent_size))
            # 獲取一個(gè)批次的真實(shí)數(shù)據(jù)
            image_batch = X_train[index * batch_size:(index + 1) * batch_size]
            label_batch = y_train[index * batch_size:(index + 1) * batch_size]
            # 生成一些噪聲標(biāo)記
            sampled_labels = np.random.randint(0, 10, batch_size)
            # 產(chǎn)生一個(gè)批次的虛假圖片
            generated_images = generator.predict(
            [noise, sampled_labels.reshape((-1, 1))], verbose=0)
            X = np.concatenate((image_batch, generated_images))
            y = np.array([1] * batch_size + [0] * batch_size)
            aux_y = np.concatenate((label_batch, sampled_labels), axis=0)
            epoch_disc_loss.append(discriminator.train_on_batch(X, [y, aux_y]))
            # 產(chǎn)生兩個(gè)批次噪聲和標(biāo)記
            noise = np.random.uniform(-1, 1, (2 * batch_size, latent_size))
            sampled_labels = np.random.randint(0, 10, 2 * batch_size)
            # 訓(xùn)練生成模型來欺騙判別模型,輸出真/假都設(shè)為真
            trick = np.ones(2 * batch_size)
            epoch_gen_loss.append(combined.train_on_batch(
               [noise, sampled_labels.reshape((-1, 1))],
                [trick, sampled_labels]))
        print('\nTesting for epoch {}:'.format(epoch + 1))
        # 評(píng)估測試集,產(chǎn)生一個(gè)新批次噪聲數(shù)據(jù)
        noise = np.random.uniform(-1, 1, (num_test, latent_size))
        sampled_labels = np.random.randint(0, 10, num_test)
        generated_images = generator.predict(
            [noise, sampled_labels.reshape((-1, 1))], verbose=False)
        X = np.concatenate((X_test, generated_images))
        y = np.array([1] * num_test + [0] * num_test)
        aux_y = np.concatenate((y_test, sampled_labels), axis=0)
        # 判別模型是否能判別
        discriminator_test_loss = discriminator.evaluate(
            X, [y, aux_y], verbose=False)
        discriminator_train_loss = np.mean(np.array(epoch_disc_loss), axis=0)
        # 創(chuàng)建兩個(gè)批次新噪聲數(shù)據(jù)
        noise = np.random.uniform(-1, 1, (2 * num_test, latent_size))
        sampled_labels = np.random.randint(0, 10, 2 * num_test)
        trick = np.ones(2 * num_test)
        generator_test_loss = combined.evaluate(
            [noise, sampled_labels.reshape((-1, 1))],
            [trick, sampled_labels], verbose=False)
        generator_train_loss = np.mean(np.array(epoch_gen_loss), axis=0)
        # 損失值等性能指標(biāo)記錄下來伪窖,并輸出
        train_history['generator'].append(generator_train_loss)
        train_history['discriminator'].append(discriminator_train_loss)
        test_history['generator'].append(generator_test_loss)
        test_history['discriminator'].append(discriminator_test_loss)
        print('{0:<22s} | {1:4s} | {2:15s} | {3:5s}'.format(
            'component', *discriminator.metrics_names))
        print('-' * 65)
        ROW_FMT = '{0:<22s} | {1:<4.2f} | {2:<15.2f} | {3:<5.2f}'
        print(ROW_FMT.format('generator (train)',
                         *train_history['generator'][-1]))
        print(ROW_FMT.format('generator (test)',
                         *test_history['generator'][-1]))
        print(ROW_FMT.format('discriminator (train)',
                         *train_history['discriminator'][-1]))
        print(ROW_FMT.format('discriminator (test)',
                         *test_history['discriminator'][-1]))
        # 每個(gè)epoch保存一次權(quán)重
        generator.save_weights(
            'params_generator_epoch_{0:03d}.hdf5'.format(epoch), True)
        discriminator.save_weights(
            'params_discriminator_epoch_{0:03d}.hdf5'.format(epoch), True)
        # 生成一些可視化虛假數(shù)字看演化過程
        noise = np.random.uniform(-1, 1, (100, latent_size))
        sampled_labels = np.array([
            [i] * 10 for i in range(10)
        ]).reshape(-1, 1)
        generated_images = generator.predict(
            [noise, sampled_labels], verbose=0)
        # 整理到一個(gè)方格
        img = (np.concatenate([r.reshape(-1, 28)
                           for r in np.split(generated_images, 10)
                           ], axis=-1) * 127.5 + 127.5).astype(np.uint8)
        Image.fromarray(img).save(
            'plot_epoch_{0:03d}_generated.png'.format(epoch))
    pickle.dump({'train': train_history, 'test': test_history},
                open('acgan-history.pkl', 'wb'))

訓(xùn)練結(jié)束逸寓,創(chuàng)建3類文件。params_discriminator_epoch_{{epoch_number}}.hdf5,判別模型權(quán)重參數(shù)覆山。params_generator_epoch_{{epoch_number}}.hdf5,生成模型權(quán)重參數(shù)竹伸。plot_epoch_{{epoch_number}}_generated.png 。

生成式對(duì)抗網(wǎng)絡(luò)改進(jìn)簇宽。生成式對(duì)抗網(wǎng)絡(luò)(generative adversarial network,GAN)在無監(jiān)督學(xué)習(xí)非常有效佩伤。常規(guī)生成式對(duì)抗網(wǎng)絡(luò)判別器使用Sigmoid交叉熵?fù)p失函數(shù),學(xué)習(xí)過程梯度消失晦毙。Wasserstein生成式對(duì)抗網(wǎng)絡(luò)(Wasserstein generative adversarial network,WGAN)生巡,使用Wasserstein距離度量,而不是Jensen-Shannon散度(Jensen-Shannon divergence,JSD)见妒。使用最小二乘生成式對(duì)抗網(wǎng)絡(luò)(least squares generative adversarial network,LSGAN)孤荣,判別模型用最小平方損失小函數(shù)(least squares loss function)。Sebastian Nowozin须揣、Botond Cseke盐股、Ryota Tomioka論文《f-GAN: Training Generative Neural Samplers using Variational Divergence Minimization》。

參考資料:
《TensorFlow技術(shù)解析與實(shí)戰(zhàn)》

歡迎付費(fèi)咨詢(150元每小時(shí))耻卡,我的微信:qingxingfengzi

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疯汁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子卵酪,更是在濱河造成了極大的恐慌幌蚊,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溃卡,死亡現(xiàn)場離奇詭異溢豆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瘸羡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門漩仙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人犹赖,你說我怎么就攤上這事队他。” “怎么了峻村?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵麸折,是天一觀的道長。 經(jīng)常有香客問我雀哨,道長磕谅,這世上最難降的妖魔是什么私爷? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮膊夹,結(jié)果婚禮上衬浑,老公的妹妹穿的比我還像新娘。我一直安慰自己放刨,他們只是感情好工秩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著进统,像睡著了一般助币。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上螟碎,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天眉菱,我揣著相機(jī)與錄音,去河邊找鬼掉分。 笑死俭缓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酥郭。 我是一名探鬼主播华坦,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼不从!你這毒婦竟也來了惜姐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤椿息,失蹤者是張志新(化名)和其女友劉穎歹袁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撵颊,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宇攻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年惫叛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倡勇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嘉涌,死狀恐怖妻熊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情仑最,我是刑警寧澤扔役,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站警医,受9級(jí)特大地震影響亿胸,放射性物質(zhì)發(fā)生泄漏坯钦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一侈玄、第九天 我趴在偏房一處隱蔽的房頂上張望婉刀。 院中可真熱鬧,春花似錦序仙、人聲如沸突颊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽律秃。三九已至,卻和暖如春治唤,著一層夾襖步出監(jiān)牢的瞬間棒动,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工宾添, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留迁客,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓辞槐,卻偏偏與公主長得像掷漱,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子榄檬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容