Embedの速度比較

単語埋め込みとかで使う、onehotとlook-up tabelの内積計算を比較する。

埋め込み操作(embedding)の式は以下のとおり。

 \boldsymbol{v} = \boldsymbol{x}\boldsymbol{W}

xは[0,1,0,0,0]って感じのonehotベクトル。欲しいインデックスにビットが立ってて、Wと内積とると欲しいベクトルが引き抜かれる感じ。

これをコードに落とす時、くそまじめにインデックスからonehot作って内積とると重すぎてダメになるので、戒めも兼ねて速度比較を行った。
以下のようなコードを用いる。

Embeddingの操作として、

1. Listを使って目当てのベクトルを引き抜く
2. 内積で引き抜く(式通り)
3. chainerのようなライブラリを使う(中身は知らない)

の三つが考えられるので、それぞれlook-up tableを用意する時間、1万回ベクトルを引き抜く操作を繰り返した時の時間を測る。

ただし、2ではindexをonehotに直す操作、3ではnumpyに包む操作が入って不公平(?)なのでそこは計測しない。
chainerのembedに関しては、中でさらに何かやってるんだろうけど、それは考えないことにする。

3回実行した結果

まあそんなもんか、という感想。
chainerはVariableで一気にbackwardできる利便性のぶん、処理速度が犠牲になってる感じ。
深いニューラルならchainerの恩恵を甘受するべきだと思う。

浅いニューラルをスクラッチで書くなら、Listを使って引き抜いた方が速い。
更新する時どうなるかまでは測ってない。
もしかしたら学習のイテレーション全体で見たらchainerが圧勝するのかもしれない。

でもまあ、更新する時もインデックス指定して微分値足すだけなのでリストが爆速なんだと思う。

 

もしもっと効率的な書き方知ってる方いたら教えてください。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です