我想使用以下公式将P
个元素的n
向量转换为Z
个元素的n+1
向量:
我能够使用以下命令在python中做到这一点
import numpy as np
def p_to_Z(p):
k = len(p)
Z = np.zeros(k+1)
Z[0] = p[0]
Z[1:k] = [p[i] / (1 - sum(p[range(i)])) for i in range(1,k)]
Z[-1] = 1
return Z
示例:
p_ex = np.array([0.3,0.4,0.1,0.2])
p_to_Z(p_ex)
output:
array([ 0.3, 0.57142857, 0.33333333, 1. , 1. ])
以及具有以下条件的矩阵:
M = np.array([[0.2, 0.05, 0.1],
[0.5, 2.0, 0.2],
[0.1, 0.2, 1.0]])
np.apply_along_axis(p_to_Z, 1, M)
array([[ 0.2 , 0.0625 , 0.13333333, 1.],
[ 0.5 , 4. ,-0.13333333, 1.],
[ 0.1 , 0.22222222, 1.42857143, 1.]])
我一直试图将其翻译为theano,但是我一直被scan函数所困扰。 有人可以帮我在theano中定义这些功能吗?我将永远感激不已。
编辑:尝试失败
import theano.tensor as tt
import numpy as np
import theano
from theano.compile.ops import as_op
p = tt.vector('p')
results, updates = theano.scan(lambda i: p[i] / (1 - tt.sum(p[:i-1])), sequences=tt.arange(1,N))
fn = theano.function([p,N],results)
p_ex = np.array([0.3,0.4,0.1,0.2])
Z = fn(p_ex,tt.get_vector_length(p_ex))
并带有装饰器:
@as_op(itypes=[tt.dvector],otypes=[tt.dvector])
def p_to_Z_theno(p):
N = tt.get_vector_length(p)
Z= theano.scan(lambda i: p[i] / (1 - tt.sum(p[:i - 1])), sequences=tt.arange(1, N))
fn = theano.function([p, N], results)
Z[0]=p[0]
Z[-1]=Z
return(Z)
第一个显然不会产生预期的结果,而第二个给出:
Traceback (most recent call last): File "/usr/lib/python3/dist-packages/IPython/core/interactiveshell.py", line 2882, in run_code
exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-21-211efc53b449>", line 1, in <module>
p_to_Z_theno(p_ex) File "/usr/local/lib/python3.6/dist-packages/theano/gof/op.py", line 615, in __call__
node = self.make_node(*inputs, **kwargs) File "/usr/local/lib/python3.6/dist-packages/theano/gof/op.py", line 983, in make_node
if not all(inp.type == it for inp, it in zip(inputs, self.itypes)): File "/usr/local/lib/python3.6/dist-packages/theano/gof/op.py", line 983, in <genexpr>
if not all(inp.type == it for inp, it in zip(inputs, self.itypes)): AttributeError: 'numpy.ndarray' object has no attribute 'type'
答案 0 :(得分:1)
让我们从向量化操作的角度开始思考。如果我们使用numpy的cumsum
函数,则您的初始方程式可以非常简单地写成:
def p2Z_numpy(p):
Z = np.r_[p, 1]
Z[1:-1] /= np.cumsum(p[:-1])
return Z
例如:
>>> p2Z_numpy([0.3, 0.4, 0.1, 0.2])
array([0.3 , 1.33333333, 0.14285714, 0.25 , 1. ])
之所以重要,是因为Theano可以进行所有相同种类的操作,但是规模更大。因此,让我们在Theano中进行相同的除法,串联和累加总和:
import theano.tensor as tt
import theano.tensor.extra_ops as te
from theano import function
p = tt.vector()
denom = 1 - te.cumsum(p[:-1])
frac = p[1:] / denom
Z = tt.concatentat([p[0:1], frac, [1]])
p2Z = function([p], Z)
对其进行测试:
>>> p2Z([0.3, 0.4, 0.1, 0.2])
array([0.3 , 0.57142857, 0.33333333, 1. , 1. ])
虽然我已将功能分解为多个步骤,但实际上您可以将其变成一个丑陋的单线代码:
p = tt.vector()
Z = tt.concatenate([p[0:1], p[1:] / (1 - te.cumsum(p[:-1])), [1]])
p2Z = function([p], Z)
甚至
p2Z = function([p], tt.concatenate([p[0:1], p[1:] / (1 - te.cumsum(p[:-1])), [1]]))