Пользовательские метрики с tf.estimator

Я хочу, чтобы тензорный поток рассчитывал коэффициент детерминации (R в квадрате) во время оценки моей оценки. Я попытался реализовать это следующим образом, вольно основываясь на реализации официальных метрик:

def r_squared(labels, predictions, weights=None,
              metrics_collections=None,
              updates_collections=None,
              name=None):

    total_error = tf.reduce_sum(tf.square(labels - tf.reduce_mean(labels)))
    unexplained_error = tf.reduce_sum(tf.square(labels - predictions))
    r_sq = 1 - tf.div(unexplained_error, total_error)

    # update_rsq_op = ?

    if metrics_collections:
        ops.add_to_collections(metrics_collections, r_sq)

    # if updates_collections:
    #     ops.add_to_collections(updates_collections, update_rsq_op)

    return r_sq #, update_rsq_op

Затем я использую эту функцию в качестве метрики в EstimatorSpec:

estim_specs = tf.estimator.EstimatorSpec(
    ...
    eval_metric_ops={
        'r_squared': r_squared(labels, predictions),
        ...
    })

Однако это не удается, поскольку моя реализация R в квадрате не возвращает update_op.

TypeError: Values of eval_metric_ops must be (metric_value, update_op) tuples, given: Tensor("sub_4:0", dtype=float64) for key: r_squared

Теперь мне интересно, что именно должен делать update_op? Мне действительно нужно реализовать update_op или я могу как-то создать какой-то фиктивный update_op? И если это необходимо, как бы я это реализовал?


person msteininger    schedule 11.12.2017    source источник
comment
Возможный дубликат Custom eval_metric_ops в Estimator в Tensorflow   -  person CvW    schedule 20.02.2018


Ответы (2)


Хорошо, так что я смог понять это. Я могу обернуть свою метрику средней метрикой и использовать ее update_op. Кажется, это работает для меня.

def r_squared(labels, predictions, weights=None,
              metrics_collections=None,
              updates_collections=None,
              name=None):

    total_error = tf.reduce_sum(tf.square(labels - tf.reduce_mean(labels)))
    unexplained_error = tf.reduce_sum(tf.square(labels - predictions))
    r_sq = 1 - tf.div(unexplained_error, total_error)

    m_r_sq, update_rsq_op = tf.metrics.mean(r_sq)

    if metrics_collections:
        ops.add_to_collections(metrics_collections, m_r_sq)

    if updates_collections:
        ops.add_to_collections(updates_collections, update_rsq_op)

    return m_r_sq, update_rsq_op
person msteininger    schedule 11.12.2017
comment
Есть идеи, как это сделать в тензорном потоке 2 без использования модулей tf.compat.v1? - person Swapnil Masurekar; 12.05.2020

Я подумал, что упомяну, что вы можете просто использовать tensorflow_addons.metrics.RQsquare(). Дополнения Tensorflow находятся на PyPi здесь, а документация — часть Tensorflow здесь. Все, что вам нужно сделать, это установить y_shape в форму вашего вывода, часто это (1,) для одной выходной переменной.

person rjurney    schedule 23.10.2020