2017-06-26 5 views
10

DNNClassifierのTensorFlowでF1スコアをカスタムメトリックとして定義しようとしています。これを行うには、私は、関数F1スコアをcalulateするTensorFlowからstreaming_precisionstreaming_recallを使用していますテンソルのストリーミングメトリクスに基づくカスタムメトリックがNaNを返す

def metric_fn(predictions=[], labels=[], weights=[]): 
    P, _ = tf.contrib.metrics.streaming_precision(predictions, labels) 
    R, _ = tf.contrib.metrics.streaming_recall(predictions, labels) 
    if P + R == 0: 
     return 0 
    return 2*(P*R)/(P+R) 

を書きました。私は、正しい精度と再現率の値を取得しますが、しかし、

validation_metrics = { 
    "accuracy": 
     tf.contrib.learn.MetricSpec(
      metric_fn=tf.contrib.metrics.streaming_accuracy, 
      prediction_key=tf.contrib.learn.PredictionKey.CLASSES), 
    "precision": 
     tf.contrib.learn.MetricSpec(
      metric_fn=tf.contrib.metrics.streaming_precision, 
      prediction_key=tf.contrib.learn.PredictionKey.CLASSES), 
    "recall": 
     tf.contrib.learn.MetricSpec(
      metric_fn=tf.contrib.metrics.streaming_recall, 
      prediction_key=tf.contrib.learn.PredictionKey.CLASSES), 
    "f1score": 
     tf.contrib.learn.MetricSpec(
      metric_fn=metric_fn, 
      prediction_key=tf.contrib.learn.PredictionKey.CLASSES) 
} 

f1scoreは常にnanです:その後、私はvalidation_metricsに新しいエントリを作っ

INFO:tensorflow:Saving dict for global step 151: accuracy = 0.982456, accuracy/baseline_label_mean = 0.397661, accuracy/threshold_0.500000_mean = 0.982456, auc = 0.982867, f1score = nan, global_step = 151, labels/actual_label_mean = 0.397661, labels/prediction_mean = 0.406118, loss = 0.310612, precision = 0.971014, precision/positive_threshold_0.500000_mean = 0.971014, recall = 0.985294, recall/positive_threshold_0.500000_mean = 0.985294 

何かが私のmetric_fnが間違っているが、私それを理解することはできません。 metric_fnによって得られた値PおよびRは、 Tensor("precision/value:0", shape=(), dtype=float32)の形式です。私はこれがちょっと奇妙だと思う。私はスカラーテンソルを期待していた。

何か助けていただければ幸いです。

答えて

6

あなたのmetric_fnで使用しているストリーミングメトリックが更新されないという事実から問題が発生する可能性があります。どのような上記の答えは動作しませんでした提案...

私はそんなに多くを知らない場合

def metric_fn(predictions=None, labels=None, weights=None): 
    P, update_op1 = tf.contrib.metrics.streaming_precision(predictions, labels) 
    R, update_op2 = tf.contrib.metrics.streaming_recall(predictions, labels) 
    eps = 1e-5; 
    return (2*(P*R)/(P+R+eps), tf.group(update_op1, update_op2)) 
+0

を使用することができます動作します、ありがとうございました。しかし、return文の最初の部分には構文エラー( '')がありません)が少しあります。 – TheWaveLad

+0

@ TheWaveLadの世話をして、thx – user1735003

-1

は、以下の(私も私の好みに小さな修正を含む)試してみてくださいTFでカスタムメトリックがどのように機能するのですか?関数名をf1scoreのように変更するのはどうですか?

おそらく、パラメータと値が同じ名前であるために発生した競合が発生している可能性があります。

1

tf.learn.MetricSpec__init__第1引数はmetric_fnです。

ドキュメントは言う:

metric_fn:メトリックとして使用するための機能を。予測、ラベル、およびウェイトがこの関数にどのように渡されるかに関する規則については、_adapt_metric_fnを参照してください。これは、このメトリックの値として解釈される単一のTensor、またはペア(value_op、update_op)を返す必要があります.value_opは、メトリックの値を取得するための呼び出しであり、update_opは各バッチに対して実行する必要があります内部状態を更新する。

あなたmetric_fnでストリーミング操作を使用したいので、あなたは、単一のテンソルを返すことはできませんが、ストリーミング操作を更新する必要がある内部状態を持っていることを考慮しなければなりません。

このように、あなたのmetric_fnの最初の部分は次のようになります。

def metric_fn(predictions=[], labels=[], weights=[]): 
    P, update_precision = tf.contrib.metrics.streaming_precision(predictions, labels) 
    R, update_recall = tf.contrib.metrics.streaming_recall(predictions, labels) 

その後、あなたは条件があなたのpython ifステートメントを使用することはできません満たされたとき0を返したい場合(つまりはtensorflow insede計算していませんグラフ)、tf.cond(グラフ内の計算)を使用する必要があります。

また、あなたは(それ以外の場合は最初の値が定義されていないかnan)のみ後の更新操作PRの値を確認したいです。

PR更新後tf.condの評価を強制するには、あなたがtf.control_dependencies

def metric_fn(predictions=[], labels=[], weights=[]): 
    P, update_precision = tf.contrib.metrics.streaming_precision(predictions, labels) 
    R, update_recall = tf.contrib.metrics.streaming_recall(predictions, labels) 

    with tf.control_dependencies([P, update_precision, R, update_recall]): 
     score = tf.cond(tf.equal(P + R, 0.), lambda: 0, lambda: 2*(P*R)/(P+R)) 
    return score, tf.group(update_precision, update_recall) 
+0

これは既にストリーミングメトリック内で処理されているので、 'control_dependencies'は必要ありません。だから最後に私の答えに沸き立つ。 – user1735003

関連する問題