web-dev-qa-db-ja.com

テンソルフローでRNNのパープレキシティを計算する方法

Word RNN のテンソルフローのWordRNN実装を実行しています

RNNのパープレキシティを計算する方法。

以下は、各エポックでのトレーニングの損失やその他のことを示すトレーニングのコードです。

for e in range(model.Epoch_pointer.eval(), args.num_epochs):
        sess.run(tf.assign(model.lr, args.learning_rate * (args.decay_rate ** e)))
        data_loader.reset_batch_pointer()
        state = sess.run(model.initial_state)
        speed = 0
        if args.init_from is None:
            assign_op = model.batch_pointer.assign(0)
            sess.run(assign_op)
            assign_op = model.Epoch_pointer.assign(e)
            sess.run(assign_op)
        if args.init_from is not None:
            data_loader.pointer = model.batch_pointer.eval()
            args.init_from = None
        for b in range(data_loader.pointer, data_loader.num_batches):
            start = time.time()
            x, y = data_loader.next_batch()
            feed = {model.input_data: x, model.targets: y, model.initial_state: state,
                    model.batch_time: speed}
            summary, train_loss, state, _, _ = sess.run([merged, model.cost, model.final_state,
                                                         model.train_op, model.inc_batch_pointer_op], feed)
            train_writer.add_summary(summary, e * data_loader.num_batches + b)
            speed = time.time() - start
            if (e * data_loader.num_batches + b) % args.batch_size == 0:
                print("{}/{} (Epoch {}), train_loss = {:.3f}, time/batch = {:.3f}" \
                    .format(e * data_loader.num_batches + b,
                            args.num_epochs * data_loader.num_batches,
                            e, train_loss, speed))
            if (e * data_loader.num_batches + b) % args.save_every == 0 \
                    or (e==args.num_epochs-1 and b == data_loader.num_batches-1): # save for the last result
                checkpoint_path = os.path.join(args.save_dir, 'model.ckpt')
                saver.save(sess, checkpoint_path, global_step = e * data_loader.num_batches + b)
                print("model saved to {}".format(checkpoint_path))
    train_writer.close()
9
Shan Khan

参照しているプロジェクトはsequence_to_sequence_loss_by_exampleを使用します。これは、クロスエントロピー損失を返します。したがって、トレーニングの困惑を計算するには、説明したように損失を指数化する必要があります ここ

train_perplexity = tf.exp(train_loss)

TensorFlowは自然対数( TF Documentation )を使用してクロスエントロピー損失を測定するため、2ではなくeをベースとして使用する必要があります。ヒントをありがとう、@ MatthiasArroと@ColinSkow。

詳細な説明

2つの確率分布PとQのクロスエントロピーは、Qに基づくコーディングスキームを開発するときに、Pのイベントをエンコードするために必要な最小平均ビット数を示します。したがって、Pは真の分布であり、通常はそうではありません。わからない。できるだけPに近いQを見つけて、イベントあたりのビット数をできるだけ少なくして、Niceコーディングスキームを開発できるようにします。

クロスエントロピーの計算に2進数を使用する場合にのみ、ビットをメジャーとして使用できるため、ビットとは言えません。ただし、TensorFlowは自然対数を使用するため、代わりにnatsのクロスエントロピーを測定しましょう。

したがって、語彙内のすべてのトークン(文字/単語)が次のトークンである可能性が同じであるという悪い言語モデルがあるとしましょう。 1000トークンの語彙の場合、このモデルのクロスエントロピーはlog(1000)= 6.9 natsになります。次のトークンを予測するときは、各ステップで1000個のトークンから均一に選択する必要があります。

より良い言語モデルは、Pに近い確率分布Qを決定します。したがって、クロスエントロピーは低くなります。つまり、3.9natsのクロスエントロピーが得られる可能性があります。ここで、パープレキシティを測定する場合は、クロスエントロピーを単純に指数化します。

exp(3.9)= 49.4

したがって、損失を計算したサンプルでは、​​約50のトークンから均一かつ独立して選択する必要があるかのように、優れたモデルは複雑でした。

12
Kilian Batzner

損失関数が基数2または基数eのデータの対数尤度を与えるかどうかによって異なります。このモデルはlegacy_seq2seq.sequence_loss_by_exampleを使用しています。これは、TensorFlowのバイナリクロスエントロピーを使用します。これは ベースeのログを使用しているように見えます 。したがって、離散確率分布(テキスト)を扱っている場合でも、eで指数化する必要があります。つまり、Colin Skowが提案したようにtf.exp(train_loss)を使用する必要があります。

0
Mattias Arro