智能系統技術叢書 生成對抗網絡入門指南》—3.4GAN的工程實踐

      網友投稿 1056 2022-05-30

      3.4 GAN的工程實踐

      之前幾節我們了解了生成對抗網絡(GAN)的設計原理。但是,實際它是如何實現的呢?在這一節中我們會詳細介紹GAN的實踐方法以及代碼的編寫[4]。

      從之前的數學推導中我們知道,我們要做的是優化下面的式子。

      (3-36)

      計算公式中的期望值可以等價于計算真實數據分布與生成數據分布的積分,在實踐中我們使用采樣的方法來逼近期望值。

      首先我們從前置的隨機分布pg(z)中取出m個隨機數{z(1), z(2), …, z(m)},其次我們再從真實數據分布pdata(x)中取出m個真實樣本{x(1), x(2), …, x(m)}我們使用平均數代替上式中的期望,公式改寫如下。

      (3-37)

      在GAN的原始論文中給出了完整的偽代碼,其中θd為判別器D的參數,θg為生成器G的參數。

      該偽代碼每次迭代過程中的前半部分為訓練判別器的過程,后半部分為訓練生成器。對于判別器,我們會訓練k次來更新參數θd,在論文的實驗中研究者把k設為1,使得實驗成本最小。生成器在每次迭代中僅更新一次,如果更新多次可能無法使得生成數據分布與真實數據分布的JS散度距離下降。

      下面我們嘗試使用TensorFlow來實現上一節中GAN訓練過程的可視化。

      偽代碼2 基礎GAN的偽代碼實現(其中對于判別器會迭代k次,

      k為超參數,大多數情況下可以使k = 1)

      for訓練的迭代次數do

      for重復k次do

      從生成器前置隨機分布pg(z)取出m個小批次樣本z(1), …, z(m);

      從真實數據分布pdata(x)取出m個小批次樣本x(1), …, x(m);

      使用隨機梯度下降更新判別器參數;

      end for

      從生成器前置隨機分布pg(z)取出m個小批次樣本z(1), …, z(m);

      使用隨機梯度下降更新生成器參數;

      end for

      首先需要設置真實數據樣本的分布,這里設置均值為3、方差為0.5的高斯分布。

      class DataDistribution(object):

      def __init__(self):

      self.mu = 3

      self.sigma = 0.5

      def sample(self, N):

      samples = np.random.normal(self.mu, self.sigma, N)

      samples.sort()

      return samples

      接著設定生成器的初始化分布,這里設定的是平均分布。

      class GeneratorDistribution(object):

      def __init__(self, range):

      self.range = range

      def sample(self, N):

      return np.linspace(-self.range, self.range, N) + \

      np.random.random(N) * 0.01

      使用下面的代碼設置一個最簡單的線性運算函數,用于后面的生成器與判別器。

      def linear(input, output_dim, scope=None, stddev=1.0):

      norm = tf.random_normal_initializer(stddev=stddev)

      const = tf.constant_initializer(0.0)

      with tf.variable_scope(scope or 'linear'):

      w = tf.get_variable('w', [input.get_shape()[1], output_dim], initializer=norm)

      b = tf.get_variable('b', [output_dim], initializer=const)

      return tf.matmul(input, w) + b

      基于該線性運算函數,我們可以完成簡單的生成器和判別器代碼。

      def generator(input, h_dim):

      h0 = tf.nn.softplus(linear(input, h_dim, 'g0'))

      h1 = linear(h0, 1, 'g1')

      return h1

      def discriminator(input, h_dim):

      h0 = tf.tanh(linear(input, h_dim * 2, 'd0'))

      h1 = tf.tanh(linear(h0, h_dim * 2, 'd1'))

      h2 = tf.tanh(linear(h1, h_dim * 2, 'd2'))

      h3 = tf.sigmoid(linear(h2, 1, 'd3'))

      return h3

      設置優化器,這里使用的是學習率衰減的梯度下降方法。

      def optimizer(loss, var_list, initial_learning_rate):

      decay = 0.95

      num_decay_steps = 150

      batch = tf.Variable(0)

      learning_rate = tf.train.exponential_decay(

      initial_learning_rate,

      batch,

      num_decay_steps,

      decay,

      staircase=True

      )

      optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(

      loss,

      global_step=batch,

      var_list=var_list

      )

      return optimizer

      下面來搭建GAN模型類的代碼,除了初始化參數之外,其中核心的兩個函數分別是模型的創建和模型的訓練。

      class GAN(object):

      def __init__(self, data, gen, num_steps, batch_size, log_every):

      self.data = data

      self.gen = gen

      self.num_steps = num_steps

      self.batch_size = batch_size

      self.log_every = log_every

      self.mlp_hidden_size = 4

      self.learning_rate = 0.03

      self._create_model()

      def _create_model(self):

      ......

      def train(self):

      ......

      創建模型。這里需要創建預訓練判別器D_pre、生成器Generator和判別器Discriminator,按照之前的公式定義生成器和判別器的損失函數loss_g與loss_d以及它們的優化器opt_g與opt_d,其中D1與D2分別代表真實數據與生成數據的判別。

      def _create_model(self):

      with tf.variable_scope('D_pre'):

      self.pre_input = tf.placeholder(tf.float32, shape=(self.batch_size, 1))

      self.pre_labels = tf.placeholder(tf.float32, shape=(self.batch_size, 1))

      D_pre = discriminator(self.pre_input, self.mlp_hidden_size)

      self.pre_loss = tf.reduce_mean(tf.square(D_pre - self.pre_labels))

      self.pre_opt = optimizer(self.pre_loss, None, self.learning_rate)

      with tf.variable_scope('Generator'):

      self.z = tf.placeholder(tf.float32, shape=(self.batch_size, 1))

      self.G = generator(self.z, self.mlp_hidden_size)

      with tf.variable_scope('Discriminator') as scope:

      self.x = tf.placeholder(tf.float32, shape=(self.batch_size, 1))

      self.D1 = discriminator(self.x, self.mlp_hidden_size)

      scope.reuse_variables()

      self.D2 = discriminator(self.G, self.mlp_hidden_size)

      self.loss_d = tf.reduce_mean(-tf.log(self.D1) - tf.log(1 - self.D2))

      self.loss_g = tf.reduce_mean(-tf.log(self.D2))

      self.d_pre_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,

      scope='D_pre')

      self.d_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=

      'Discriminator')

      self.g_params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope=

      'Generator')

      self.opt_d = optimizer(self.loss_d, self.d_params, self.learning_rate)

      self.opt_g = optimizer(self.loss_g, self.g_params, self.learning_rate)

      訓練模型的代碼如下所示,首先需要預先訓練判別器D_pre,然后將訓練后的參數共享給判別器Discriminator。接著就可以正式訓練生成器Generator與判別器Discriminator了。

      def train(self):

      with tf.Session() as session:

      tf.global_variables_initializer().run()

      # pretraining discriminator

      num_pretrain_steps = 1000

      for step in range(num_pretrain_steps):

      d = (np.random.random(self.batch_size) - 0.5) * 10.0

      labels = norm.pdf(d, loc=self.data.mu, scale=self.data.sigma)

      pretrain_loss, _ = session.run([self.pre_loss, self.pre_opt], {

      self.pre_input: np.reshape(d, (self.batch_size, 1)),

      self.pre_labels: np.reshape(labels, (self.batch_size, 1))

      })

      self.weightsD = session.run(self.d_pre_params)

      for i, v in enumerate(self.d_params):

      session.run(v.assign(self.weightsD[i]))

      for step in range(self.num_steps):

      # update discriminator

      x = self.data.sample(self.batch_size)

      z = self.gen.sample(self.batch_size)

      loss_d, _ = session.run([self.loss_d, self.opt_d], {

      self.x: np.reshape(x, (self.batch_size, 1)),

      self.z: np.reshape(z, (self.batch_size, 1))

      })

      # update generator

      z = self.gen.sample(self.batch_size)

      loss_g, _ = session.run([self.loss_g, self.opt_g], {

      self.z: np.reshape(z, (self.batch_size, 1))

      })

      if step % self.log_every == 0:

      print('{}:{}\t{}'.format(step, loss_d, loss_g))

      if step % 100 == 0 or step==0 or step == self.num_steps -1 :

      self._plot_distributions(session)

      可視化代碼如下,使用對數據進行采樣的方式來展示生成數據與真實數據的分布。

      def _samples(self, session, num_points=10000, num_bins=100):

      xs = np.linspace(-self.gen.range, self.gen.range, num_points)

      bins = np.linspace(-self.gen.range, self.gen.range, num_bins)

      # data distribution

      d = self.data.sample(num_points)

      pd, _ = np.histogram(d, bins=bins, density=True)

      # generated samples

      zs = np.linspace(-self.gen.range, self.gen.range, num_points)

      g = np.zeros((num_points, 1))

      for i in range(num_points // self.batch_size):

      g[self.batch_size * i:self.batch_size * (i + 1)] = session.run(self.G, {

      self.z: np.reshape(

      zs[self.batch_size * i:self.batch_size * (i + 1)],

      (self.batch_size, 1)

      )

      })

      pg, _ = np.histogram(g, bins=bins, density=True)

      return pd, pg

      def _plot_distributions(self, session):

      pd, pg = self._samples(session)

      p_x = np.linspace(-self.gen.range, self.gen.range, len(pd))

      f, ax = plt.subplots(1)

      ax.set_ylim(0, 1)

      plt.plot(p_x, pd, label='Real Data')

      plt.plot(p_x, pg, label='Generated Data')

      《智能系統與技術叢書 生成對抗網絡入門指南》—3.4GAN的工程實踐

      plt.title('GAN Visualization')

      plt.xlabel('Value')

      plt.ylabel('Probability Density')

      plt.legend()

      plt.show()

      最后設置主函數用于運行項目,分別設置迭代次數、批次數量以及希望展示可視化的間隔,這里的設置分別為1200、12和10。

      def main(args):

      model = GAN(

      DataDistribution(),

      GeneratorDistribution(range=8),

      1200, #num_steps

      12, #batch_size

      10, #log_every

      )

      model.train()

      運行過程中我們會分別看到圖3-11到圖3-13的幾個階段,GAN的生成器從平均分布開始會逐漸逼近最終的高斯分布,實現生成數據與真實數據分布的重合。

      圖3-11 GAN可視化初始階段狀態

      圖3-12 GAN可視化訓練中狀態

      圖3-13 GAN可視化最終狀態

      語言生成

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:揭秘三大軟件設計開發方法(DDD,TDD,BDD),到底哪個好?
      下一篇:用 RxJS 連接世界
      相關文章
      mm1313亚洲国产精品美女| 妇女自拍偷自拍亚洲精品| 亚洲精品高清一二区久久| 欧美日韩亚洲精品| 亚洲精品无码一区二区| 亚洲国产区男人本色在线观看| 亚洲午夜久久久精品电影院| 亚洲色欲或者高潮影院| 亚洲AV日韩精品久久久久久久 | 亚洲小说区图片区另类春色| 亚洲国产成人五月综合网 | 国产精品亚洲天堂| 日韩色视频一区二区三区亚洲 | 亚洲免费视频网站| 亚洲一区二区三区夜色| 99久久精品国产亚洲| 亚洲网站在线播放| 亚洲国产精品无码久久久| 亚洲一区二区三区四区视频| 亚洲资源最新版在线观看| 中文字幕无码精品亚洲资源网久久| 美女视频黄免费亚洲| 亚洲AV无码成人精品区日韩| 亚洲精品色在线网站| 亚洲成A人片在线观看中文| 国产亚洲成人久久| 国产亚洲高清不卡在线观看| 亚洲av日韩综合一区在线观看| 亚洲视频在线免费观看| 亚洲福利电影一区二区?| 亚洲中字慕日产2020| 亚洲一卡一卡二新区无人区| 亚洲国产精品无码第一区二区三区| 亚洲AV无码专区在线观看成人 | 亚洲国产av无码精品| 国产日产亚洲系列| 亚洲AV日韩精品久久久久久久| 亚洲成a人片7777| 亚洲一卡2卡三卡4卡无卡下载| 在线亚洲精品视频| 亚洲色偷偷综合亚洲AVYP|