Как можно сопоставить векторизованную функцию с массивом numpy без использования цикла for? - PullRequest
0 голосов
/ 14 октября 2018

Итак, вот что у меня уже есть:

import numpy as np
import matplotlib.pyplot as plt

def monteCarloPi(n):
    np.random.seed()                 #seed the random number generator
    y = np.random.rand(n)*2 - 1      #n random samples on (-1,1)
    x = np.linspace(-1,1,n)          #x axis to plot against

    square = np.array([x,y])         #collecting axes as a single object

    mask1 = ((x**2 + y**2) < 1)      #filters

    hits = np.sum(mask1)             #calculating approximation
    ratio = hits/n
    pi_approx = ratio * 4

    return pi_approx

Вот что я бы хотел бы сделать:

x = np.arange(100,1000)
y = monteCarloPi(x)
plt.scatter(x,y)

Однако, когда я запускаю вышеБлок кода, я получаю следующую ошибку:

---------------------------------------------------------------------
TypeError                           Traceback (most recent call last)
<ipython-input-52-bf4dcedaa309> in <module>()
      1 x = np.arange(100,1000)
----> 2 y = monteCarloPi(x)
      3 plt.scatter(x,y)

    <ipython-input-51-8d5b36e22d4b> in monteCarloPi(n)
      1 def monteCarloPi(n):
      2     np.random.seed()                 #seed the random number generator
----> 3     y = np.random.rand(n)*2 - 1      #n random samples on (-1,1)
      4     x = np.linspace(-1,1,n)          #x axis to plot against
      5 

mtrand.pyx in mtrand.RandomState.rand()

mtrand.pyx in mtrand.RandomState.random_sample()

mtrand.pyx in mtrand.cont0_array()

TypeError: only integer scalar arrays can be converted to a scalar index

Исходя из моего понимания того, как вещание работает в numpy, это должно работать.Я мог бы просто использовать цикл for, но он очень быстро становится очень медленным по мере увеличения количества сэмплов.

halp

1 Ответ

0 голосов
/ 19 февраля 2019

Вот один из вариантов, в котором основан максимальный размер выборки, тогда выполняется субсэмплинг, если start>0 (обработка ошибок не включена).

import numpy as np
import matplotlib.pyplot as plt

def monteCarloPi(n,start=0,stride=1):
    np.random.seed()                 # seed the random number generator
    y = np.random.rand(n)*2 - 1      # n random samples on (-1,1)
    x = np.linspace(-1,1,n)          # x axis to plot against
    mask = ( x**2 + y**2 ) < 1       # masking
    samples = {}
    inds = arange(n)
    for k in range(n-start,n+1,stride):
        sub_inds = np.random.choice(inds,k,replace=False)
        sub_mask = mask[sub_inds]
        sub_hits = np.sum(sub_mask)
        ratio    = sub_hits/n
        pi_approx = ratio * 4
        samples[k]=pi_approx
    return pi_approx

Для этого все еще требуется цикл for, но он обрабатывается внутри метода быстро, так как вы выполняете выборку из одной большой случайной выборки.Чтобы восстановить исходный вызов (от n=100 до n=1000 [обратите внимание, что здесь я набираю n=1000]):

estimates = monteCarloPi(1000,start=900)
plt.plot(estimates.keys(),estimates.values())

Конечно, вы можете передать исходный x=arange(100,1001),но тогда в методе потребуется проверка ошибок (чтобы убедиться, что массив или список был передан), а затем n будет равен последнему элементу x (n=x[-1]), и, наконец,зацикливание будет выполнено над элементами x (for k in x:).

...