在 tf.keras 的 model.fit 中,有没有办法将每个样本分批传递 n 次?

Posted

技术标签:

【中文标题】在 tf.keras 的 model.fit 中,有没有办法将每个样本分批传递 n 次?【英文标题】:In model.fit in tf.keras, is there a way to pass each sample in a batch n times? 【发布时间】:2021-09-13 18:34:17 【问题描述】:

我正在尝试为利用 Monte Carlo (MC) 辍学的模型编写自定义损失函数。我希望模型在将预测输入到损失函数之前,以批次 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)

我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

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

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 都相同。

【讨论】:

以上是关于在 tf.keras 的 model.fit 中,有没有办法将每个样本分批传递 n 次?的主要内容,如果未能解决你的问题,请参考以下文章

使用 tf.keras.Model.fit 进行训练时如何将自定义摘要添加到 tensorboard

tf.keras model.fit():在相同数据上火车损失和val损失之间的巨大差异

Model.fit()是否将整个训练数据集上传到GPU?

model.predict 不适用于 Keras 自定义层(推理错误)

中止训练时如何获取 Keras 历史对象?

Keras中的TypeError:即使已经提供了shuffle =“batch”,也要传递shuffle =“batch”