【问题标题】:1D Random Walk from Matlab to Python从 Matlab 到 Python 的一维随机游走
【发布时间】:2016-05-05 13:37:57
【问题描述】:

我有一个生成一维随机游走的 Matlab 代码。

%% probability to move up or down
prob = [0.05, 0.95];

start = 2;  %% start with 2
positions(1) = start; 

for i=2:1000 
    rr = rand(1); 
    down = rr<prob(1) & positions(i-1)>1;  
    up = rr>prob(2) & positions(i-1)<4;  
    positions(i) = positions(i-1)-down + up; 
figure(1), clf
plot(positions)

这给了我下面的情节1D Random Walk with Matlab

我需要尝试用 Python 翻译这个,我想出了这个(使用 numpy):

import random
import numpy as np
import matplotlib.pyplot as plt

prob = [0.05, 0.95]  ##probability to move up or down
N = 100 ##length of walk

def randomWalk(N):
    positions=np.zeros(N)
    start = 2 ##Start at 2
    positions[0] = start
    for i in range(1,100):
        rr = random.randint(0,1)

        if rr<prob[0] and positions[i-1]>1: 
            start -= 1
        elif rr>prob[1] and positions[i-1]<4:
            start += 1
        positions[i] = start
    return positions

plt.plot(randomWalk(N))
plt.show()

看起来和我想要的很接近(见下图):1D Random Walk with Python

但我想知道它们是否真的等价,因为它们看起来确实不同:Python 代码似乎比 Matlab 代码更尖。

我的 Python 代码中缺少什么来实现完美的逐步增加/减少(类似于 Matlab 代码)?也许它需要一个“else”来告诉它保持不变,除非满足这两个条件。我该如何实现?

【问题讨论】:

    标签: python matlab code-conversion random-walk


    【解决方案1】:

    你正在做很多不同的事情。

    首先,您在 MATLAB 中使用 rand,它返回一个介于 0 和 1 之间的随机浮点数。在 python 中,您使用的是 randint,它返回一个随机整数。你在做randint(0, 1),意思是“一个从0到1的随机整数,不包括0”。所以它永远是 1。你想要random.random(),它返回一个介于 0 和 1 之间的随机浮点数。

    接下来,您将在 MATLAB 中计算 down up,但在 Python 中,您将在 Python 中计算 down up。对于您的特定概率情况,这些最终会产生相同的结果,但它们在语法上是不同的。在这种情况下,您可以使用与 MATLAB for Python 几乎相同的语法。

    最后,您为 MATLAB 计算的样本比 Python 多得多(大约多 10 倍)。

    这是您的 MATLAB 代码到 Python 的直接端口。对我来说,结果与您的 MATLAB 示例几乎相同(当然,随机数不同):

    import random
    import matplotlib.pyplot as plt
    
    prob = [0.05, 0.95]  # Probability to move up or down
    
    start = 2  #Start at 2
    positions = [start]
    
    for _ in range(1, 1000):
        rr = random.random()
        down = rr < prob[0] and positions[-1] > 1
        up = rr > prob[1] and positions[-1] < 4
        positions.append(positions[-1] - down + up)
    
    plt.plot(positions)
    plt.show()
    

    如果速度是一个问题,您可能可以通过使用 np.random.random(1000) 预先生成随机数并以矢量化方式预先进行概率比较来加快速度。

    所以是这样的:

    import random
    import numpy as np
    import matplotlib.pyplot as plt
    
    prob = [0.05, 0.95]  # Probability to move up or down
    
    start = 2  #Start at 2
    positions = [start]
    
    rr = np.random.random(1000)
    downp = rr < prob[0]
    upp = rr > prob[1]
    
    for idownp, iupp in zip(downp, upp):
        down = idownp and positions[-1] > 1
        up = iupp and positions[-1] < 4
        positions.append(positions[-1] - down + up)
    
    plt.plot(positions)
    plt.show()
    

    编辑:为了更多地解释第二个示例,基本上我正在做的是预先计算每个步骤的概率是低于第一个阈值还是高于第二个阈值。这比计算随机样本并在循环的每一步进行比较要快得多。然后我使用zip 将这两个随机序列组合成一个序列,其中每个元素是两个序列中的一对对应元素。这是假设 python 3,如果你使用 python 2,你应该使用 itertools.izip 而不是 zip

    所以大致相当于这样:

    import random
    import numpy as np
    import matplotlib.pyplot as plt
    
    prob = [0.05, 0.95]  # Probability to move up or down
    
    start = 2  #Start at 2
    positions = [start]
    
    rr = np.random.random(1000)
    downp = rr < prob[0]
    upp = rr > prob[1]
    
    for i in range(len(rr)):
        idownp = downp[i]
        iupp = upp[i]
        down = idownp and positions[-1] > 1
        up = iupp and positions[-1] < 4
        positions.append(positions[-1] - down + up)
    
    plt.plot(positions)
    plt.show()
    

    在 python 中,通常更喜欢迭代值,而不是索引。几乎从来没有需要迭代索引的情况。如果您发现自己在做类似for i in range(len(foo)): 或类似的事情,那么您几乎可以肯定做错了什么。您应该直接遍历foo,或者如果您需要其他东西的索引,您可以使用for i, ifoo in enumerate(foo): 之类的东西,它可以获取 foo 的元素及其索引。

    由于 MATLAB 语言的各种限制,迭代索引在 MATLAB 中很常见。从技术上讲,我可以在 MATLAB 中做类似于我在那个 Python 示例中所做的事情,但是在 MATLAB 中,它需要大量的样板文件才能安全,并且在大多数情况下会非常慢。然而,在 Python 中,它是最快、最简洁的方法。

    【讨论】:

    • 非常感谢@TheBlackCat!如果您不介意,您能否解释一下第二段代码中的这一行到底是做什么的:“for idownp, iupp in zip(downp, upp)”。我了解 zip 部分,但我想知道“idown”和“iup”?
    • 这个问题的答案是一个但太多的评论,所以我编辑了我的原始答案以包含解释。请查看编辑。如果仍然不清楚,请发表另一条评论,进一步解释不清楚的地方。
    • 非常感谢您的详细回答,TheBlackCat!我完全不知道迭代索引的问题,我学到了一些新的有用的东西,我可以在我的其他脚本中使用!
    • 感谢@TheBlackCat 提供此答案。如果您不介意回答,我有一个问题。您使用 1 和 4 作为 down = idownp 和 position[-1] > up = iupp 和 position[-1]
    猜你喜欢
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    相关资源
    最近更新 更多