keras打印loss对权重的导数方式
Notes
怀疑模型梯度爆炸,想打印模型loss对各权重的导数看看。如果如果fit来训练的话,可以用keras.callbacks.TensorBoard实现。
但此次使用train_on_batch来训练的,用K.gradients和K.function实现。
Codes
以一份VAE代码为例
#-*-coding:utf8-*-
importkeras
fromkeras.modelsimportModel
fromkeras.layersimportInput,Lambda,Conv2D,MaxPooling2D,Flatten,Dense,Reshape
fromkeras.lossesimportbinary_crossentropy
fromkeras.datasetsimportmnist,fashion_mnist
importkeras.backendasK
fromscipy.statsimportnorm
importnumpyasnp
importmatplotlib.pyplotasplt
BATCH=128
N_CLASS=10
EPOCH=5
IN_DIM=28*28
H_DIM=128
Z_DIM=2
(x_train,y_train),(x_test,y_test)=fashion_mnist.load_data()
x_train=x_train.reshape(len(x_train),-1).astype('float32')/255.
x_test=x_test.reshape(len(x_test),-1).astype('float32')/255.
defsampleing(args):
"""reparameterize"""
mu,logvar=args
eps=K.random_normal([K.shape(mu)[0],Z_DIM],mean=0.0,stddev=1.0)
returnmu+eps*K.exp(logvar/2.)
#encode
x_in=Input([IN_DIM])
h=Dense(H_DIM,activation='relu')(x_in)
z_mu=Dense(Z_DIM)(h)#mean,不用激活
z_logvar=Dense(Z_DIM)(h)#logvariance,不用激活
z=Lambda(sampleing,output_shape=[Z_DIM])([z_mu,z_logvar])#只能有一个参数
encoder=Model(x_in,[z_mu,z_logvar,z],name='encoder')
#decode
z_in=Input([Z_DIM])
h_hat=Dense(H_DIM,activation='relu')(z_in)
x_hat=Dense(IN_DIM,activation='sigmoid')(h_hat)
decoder=Model(z_in,x_hat,name='decoder')
#VAE
x_in=Input([IN_DIM])
x=x_in
z_mu,z_logvar,z=encoder(x)
x=decoder(z)
out=x
vae=Model(x_in,[out,out],name='vae')
#loss_kl=0.5*K.sum(K.square(z_mu)+K.exp(z_logvar)-1.-z_logvar,axis=1)
#loss_recon=binary_crossentropy(K.reshape(vae_in,[-1,IN_DIM]),vae_out)*IN_DIM
#loss_vae=K.mean(loss_kl+loss_recon)
defloss_kl(y_true,y_pred):
return0.5*K.sum(K.square(z_mu)+K.exp(z_logvar)-1.-z_logvar,axis=1)
#vae.add_loss(loss_vae)
vae.compile(optimizer='rmsprop',
loss=[loss_kl,'binary_crossentropy'],
loss_weights=[1,IN_DIM])
vae.summary()
#获取模型权重variable
w=vae.trainable_weights
print(w)
#打印KL对权重的导数
#KL要是Tensor,不能是上面的函数`loss_kl`
grad=K.gradients(0.5*K.sum(K.square(z_mu)+K.exp(z_logvar)-1.-z_logvar,axis=1),
w)
print(grad)#有些是None的
grad=grad[gradisnotNone]#去掉None,不然报错
#打印梯度的函数
#K.function的输入和输出必要是list!就算只有一个
show_grad=K.function([vae.input],[grad])
#vae.fit(x_train,#y_train,#不能传y_train
#batch_size=BATCH,
#epochs=EPOCH,
#verbose=1,
#validation_data=(x_test,None))
'''以train_on_batch方式训练'''
forepochinrange(EPOCH):
forbinrange(x_train.shape[0]//BATCH):
idx=np.random.choice(x_train.shape[0],BATCH)
x=x_train[idx]
l=vae.train_on_batch([x],[x,x])
#计算梯度
gd=show_grad([x])
#打印梯度
print(gd)
#showmanifold
PIXEL=28
N_PICT=30
grid_x=norm.ppf(np.linspace(0.05,0.95,N_PICT))
grid_y=grid_x
figure=np.zeros([N_PICT*PIXEL,N_PICT*PIXEL])
fori,xiinenumerate(grid_x):
forj,yjinenumerate(grid_y):
noise=np.array([[xi,yj]])#必须秩为2,两层中括号
x_gen=decoder.predict(noise)
#print('x_genshape:',x_gen.shape)
x_gen=x_gen[0].reshape([PIXEL,PIXEL])
figure[i*PIXEL:(i+1)*PIXEL,
j*PIXEL:(j+1)*PIXEL]=x_gen
fig=plt.figure(figsize=(10,10))
plt.imshow(figure,cmap='Greys_r')
fig.savefig('./variational_autoencoder.png')
plt.show()
补充知识:keras自定义损失自动求导时出现None
问题记录,keras自定义损失自动求导时出现None,后来想到是因为传入的变量没有使用,所以keras无法求出偏导,修改后问题解决。就是不愿使用的变量×0,求导后还是0就可以了。
defmy_complex_loss_graph(y_label,emb_uid,lstm_out,y_true_1,y_true_2,y_true_3,out_1,out_2,out_3): mse_out_1=mean_squared_error(y_true_1,out_1) mse_out_2=mean_squared_error(y_true_2,out_2) mse_out_3=mean_squared_error(y_true_3,out_3) #emb_uid=K.reshape(emb_uid,[-1,32]) cosine_sim=tf.reduce_sum(0.5*tf.square(emb_uid-lstm_out)) cost=0*cosine_sim+K.sum([0.5*mse_out_1,0.25*mse_out_2,0.25*mse_out_3],axis=1,keepdims=True) #print(mse_out_1) final_loss=cost returnK.mean(final_loss)
以上这篇keras打印loss对权重的导数方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。