17.Keras后端之VAE实战

1.Keras后端

Keras 是一个模型级库,为开发深度学习模型提供了高层次的构建模块。它不处理诸如张量乘积和卷积等低级操作。相反,它依赖于一个专门的、优化的张量操作库来完成这个操作,它可以作为 Keras 的「后端引擎」。相比单独地选择一个张量库,而将 Keras 的实现与该库相关联,Keras 以模块方式处理这个问题,并且可以将几个不同的后端引擎无缝嵌入到 Keras 中。

打个比方,之前我们这样用:
import tensorflow as tf

a = tf.placeholder(shape=(2,5))
b = tf.placeholder(shape=(2,5))
c = tf.reduce_sum(a,b)
现在我们可以这样用:
#导入keras后端
import keras.backend as K

a = K.placeholder(shape=(2,5))
b = K.placeholder(shape=(2,5))
c = K.sum(a,b)

具体用法见Keras后端


2.自定义损失函数

前面学习Keras,我们都是用的自带的损失函数,Keras自带损失函数在损失函数的使用

2.1自带损失函数使用方法:

方法(1):
#导入model类
from keras.models import Model
#需要的损失函数
from keras.losses import binary_crossentropy

a = Model(inputs,outputs)
a.compile(optimizer='adam',loss=binary_crossentropy)
方法(2):
#导入model类
from keras.models import Model

a = Model(inputs,outputs)
a.compile(optimizer='adam',loss='binary_crossentropy')

2.2自定义损失函数:

方法(1):
#导入keras后端
import keras.backend as K
#导入model类
from keras.models import Model

a = Model(inputs,outputs)
#自定义损失函数
#简单的例子
def myloss(y_true,y_pred):
    loss = K.pow(y_true-y_pred,2)
    return K.mean(loss)
    
a.compile(optimizer='adam',loss=myloss)
vae.fit(x_train,y_train,
       shuffle=True,
       epochs=30,
       batch_size=100)
注意下图标注地方

在这里插入图片描述
其中def myloss(y_true,y_pred):中的参数是固定的,每次训练传入第一个是真实值,第二个是预测值。

方法(2):
#导入keras后端
import keras.backend as K
#导入model类
from keras.models import Model

a = Model(inputs,outputs)

#自定义损失函数
#简单的例子
loss = K.pow(inputs-outputs,2)
myloss = K.mean(loss)
a.add_loss(myloss)
    
a.compile(optimizer='adam')
vae.fit(x_train,
       shuffle=True,
       epochs=30,
       batch_size=100)
注意下图标注地方

在这里插入图片描述
由于我们损失函数没有用到y_true,所以训练的时候可以不传入y_ture,但是在方法(1)中,不管是否用了y_true,都需要在训练的时候传入!


3.自定义函数

在Tensorflow中我们要自定义函数并使用是这样的:
import tensorflow as tf

#计算Z
def get_z(args):
	mu,logvar = args
    #标准正态分布
    eps = tf.random_normal(shape=tf.shape(mu))
    #返回Z的分布
    return mu + tf.exp(logvar / 2) * eps

#获取Z的分布
z = get_z([z_mu,z_logvar])
但在Keras中就不一样了,得这样:
#导入keras后端
import keras.backend as K
#导入Lamda
from keras.layers import Lambda

#潜在空间采样的函数
def get_z(args):
    mu,logvar = args
    eps = K.random_normal(shape=K.shape(mu))
    return mu + K.exp(logvar / 2) * eps
 
z = Lambda(get_z)([z_mu,z_logvar])

Lambda用法在核心网络层中有解释,Lambda的位置是在核心网络层,也就是说它的用法和Dense()()一样,Lambda(这一层的输出)(前面层的输出),传递进去的必须是tensor


4.Keras之VAE实现

Tensorflow:1.9.0

源码点这里
首先声明效果不咋地啊
在这里插入图片描述

