【发布时间】:2020-10-24 23:02:49
【问题描述】:
我想在 tf.Keras 中编写一个具有几个损失函数的神经网络。一个是带有因子加载的标准 mse(均方误差),而另一个基本上是隐藏层输出的正则化项。第二个损失是通过self.add_loss() 在继承自tf.keras.layers.Layer 的用户定义类中添加的。我有几个问题(虽然第一个更重要)。
1) 尝试将两种损失结合在一起时出现的错误如下:
ValueError: Shapes must be equal rank, but are 0 and 1
From merging shape 0 with other shapes. for '{{node AddN}} = AddN[N=2, T=DT_FLOAT](loss/weighted_loss/value, model/new_layer/mul_1)' with input shapes: [], [100].
所以它来自这样一个事实,即应该加起来形成一个唯一损失值的张量具有不同的形状(和等级)。尽管如此,当我尝试在训练期间打印损失时,我清楚地看到作为损失返回的向量具有batch_size 和排名 1 的形状。难道当 2 个损失相加时,我必须提供它们(或至少add_loss) 作为标量的损失?我知道 mse 通常作为向量返回,其中每个条目都是批次中一个样本的 mse,因此具有 batch_size 作为形状。我想我试图对“正则化”损失做同样的事情。你对这种行为有什么解释吗?
给出错误的示例代码如下:
import numpy as np
import tensorflow as tf
from tensorflow.keras import backend as K
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Input
def rate_mse(rate=1e5):
@tf.function # also needed for printing
def loss(y_true, y_pred):
tmp = rate*K.mean(K.square(y_pred - y_true), axis=-1)
# tf.print('shape %s and rank %s output in mse'%(K.shape(tmp), tf.rank(tmp)))
tf.print('shape and rank output in mse',[K.shape(tmp), tf.rank(tmp)])
tf.print('mse loss:',tmp) # print when I put tf.function
return tmp
return loss
class newLayer(tf.keras.layers.Layer):
def __init__(self, rate=5e-2, **kwargs):
super(newLayer, self).__init__(**kwargs)
self.rate = rate
# @tf.function # to be commented for NN training
def call(self, inputs):
tmp = self.rate*K.mean(inputs*inputs, axis=-1)
tf.print('shape and rank output in regularizer',[K.shape(tmp), tf.rank(tmp)])
tf.print('regularizer loss:',tmp)
self.add_loss(tmp, inputs=True)
return inputs
tot_n = 10000
xx = np.random.rand(tot_n,1)
yy = np.pi*xx
train_size = int(0.9*tot_n)
xx_train = xx[:train_size]; xx_val = xx[train_size:]
yy_train = yy[:train_size]; yy_val = yy[train_size:]
reg_layer = newLayer()
input_layer = Input(shape=(1,)) # input
hidden = Dense(20, activation='relu', input_shape=(2,))(input_layer) # hidden layer
hidden = reg_layer(hidden)
output_layer = Dense(1, activation='linear')(hidden)
model = Model(inputs=[input_layer], outputs=[output_layer])
model.compile(optimizer='Adam', loss=rate_mse(), experimental_run_tf_function=False)
#model.compile(optimizer='Adam', loss=None, experimental_run_tf_function=False)
model.fit(xx_train, yy_train, epochs=100, batch_size = 100,
validation_data=(xx_val,yy_val), verbose=1)
#new_xx = np.random.rand(10,1); new_yy = np.pi*new_xx
#model.evaluate(new_xx,new_yy)
print(model.predict(np.array([[1]])))
2) 我还有一个与此代码相关的次要问题。我注意到在函数rate_mse 内使用tf.print 打印仅适用于tf.function。类似地,newLayer 的call 方法只有在训练期间注释了相同的装饰器时才会考虑。有人可以解释为什么会这样或向我推荐一个可能的解决方案吗?
提前感谢可以为我提供帮助的人。我目前使用的是 Tensorflow 2.2.0,keras 版本是 2.3.0-tf。
【问题讨论】:
-
您自己找到答案了吗?我仍然无法弄清楚如何才能完成这项工作。
-
@MikeMartin 不,抱歉。最后,我不得不忽略这一点。
标签: python-3.x neural-network layer tf.keras tensorflow2.x