成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

飛槳PaddlePaddle手把手教你完成圖像生成任務

企業動態
本文中,我們利用DCGAN生成了手寫數字圖片,您可以嘗試更換數據集生成符合個人需求的圖片,完成您的圖像生成任務,快來試試吧!

生成對抗網絡(Generative Adversarial Network,簡稱GAN)是非監督式學習的一種方法,通過讓兩個神經網絡相互博弈的方式進行學習。

生成對抗網絡由兩種子網絡組成:一個生成器與一個判別期。生成器從潛在空間(latent space)中隨機采樣作為輸入,其輸出結果需要盡量模仿訓練集中的真實圖像。判別器的輸入為真實圖像或生成網絡的輸出圖像,其目的是將生成器的輸出圖像從真實圖像中盡可能分辨出來。而生成器則要盡可能地欺騙判別器。兩個網絡相互對抗、不斷調整參數,提升自己的能力。

生成對抗網絡常用于生成以假亂真的圖片,常用場景有手寫體生成、人臉合成、風格遷移、圖像修復等。此外,該方法還被用于生成視頻、三維物體模型等。

項目地址:

https://github.com/PaddlePaddle/book/tree/develop/09.gan

效果展示

 

先來看一下DCGAN的最終效果:將 MNIST 數據集輸入網絡進行訓練,經過19輪訓練后的結果如下圖,前8行是真實圖片的樣子,后8行是網絡生成的圖像效果。可以看到,生成的圖片已經非常接近真實圖片的樣子。

 

模型概覽

GAN

GAN是一種通過對抗的方式,去學習數據分布的生成模型。以生成圖片為例說明:

  • 生成器(G)接收一個隨機的噪聲z,盡可能的生成近似樣本的圖片,記為G(z)。
  • 判別器(D)接收一張輸入圖片x,盡可以去判別該圖像是真實圖片還是網絡生成的假圖片,判別器的輸出 D(x) 代表 x 為真實圖片的概率。如果 D(x)=1 說明判別器認為該輸入一定是真實圖片,如果 D(x)=0 說明判別器認為該輸入一定是假圖片。

在訓練的過程中,兩個網絡互相對抗,最終形成了一個動態的平衡,上述過程用公式可以被描述為:

在最理想的情況下,G 可以生成與真實圖片極其相似的圖片G(z),而 D 很難判斷這張生成的圖片是否為真,對圖片的真假進行隨機猜測,即 D(G(z))=0.5。

下圖展示了生成對抗網絡的訓練過程,假設在訓練開始時,真實樣本分布、生成樣本分布以及判別模型分別是圖中的黑線、綠線和藍線。在訓練開始時,判別模型是無法很好地區分真實樣本和生成樣本的。接下來當我們固定生成模型,而優化判別模型時,優化結果如第二幅圖所示,可以看出,這個時候判別模型已經可以較好地區分生成圖片和真實圖片了。第三步是固定判別模型,改進生成模型,試圖讓判別模型無法區分生成圖片與真實圖片,在這個過程中,可以看出由模型生成的圖片分布與真實圖片分布更加接近,這樣的迭代不斷進行,直到最終收斂,生成分布和真實分布重合,判別模型無法區分真實圖片與生成圖片。

圖:GAN 訓練過程

但是在實際過程中,很難得到這個完美的平衡點,關于GAN的收斂理論還在持續不斷的研究中。

DCGAN

DCGAN是深層卷積網絡與 GAN 的結合,其基本原理與 GAN 相同,只是將生成器和判別器用兩個卷積網絡(CNN)替代。為了提高生成樣本的質量和網絡的收斂速度,論文中的 DCGAN 在網絡結構上進行了一些改進:

  • 取消 pooling 層:在網絡中,所有的pooling層使用步幅卷積(strided convolutions)(判別器)和微步幅度卷積(fractional-strided convolutions)(生成器)進行替換。
  • 加入 batch normalization:在生成器和判別器中均加入batchnorm。
  • 使用全卷積網絡:去掉了FC層,以實現更深的網絡結構。
  • 激活函數:在生成器(G)中,最后一層使用Tanh函數,其余層采用 ReLu 函數 ; 判別器(D)中都采用LeakyReLu。

