web-dev-qa-db-ja.com

TensorFlowに組み込みのKL発散損失関数はありますか?

prob_aprob_bの2つのテンソルがあり、形状は[None, 1000]で、prob_aからprob_bへのKLダイバージェンスを計算します。 TensorFlowにはこのための組み込み関数はありますか? tf.contrib.distributions.kl(prob_a, prob_b)を使用してみましたが、次のようになります。

NotImplementedError:dist_aタイプのTensorおよびdist_bタイプのTensorに登録されているKL(dist_a || dist_b)がありません

組み込み関数がない場合、良い回避策は何ですか?

15
Transcendental

入力テンソル_prob_a_と_prob_b_が最後の軸に沿って1になる確率テンソルであるとすると、次のようになります。

_def kl(x, y):
    X = tf.distributions.Categorical(probs=x)
    Y = tf.distributions.Categorical(probs=y)
    return tf.distributions.kl_divergence(X, Y)

result = kl(prob_a, prob_b)
_

簡単な例:

_import numpy as np
import tensorflow as tf
a = np.array([[0.25, 0.1, 0.65], [0.8, 0.15, 0.05]])
b = np.array([[0.7, 0.2, 0.1], [0.15, 0.8, 0.05]])
sess = tf.Session()
print(kl(a, b).eval(session=sess))  # [0.88995184 1.08808468]
_

あなたは同じ結果を得るでしょう

_np.sum(a * np.log(a / b), axis=1) 
_

ただし、この実装は少しバグがあります(Tensorflow 1.8.0で確認)。

aに確率がゼロの場合。 _[0.8, 0.2, 0.0]_の代わりに_[0.8, 0.15, 0.05]_を試すと、Kullback-Leiblerの定義により0 * log(0 / b)はゼロとして貢献するはずですが、nanを取得します。

これを緩和するには、いくつかの小さな数値定数を追加する必要があります。そのような状況でランタイムエラーを発生させるためにtf.distributions.kl_divergence(X, Y, allow_nan_stats=False)を使用することも賢明です。

また、bにゼロがある場合、_allow_nan_stats=False_オプションでキャッチされないinf値が取得されるため、それらも処理する必要があります。

9
meferne

Softmax_cross_entropy_with_logitsがあるため、KLで最適化する必要はありません。

KL(prob_a, prob_b)  
  = Sum(prob_a * log(prob_a/prob_b))  
  = Sum(prob_a * log(prob_a) - prob_a * log(prob_b))  
  = - Sum(prob_a * log(prob_b)) + Sum(prob_a * log(prob_a)) 
  = - Sum(prob_a * log(prob_b)) + const 
  = H(prob_a, prob_b) + const 

Prob_aがconstでない場合。 2つのエントロピーのサブに書き換えることができます。

KL(prob_a, prob_b)  
  = Sum(prob_a * log(prob_a/prob_b))  
  = Sum(prob_a * log(prob_a) - prob_a * log(prob_b))  
  = - Sum(prob_a * log(prob_b)) + Sum(prob_a * log(prob_a)) 
  = H(prob_a, prob_b) - H(prob_a, prob_a)  
7
Jiecheng Zhao

実装されていない理由はわかりませんが、回避策があるかもしれません。 KLダイバージェンスは次のように定義されます。

KL(prob_a, prob_b) = Sum(prob_a * log(prob_a/prob_b))

一方、クロスエントロピーHは次のように定義されます。

H(prob_a, prob_b) = -Sum(prob_a * log(prob_b))

したがって、変数_y = prob_a/prob_b_を作成する場合、負のH(proba_a, y)を呼び出すことにより、KLダイバージェンスを取得できます。 Tensorflow表記では、次のようになります。

KL = tf.reduce_mean(-tf.nn.softmax_cross_entropy_with_logits(prob_a, y))

5
E.J. White

tf.contrib.distributions.klTensorではなくtf.distributionのインスタンスを取ります。

例:

  ds = tf.contrib.distributions
  p = ds.Normal(loc=0., scale=1.)
  q = ds.Normal(loc=1., scale=2.)
  kl = ds.kl_divergence(p, q)
  # ==> 0.44314718
2
jvdillon

関数from this code (from this Medium post)を使用して、正規ガウス分布から任意の与えられたテンソルのKLダイバージェンスを計算しました。ここで、sdは標準偏差であり、mnはテンソルです。

latent_loss = -0.5 * tf.reduce_sum(1.0 + 2.0 * sd - tf.square(mn) - tf.exp(2.0 * sd), 1)

ロジットaおよびbへのアクセス権があると仮定します。

prob_a = tf.nn.softmax(a)
cr_aa = tf.nn.softmax_cross_entropy_with_logits(prob_a, a)
cr_ab = tf.nn.softmax_cross_entropy_with_logits(prob_a, b)
kl_ab = tf.reduce_sum(cr_ab - cr_aa)
0
Sara

私はこれがうまくいくと思います:

tf.reduce_sum(p * tf.log(p/q))

ここで、pは実際の確率分布、qはおおよその確率分布です。

0