美文网首页
(6)生成式深度学习

(6)生成式深度学习

作者: 纵春水东流 | 来源:发表于2021-05-13 11:45 被阅读0次

    1、字符级别文本生成

    import keras
    import numpy as np
    #下载数据
    path = keras.utils.get_file('nietzsche.txt',origin='https://s3.amazonaws.com/text-datasets/nietzsche.txt')
    text = open(path).read().lower()
    print('Corpus length:', len(text))
    
    #向量化数据
    maxlen = 60
    step = 3
    sentences = []
    next_chars = []
    for i in range(0, len(text) - maxlen, step):
        sentences.append(text[i: i + maxlen])
        next_chars.append(text[i + maxlen])
    print('Number of sequences:', len(sentences))
    
    chars = sorted(list(set(text)))
    print('Unique characters:', len(chars))
    char_indices = dict((char, chars.index(char)) for char in chars)
    
    print('Vectorization...')
    x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)
    y = np.zeros((len(sentences), len(chars)), dtype=np.bool)
    for i, sentence in enumerate(sentences):
        for t, char in enumerate(sentence):
            x[i, t, char_indices[char]] = 1
            y[i, char_indices[next_chars[i]]] = 1
    
    #搭建模型
    from keras import layers
    model = keras.models.Sequential()
    model.add(layers.LSTM(128, input_shape=(maxlen, len(chars))))
    model.add(layers.Dense(len(chars), activation='softmax'))
    
    optimizer = keras.optimizers.RMSprop(lr=0.01)
    model.compile(loss='categorical_crossentropy', optimizer=optimizer)
    #训练模型
    def sample(preds, temperature=1.0):
        preds = np.asarray(preds).astype('float64')
        preds = np.log(preds) / temperature
        exp_preds = np.exp(preds)
        preds = exp_preds / np.sum(exp_preds)
        probas = np.random.multinomial(1, preds, 1)
        return np.argmax(probas)
    import random
    import sys
    for epoch in range(1, 60):
        print('epoch', epoch)
        model.fit(x, y, batch_size=128, epochs=1)
        start_index = random.randint(0, len(text) - maxlen - 1)
        generated_text = text[start_index: start_index + maxlen]
        print('--- Generating with seed: "' + generated_text + '"')
        
        for temperature in [0.2, 0.5, 1.0, 1.2]:
            print('------ temperature:', temperature)
            sys.stdout.write(generated_text)
    
            for i in range(400):
                sampled = np.zeros((1, maxlen, len(chars)))
                for t, char in enumerate(generated_text):
                    sampled[0, t, char_indices[char]] = 1.
    
            preds = model.predict(sampled, verbose=0)[0]
            next_index = sample(preds, temperature)
            next_char = chars[next_index]
    
            generated_text += next_char
            generated_text = generated_text[1:]
    
            sys.stdout.write(next_char)
    
    
    

    2、DeepDream
    DeepDream可视化神经网络学到的特征,首先图像正向传播,计算每一层激活对应的梯度,通过修改图像使得这些激活最大化,强化网络看到的模式,从而导致一个梦幻般的图像。这个过程称为感知

    import tensorflow as tf
    import numpy as np
    import matplotlib as mpl
    import IPython.display as display
    import PIL.Image
    from tensorflow.keras.preprocessing import image
    
    
    url = 'https://storage.googleapis.com/download.tensorflow.org/example_images/YellowLabradorLooking_new.jpg'
    # Download an image and read it into a NumPy array.
    def download(url, max_dim=None):
      name = url.split('/')[-1]
      image_path = tf.keras.utils.get_file(name, origin=url)
      img = PIL.Image.open(image_path)
      if max_dim:
        img.thumbnail((max_dim, max_dim))
      return np.array(img)
    
    # Normalize an image
    def deprocess(img):
      img = 255*(img + 1.0)/2.0
      return tf.cast(img, tf.uint8)
    
    # Display an image
    def show(img):
      display.display(PIL.Image.fromarray(np.array(img)))
    
    
    # Downsizing the image makes it easier to work with.
    original_img = download(url, max_dim=500)
    show(original_img)
    display.display(display.HTML('Image cc-by: <a "href=https://commons.wikimedia.org/wiki/File:Felis_catus-cat_on_snow.jpg">Von.grzanka</a>'))
    
    ########################
    base_model = tf.keras.applications.InceptionV3(include_top=False, weights='imagenet')
    
    # Maximize the activations of these layers
    # 最大化这两个层的输出
    names = ['mixed3', 'mixed5']
    layers = [base_model.get_layer(name).output for name in names]
    
    # Create the feature extraction model,创建特征提取模型
    dream_model = tf.keras.Model(inputs=base_model.input, outputs=layers)
    
    
    #计算损失,损失是所选层的激活和,每一个层的损失都正则化,通过最大化损失来强调特征
    def calc_loss(img, model):
      # Pass forward the image through the model to retrieve the activations.
      # Converts the image into a batch of size 1.
      img_batch = tf.expand_dims(img, axis=0)
      layer_activations = model(img_batch)
      if len(layer_activations) == 1:
        layer_activations = [layer_activations]
    
      losses = []
      for act in layer_activations:
        loss = tf.math.reduce_mean(act)
        losses.append(loss)
    
      return  tf.reduce_sum(losses)
    
    
    #计算出损失后,下一步是计算梯度,并把这些梯度加到原来的图像中去
    #把这些梯度加到图像中去,强化了网络所学到的特征,每一步,创建一个图像特定层的激活
    #方法如下,使用tf.function提升性能,
    class DeepDream(tf.Module):
      def __init__(self, model):
        self.model = model
    
      @tf.function(
          input_signature=(
            tf.TensorSpec(shape=[None,None,3], dtype=tf.float32),
            tf.TensorSpec(shape=[], dtype=tf.int32),
            tf.TensorSpec(shape=[], dtype=tf.float32),)
      )
      def __call__(self, img, steps, step_size):
          print("Tracing")
          loss = tf.constant(0.0)
          for n in tf.range(steps):
            with tf.GradientTape() as tape:
              # This needs gradients relative to `img`
              # `GradientTape` only watches `tf.Variable`s by default
              tape.watch(img)
              loss = calc_loss(img, self.model)
    
            # Calculate the gradient of the loss with respect to the pixels of the input image.
            gradients = tape.gradient(loss, img)
    
            # Normalize the gradients.
            gradients /= tf.math.reduce_std(gradients) + 1e-8 
            
            # In gradient ascent, the "loss" is maximized so that the input image increasingly "excites" the layers.
            # You can update the image by directly adding the gradients (because they're the same shape!)
            img = img + gradients*step_size
            img = tf.clip_by_value(img, -1, 1)
    
          return loss, img
    deepdream = DeepDream(dream_model)
    ################
    def run_deep_dream_simple(img, steps=100, step_size=0.01):
      # Convert from uint8 to the range expected by the model.
      img = tf.keras.applications.inception_v3.preprocess_input(img)
      img = tf.convert_to_tensor(img)
      step_size = tf.convert_to_tensor(step_size)
      steps_remaining = steps
      step = 0
      while steps_remaining:
        if steps_remaining>100:
          run_steps = tf.constant(100)
        else:
          run_steps = tf.constant(steps_remaining)
        steps_remaining -= run_steps
        step += run_steps
    
        loss, img = deepdream(img, run_steps, tf.constant(step_size))
        
        display.clear_output(wait=True)
        show(deprocess(img))
        print ("Step {}, loss {}".format(step, loss))
    
    
      result = deprocess(img)
      display.clear_output(wait=True)
      show(result)
    
      return result
    
    dream_img = run_deep_dream_simple(img=original_img, steps=100, step_size=0.01)
    ###################
    
    

    3、神经风格迁移

    
    

    4、用变分自编码器生成图像
    自编码器将输入编码到低维度空间,然后再解码回来。经典的自编码器不会得到特别有用或具有良好结构的潜在空间,它们也没有对数据做多少压缩。VAE向编码器添加了一点统计魔法,迫使其学习连续的,高度结构化的潜在空间。VAE将图像转化为统计分布的参数,即平均值与方差。本质上来说,我们假设输入的图像是由统计过程生成的
    VAE工作原理:
    (1)一个编码器模块将输入样本input_img转换为表示潜在空间的两个参数z_mean和z_log_variance。
    (2)我们假定潜在正态分布能够生成图像,并从这个分布中随机采样一个点z:z=z_mean+exp(z_log_variance)*epsilon,这个epsilon是随机张量
    (3)一个解码器将潜在空间的这个点映射回原始图像
    因为epsilon是随机的,所以这个过程可以确保,与input_img编码的潜在位置靠近的点都能被编码成与input_img相似的图像,从而迫使潜在空间能够连续地有意义。潜在空间的任意两个相邻的点都会被解码成高度相似的图象
    VAE的参数通过两个损失函数进行训练:一个是重构损失(reconstruction loss),它迫使解码后的样本匹配初始输入;另一个是正则化损失,它有助于学习具有良好结构的潜在空间,并可以降低训练数据上的过拟合

    #%%编码器
    import numpy as np
    import keras
    from keras import layers,Model,models,utils
    from keras import backend as K  
    from keras.datasets import mnist
    
    img_shape = (28,28,1) 
    latent_dim = 2
    
    input_img = layers.Input(shape=img_shape)
    x = layers.Conv2D(32,3,padding='same',activation='relu')(input_img)
    x = layers.Conv2D(64,3,padding='same',activation='relu',strides=2)(x)
    x = layers.Conv2D(64,3,padding='same',activation='relu')(x)
    x = layers.Conv2D(64,3,padding='same',activation='relu')(x)
    inter_shape = K.int_shape(x)
    x = layers.Flatten()(x)
    x = layers.Dense(32,activation='relu')(x)
    
    encode_mean = layers.Dense(2,name = 'encode_mean')(x)       #????
    encode_log_var = layers.Dense(2,name = 'encode_logvar')(x)  #??????
    
    encoder = Model(input_img,[encode_mean,encode_log_var],name = 'encoder')
    
    #%%解码器
    input_code = layers.Input(shape=[2])
    x = layers.Dense(np.prod(inter_shape[1:]),activation='relu')(input_code)
    x = layers.Reshape(target_shape=inter_shape[1:])(x)
    x = layers.Conv2DTranspose(32,3,padding='same',activation='relu',strides=2)(x)
    x = layers.Conv2D(1,3,padding='same',activation='sigmoid')(x)
    
    decoder = Model(input_code,x,name = 'decoder')
    
    #%%整体待训练模型
    def sampling(arg):
      mean = arg[0]
      logvar = arg[1]
      epsilon = K.random_normal(shape=K.shape(mean),mean=0.,stddev=1.)  #??????????
      return mean + K.exp(0.5*logvar) * epsilon                         #?????????
    input_img = layers.Input(shape=img_shape,name = 'img_input')
    code_mean, code_log_var = encoder(input_img)                        #????????????
    x = layers.Lambda(sampling,name = 'sampling')([code_mean, code_log_var])
    x = decoder(x)
    training_model = Model(input_img,x,name = 'training_model') 
     
    decode_loss = keras.metrics.binary_crossentropy(K.flatten(input_img), K.flatten(x))
    kl_loss = -5e-4*K.mean(1+code_log_var-K.square(code_mean)-K.exp(code_log_var))
    training_model.add_loss(K.mean(decode_loss+kl_loss)) #??????????
    training_model.compile(optimizer='rmsprop')
    
    
    #%%训练
    (x_train,y_train),(x_test,y_test) = mnist.load_data()
    x_train = x_train.astype('float32')/255
    x_train = x_train[:,:,:,np.newaxis] 
     
    training_model.fit(
      x_train,
      batch_size=512,
      epochs=100, 
      validation_data=(x_train[:2],None))
    
    #%%生成测试
    from scipy.stats import norm
    import numpy as np
    import matplotlib.pyplot as plt
    n = 20
    x = y = norm.ppf(np.linspace(0.01,0.99,n))  #?????????
    X,Y = np.meshgrid(x,y)                      #????
    X = X.reshape([-1,1])                       #????
    Y = Y.reshape([-1,1]) 
    input_points = np.concatenate([X,Y],axis=-1)#?????
    for i in input_points:
      plt.scatter(i[0],i[1])
    plt.show()
    
    img_size = 28
    predict_img = decoder.predict(input_points)
    pic = np.empty([img_size*n,img_size*n,1])
    for i in range(n):
      for j in range(n):
        pic[img_size*i:img_size*(i+1), img_size*j:img_size*(j+1)] = predict_img[i*n+j]
    plt.figure(figsize=(10,10))
    plt.axis('off')
    pic = np.squeeze(pic)
    plt.imshow(pic,cmap='bone')
    plt.show()
    

    5、生成对抗网络

    相关文章

      网友评论

          本文标题:(6)生成式深度学习

          本文链接:https://www.haomeiwen.com/subject/kknfdltx.html