zoukankan      html  css  js  c++  java
  • 吴裕雄--天生自然神经网络与深度学习实战Python+Keras+TensorFlow:生成型与条件型生成型对抗网络

    from keras.layers import LeakyReLU
    from keras.layers import BatchNormalization
    from keras.optimizers import RMSprop
    import math
    
    def  build_generator(inputs, image_size):
      '''
      生成者网络与编解码网络中的解码器如出一辙,输入给它的一维随机向量相当于输入解码器网络的编码向量,
      解码器网络将一维向量反向构造成图片所对应的二维向量,这也是生成者要做的工作,所以下面代码与我们做过
      的解码器网络几乎一模一样
      '''
      image_resize = image_size // 4
      kernel_size = 5
      layer_filters = [128, 64, 32, 1]
      
      x = Dense(image_resize * image_resize * layer_filters[0])(inputs)
      x = Reshape((image_resize, image_resize, layer_filters[0]))(x)
      
      #构造三层反卷积网络
      for filters in layer_filters:
        if filters > layer_filters[-2]:
          strides = 2
        else:
          strides = 1
        
        #使用batch normalization将输入反卷积网络的向量做预处理,没有这一步GAN的训练就会失败
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2DTranspose(filters = filters, kernel_size = kernel_size,
                           strides = strides,
                           padding = 'same')(x)
      
      x = Activation('sigmoid')(x)
      generator = Model(inputs, x, name = 'generator')
      return generator
    def  build_discriminator(inputs):
      '''
      识别者网络与编码器很像,它使用三层卷积网络从图片中抽取信息,最后使用sigmoid函数输出
      图片是否为真的概率
      '''
      kernel_size = 5
      layer_filters = [32, 64, 128, 256]
      x = inputs
      for filters in layer_filters:
        if filters == layer_filters[-1]:
          strides = 1
        else:
          strides = 2
        x = LeakyReLU(alpha = 0.2)(x)
        x = Conv2D(filters=filters, 
                   kernel_size=kernel_size ,
                  strides = strides,
                  padding = 'same')(x)
        
      x = Flatten()(x)
      x = Dense(1)(x)
      x = Activation('sigmoid')(x)
      discriminator = Model(inputs, x, name='discriminator')
      return discriminator
    def  build_and_train_models():
      '''
      将生成者和识别者连城一个网络进行训练
      '''
      (x_train, _), (_, _) = mnist.load_data()
      image_size = x_train.shape[1]
      x_train = np.reshape(x_train, [-1, image_size, image_size, 1])
      x_train = x_train.astype('float32') / 255
      #设置训练相关的参数
      model_name = '/content/gdrive/My Drive/dcgan_mnist'
      latent_size = 100
      batch_size = 64
      train_steps = 40000
      lr = 2e-4
      decay = 6e-8
      input_shape = (image_size, image_size, 1)
      #构建识别者网络
      inputs = Input(shape = input_shape, name = 'discriminator_input')
      discriminator = build_discriminator(inputs)
      optimizer = RMSprop(lr = lr, decay = decay)
      discriminator.compile(loss = 'binary_crossentropy', optimizer = optimizer,
                           metrics = ['accuracy'])
      #构建生成者网络
      input_shape = (latent_size, )
      inputs = Input(shape = input_shape, name = 'z_input')
      generator = build_generator(inputs, image_size)
      optimizer = RMSprop(lr = lr * 0.5, decay = decay * 0.5)
      #将生成者和识别者连接成一个网络时要冻结识别者,因为训练生成者时识别者网络要保持不变
      discriminator.trainable = False
      adversarial = Model(inputs, discriminator(generator(inputs)),
                         name = model_name)
      adversarial.compile(loss = 'binary_crossentropy',
                         optimizer = optimizer,
                         metrics = ['accuracy'])
      
      models = (generator, discriminator, adversarial)
      params = (batch_size, latent_size, train_steps, model_name)
      train(models, x_train, params)
      
    def  train(models, x_train, params):
      '''
      训练时需要遵守的步骤是,先冻结生成者网络,把真实图片输入到识别者网络,训练识别者网络识别真实图片。
      然后冻结识别者网络,让生成者网络构造图片输入给识别者网络识别,根据识别结果来改进生成者网络
      '''
      #先获得生成者,识别者,以及两者的结合体
      generator, discriminator, adversarial = models
      batch_size, latent_size , train_steps, model_name = params
      save_interval = 500
      
      #构造给生成者网络的一维随机向量
      noise_input = np.random.uniform(-1.0, 1.0, size = [16, latent_size])
      train_size = x_train.shape[0]
      for i in range(train_steps):
        #先训练识别者网络,将真实图片和伪造图片同时输入识别者,让识别者学会区分真假图片
        rand_indexes = np.random.randint(0, train_size, size = batch_size)
        real_images = x_train[rand_indexes]
        noise = np.random.uniform(-1.0, 1.0, size = [batch_size, latent_size])
        #让生成者构造虚假图片
        fake_images = generator.predict(noise)
        x = np.concatenate((real_images, fake_images))
        y = np.ones([2 * batch_size, 1])
        #真实图片对应标签1,虚假图片对应标签0
        y[batch_size : , :] = 0.0
        loss, acc = discriminator.train_on_batch(x, y)
        log = "%d: [discriminator loss: %f, acc: %f]" % (i, loss, acc)
        
        #冻结识别者,让生成者构造一系列图片输入识别者,根据识别者识别结果改进生成者网络
        noise = np.random.uniform(-1.0, 1.0, size = [batch_size, latent_size])
        y = np.ones([batch_size, 1])
        #训练生成者时需要使用到识别者返回的结果,因此我们从两者连接后的网络进行训练
        loss, acc = adversarial.train_on_batch(noise, y)
        log = "%s [adversarial loss: %f, acc: %f]" % (log, loss, acc)
        print(log)
        if (i + 1) % save_interval == 0:
          if (i + 1) == train_steps:
            show = True
          else:
            show = False
          #将生成者构造的图片绘制出来
          plot_images(generator, noise_input = noise_input,
                     show = show, step = (i + 1),
                     model_name = model_name)
          #将生成者当前的网络参数存储成文件
        generator.save(model_name + ".h5")
      
    def  plot_images(generator, noise_input, show = False,
                    step = 0,
                    model_name = ''):
      os.makedirs(model_name, exist_ok = True)
      filename = os.path.join(model_name, "%05d.png" % step)
      images = generator.predict(noise_input)
      plt.figure(figsize = (2.2, 2.2))
      num_images = images.shape[0]
      image_size = images.shape[1]
      rows = int(math.sqrt(noise_input.shape[0]))
      for i in range(num_images):
        plt.subplot(rows, rows, i + 1)
        image = np.reshape(images[i], [image_size, image_size])
        plt.imshow(image, cmap= 'gray')
        plt.axis('off')
        
      plt.savefig(filename)
      if show:
        plt.show()
      else:
        plt.close('all')
    from google.colab import drive
    drive.mount('/content/gdrive')

    from keras.datasets import mnist
    from keras.layers import LeakyReLU
    from keras.layers import Activation
    from keras.optimizers import RMSprop
    import os
     
    build_and_train_models()

    from keras.models import load_model
    import os
    
    generator = load_model('/content/gdrive/My Drive/dcgan_mnist.h5')
    #构造一批随机初始化的一维向量让生成者网络创造图片
    noise = np.random.randint(-1.0, 1.0, size=[16, 100])
    plot_images(generator, noise_input = noise,
               show = True, model_name="test_image")

    from keras.layers.merge import concatenate
    from keras.utils import to_categorical
    
    def build_cgan_discriminator(inputs, y_labels, image_size):
      '''
      识别图片,并将图片与输入的one-hot-vector关联起来
      '''
      kernel_size = 5
      layer_filters = [32, 64, 128, 256]
      x = inputs
      y = Dense(image_size * image_size)(y_labels)
      y = Reshape((image_size, image_size, 1))(y)
      #把图片数据与one-hot-vector拼接起来,这里是唯一与前面代码不同之处
      x = concatenate([x, y])
     
      for filters in layer_filters:
        if filters == layer_filters[-1]:
          strides = 1
        else:
          strides = 2
        x = LeakyReLU(alpha=0.2)(x)
        x = Conv2D(filters = filters,
                  kernel_size = kernel_size,
                  strides = strides,
                  padding = 'same')(x)
        
      x = Flatten()(x)
      x = Dense(1)(x)
      x = Activation('sigmoid')(x)
      discriminator = Model([inputs, y_labels], x ,
                           name = 'discriminator')
      return discriminator
    def  build_cgan_generator(inputs, y_labels, image_size):
      '''
      生成者网络在构造图片时,需要将输入向量与对应的one-hot-vector结合在一起考虑
      '''
      image_resize = image_size // 4
      kernel_size = 5
      layer_filters = [128, 64, 32, 1]
      #将输入向量与One-hot-vector结合在一起
      x = concatenate([inputs, y_labels], axis = 1)
      x = Dense(image_resize * image_resize * layer_filters[0])(x)
      x = Reshape((image_resize, image_resize, layer_filters[0]))(x)
      for filters in layer_filters:
        if filters > layer_filters[-2]:
          strides = 2
        else:
          strides = 1
        
        x = BatchNormalization()(x)
        x = Activation('relu')(x)
        x = Conv2DTranspose(filters = filters,
                           kernel_size = kernel_size,
                           strides = strides,
                           padding = 'same')(x)
      x = Activation('sigmoid')(x)
      generator = Model([inputs, y_labels], x, name='generator')
      return generator
    def  train_cgan(models, data, params):
      generator, discriminator, adversarial = models
      #获取图片数据以及图片对应数字的one-hot-vector
      x_train, y_train = data
      batch_size, latent_size, train_steps, num_labels, model_name = params
      save_interval = 500
      noise_input = np.random.uniform(-1.0, 1.0, size=[16, latent_size])
      '''
      np.eye产生对角矩阵,例如np.eye(3) = [[1,0,0], [0,1,0], [0,0,1]],
      于是np.eye(3)[2, 3, 1] = [[0,1,0], [0,0,1], [1,0,0]]
      '''
      noise_class = np.eye(num_labels)[np.arange(0, 16) % num_labels]
      train_size = x_train.shape[0]
      print(model_name, "Labels for generated images: ", np.argmax(noise_class, 1))
      for i in range(train_steps):
        rand_indexes = np.random.randint(0, train_size, size = batch_size)
        real_images = x_train[rand_indexes]
        #增加图片对应的one-hot-vector
        real_labels = y_train[rand_indexes]
        
        noise = np.random.uniform(-1.0, 1.0, size = [batch_size, latent_size])
        #增加构造图片对应的one-hot-vector
        fake_labels = np.eye(num_labels)[np.random.choice(num_labels, batch_size)]
        fake_images = generator.predict([noise, fake_labels])
        #把真实图片和虚假图片连接起来
        x = np.concatenate((real_images, fake_images))
        #将真实图片对应的one-hot-vecotr和虚假图片对应的One-hot-vector连接起来
        y_labels = np.concatenate((real_labels, fake_labels))
        
        y = np.ones([2 * batch_size, 1])
        #上半部分图片为真,下半部分图片为假
        y[batch_size:, :] = 0.0
        #先训练识别者网络,这里需要将图片及对应的one-hot-vector输入
        loss, acc = discriminator.train_on_batch([x, y_labels], y)
        log = "%d: [discriminator loss : %f, acc: %f]" % (i, loss, acc)
        '''
        冻结识别者网络,构造随机一维向量以及指定数字的one-hot-vector输入生成者
        网络进行训练
        '''
        noise = np.random.uniform(-1.0, 1.0, size=[batch_size, latent_size])
        fake_labels = np.eye(num_labels)[np.random.choice(num_labels, batch_size)]
        y = np.ones([batch_size, 1])
        loss, acc = adversarial.train_on_batch([noise, fake_labels], y)
        log = "%s [adversarial loss :%f, acc: %f]" % (log, loss, acc)
        if (i + 1) % save_interval == 0:
          print(log)
          if (i+1) == train_steps:
            show = True
          else:
            show = False
          plot_images_cgan(generator, 
                     noise_input = noise_input,
                     noise_class = noise_class,
                     show = show,
                     step = (i+1),
                     model_name = model_name)
          generator.save(model_name + ".h5")
    def  build_and_train_models_cgan():
      (x_train, y_train), (_,_) = mnist.load_data()
      image_size = x_train.shape[1]
      x_train = np.reshape(x_train, [-1, image_size, image_size, 1])
      x_train = x_train.astype('float32') / 255
      #获得要生成数字的最大值
      num_labels = np.amax(y_train) + 1
      #转换为one-hot-vector
      y_train = to_categorical(y_train)
      
      model_name = "/content/gdrive/My Drive/cgan_mnist"
      latent_size = 100
      batch_size = 64
      train_steps = 40000
      lr = 2e-4
      decay = 6e-8
      input_shape = (image_size, image_size, 1)
      label_shape = (num_labels, )
      inputs = Input(shape=input_shape, name='discriminator_input')
      labels = Input(shape=label_shape, name = 'class_labels')
      #构建识别者网络时要传入图片对应的One-hot-vector
      discriminator = build_cgan_discriminator(inputs, labels, image_size)
      optimizer = RMSprop(lr=lr, decay = decay)
      discriminator.compile(loss='binary_crossentropy', 
                             optimizer=optimizer,
                             metrics = ['accuracy'])
      
      input_shape = (latent_size,)
      inputs = Input(shape=input_shape, name='z_input')
      #构造生成者时也要传入one-hot-vector
      generator = build_cgan_generator(inputs, labels, image_size)
      optimizer = RMSprop(lr = lr*0.5, decay = decay * 0.5)
      #将生成者和识别者连接起来时要冻结识别者
      discriminator.trainable = False
      outputs = discriminator([generator([inputs, labels]), labels])
      adversarial = Model([inputs, labels], outputs, name = model_name)
      adversarial.compile(loss ='binary_crossentropy',
                          optimizer = optimizer,
                          metrics = ['accuracy'])
      models = (generator, discriminator, adversarial)
      data = (x_train, y_train)
      params = (batch_size, latent_size, train_steps, num_labels, model_name)
      train_cgan(models, data, params)
    def  plot_images_cgan(generator, 
                     noise_input, 
                     noise_class,
                     show = False,
                    step = 0,
                    model_name = ''):
      os.makedirs(model_name, exist_ok = True)
      filename = os.path.join(model_name, "%05d.png" % step)
      images = generator.predict([noise_input, noise_class])
      print(model_name, "labels for generated images: ", np.argmax(noise_class, 
                                                                   axis =1))
      plt.figure(figsize = (2.2, 2.2))
      num_images = images.shape[0]
      image_size = images.shape[1]
      rows = int(math.sqrt(noise_input.shape[0]))
      for i in range(num_images):
        plt.subplot(rows, rows, i + 1)
        image = np.reshape(images[i], [image_size, image_size])
        plt.imshow(image, cmap= 'gray')
        plt.axis('off')
        
      plt.savefig(filename)
      if show:
        plt.show()
      else:
        plt.close('all')
    from keras.layers import LeakyReLU
    from keras.layers import BatchNormalization
    from keras.optimizers import RMSprop
    import math
    from keras.layers import Activation, Dense, Input
    
    build_and_train_models_cgan()

  • 相关阅读:
    redis_03 _ 高性能IO模型:为什么单线程Redis能那么快
    redis_02 _ 数据结构:快速的Redis有哪些慢操作?
    redis-01 _ 基本架构:一个键值数据库包含什么?
    mysql_28 _ 读写分离有哪些坑
    mysql_27 _ 主库出问题了,从库怎么办
    小程序的转发功能
    简单几何(求交点) UVA 11178 Morley's Theorem
    测试开发CICD——Docker——windows8上环境安装
    测试开发进阶——spring boot——MVC——MyBatis初步了解(转载)
    BZOJ 2226 [Spoj 5971] LCMSum
  • 原文地址:https://www.cnblogs.com/tszr/p/12269774.html
Copyright © 2011-2022 走看看