初心者
備忘録
Keras

Keresメモ:Kerasにperplexityがなかったので書いてみる

動機

初めはTensorflowでseq2seqをやろうとしていて、サンプルコードを見ながら学習し、近頃Kerasに移行してみました。backendはそのままTenforflowです。

Tensorflowのチュートリアルで提供されているサンプルコードでは、perplexityという指標が学習中にログとして表示されるようになっていて、これがモデルの性能を評価する上での一つの指標となっています。

これをKerasでも利用しようと思ったのですが、KerasのMetricsにはperplexityがなかったので自分で書いてみました。

正確には、自分で書いた後おかしなエラーが出たので他にやっている人がいないか調べたら、すでに議論している方々がいたので、素直にその方々の話の流れに乗っかりました。
(ちなみに上記エラーは、perplexityとは全く関係ありませんでした。)

perplexityとは

perplexityを自ら説明する自信はないので、勉強の際にお世話になったページをリンクで貼っておきます。

トピックモデルの評価指標 Perplexity とは何なのか? - SlideShare

seq2seqにおいては、encoderから出力された固定長ベクトルとdecoder自身の過去の出力をもとに、decoderが次の単語を予測していきます。

簡単に言うと、「次の単語は○○である」の予測確率が0.01だとしたら、それは同程度の確からしさを持った100単語の中から1単語を選ぶ、と捉えることができます。

Tensorflowのサンプル:translate.pyには、218行目にさらっと登場しています。
1バッチ1ステップとして、100ステップ学習した後にバッチ毎のlossの平均を取り、

perplexity = \mathrm{e}^{loss}

としています。
このperplexity、2のloss乗となっている場合もあるのですが、どのような差なのでしょう。lossを計算するときにlogの底を何にしたかで変わる、という認識で良いのでしょうか。

実装

https://github.com/fchollet/keras/issues/2317

Kerasでperplexityを使いたい人たちが、ここで議論をしていました。
私もたまたま同じようなエラーが出たので投稿してみたのですが、後日全く関係ないミスから生じたものだとわかり、自分で訂正するという醜態をさらしています。

from keras.losses import categorical_crossentropy
from keras import backend as K
import math

def ppx(y_true, y_pred):
     loss = categorical_crossentropy(y_true, y_pred)
     perplexity = K.cast(K.pow(math.e, K.mean(loss, axis=-1)), K.floatx())
     return perplexity

Tensorflowでは先述の式の通りネーピア数を使っていましたし、KerasはTensorflowをbackendにしているので、そのままネーピア数を用いています。

型をfloatxにキャストしたり、などというのはKerasに始めから用意されているlossやmetricsがやっている事を真似しています。

次にやりたいこと

語彙すべてを対象にしてsoftmaxをやっていては遅すぎるので、Tensorflowのチュートリアルでも紹介されているsampled softmaxをやりたい。