如何使自定义指标对 TFMA/Beam 可用?
How to make a custom metric available to TFMA/Beam?
我创建了一个自定义 Keras 指标,类似于下面的演示实现:
import tensorflow as tf
class MyMetric(tf.keras.metrics.Mean):
def __init__(self, name='my_metric', dtype=None):
super(MyMetric, self).__init__(name=name, dtype=dtype)
def update_state(self, y_true, y_pred, sample_weight=None):
return super(MyMetric, self).update_state(
y_pred, sample_weight=sample_weight)
我已经将实现变成了带有 init/main 文件的 Python 模块,并将路径添加到系统的 PYTHONPATH
。
我可以在训练 Keras 模型时使用该指标。
遗憾的是,我还没有找到使自定义指标可用于 TensorFlow 模型分析 (TFMA) 的方法。
在我的交互式上下文笔记本中,我可以在创建 eval_config
时加载指标。
import tensorflow as tf
import tensorflow_model_analysis as tfma
from mymetric.metric import MyMetric
metrics = [MyMetric()]
metrics_specs = tfma.metrics.specs_from_metrics(metrics)
eval_config = tfma.EvalConfig(
model_specs=[tfma.ModelSpec(label_key='label_xf')],
metrics_specs=metrics_specs,
slicing_specs=[tfma.SlicingSpec()]
)
evaluator = Evaluator(
examples=example_gen.outputs['examples'],
model=trainer.outputs['model'],
baseline_model=model_resolver.outputs['model'],
eval_config=eval_config)
当我尝试执行 evaluator
时,指标列在指标规范中
metrics_specs {
metrics {
class_name: "MyMetric"
config: "{\"dtype\": \"float32\", \"name\": \"my_metric\"}"
threshold {
}
}
}
但执行失败并出现错误
ValueError: Unknown metric function: MyMetric
由于度量计算是通过 Apache Beam 的 executor.Do
函数执行的,我假设 Beam 找不到模块(即使它在 PYTHONPATH 上)。如果是这种情况,我怎样才能使模块在 PYTHONPATH 配置之外对 Apache Beam 可用?
回溯:
/usr/local/lib/python3.6/dist-packages/tensorflow_model_analysis/metrics/metric_specs.py in _deserialize_tf_metric(metric_config, custom_objects)
741 cls_name, cfg = _tf_class_and_config(metric_config)
742 with tf.keras.utils.custom_object_scope(custom_objects):
--> 743 return tf.keras.metrics.deserialize({'class_name': cls_name, 'config': cfg})
744
745
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/metrics.py in deserialize(config, custom_objects)
3441 module_objects=globals(),
3442 custom_objects=custom_objects,
-> 3443 printable_module_name='metric function')
3444
3445
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/utils/generic_utils.py in deserialize_keras_object(identifier, module_objects, custom_objects, printable_module_name)
345 config = identifier
346 (cls, cls_config) = class_and_config_for_serialized_keras_object(
--> 347 config, module_objects, custom_objects, printable_module_name)
348
349 if hasattr(cls, 'from_config'):
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/utils/generic_utils.py in class_and_config_for_serialized_keras_object(config, module_objects, custom_objects, printable_module_name)
294 cls = get_registered_object(class_name, custom_objects, module_objects)
295 if cls is None:
--> 296 raise ValueError('Unknown ' + printable_module_name + ': ' + class_name)
297
298 cls_config = config['config']
ValueError: Unknown metric function: MyMetric
您需要指定模块,以便 TFX 知道在哪里可以找到您的 MyMetric class。一种方法是将其指定为指标规范的一部分:
from tensorflow_model_analysis import config
metric_config = [config.MetricConfig(class_name='MyMetric', module='mymodule.mymetric')]
metrics_specs = [config.MetricsSpec(metrics=metric_config)]
您还需要创建一个名为 mymodule
的模块,并将您的 MyMetric
class 放入 mymetric.py
中才能正常工作。还要确保可以从执行代码的位置访问该模块(如果您已将它添加到 PYTHONPATH 中,情况应该如此)。
我创建了一个自定义 Keras 指标,类似于下面的演示实现:
import tensorflow as tf
class MyMetric(tf.keras.metrics.Mean):
def __init__(self, name='my_metric', dtype=None):
super(MyMetric, self).__init__(name=name, dtype=dtype)
def update_state(self, y_true, y_pred, sample_weight=None):
return super(MyMetric, self).update_state(
y_pred, sample_weight=sample_weight)
我已经将实现变成了带有 init/main 文件的 Python 模块,并将路径添加到系统的 PYTHONPATH
。
我可以在训练 Keras 模型时使用该指标。
遗憾的是,我还没有找到使自定义指标可用于 TensorFlow 模型分析 (TFMA) 的方法。
在我的交互式上下文笔记本中,我可以在创建 eval_config
时加载指标。
import tensorflow as tf
import tensorflow_model_analysis as tfma
from mymetric.metric import MyMetric
metrics = [MyMetric()]
metrics_specs = tfma.metrics.specs_from_metrics(metrics)
eval_config = tfma.EvalConfig(
model_specs=[tfma.ModelSpec(label_key='label_xf')],
metrics_specs=metrics_specs,
slicing_specs=[tfma.SlicingSpec()]
)
evaluator = Evaluator(
examples=example_gen.outputs['examples'],
model=trainer.outputs['model'],
baseline_model=model_resolver.outputs['model'],
eval_config=eval_config)
当我尝试执行 evaluator
时,指标列在指标规范中
metrics_specs {
metrics {
class_name: "MyMetric"
config: "{\"dtype\": \"float32\", \"name\": \"my_metric\"}"
threshold {
}
}
}
但执行失败并出现错误
ValueError: Unknown metric function: MyMetric
由于度量计算是通过 Apache Beam 的 executor.Do
函数执行的,我假设 Beam 找不到模块(即使它在 PYTHONPATH 上)。如果是这种情况,我怎样才能使模块在 PYTHONPATH 配置之外对 Apache Beam 可用?
回溯:
/usr/local/lib/python3.6/dist-packages/tensorflow_model_analysis/metrics/metric_specs.py in _deserialize_tf_metric(metric_config, custom_objects)
741 cls_name, cfg = _tf_class_and_config(metric_config)
742 with tf.keras.utils.custom_object_scope(custom_objects):
--> 743 return tf.keras.metrics.deserialize({'class_name': cls_name, 'config': cfg})
744
745
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/metrics.py in deserialize(config, custom_objects)
3441 module_objects=globals(),
3442 custom_objects=custom_objects,
-> 3443 printable_module_name='metric function')
3444
3445
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/utils/generic_utils.py in deserialize_keras_object(identifier, module_objects, custom_objects, printable_module_name)
345 config = identifier
346 (cls, cls_config) = class_and_config_for_serialized_keras_object(
--> 347 config, module_objects, custom_objects, printable_module_name)
348
349 if hasattr(cls, 'from_config'):
/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/utils/generic_utils.py in class_and_config_for_serialized_keras_object(config, module_objects, custom_objects, printable_module_name)
294 cls = get_registered_object(class_name, custom_objects, module_objects)
295 if cls is None:
--> 296 raise ValueError('Unknown ' + printable_module_name + ': ' + class_name)
297
298 cls_config = config['config']
ValueError: Unknown metric function: MyMetric
您需要指定模块,以便 TFX 知道在哪里可以找到您的 MyMetric class。一种方法是将其指定为指标规范的一部分:
from tensorflow_model_analysis import config
metric_config = [config.MetricConfig(class_name='MyMetric', module='mymodule.mymetric')]
metrics_specs = [config.MetricsSpec(metrics=metric_config)]
您还需要创建一个名为 mymodule
的模块,并将您的 MyMetric
class 放入 mymetric.py
中才能正常工作。还要确保可以从执行代码的位置访问该模块(如果您已将它添加到 PYTHONPATH 中,情况应该如此)。