Tensorflow 批量计算损失函数的有效方法?

Tensorflow 批量计算损失函数的有效方法?,tensorflow,keras,bigdata,Tensorflow,Keras,Bigdata,我正在使用自动编码器进行异常检测。所以,我已经完成了模型的训练,现在我想计算数据集中每个条目的重建损失。因此,我可以将异常分配给重建损失高的数据点 这是我目前计算重建损失的代码 但这真的很慢。据我估计,浏览数据集需要5个小时,而训练一个历元大约需要55分钟。 我觉得转换为张量运算是代码的瓶颈,但我找不到更好的方法 我尝试过改变批量大小,但没有多大区别。我必须使用转换为张量部分,因为如果我正常进行转换,K.eval会抛出一个错误 蟒蛇 for i in range(0, encoded_data

我正在使用自动编码器进行异常检测。所以,我已经完成了模型的训练,现在我想计算数据集中每个条目的重建损失。因此,我可以将异常分配给重建损失高的数据点

这是我目前计算重建损失的代码 但这真的很慢。据我估计,浏览数据集需要5个小时,而训练一个历元大约需要55分钟。 我觉得转换为张量运算是代码的瓶颈,但我找不到更好的方法

我尝试过改变批量大小,但没有多大区别。我必须使用转换为张量部分,因为如果我正常进行转换,K.eval会抛出一个错误

蟒蛇

 for i in range(0, encoded_dataset.shape[0], batch_size):    
    y_true = tf.convert_to_tensor(encoded_dataset[i:i+batch_size].values,
 np.float32)
     y_pred= tf.convert_to_tensor(ae1.predict(encoded_dataset[i:i+batch_size].values),
 np.float32)
    # Append the batch losses (numpy array) to the list
    reconstruction_loss_transaction.append(K.eval(loss_function( y_true, y_pred))) 
我每一个时代都能训练55分钟。所以我觉得预测不应该每个历元花费5个小时。encoded_dataset是一个将整个数据集作为数据帧存储在主内存中的变量。 我正在使用Azure VM实例。
K.eval(loss\u函数(y\u true,y\u pred)
用于查找批次中每一行的损失 因此,y_true的大小将是
(batch_size,2000)
,y_pred的大小也将是

K.eval(loss\u函数(y\u true,y\u pred)
将为我提供

(批处理大小,1)
计算y的每行上的二进制交叉熵 _真的和你一样

从评论中删除:

我怀疑
ae1.predict
K.eval(loss_function)
的行为方式出乎意料。
ae1.predict
通常应用于输出损失函数值以及
y_pred
。创建模型时,指定损失值是另一个输出(可以有多个输出列表),然后只需在此处调用predict一次,即可在一次调用中同时获得损失值

但是我想要每一行的损失。predict方法返回的损失不是整个批次的平均损失吗

答案取决于损失函数是如何实现的。这两种方法在引擎盖下的TF中都会产生完全有效且相同的结果。您可以在获取梯度w.r.t.损失之前对批次的损失进行平均,或者将梯度w.r.t.作为损失向量。TF中的梯度操作将对每个批次的损失进行平均如果您使用后一种方法(请看,这实际上很难做到)

如果Keras使用内置在损耗中的
reduce_mean
实现损耗,您可以定义自己的损耗。如果您使用平方损耗,则用lambda y_true,y_pred:tf.square(y_pred-y_true)替换“mean_squared_error”。这将产生平方误差而不是MSE(与梯度没有差异),但是


在任何情况下,只要您不使用
tf.reduce_mean
,这都会产生每个样本的损失,这在损失中是完全可选的。另一种选择是只需将损失与您优化的内容分开计算,并将其作为模型的输出,也完全有效。

我已经删除了我以前的答案,您能将您的问题编辑为e吗解释一下K.eval(loss_function(y_true,y_pred))
是什么?我对我们在那里看到的东西感到困惑。我已经做了更改。
ae1.predict
如何与
y_true
获取相同的数据?两者都作为输入
编码的数据集[I:I+批量大小].values
。如果执行预测,则会传入输入数据,但似乎是在使用标签进行预测。我假设
values
以某种方式同时包含数据和标签,这在代码段中并不明显。在这种情况下,您可能会多次移动完整的输入数据。但是,这不是很明显清楚。问题很好。答案取决于损失函数是如何实现的。这两种方法都可以在引擎盖下的TF中产生完全有效且相同的结果。你可以在取梯度w.r.t.损失之前对批次的损失进行平均,或者取梯度w.r.t.损失向量。TF中的梯度操作将执行平均如果您使用后一种方法,您的损失会老化(请参阅关于采用每批次梯度的文章,这实际上很难做到)。如果keras使用内置于损失中的
reduce\u mean
来实现损失,您可以定义自己的损失。如果您使用平方损失,将
'mean\u squared\u error'
替换为
lambda y\u true,y\u pred:tf.square(y\u pred-y\u true)
。这将产生平方误差而不是均方误差(与梯度没有差异),但请在此处查找包含平均值的变量:。在任何情况下,只要您不使用
tf.reduce_mean
,这在损失中完全是可选的。请告诉我这是否解决了问题,我将把讨论转移到一个答案。