我试图评估随机游走的最终位置的概率,但我的程序速度有些问题。基本上我想要做的是将包含随机游走概率的字典作为输入(例如p = {0:0.5,1:0.2。-1:0.3}意味着那里有50个%概率X保持在0,20%概率X增加1,30%概率X减少1),然后计算n次迭代后所有可能的未来状态的概率。
例如,如果p = {0:0.5,1:0.2。 -1:0.3}和n = 2然后它将返回{0:0.37,1:0.2,-1:0.3,2:0.04,-2:0.09} 如果p = {0:0.5,1:0.2。 -1:0.3}和n = 1然后它将返回{0:0.5,1:0.2。 -1:0.3}
我有工作代码,如果n很低并且如果p字典很小,那么它运行得相对较快,但当n> 500和字典有大约50个值,它需要花费5分钟来计算。我猜这是因为它仅在一个处理器上执行,所以我继续修改它以便使用python的多处理模块(因为我读到多线程并不能提高并行计算性能,因为GIL)。
我的问题是,多处理没有太大的改进,现在我不确定它是不是因为我实现它错误或者因为python中的多处理开销。我只是想知道在某个地方是否存在一个库来评估随机行走的所有可能性的所有概率当n> 1时。 500并行?如果我找不到任何东西,我的下一步就是将自己的功能编写为C语言中的扩展名,但这是我第一次这样做,虽然我已经用C语言编码了。 / p>
原始非多重处理代码
def random_walk_predictor(probabilities_tree, period):
ret = probabilities_tree
probabilities_leaves = ret.copy()
for x in range(period):
tmp = {}
for leaf in ret.keys():
for tree_leaf in probabilities_leaves.keys():
try:
tmp[leaf + tree_leaf] = (ret[leaf] * probabilities_leaves[tree_leaf]) + tmp[leaf + tree_leaf]
except:
tmp[leaf + tree_leaf] = ret[leaf] * probabilities_leaves[tree_leaf]
ret = tmp
return ret
MultiProcessed代码
from multiprocessing import Manager,Pool
from functools import partial
def probability_calculator(origin, probability, outp, reference):
for leaf in probability.keys():
try:
outp[origin + leaf] = outp[origin + leaf] + (reference[origin] * probability[leaf])
except KeyError:
outp[origin + leaf] = reference[origin] * probability[leaf]
def random_walk_predictor(probabilities_leaves, period):
probabilities_leaves = tree_developer(probabilities_leaves)
manager = Manager()
prob_leaves = manager.dict(probabilities_leaves)
ret = manager.dict({0:1})
p = Pool()
for x in range(period):
out = manager.dict()
partial_probability_calculator = partial(probability_calculator, probability = prob_leaves, outp = out, reference = ret.copy())
p.map(partial_probability_calculator, ret.keys())
ret = out
return ret.copy()
答案 0 :(得分:2)
倾向于使用分析解决方案来准确地解决这种看起来类似于二项分布的problem,但我会假设你真的要求为更通用的类提供计算解决方案问题。
不是使用python词典,而是根据潜在的数学问题更容易思考。构建一个矩阵A
,描述从一个州到另一个州的概率。构建状态x
,描述在某个时间位于给定位置的概率。
因为在n
转换之后,您可以从原点(向任一方向)最多步进n
步 - 您的状态需要有2n + 1行,并且A
需要正方形,大小为2n + 1乘2n + 1。
对于两个时间步问题,您的转换矩阵将为5x5,如下所示:
[[ 0.5 0.2 0. 0. 0. ]
[ 0.3 0.5 0.2 0. 0. ]
[ 0. 0.3 0.5 0.2 0. ]
[ 0. 0. 0.3 0.5 0.2]
[ 0. 0. 0. 0.3 0.5]]
你在0时的状态将是:
[[ 0.]
[ 0.]
[ 1.]
[ 0.]
[ 0.]]
系统的一步演变可以通过乘以A
和x
来预测。
所以t = 1,
x.T = [[ 0. 0.2 0.5 0.3 0. ]]
并且在t = 2,
x.T = [[ 0.04 0.2 0.37 0.3 0.09]]
因为即使是适度的时间步长,这可能需要相当多的存储空间(A
需要n ^ 2存储空间),但是非常稀疏,我们可以使用稀疏矩阵来减少存储空间(以及加快我们的计算速度)。这样做意味着A
需要大约3n个元素。
import scipy.sparse as sp
import numpy as np
def random_walk_transition_probability(n, left = 0.3, centre = 0.5, right = 0.2):
m = 2*n+1
A = sp.csr_matrix((m, m))
A += sp.diags(centre*np.ones(m), 0)
A += sp.diags(left*np.ones(m-1), -1)
A += sp.diags(right*np.ones(m-1), 1)
x = np.zeros((m,1))
x[n] = 1.0
for i in xrange(n):
x = A.dot(x)
return x
print random_walk_transition_probability(4)
<强>计时强>
%timeit random_walk_transition_probability(500)
100 loops, best of 3: 7.12 ms per loop
%timeit random_walk_transition_probability(10000)
1 loops, best of 3: 1.06 s per loop