圖:DCGAN中的生成器(G)

快速開始

本文的DCGAN任務依賴于 Paddle Fluid v1.3 及以上版本,請參考官網安裝指南進行安裝。

數據準備

本文使用數據規模較小的MNIST 訓練生成器和判別器,該數據集可通過paddle.dataset模塊自動下載到本地。

加載包

首先加載 Paddle Fluid和其他相關包:

  1. import sys 
  2.  
  3. import os 
  4.  
  5. import matplotlib 
  6.  
  7. import PIL 
  8.  
  9. import six 
  10.  
  11. import numpy as np 
  12.  
  13. import math 
  14.  
  15. import time 
  16.  
  17. import paddle 
  18.  
  19. import paddle.fluid as fluid 
  20.  
  21. matplotlib.use('agg'
  22.  
  23. import matplotlib.pyplot as plt 
  24.  
  25. import matplotlib.gridspec as gridspec 
  26.  
  27. from __future__ import absolute_import 
  28.  
  29. from __future__ import division 
  30.  
  31. from __future__ import print_function 

定義輔助工具

定義 plot 函數,將圖像生成過程可視化:

  1. def plot(gen_data): 
  2.  
  3. pad_dim = 1 
  4.  
  5. paded = pad_dim + img_dim 
  6.  
  7. gen_data = gen_data.reshape(gen_data.shape[0], img_dim, img_dim) 
  8.  
  9. n = int(math.ceil(math.sqrt(gen_data.shape[0]))) 
  10.  
  11. gen_data = (np.pad( 
  12.  
  13. gen_data, [[0, n * n - gen_data.shape[0]], [pad_dim, 0], [pad_dim, 0]], 
  14.  
  15. 'constant').reshape((n, n, paded, paded)).transpose((0213)) 
  16.  
  17. .reshape((n * paded, n * paded))) 
  18.  
  19. fig = plt.figure(figsize=(88)) 
  20.  
  21. plt.axis('off'
  22.  
  23. plt.imshow(gen_data, cmap='Greys_r', vmin=-1, vmax=1
  24.  
  25. return fig 

定義超參數

  1. gf_dim = 64 # 生成器的feature map的基礎通道數量,生成器中所有的feature map的通道數量都是基礎通道數量的倍數 
  2.  
  3. df_dim = 64 # 判別器的feature map的基礎通道數量,判別器中所有的feature map的通道數量都是基礎通道數量的倍數 
  4.  
  5. gfc_dim = 1024 * 2 # 生成器的全連接層維度 
  6.  
  7. dfc_dim = 1024 # 判別器的全連接層維度 
  8.  
  9. img_dim = 28 # 輸入圖片的尺寸 
  10.  
  11. NOISE_SIZE = 100 # 輸入噪聲的維度 
  12.  
  13. LEARNING_RATE = 2e-4 # 訓練的學習率 
  14.  
  15. epoch = 20 # 訓練的epoch數 
  16.  
  17. output = "./output_dcgan" # 模型和測試結果的存儲路徑 
  18.  
  19. use_cudnn = False # 是否使用cuDNN 
  20.  
  21. use_gpu=False # 是否使用GPU訓練 

 

定義網絡結構

bn 層

調用 fluid.layers.batch_norm 接口實現bn層,激活函數默認使用ReLu。

  1. def bn(x, name=None, act='relu'): 
  2.  
  3. return fluid.layers.batch_norm( 
  4.  
  5. x, 
  6.  
  7. param_attr=name + '1'
  8.  
  9. bias_attr=name + '2'
  10.  
  11. moving_mean_name=name + '3'
  12.  
  13. moving_variance_name=name + '4'
  14.  
  15. name=name, 
  16.  
  17. act=act) 

卷積層

調用 fluid.nets.simple_img_conv_pool 實現卷積池化組,卷積核大小為3x3,池化窗口大小為2x2,窗口滑動步長為2,激活函數類型由具體網絡結構指定。

  1. def conv(x, num_filters, name=None, act=None): 
  2.  
  3. return fluid.nets.simple_img_conv_pool( 
  4.  
  5. input=x, 
  6.  
  7. filter_size=5
  8.  
  9. num_filters=num_filters, 
  10.  
  11. pool_size=2
  12.  
  13. pool_stride=2
  14.  
  15. param_attr=name + 'w'
  16.  
  17. bias_attr=name + 'b'
  18.  
  19. use_cudnn=use_cudnn, 
  20.  
  21. act=act) 

全連接層

  1. def fc(x, num_filters, name=None, act=None): 
  2.  
  3. return fluid.layers.fc(input=x, 
  4.  
  5. size=num_filters, 
  6.  
  7. act=act, 
  8.  
  9. param_attr=name + 'w'
  10.  
  11. bias_attr=name + 'b'

轉置卷積層

在生成器中,需要用隨機采樣值生成全尺寸圖像,dcgan使用轉置卷積層進行上采樣,在Fluid中,我們調用 fluid.layers.conv2d_transpose 實現轉置卷積。

  1. def deconv(x, 
  2.  
  3. num_filters, 
  4.  
  5. name=None, 
  6.  
  7. filter_size=5
  8.  
  9. stride=2
  10.  
  11. dilation=1
  12.  
  13. padding=2
  14.  
  15. output_size=None, 
  16.  
  17. act=None): 
  18.  
  19. return fluid.layers.conv2d_transpose( 
  20.  
  21. input=x, 
  22.  
  23. param_attr=name + 'w'
  24.  
  25. bias_attr=name + 'b'
  26.  
  27. num_filters=num_filters, 
  28.  
  29. output_size=output_size, 
  30.  
  31. filter_size=filter_size, 
  32.  
  33. stride=stride, 
  34.  
  35. dilation=dilation, 
  36.  
  37. padding=padding, 
  38.  
  39. use_cudnn=use_cudnn, 
  40.  
  41. act=act) 

判別器

判別器使用真實數據集和生成器生成的假圖片共同進行訓練,在訓練過程中盡量使真實數據集的輸出結果為1,生成的假圖片輸出結果為0。本文中實現的判別器由兩個卷積池化層和兩個全連接層組成,其中最后一個全連接層的神經元個數為1,輸出一個二分類結果。

  1. def D(x): 
  2.  
  3. x = fluid.layers.reshape(x=x, shape=[-112828]) 
  4.  
  5. x = conv(x, df_dim, act='leaky_relu',name='conv1'
  6.  
  7. x = bn(conv(x, df_dim * 2,name='conv2'), act='leaky_relu',name='bn1'
  8.  
  9. x = bn(fc(x, dfc_dim,name='fc1'), act='leaky_relu',name='bn2'
  10.  
  11. x = fc(x, 1, act='sigmoid',name='fc2'
  12.  
  13. return x 

生成器

生成器由兩組帶BN的全連接層和兩組轉置卷積層組成,網絡輸入為隨機的噪聲數據,最后一層轉置卷積的卷積核數為1,表示輸出為灰度圖片。

  1. def G(x): 
  2.  
  3. x = bn(fc(x, gfc_dim,name='fc3'),name='bn3'
  4.  
  5. x = bn(fc(x, gf_dim * 2 * img_dim // 4 * img_dim // 4,name='fc4'),name='bn4') 
  6.  
  7. x = fluid.layers.reshape(x, [-1, gf_dim * 2, img_dim // 4, img_dim // 4]) 
  8.  
  9. x = deconv(x, gf_dim * 2, act='relu', output_size=[1414],name='deconv1'
  10.  
  11. x = deconv(x, num_filters=1, filter_size=5, padding=2, act='tanh', output_size=[2828],name='deconv2'
  12.  
  13. x = fluid.layers.reshape(x, shape=[-128 * 28]) 
  14.  
  15. return x 

損失函數

損失函數使用 sigmoid_cross_entropy_with_logits

  1. def loss(x, label): 
  2.  
  3. return fluid.layers.mean( 
  4.  
  5. fluid.layers.sigmoid_cross_entropy_with_logits(x=x, label=label)) 

創建Program

  1. d_program = fluid.Program() 
  2.  
  3. dg_program = fluid.Program() 
  4.  
  5. # 定義判別真實圖片的program 
  6.  
  7. with fluid.program_guard(d_program): 
  8.  
  9. # 輸入圖片大小為28*28=784 
  10.  
  11. img = fluid.layers.data(name='img', shape=[784], dtype='float32'
  12.  
  13. # 標簽shape=1 
  14.  
  15. label = fluid.layers.data(name='label', shape=[1], dtype='float32'
  16.  
  17. d_logit = D(img) 
  18.  
  19. d_loss = loss(d_logit, label) 
  20.  
  21. # 定義判別生成圖片的program 
  22.  
  23. with fluid.program_guard(dg_program): 
  24.  
  25. noise = fluid.layers.data( 
  26.  
  27. name='noise', shape=[NOISE_SIZE], dtype='float32'
  28.  
  29. # 噪聲數據作為輸入得到生成圖片 
  30.  
  31. g_img = G(x=noise) 
  32.  
  33. g_program = dg_program.clone() 
  34.  
  35. g_program_test = dg_program.clone(for_test=True) 
  36.  
  37. # 判斷生成圖片為真實樣本的概率 
  38.  
  39. dg_logit = D(g_img) 
  40.  
  41. # 計算生成圖片被判別為真實樣本的loss 
  42.  
  43. dg_loss = loss( 
  44.  
  45. dg_logit, 
  46.  
  47. fluid.layers.fill_constant_batch_size_like( 
  48.  
  49. input=noise, dtype='float32', shape=[-11], value=1.0)) 

使用adam作為優化器,分別優化判別真實圖片的loss和判別生成圖片的loss。

  1. opt = fluid.optimizer.Adam(learning_rate=LEARNING_RATE) 
  2.  
  3. opt.minimize(loss=d_loss) 
  4.  
  5. parameters = [p.name for p in g_program.global_block().all_parameters()] 
  6.  
  7. opt.minimize(loss=dg_loss, parameter_list=parameters) 

數據集 Feeders 配置

下一步,我們開始訓練過程。paddle.dataset.mnist.train()用做訓練數據集。這個函數返回一個reader——飛槳(PaddlePaddle)中的reader是一個Python函數,每次調用的時候返回一個Python yield generator。

下面shuffle是一個reader decorator,它接受一個reader A,返回另一個reader B。reader B 每次讀入buffer_size條訓練數據到一個buffer里,然后隨機打亂其順序,并且逐條輸出。

batch是一個特殊的decorator,它的輸入是一個reader,輸出是一個batched reader。在飛槳(PaddlePaddle)里,一個reader每次yield一條訓練數據,而一個batched reader每次yield一個minibatch。

  1. batch_size = 128 # Minibatch size 
  2.  
  3. train_reader = paddle.batch( 
  4.  
  5. paddle.reader.shuffle( 
  6.  
  7. paddle.dataset.mnist.train(), buf_size=60000), 
  8.  
  9. batch_size=batch_size) 

創建執行器

  1. if use_gpu: 
  2.  
  3. exe = fluid.Executor(fluid.CUDAPlace(0)) 
  4.  
  5. else: 
  6.  
  7. exe = fluid.Executor(fluid.CPUPlace()) 
  8.  
  9. exe.run(fluid.default_startup_program()) 

開始訓練

訓練過程中的每一次迭代,生成器和判別器分別設置自己的迭代次數。為了避免判別器快速收斂到0,本文默認每迭代一次,訓練一次判別器,兩次生成器。

  1. t_time = 0 
  2.  
  3. losses = [[], []] 
  4.  
  5. # 判別器的迭代次數 
  6.  
  7. NUM_TRAIN_TIMES_OF_DG = 2 
  8.  
  9. # 最終生成圖像的噪聲數據 
  10.  
  11. const_n = np.random.uniform( 
  12.  
  13. low=-1.0, high=1.0
  14.  
  15. size=[batch_size, NOISE_SIZE]).astype('float32'
  16.  
  17. for pass_id in range(epoch): 
  18.  
  19. for batch_id, data in enumerate(train_reader()): 
  20.  
  21. if len(data) != batch_size: 
  22.  
  23. continue 
  24.  
  25. # 生成訓練過程的噪聲數據 
  26.  
  27. noise_data = np.random.uniform( 
  28.  
  29. low=-1.0, high=1.0
  30.  
  31. size=[batch_size, NOISE_SIZE]).astype('float32'
  32.  
  33. # 真實圖片 
  34.  
  35. real_image = np.array(list(map(lambda x: x[0], data))).reshape( 
  36.  
  37. -1784).astype('float32'
  38.  
  39. # 真實標簽 
  40.  
  41. real_labels = np.ones( 
  42.  
  43. shape=[real_image.shape[0], 1], dtype='float32'
  44.  
  45. # 虛假標簽 
  46.  
  47. fake_labels = np.zeros( 
  48.  
  49. shape=[real_image.shape[0], 1], dtype='float32'
  50.  
  51. total_label = np.concatenate([real_labels, fake_labels]) 
  52.  
  53. s_time = time.time() 
  54.  
  55. # 虛假圖片 
  56.  
  57. generated_image = exe.run(g_program, 
  58.  
  59. feed={'noise': noise_data}, 
  60.  
  61. fetch_list={g_img})[0
  62.  
  63. total_images = np.concatenate([real_image, generated_image]) 
  64.  
  65. # D 判斷虛假圖片為假的loss 
  66.  
  67. d_loss_1 = exe.run(d_program, 
  68.  
  69. feed={ 
  70.  
  71. 'img': generated_image, 
  72.  
  73. 'label': fake_labels, 
  74.  
  75. }, 
  76.  
  77. fetch_list={d_loss})[0][0
  78.  
  79. # D 判斷真實圖片為真的loss 
  80.  
  81. d_loss_2 = exe.run(d_program, 
  82.  
  83. feed={ 
  84.  
  85. 'img': real_image, 
  86.  
  87. 'label': real_labels, 
  88.  
  89. }, 
  90.  
  91. fetch_list={d_loss})[0][0
  92.  
  93. d_loss_n = d_loss_1 + d_loss_2 
  94.  
  95. losses[0].append(d_loss_n) 
  96.  
  97. # 訓練生成器 
  98.  
  99. for _ in six.moves.xrange(NUM_TRAIN_TIMES_OF_DG): 
  100.  
  101. noise_data = np.random.uniform( 
  102.  
  103. low=-1.0, high=1.0
  104.  
  105. size=[batch_size, NOISE_SIZE]).astype('float32'
  106.  
  107. dg_loss_n = exe.run(dg_program, 
  108.  
  109. feed={'noise': noise_data}, 
  110.  
  111. fetch_list={dg_loss})[0][0
  112.  
  113. losses[1].append(dg_loss_n) 
  114.  
  115. t_time += (time.time() - s_time) 
  116.  
  117. if batch_id % 10 == 0 and not run_ce: 
  118.  
  119. if not os.path.exists(output): 
  120.  
  121. os.makedirs(output) 
  122.  
  123. # 每輪的生成結果 
  124.  
  125. generated_images = exe.run(g_program_test, 
  126.  
  127. feed={'noise': const_n}, 
  128.  
  129. fetch_list={g_img})[0
  130.  
  131. # 將真實圖片和生成圖片連接 
  132.  
  133. total_images = np.concatenate([real_image, generated_images]) 
  134.  
  135. fig = plot(total_images) 
  136.  
  137. msg = "Epoch ID={0} Batch ID={1} D-Loss={2} DG-Loss={3}\n ".format( 
  138.  
  139. pass_id, batch_id, 
  140.  
  141. d_loss_n, dg_loss_n) 
  142.  
  143. print(msg) 
  144.  
  145. plt.title(msg) 
  146.  
  147. plt.savefig( 
  148.  
  149. '{}/{:04d}_{:04d}.png'.format(output, pass_id, 
  150.  
  151. batch_id), 
  152.  
  153. bbox_inches='tight'
  154.  
  155. plt.close(fig) 

打印特定輪次的生成結果:

  1. def display_image(epoch_no,batch_id): 
  2.  
  3. return PIL.Image.open('output_dcgan/{:04d}_{:04d}.png'.format(epoch_no,batch_id)) 
  4.  
  5. # 觀察第10個epoch,460個batch的生成圖像: 
  6.  
  7. display_image(10,460

 

總結

DCGAN采用一個隨機噪聲向量作為輸入,輸入通過與CNN類似但是相反的結構,將輸入放大成二維數據。采用這種結構的生成模型和CNN結構的判別模型,DCGAN在圖片生成上可以達到相當可觀的效果。本文中,我們利用DCGAN生成了手寫數字圖片,您可以嘗試更換數據集生成符合個人需求的圖片,完成您的圖像生成任務,快來試試吧!

更多內容,可點擊文末閱讀原文或查看:

https://github.com/PaddlePaddle/book/tree/develop/09.gan

ps:最后給大家推薦一個GPU福利-Tesla V100免費算力!配合PaddleHub能讓模型原地起飛~掃碼下方二維碼申請~

 

 

責任編輯:張燕妮 來源: 51CTO官微
相關推薦

2014-08-08 13:22:54

測試手機站點移動設備

2021-11-09 06:55:03

水印圖像開發

2011-01-10 14:41:26

2025-05-07 00:31:30

2011-05-03 15:59:00

黑盒打印機

2021-07-14 09:00:00

JavaFX開發應用

2011-02-22 13:46:27

微軟SQL.NET

2021-02-26 11:54:38

MyBatis 插件接口

2021-12-28 08:38:26

Linux 中斷喚醒系統Linux 系統

2022-03-14 14:47:21

HarmonyOS操作系統鴻蒙

2022-07-27 08:16:22

搜索引擎Lucene

2022-01-08 20:04:20

攔截系統調用

2023-04-26 12:46:43

DockerSpringKubernetes

2022-12-07 08:42:35

2020-07-09 08:59:52

if else模板Service

2020-04-14 10:20:12

MySQL數據庫死鎖

2021-08-04 08:55:02

Socket Java開發

2011-01-06 10:39:25

.NET程序打包

2024-10-16 11:40:47

2016-04-27 09:49:16

用戶模型產品總結
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 视频在线一区二区 | 日韩免费电影 | 成人精品福利 | 91中文字幕 | 国产精品不卡一区二区三区 | 亚洲精品久久国产高清情趣图文 | 国产成人精品视频在线观看 | 黄色免费在线观看网站 | 久久精品在线免费视频 | 久久国产欧美一区二区三区精品 | 亚洲成人一二区 | 亚州影院 | 欧美网站一区 | 国产成人精品一区二区三区四区 | 偷拍亚洲色图 | 欧美极品一区二区 | 日韩毛片在线视频 | 亚洲欧洲成人 | 91精品国产91久久久久久最新 | 91国产精品 | 日韩精彩视频 | 精精精精xxxx免费视频 | 在线视频日韩精品 | 国产高清在线精品一区二区三区 | 日本久草| 亚洲av毛片成人精品 | 一区二区久久 | 亚洲久久一区 | 国产成人精品免费 | 亚洲欧洲成人av每日更新 | 免费三级黄 | 免费午夜电影 | 精品无码久久久久久国产 | 日韩av免费在线电影 | 精品国产视频 | 久久久精品一区二区 | 日韩中文字幕视频在线观看 | 日韩欧美一区二区三区免费观看 | 性视频一区 | 亚洲电影专区 | 亚洲国产黄色av |