Tensorflow 2自定义损耗返回nan
我有一个模型,我用二进制交叉熵编译它,训练过程很顺利,损失被打印出来Tensorflow 2自定义损耗返回nan,tensorflow,keras,tensorflow2.0,Tensorflow,Keras,Tensorflow2.0,我有一个模型,我用二进制交叉熵编译它,训练过程很顺利,损失被打印出来 model = MyModel() model.compile(optimizer="adadelta", loss="binary_crossentropy") data1, data2 = get_random_data(4, 3) # this method return data1:(1000,4),data2:(1000,3) model.fit([data1, data2]
model = MyModel()
model.compile(optimizer="adadelta", loss="binary_crossentropy")
data1, data2 = get_random_data(4, 3) # this method return data1:(1000,4),data2:(1000,3)
model.fit([data1, data2], y, batch_size=4)
然后我编写了一个自定义损失函数,损失变成nan
import tensorflow.keras.backend as K
class MyModel():
...
def batch_loss(self, y_true, y_pred_batch):
bottom = K.sum(K.exp(y_pred_batch))
batch_softmax = K.exp(y_pred_batch) / bottom
batch_log_likelihood = K.log(batch_softmax)
loss = K.sum(batch_log_likelihood)
return loss
model.compile(optimizer="adadelta", loss=model.batch_loss) # change above compile code to this
我使用一个batch_loss(tf.ones((1,)))
来测试我的loss函数,似乎它返回了正确的结果
但当它与培训一起运行时,它会变成nan
,我应该从哪里开始调试
模型和数据代码(适用于需要复制的用户):
我认为您的错误是由调用
exp()
引起的。此函数快速增长并返回nan。我认为您的错误是由调用exp()
引起的。此函数快速增长并返回nan。模型输出的值相当大。再加上在函数中调用tf.exp
,值会快速增长到nan
。你可以考虑应用一个激活函数,比如<代码> SigMoID,将值保持在0到1之间。< P>你的模型输出的值相当大。再加上在函数中调用tf.exp
,值会快速增长到nan
。你可以考虑应用一个激活函数,比如<代码> SigMoID,使值保持在0到1之间。两个答案都得到了答案。我使用了tf.print
,发现它们没有标准化为[0,1]。两个答案都有道理。我使用了tf.print
,发现它们没有标准化为[0,1]。
class MyModel(tf.keras.models.Model):
def __init__(self):
super().__init__()
self.t1A = tf.keras.layers.Dense(300, activation='relu', input_dim=1)
self.t1B = tf.keras.layers.Dense(300, activation='relu', input_dim=1)
self.t1v = tf.keras.layers.Dense(128, activation='relu')
self.t2A = tf.keras.layers.Dense(300, activation='relu')
self.t2B = tf.keras.layers.Dense(300, activation='relu')
self.t2v = tf.keras.layers.Dense(128, activation='relu')
self.out = tf.keras.layers.Dot(axes=1)
def call(self, inputs, training=None, mask=None):
u, i = inputs[0], inputs[1]
u = self.t1A(u)
u = self.t1B(u)
u = self.t1v(u)
i = self.t2A(i)
i = self.t2B(i)
i = self.t2v(i)
out = self.out([u, i])
return out
def get_random_data(user_feature_num, item_feature_num):
def get_random_ndarray(data_size, dis_list, feature_num):
data_list = []
for i in range(feature_num):
arr = np.random.randint(dis_list[i], size=data_size)
data_list.append(arr)
data = np.array(data_list)
return np.transpose(data, axes=(1, 0))
uf_dis, if_dis, data_size = [1000, 2, 10, 20], [10000, 50, 60], 1000
y = np.zeros(data_size)
for i in range(int(data_size/10)):
y[i] = 1
return get_random_ndarray(data_size, uf_dis, feature_num=user_feature_num), \
get_random_ndarray(data_size, if_dis, feature_num=item_feature_num), y