在model.fit in tf.keras中,有没有办法让每个样本在batch中传递n次?

In model.fit in tf.keras, is there a way to pass each sample in a batch n times?

我正在尝试为利用 Monte Carlo (MC) dropout 的模型编写自定义损失函数。我希望模型 运行 通过批处理中的每个样本 n 次,然后再将预测提供给损失函数。当前的玩具代码如下所示。该模型有 24 个输入和 10 个输出以及 5000 个训练样本。

import numpy as np
import tensorflow as tf

X = np.random.rand(5000,24)
y = np.random.rand(5000,10)

def MC_Loss(y_true,y_pred):
    mu = tf.math.reduce_mean(y_pred,axis=0)
    #error = tf.square(y_true-mu)
    error = tf.square(y_true-y_pred)
    var = tf.math.reduce_variance(y_pred,axis=0)
    return tf.math.divide(error,var)/2 + tf.math.log(var)/2 + tf.math.log(2*np.pi)/2

input_layer = tf.keras.layers.Input(shape=(X.shape[1],))
hidden_layer = tf.keras.layers.Dense(units=100,activation='elu')(input_layer)
do_layer = tf.keras.layers.Dropout(rate=0.20)(hidden_layer,training=True)
output_layer = tf.keras.layers.Dense(units=10,activation='sigmoid')(do_layer)

model = tf.keras.models.Model(input_layer,output_layer)
model.compile(loss=MC_Loss,optimizer='Adam')

model.fit(X,y,epochs=100,batch_size=128,shuffle=True)

y_truey_pred的当前形状是(None,10)None是batch_size。我希望能够为批次中的每个样本提供 n 值,因此我可以获得每个样本的均值和标准差以用于损失函数。我想要这些值,因为每个样本的平均值和标准偏差应该是唯一的,而不是在一个批次中对所有样本进行计算。 musigma 的当前形状是 (10,) 我希望它们是 (None,10) 这意味着 y_truey_pred 的形状(None,n,10).

我怎样才能做到这一点?

我相信经过一些实验我找到了解决方案。修改后的代码如下所示。

import numpy as np
import tensorflow as tf

n = 100

X = np.random.rand(5000,24)
X1 = np.concatenate(([X.reshape(X.shape[0],1,X.shape[1]) for _ in range(n)]),axis=1)
y = np.random.rand(5000,10)
y1 = np.concatenate(([y.reshape(y.shape[0],1,y.shape[1]) for _ in range(n)]),axis=1)

def MC_Loss(y_true,y_pred):
    mu = tf.math.reduce_mean(y_pred,axis=1)
    obs = tf.math.reduce_mean(y_true,axis=1)
    error = tf.square(obs-mu)
    var = tf.math.reduce_variance(y_pred,axis=1)
    return tf.math.divide(error,var)/2 + tf.math.log(var)/2 + tf.math.log(2*np.pi)/2

input_layer = tf.keras.layers.Input(shape=(X.shape[1]))
hidden_layer = tf.keras.layers.Dense(units=100,activation='elu')(input_layer)
do_layer = tf.keras.layers.Dropout(rate=0.20)(hidden_layer,training=True)
output_layer = tf.keras.layers.Dense(units=10,activation='sigmoid')(do_layer)

model = tf.keras.models.Model(input_layer,output_layer)
model.compile(loss=MC_Loss,optimizer='Adam')

model.fit(X1,y1,epochs=100,batch_size=128,shuffle=True)

所以我现在正在做的是围绕中间轴堆叠输入和输出,创建 n 所有输入和输出样本的相同集合。而 tensorflow 显示警告,因为模型是在不知道此中间轴的情况下创建的。它仍然可以毫无问题地进行训练,并且形状符合预期。

注意:由于 y_true 现在具有 (None,n,10) 的形状,您必须取关于中间轴的平均值,因为所有 n 相同。