方策勾配で強化学習を行う際に、方策が決定論的になっていないか監視するために、ログにエントロピーを出力するようにしたい。
エントロピーは、
で計算できるが、確率がほぼ0の場合、が-infになるため、この式のままでは計算できない。
の最小値をクリップして、
F.log(F.clip(p, 1e-32, 1.0))
のようにすると、-infになることを防ぐことができるが、ニューラルネットワークの出力をロジットにしている場合、よりスマートに実装できる。
ロジットを使ったエントロピーの計算
ロジットをとすると、ソフトマックスの定義から、
となる。
ここで、がオーバーフローする可能性があるため、指数部からの最大値を引いて
のように変形する。
これを使うと、Chainerでは、エントロピーの計算を以下のように実装できる。
p = F.softmax(y) #entropy = F.sum(- p * F.log(p), axis=1) y_max = F.max(y, axis=1, keepdims=True) log_p = y - (F.log(F.sum(F.exp(y - y_max), axis=1, keepdims=True)) + y_max) entropy = F.sum(- p * log_p, axis=1)
※コメントしている行のまま計算すると結果が、nanになる場合がある。
シグモイドの場合
結果がシグモイドの場合は、
となるので、とは、それぞれ、
となる。
これを使って、Chainerでは、エントロピーの計算を以下のように実装できる。
p = F.sigmoid(y) #entropy = -(p * F.log(p) + (1 - p) * F.log(1 - p)) log1p_ey = F.log1p(F.exp(y)) entropy = -(p * (y - log1p_ey) + (1 - p) * -log1p_ey)
※コメントしている行のまま計算すると結果が、nanになる場合がある。