import keras
import numpy as np
import os
import matplotlib.gridspec as gridspec
import tensorflow as tf
import matplotlib.pyplot as plt
#导入backend后端库
import keras.backend as K
#导入model类
from keras.models import Model
#需要的损失函数
from keras.losses import binary_crossentropy
#导入keras.layers中相关模块
from keras.layers import Dense,Input,Lambda
#导入优化器
from keras.optimizers import Adam
#导入callback回调函数
import keras.callbacks as callb
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data/',one_hot=True)
if not os.path.exists('out/'):
    os.makedirs('out/')

#画图方法
def plot(samples):
    fig = plt.figure(figsize=(4, 4))
    gs = gridspec.GridSpec(4, 4)
    gs.update(wspace=0.05, hspace=0.05)

    for i, sample in enumerate(samples):
        ax = plt.subplot(gs[i])
        plt.axis('off')
        ax.set_xticklabels([])
        ax.set_yticklabels([])
        ax.set_aspect('equal')
        plt.imshow(sample.reshape(28, 28), cmap='Greys_r')
    return fig

#定义参数
batch_size = 300
epochs = 100
step = 20
input_dim = 784
z_dim = 2
input_shape = (input_dim,)
z_shape = (z_dim,)


#读取数据
x_train = mnist.train.images
x_test = mnist.test.images
x_train /= 255.
x_test /= 255.


input_img = Input(input_shape)

encode = Dense(512,activation='relu',
                kernel_initializer=keras.initializers.TruncatedNormal(stddev=0.001))(input_img)
encode = Dense(256,activation='relu',
               kernel_initializer=keras.initializers.TruncatedNormal(stddev=0.001))(encode)

mu = Dense(z_dim)(encode)
logvar = Dense(z_dim)(encode)


#自定义函数
def get_z(args):
    z_mu, z_logvar = args
    epsilon = K.random_normal(shape=K.shape(z_mu))
    return z_mu + K.exp(z_logvar / 2) * epsilon


z = Lambda(get_z)([mu,logvar])

decode_1 = Dense(256,activation='relu',
               kernel_initializer=keras.initializers.TruncatedNormal(stddev=0.001))
decode_2 = Dense(512,activation='relu',
               kernel_initializer=keras.initializers.TruncatedNormal(stddev=0.001))
decode_3 = Dense(input_dim,activation='sigmoid',
               kernel_initializer=keras.initializers.TruncatedNormal(stddev=0.001))
decode = decode_1(z)
decode = decode_2(decode)
logits = decode_3(decode)


#修改优化器中的学习率
adam = Adam(lr=0.001,decay=0.0005)
#创建模型
vae = Model(input_img,logits)


def myloss(y_true,y_pred):
    BCE = binary_crossentropy(y_true,y_pred)
    #KL散度
    KLD = 0.5*K.sum(K.pow(mu, 2) + K.exp(logvar) - 1 - logvar,1)
    # VAE loss
    return K.mean(KLD + BCE)


#编译模型
vae.compile(optimizer=adam,loss=myloss)

#定义每轮结束操作
def epoch_end_operation(epoch):
    if epoch%step == 0:
        loss = vae.evaluate(x_test,x_test,verbose=0)
        print('第%s轮测试后结果:' % epoch)
        print('loss:%.4f' % loss)
        print()
        i = 0
        i += int(epoch/step)
        test_z = np.random.randn(16, z_dim)
        input_z = Input(z_shape)
        test_decode = decode_1(input_z)
        test_decode = decode_2(test_decode)
        test_logits = decode_3(test_decode)
        generate = Model(input_z,test_logits)
        pred_samples = generate.predict(test_z)
        fig = plot(pred_samples)
        plt.savefig('out/{}.png'.format(str(i).zfill(3)), bbox_inches='tight')

#自定义回调函数
class Pred_Plot(callb.Callback):
    def on_epoch_end(self, epoch, logs={}):
        epoch_end_operation(epoch+1)
        
pred_plot = Pred_Plot()

#需要执行的回调函数列表
callback_list = [pred_plot]

vae.fit(x_train,x_train,
        batch_size=batch_size,
        epochs=epochs,
        verbose=0,
        callbacks=callback_list)
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值