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)