从Matlab到Python的1D随机游走

时间:2016-05-05 13:37:58

标签: python matlab code-conversion random-walk

我有一个生成一维随机游走的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代码)?也许它需要一个“其他”来告诉它保持不变,除非满足这两个条件。我该如何实现?

1 个答案:

答案 0 :(得分:1)

你正在做一些不同的事情。

首先,您在MATLAB中使用rand,它返回0到1之间的随机浮点数。在python中,您使用的是randint,它返回一个随机整数。你正在做randint(0, 1),这意味着&#34;一个从0到1的随机整数,不包括0和#34;。所以它总是1.你想要random.random(),它返回0到1之间的随机浮点数。

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

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

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

up

如果速度是一个问题,你可以通过使用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() 将这两个随机序列组合成一个序列,其中每个元素是来自两个序列的一对相应元素。这是假设python 3,如果你使用python 2,你应该使用zip而不是itertools.izip

所以它大致相当于:

zip

在python中,通常首选迭代值而不是索引。几乎从来没有需要迭代索引的情况。如果你发现自己在做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() 之类的东西,或类似的东西,你几乎肯定做错了什么。你应该直接迭代for i in range(len(foo)):,或者如果你需要其他东西的索引,你可以使用类似foo的东西,它可以获得foo及其索引的元素。

由于MATLAB语言存在各种限制,迭代索引在MATLAB中很常见。在技​​术上可以做类似于我在MATLAB中的Python示例中所做的事情,但是在MATLAB中它需要很多样板才能安全并且在大多数情况下会非常慢。但是,在Python中,它是最快速,最干净的方法。