我使用keras方法fit()
将自定义指标传递给模型。 度量是有状态的 - 即是Metric
的子类,如 https://keras.io/api/metrics/#as-subclasses-of-metric-stateful 中所述 当我使用tf.distribute.MirroredStrategy()
在多 GPU 环境中运行代码时,我的指标代码会在每个 GPU 上单独调用,并传递batch_size/no_of_gpus
示例,这是合理的预期。
接下来发生的事情是,度量值的多个标量(每个 GPU 一个)需要减少到单个标量,而我一直得到的是sum
减少,而我想控制它。 请记住,reduction
参数是 keras 中的Loss
参数之一,Metric
类中没有这样的东西:https://github.com/tensorflow/tensorflow/blob/acbc065f8eb2ed05c7ab5c42b5c5bd6abdd2f91f/tensorflow/python/keras/metrics.py#L87
(我尝试的唯一疯狂的事情是从Mean
类继承,该类是Metric
的子类,但这并没有改变任何东西)
指标代码中提到了reduction
,但这是对单个指标对象和多 GPU 设置中多个累积值的减少 - 事实并非如此,因为每个指标都在自己的 GPU 中工作,并且最终以某种方式聚合。
我调试它以了解这种行为的方式是 - 我在度量方法中打印形状和结果update_state
。然后我在回调中查看了logs
对象on_batch_end
指标的值。
我尝试查看TF代码,但找不到发生这种情况的地方。 我希望能够控制这种行为 - 所以要么为指标选择"平均值"或"总和",要么至少知道它在代码中的位置。
编辑:我想这个 https://github.com/tensorflow/tensorflow/issues/39268 对这个问题有更多的了解
我面临着与您相同的问题(这就是我找到您的问题的原因)。
看到您提出问题已经 15 天了,还没有答案/评论,我想我可能会分享我的临时解决方法。
和您一样,我也认为在组合多个 GPU 的进度时已经执行了SUM
缩减。我所做的是将 GPU 的数量(例如,由tf.distribute
策略对象的num_replicas_in_sync
属性给出)传递到子类化指标对象的__init__(...)
构造函数中,并使用它来划分results()
方法中的返回值。
您可能还可以使用指标对象中的tf.distribute.get_strategy()
来使其"策略感知",并使用这些信息来决定如何以临时方式修改值,以便SUM
缩减将产生您想要的结果。
我希望这现在有所帮助,无论是作为建议还是确认您并不孤单。
在实现 Keras Metric 类的子类时,必须正确覆盖 merge_state() 函数。如果不覆盖此函数,将使用默认实现 - 这是一个简单的总和。
请参阅:https://www.tensorflow.org/api_docs/python/tf/keras/metrics/Metric