動機
初めは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の底を何にしたかで変わる、という認識で良いのでしょうか。
実装
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をやりたい。