6

バックグラウンド:

通常、「x = fmatrix()」のような入力で theano 関数を定義しますが、CTC コストで動作するように keras (theano に基づく深層学習ライブラリ) を変更しているときに、非常に奇妙な問題に気付きました。のコスト関数は次のように宣言されます。

x = tensor.zeros(shape=[M,N], dtype='float32')

それ以外の

x = fmatrix()

トレーニング プロセスははるかに速く収束します。

簡単な問題:

上記のコード全体はかなり大きいです。そこで、次のように問題を単純化しようとします: レーベンシュタイン編集距離を計算する関数を

import theano
from theano import tensor
from theano.ifelse import ifelse
def editdist(s, t):
    def update(x, previous_row, target):
        current_row = previous_row + 1
        current_row = tensor.set_subtensor(current_row[1:], tensor.minimum(current_row[1:], tensor.add(previous_row[:-1], tensor.neq(target,x))))
        current_row = tensor.set_subtensor(current_row[1:], tensor.minimum(current_row[1:], current_row[0:-1] + 1))
        return current_row
    source, target = ifelse(tensor.lt(s.shape[0], t.shape[0]), (t, s), (s, t))
    previous_row = tensor.arange(target.size + 1, dtype=theano.config.floatX)
    result, updates = theano.scan(fn = update, sequences=source, outputs_info=previous_row, non_sequences=target, name='editdist')
    return result[-1,-1]

次に、2 つの関数 f1 と f2 を次のように定義します。

x1 = tensor.fvector()
x2 = tensor.fvector()
r1 = editdist(x1,x2)
f1 = theano.function([x1,x2], r1)
x3 = tensor.zeros(3, dtype='float32')
x4 = tensor.zeros(3, dtype='float32')
r2 = editdist(x3,x4)
f2 = theano.function([x3,x4], r2)

f1 と f2 で計算すると、結果は異なります。

>>f1([1,2,3],[1,3,3])
   array(1.0)

>>f2([1,2,3],[1,3,3])
   array(3.0)

f1 は正しい結果を返しますが、f2 はそうではありません。

だから私の問題は次のとおりです: theano 関数を定義する正しい方法は何ですか? そして、実際に f2 で何がうまくいかなかったのでしょうか?

アップデート:

バージョン 0.8.0.dev0 の theano を使用しています。theano 0.7.0 を試したところ、f1 と f2 の両方で正しい結果が得られました。多分これはtheanoのバグですか?

Update_1st 2016 年 1 月 27 日:

この問題に関する @lamblin の説明 ( https://github.com/Theano/Theano/issues/3925#issuecomment-175088918 ) によると、これは実際には theano のバグであり、最新 (1- 26-2016) バージョン。便宜上、ランブリンの説明をここに引用します。

最初の方法が最も自然な方法ですが、理論的にはどちらも同等のはずです。x3 と x4 は「alloc」操作の出力として作成され、その入力は x1 と x2 のような自由な入力ではなく定数 3 になりますが、[x3, x4] を入力としてtheano.function は、計算グラフをその場でカットする必要があります。

私の推測では、x3 または x4 は常に定数 0 であることが保証されていると信じて、scan の最適化が時期尚早であり、それらに値が提供されたときに正しくないことが証明されたいくつかの単純化を行います。それはスキャンの実際のバグでしょう。」

Update_2nd 2016 年 1 月 27 日:

残念ながら、バグはまだ完全には修正されていません。バックグラウンド セクションで、コスト関数の 1 つの入力が tensor.zeros() として宣言されている場合、収束プロセスがはるかに高速になると述べました。その理由を見つけました。不思議なことに、これは収束に役立ちましたが、間違った結果です。ここ ( https://github.com/daweileng/TheanoDebug ) で簡単な問題再現デモを管理し、ctc_bench.py​​ を実行すると、結果を確認できます。

4

1 に答える 1