2017-05-23 5 views
17

私は、大きな語彙を扱うことができる階層的なsoftmaxモデル、例えば10Mクラスのオーダーを実装することに興味があります。大規模なクラスにスケーラビリティがあり、効率的になるようにするには、これを行う最善の方法は何ですか?例えば、少なくともone paperは、各ノードがクラスする2レベルのツリーを使用する場合、HSが大きなボキャブのスピードアップを〜25倍に達成できることを示しています。sqrt(N)私は、任意の枝ツリーの任意の枝分かれ係数を持つより一般的なバージョンにも興味があります。Tensorflowのスケーラブルで効率的な階層的Softmax?

私はここを参照してくださいいくつかのオプションがあります:

1)私たちはインデックスと分割を収集し、すべてのバッチのためのtf.gatherを実行しますが。これは、大規模なバッチサイズと太ったツリーで問題が発生し、係数が重複してOOMエラーにつながります。

2)#1と同様に、tf.embedding_lookupを使用するとOOMエラーの助けになりますが、すべてがCPU上に保持され、かなり遅くなります。

3)tf.map_fnparallel_iterations=1を使用して、それぞれのサンプルを別々に処理し、ギャザーを使用します。これははるかにスケーラブルですが、実際にはシリアライゼーションのために25倍のスピードアップに近づくことはありません。

HSを実装する方法はありますか?深くて狭いものと狭いものと広いものと広いものとの異なる方法がありますか?

+0

これらはタスクによって異なります。言語モデルのバッチサイズは約400で、隠れサイズは約300です。他のタスクは、imagenet分類のようにバッチサイズが小さく、隠されたサイズが大きくなる場合があります。 VRAMとRAMは問題に比べてかなり大きい(GPU RAMはそうではないが)。 –

+0

TensorflowであなたのHS実装を見てみることはできますか?私は現在それも必要です。 –

+1

少し面倒ですが、ここをクリックしてください:https://github.com/tansey/sdp/blob/87e701c9b0ff3eacab29713cb2c9e7181d5c26aa/tfsdp/models.py#L205 - 私は、pytorchや他の動的グラフフレームワークの使用をお勧めします。 –

答えて

7

あなたはGPUクラスのパフォーマンスをしたいことを言及:

が、現在CPU上のすべてを保持し、かなり

を物事を遅くし、300単位隠されたサイズを使用したいと10M単語辞書。

これは、(float32と仮定した場合)、出力レイヤのパラメータとグラデーションを保存するためには4 * 300 * 10M * 2バイト= 24 GBが必要です。

階層型Softmax(HSM)は、メモリ要件を軽減するものではなく、トレーニングをスピードアップします。

あなたにも保存する必要がありますので、現実的に、あなたは、より多くのGPUのメモリが必要になります:

  • 他のパラメータとその勾配

  • オプティマイザデータ、例えば勢いのトレーニングで速度

  • アクティベーションと逆伝播一時的なデータ

  • あなたはGPUを上のすべての計算を行いたい場合は、フレームワーク固有のためのオーバーヘッド

は、あなたがいないでしょうこのレイヤーを複数の高メモリGPUに分散することができます。

は、あなたが(合計9Mワード)クラスあたり3K言葉で3Kクラスと2レベルのHSMを、持っていると仮定してみましょう、このコンクリートを作るために:

はしかし、あなたは今、別の問題を抱えています。 3Kクラスを8つのGPUに分散し、各クラスが384のクラスをホストするようにします。

バッチ内のすべてのターゲットワードが同じ384クラスのものである場合、つまりは同じGPUに属しますか? 1つのGPUはすべての作業を行い、残りの7つはそれを待ちます。

バッチ内のターゲットワードが異なるGPUに属していても、TensorFlowでこの計算を実行する場合は、最悪の場合のシナリオと同じパフォーマンスが得られます(これはTensorFlowは、「指定-と・ラン」のフレームワークである - 計算グラフは最高のケースと最悪のケースでも同じです)

の両方にこれを行うための最善の方法は、大規模なクラス数に拡張することは何ですか効率的ですか?

上記のモデル並列性の非効率性(各GPUはバッチ全体を処理する必要があります)は、すべてを1か所に保持しようとする必要があることを示しています。

ホスト上のすべてを実装しているか、1つの巨大なGPUを実装しているとします。

  1. あなたはシーケンスをモデル化していない、またはあなたがしているが、全体のシーケンスのための唯一の出力がある場合、その後、あなたが呼ばれたパラメータを、コピーからメモリのオーバーヘッドは、メモリに比べて無視できる程度であれば上述の要件:(コピーは非効率的ではあるが)

    400 ==バッチサイズクラスの< <数== 3K

    この場合、あなたは単に

  2. または embedding_lookupを使用することができます
  3. しかし、すべてのタイムステップで出力された長さのモデルシーケンス(100など)を実行すると、パラメータのコピーが大きな問題になります。

    この場合、C++/CUDA Cにドロップダウンして、このレイヤー全体とそのグラデーションをカスタムオペレーションとして実装する必要があります。

+0

これを実装する唯一の効率的な方法は、#2で提案した標準の 'embedding_lookup'を使うことです。妥当と思われますが、実際のデータセットで説明しているGPUがどれだけ遅れているのが本当にわかりますか?また、サンプリングされたソフトマックスは、私がリンクした論文と比較され、他の多くの論文で完全に比較されています。 –

+0

また、1つのGPUですべてを処理できるのであれば?将来、私は例えば32GBのGPUを持っていると言います。 –

+0

@WesleyTansey "sampled softmaxが比較されます" - 私は今それを見る。これと他のアップデートを見てください。 – MaxB

関連する問題