Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于评估随机游动的python库?_Python_Multithreading_Python Multiprocessing_Random Walk - Fatal编程技术网

用于评估随机游动的python库?

用于评估随机游动的python库?,python,multithreading,python-multiprocessing,random-walk,Python,Multithreading,Python Multiprocessing,Random Walk,我试图评估随机游动结束位置的概率,但我的程序速度有点问题。基本上,我想做的是把一个包含随机游动概率的字典作为输入(例如,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,那么它将返

我试图评估随机游动结束位置的概率,但我的程序速度有点问题。基本上,我想做的是把一个包含随机游动概率的字典作为输入(例如,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>500时,是否有一个库可以计算随机游动的所有可能性?如果我找不到任何东西,我的下一步就是用C编写自己的函数作为扩展,但这将是我第一次这样做,尽管我已经用C编写了一段时间了

原始非多处理代码

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
多处理代码

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()

通常会有解析解来精确地解决这类类似于二项式分布的问题,但我假设你真的需要一个更一般的问题的计算解

与其使用python字典,不如从底层数学问题的角度来考虑这一点。建立一个矩阵,描述从一种状态到另一种状态的概率。构建一个状态
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

如果我的p dict不止是0,1,-1呢?例如,在我用来测试p dict的数据集中,它有大约50个不连续的值。这仅仅是一个迭代它们并进行a+=sp.diags(p*np.ones(m-1),q)的问题,其中p是概率,q是值?比如说,有意义吗?我修改了它,因为我做错了什么,但我只是测试了它修改了,是修改后的代码,它工作得很快!这真的很好,非常感谢!我只是好奇为什么它比我的代码快这么多?因为它们本质上做的是相同的运算,将每片叶子与所有概率相乘,然后将结果相加。是因为查字典很慢吗?因此,由于我反复做了大量的工作,性能问题的产生有几个原因——python字典是具有摊销O(1)的关联容器,乍一看,它类似于具有O(1)查找的数组。之所以会出现这种差异,是因为字典查找(在对插槽进行读/写操作时发生)需要先散列密钥,然后才能执行读或写操作,这意味着它将比使用直接addresing的容器慢。这在任何语言中都是正确的(即,数据结构不是正确的选择)。第二部分是ScPy部分地在C和C++中实现。在这种情况下,原始操作可能在C中实现,也可能不在C中实现(scipy.sparse是一个混合库,很难从外部判断发生了什么)。然而,根据过去的经验,我相信scipy开发人员已经尽可能地优化了这段代码,并且需要尽可能少的操作(无论是python还是C++)来解决我的问题。在你的问题领域信任你的核心库开发人员。最后,密集和稀疏的矩阵乘法都是有效的。除了这些技巧之外,矩阵乘法只是加法和乘法,两者都非常快,并且只需要很少的分支(即,这与数学和处理器体系结构有关)