Вы делаете кучу вещей по-разному.
Во-первых, вы используете rand
в MATLAB, который возвращает случайное значение с 0 до 1. В python вы используете randint
, который возвращает случайное целое число. Вы делаете randint(0, 1)
, что означает «случайное целое число от 0 до 1, не считая 0». Так что это всегда будет 1. Вы хотите random.random()
, которая возвращает случайный поплавок между 0 и 1.
Далее вы вычислительный down
иup
в MATLAB, но в Python вы вычислительное down
илиup
в Python. Для вашего конкретного случая вероятностей они в конечном итоге имеют одинаковый результат, но они синтаксически различны. В этом случае вы можете использовать почти идентичный синтаксис для MATLAB для 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)
для генерации случайных чисел до -front, а также проводить сопоставления вероятностей вверх, а также векторизованным образом.
Так что-то вроде этого:
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()
Edit: Для того, чтобы объяснить немного больше о втором примере, в основном то, что я делаю, заранее вычисляя ли вероятность ниже первого порогового значения или выше второго для каждый шаг впереди времени. Это намного быстрее, чем вычисление случайной выборки и сравнение на каждом этапе цикла. Затем я использую 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. Технически возможно сделать что-то похожее на то, что я сделал на этом примере Python в MATLAB, но в MATLAB для этого требуется много шаблонов, которые будут безопасными и в большинстве случаев будут очень медленными. В Python, однако, это самый быстрый и чистый подход.
Большое вам спасибо @TheBlackCat! Если вы не возражаете, не могли бы вы объяснить, что именно делает эта строка во втором фрагменте кода: «для idownp, iupp в zip (downp, upp)». Я понимаю часть zip, но мне интересно о «idown» и «iup»? – Spica
Ответ на этот вопрос - слишком много для комментария, поэтому я отредактировал свой первоначальный ответ, чтобы включить объяснение. См. Изменения. Если это еще не ясно, пожалуйста, напишите еще один комментарий, объясняющий далее, что неясно. – TheBlackCat
Большое спасибо за подробный ответ, TheBlackCat! Я вообще не знал о проблеме итерации по индексу, я узнал что-то новое и полезное, я могу использовать в других скриптах! – Spica