tensorflow - 批量计算损失函数的有效方法?
问题描述
我正在使用自动编码器进行异常检测。所以,我已经完成了模型的训练,现在我想计算数据集中每个条目的重建损失。这样我就可以将异常分配给具有高重建损失的数据点。
这是我当前计算重建损失的代码但这真的很慢。据我估计,遍历数据集需要 5 个小时,而训练一个 epoch 大约需要 55 分钟。我觉得转换为张量操作是代码的瓶颈,但我找不到更好的方法来做到这一点。
我试过改变批量大小,但没有太大区别。我必须使用转换为张量的部分,因为如果我正常执行,K.eval 会引发错误。
Python
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)))
我能够在每个 epoch 55 分钟内进行训练。所以我觉得每个时期的预测不应该花费 5 个小时。encrypted_dataset 是一个变量,它将主存储器中的整个数据集作为一个数据帧。我正在使用 Azure VM 实例。
K.eval(loss_function(y_true,y_pred)
是找到批次的每一行的损失所以 y_true 将是大小(batch_size,2000)
,所以 y_pred
K.eval(loss_function(y_true,y_pred)
会给我一个输出
(batch_size,1)
评估 y_true 和 y_pred 每一行的二元交叉熵
解决方案
移自评论:
我的怀疑是,ae1.predict
并且K.eval(loss_function)
正在以意想不到的方式表现。ae1.predict
通常应该用于输出损失函数值以及y_pred
. 创建模型时,指定损失值是另一个输出(您可以有多个输出的列表),然后只需在此处调用一次 predict 即可在一次调用中获取两个y_pred
损失值。
但我想要每一行的损失。predict 方法返回的损失不会是整个批次的平均损失吗?
答案取决于损失函数是如何实现的。两种方式都在 TF 中产生完全有效且相同的结果。您可以在对损失进行梯度计算之前对批次的损失进行平均,或者将梯度作为损失向量。如果您使用后一种方法,TF 中的梯度操作将为您执行损失的平均(请参阅关于采用每个样本梯度的 SO 文章,实际上很难做到)。
如果 Keras 使用reduce_mean
内置的损失来实现损失,您可以定义自己的损失。如果您使用平方损失,请将 'mean_squared_error' 替换为 lambda y_true, y_pred: tf.square(y_pred - y_true)。这将产生平方误差而不是 MSE(与梯度没有区别),但请在此处查找包括 mean 的变体。
在任何情况下,只要您不使用tf.reduce_mean
,这都会产生每个样本的损失,这在损失中纯粹是可选的。另一种选择是简单地将损失与您优化的内容分开计算,并将其作为模型的输出,也完全有效。
推荐阅读
- python - 在 Jupyter 中使用 Pandas 自动完成的问题
- matlab-guide - 我在 matlab 中使用 cwtft 时遇到问题
- encryption - 检查 X509Certificate2 是否适用于 Google Chrome 和 Mozilla Firefox 中的 http/2
- spring-integration - 如何从 SftpOutboundGateway 接收价值
- hibernate - ORA-01000: nombre maximum de curseurs ouverts dépassé
- ios - 在Objective C中点击后退按钮时如何将界面方向从横向更改为纵向
- gtk - 在 GTK+ 中使用 GTKInspector 模拟触摸屏
- pandas - 将缺少系列索引的值与主索引合并
- docker - 从 docker 容器运行 tensorflow-2.0
- json - 如何将 JSON 数据转换为 Kotlin 对象