2

我有一个生成一维随机游走的 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”来告诉它保持不变,除非满足这两个条件。我该如何实施?

4

1 回答 1

1

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

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

接下来,您在 MATLAB 中进行计算down up但在 Python 中您正在计算down up在 Python 中。对于您的特定概率情况,这些最终会产生相同的结果,但它们在语法上是不同的。在这种情况下,您可以使用与 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 中,它是最快和最干净的方法。

于 2016-05-05T14:56:00.033 回答