2

1D ランダム ウォークを生成する 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)

これにより、Matlabを使用した1Dランダムウォークの下のプロットが得られます

これを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コードよりもスパイキーに見えます.

完全な段階的増加/減少 (Matlab コードと同様) を達成するために、私の Python コードには何が欠けていますか? 2 つの条件が満たされない限り同じままであることを示す「else」が必要な場合があります。どうすればそれを実装できますか?

4

1 に答える 1

1

あなたはたくさんのことを異なってやっています。

1 つは、rand0 から 1 の間のランダムな浮動小数点数を返す MATLAB で使用しています。Python ではrandint、ランダムな整数を返す を使用しています。randint(0, 1)これは、「0 を含まない 0 から 1 までのランダムな整数」を意味します。したがって、常に 1 になりますrandom.random()。0 と 1 の間のランダムな float を返す が必要です。

次に、MATLAB で計算down していますが、Python では or Python で計算しています。確率の特定のケースでは、これらは最終的に同じ結果になりますが、構文的に異なります。この場合、MATLAB for Python とほぼ同じ構文を使用できます。updown up

最後に、Python よりも MATLAB の方が多くのサンプルを計算しています (約 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()

編集: 2 番目の例についてもう少し説明すると、基本的に私が行っているのは、確率が最初のしきい値を下回っているか、2 番目を上回っているかを前もって計算することです。これは、ループの各ステップでランダムなサンプルを計算して比較を行うよりもはるかに高速です。次にzip、これらの 2 つのランダム シーケンスを 1 つのシーケンスに結合するために使用しています。各要素は、2 つのシーケンスの対​​応する要素のペアです。これは 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 ではインデックスの反復処理が一般的です。Python の例で行ったのと同様のことを MATLAB で行うことは技術的に可能ですが、MATLAB では、安全のために多くのボイラープレートが必要であり、ほとんどの場合非常に遅くなります。ただし、Python では、これが最も高速でクリーンなアプローチです。

于 2016-05-05T14:56:00.033 に答える