为什么theano.tensor.stack()使函数编译时间更快?

时间:2015-08-04 18:51:11

标签: python theano

我正在编写一个函数,它接收一系列酶和底物浓度,并返回一系列最大反应速率。

import theano.tensor as T
from theano import function

self.rateFunction = function(enzyme_vars_array + substrate_vars_array, rateExpressionsArray, on_unused_input='ignore')

enzyme_vars_array和substrate_vars数组是使用T.dscalar('name_of_thing')构建的传感器列表。

rateExpressionsArray是一个python表达式列表,它根据theano张量给出了反应的动力学速率。 enzyme_vars_array和substrate_vars数组。因为可能没有使用某些酶和底物浓度,所以我已经包含了on_unused_input ='ignore'标志。

这些输入的大小为:

len(enzyme_vars_array)= 132

len(substrate_vars array)= 17

len(rateExpressionsArray)= 2402

运行这行代码会导致编译时间过长,至少5分钟(我最终放弃了等待)。

然而,这一次更改将编译时间缩短到几秒钟:

self.rateFunction = function(enzyme_vars_array + substrate_vars_array, T.stack(rateExpressionsArray), on_unused_input='ignore')

什么是theano.tensor.stack()正在做什么导致编译时间的这种巨大变化?原来的配方怎么这么慢?

修改

在编写可以运行的示例代码时,这个问题变得更加奇怪。此代码生成enzyme_vars_array,substrate_ars_array和rateExpressionArray的示例:

import theano.tensor as T
from theano import function
import numpy as np


enzyme_names = ['e1','e2','e3','e4','e5','e6','e7','e8','e9','e10','e11','e12','e13','e14','e15','e16','e17','e18','e19','e20', '21','e22','e23','e24','e25','e26','e27','e28','e29','e30','e31','e32','e33','e34','e35','e36','e37','e38','e39','e40','e41','e42','e43','e44','e45','e46','e47','e48','e49','e50','e61','e62','e63','e64','e65','e66','e67','e68','e69','e70','e71','e72','e73','e74','e75','e76','e77','e78','e79','e80','e81','e82','e83','e84','e85','e86','e87','e88','e89','e90','e91','e92','e93','e94','e95','e96','e97','e98','e99','e100','e101','e102','e103','e104','e105','e106','e107','e108','e109','e110','e111','e112','e113','e114','e115','e116','e117','e118','e119','e120','e121','e122','e123','e124','e125','e126','e127','e128','e129','e130','e131','e132']

substrate_names = ['s1','s2','s3','s4','s5','s6','s7','s8','s9','s10','s11','s12','s13','s14','s15','s16','s17']

enzyme_vars_array = T.dscalars(*enzyme_names)

substrate_vars_array = T.dscalars(*substrate_names)


rateExpressionsArray = [0]*2292

# Populate rateExpressionsArray with random expressions in terms of the theano variables
for index, rateExpression in enumerate(rateExpressionsArray):
    random_enzyme_index = np.random.randint(len(enzyme_vars_array))
    random_substrate_index = np.random.randint(len(substrate_vars_array))

    rateExpressionsArray[index] = enzyme_vars_array[random_enzyme_index] * substrate_vars_array[random_substrate_index]


rateFunction = function(enzyme_vars_array + substrate_vars_array, rateExpressionsArray, on_unused_input='ignore')

这是我期望运行缓慢的代码(因为它在没有T.stack的情况下运行)。然而,在这个例子中,它现在以完全合理的速度运行。当我用这个替换最后一行时:

rateFunction = function(enzyme_vars_array + substrate_vars_array, T.stack(rateExpressionsArray), on_unused_input='ignore')

它再次运行得非常慢,与我在实际代码中观察到的行为相反!

我认为这个例子和我的实际代码之间可能存在差异,并且意识到我的真​​实的rateExpressionsArray非常稀疏,它主要由占位符组成,它只返回一个默认值,只有几个真实表达式。所以重写我的示例代码看起来更像这样,我有:

import theano.tensor as T
from theano import function
import numpy as np


enzyme_names = ['e1','e2','e3','e4','e5','e6','e7','e8','e9','e10','e11','e12','e13','e14','e15','e16','e17','e18','e19','e20', '21','e22','e23','e24','e25','e26','e27','e28','e29','e30','e31','e32','e33','e34','e35','e36','e37','e38','e39','e40','e41','e42','e43','e44','e45','e46','e47','e48','e49','e50','e61','e62','e63','e64','e65','e66','e67','e68','e69','e70','e71','e72','e73','e74','e75','e76','e77','e78','e79','e80','e81','e82','e83','e84','e85','e86','e87','e88','e89','e90','e91','e92','e93','e94','e95','e96','e97','e98','e99','e100','e101','e102','e103','e104','e105','e106','e107','e108','e109','e110','e111','e112','e113','e114','e115','e116','e117','e118','e119','e120','e121','e122','e123','e124','e125','e126','e127','e128','e129','e130','e131','e132']

substrate_names = ['s1','s2','s3','s4','s5','s6','s7','s8','s9','s10','s11','s12','s13','s14','s15','s16','s17']

enzyme_vars_array = T.dscalars(*enzyme_names)

substrate_vars_array = T.dscalars(*substrate_names)


# This is the placeholder expression which returns an input unmodified
noRate = T.dscalar('noRate')
rateExpressionsArray = [noRate]*2292

# Include only a handful of nontrivial expressions
for index in xrange(1,50):
    random_enzyme_index = np.random.randint(len(enzyme_vars_array))
    random_substrate_index = np.random.randint(len(substrate_vars_array))
    rateExpressionsArray[index] = enzyme_vars_array[random_enzyme_index] * substrate_vars_array[random_substrate_index]


rateFunction = function(enzyme_vars_array + substrate_vars_array + [noRate], T.stack(rateExpressionsArray), on_unused_input='ignore')

这会产生原始行为 - 当rateExpressionArray中只有少数几个索引是非平凡的表达式时,代码会快速运行T.stack()并且在没有T.stack()的情况下运行缓慢。要复制慢速版本,请将最后一行替换为:

rateFunction = function(enzyme_vars_array + substrate_vars_array + [noRate], rateExpressionsArray, on_unused_input='ignore')

所以似乎T.stack在稀疏输入和密集输入上产生不同的行为?我现在对stack()的功能和机制更加困惑。任何有关这里发生的事情的见解都将非常感激!

0 个答案:

没有答案