Jed*_*edi 6 python theano keras
通常我会使用像'x = fmatrix()'这样的输入来定义一个theano函数,但是,在修改keras(基于theano的深度学习库)以使其与CTC成本一起工作时,我注意到一个非常奇怪的问题:如果一个输入成本函数的声明为
x = tensor.zeros(shape=[M,N], dtype='float32')
Run Code Online (Sandbox Code Playgroud)
代替
x = fmatrix()
Run Code Online (Sandbox Code Playgroud)
培训过程将更快地收敛.
上面的整个代码都很大.所以我尝试简化问题,如下所示:说一个计算Levenshtein编辑距离的函数
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]
Run Code Online (Sandbox Code Playgroud)
然后我定义了两个函数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)
Run Code Online (Sandbox Code Playgroud)
使用f1和f2计算时,结果不同:
>>f1([1,2,3],[1,3,3])
array(1.0)
>>f2([1,2,3],[1,3,3])
array(3.0)
Run Code Online (Sandbox Code Playgroud)
f1给出了正确的结果,但f2没有.
所以我的问题是:定义theano函数的正确方法是什么?而且,f2究竟出了什么问题?
我正在使用版本0.8.0.dev0的theano.我刚尝试了theano 0.7.0,f1和f2都给出了正确的结果.也许这是theano的错误?
根据@lamblin在这个问题上的解释(https://github.com/Theano/Theano/issues/3925#issuecomment-175088918),这实际上是theano的一个bug,并且已经修复了最新版本(1- 26-2016)版本.为方便起见,这里引用了lamblin的解释:
第一种方式是最自然的方式,但理论上两者都应该是等价的.x3和x4被创建为"alloc"操作的输出,其输入将是常量3,而不是像x1和x2这样的自由输入,但这应该无关紧要,因为您将[x3,x4]作为输入传递给theano.function,它应该在那里削减计算图.
我的猜测是扫描过早优化,认为x3或x4保证始终为常数0,并且在为它们提供值时进行一些证明不正确的简化.那将是扫描中的一个实际错误."
不幸的是,这个bug尚未完全修复.在后面部分我提到如果cost函数的一个输入被声明为tensor.zeros(),收敛过程会快得多,我找到了原因:当输入声明为tensor.zeros()时,cost函数给出了不正确的结果,虽然神秘,这有助于收敛.我在这里管理了一个简化的问题再现演示(https://github.com/daweileng/TheanoDebug),运行ctc_bench.py,你可以看到结果.
theano.tensor.zeros(...)
不能取 0 以外的任何其他值。
当然,除非您将节点添加到图中并使用 修改零张量的部分theano.tensor.set_subtensor
。
输入张量theano.tensor.fmatrix
可以采用您输入的任何值。