Optimize np.random.normal - отрисовка случайных величин - PullRequest
0 голосов
/ 17 марта 2019

Я пишу программу, которая может оценить вариант корзины. Обобщая ключ к решению моей проблемы, я рисую много случайных величин ~ 70'000'000 и выполняю с ними определенные вычисления. Прямо сейчас я рисую случайные выборки в матрице с размерностью (10,100000)и повторяя шаг около 700, чтобы получить достойное приближение.Общее время вычислений: 99 секунд.

После профилирования моего кода с помощью cProfile я понял, что 51% моего вычислительного времени тратится на рисование этих случайных выборок ,что я и сделал, используя np.random.normal [d = 10, N = 100000].

def getZ(h_n):
    # Get A Matrix (d,N) consisting of Gaussian N(0,h_n) Variables
    return np.random.normal(0, h_n, (d, N))

Поэтому мой вопрос касается вопроса, существует ли более эффективный способ рисования моих случайных выборок.

Большое спасибо за вашу помощь:)


Приложение (код, который я использую + общий cProfile, может быть полезен длячитатель интереса):

Код без предварительных определений:

"""Implementation of Approximation"""

"Construct Covariance Matrix and Decomposition"
# Create Matrix Eta which is the matrix of Covariances
Eta   = np.eye(d) + rho * (np.ones(d) - np.eye(d))
# Use the Cholesky Decomposition to derive L, which has the value that Eta = L*L'
L     = np.linalg.cholesky(Eta)

"Construct price Processes"
# Generate Delta_W trough sqrt(T)*L*Z with Z~N(0,1), Delta_W is a matrix of dim = (d,N)
# For the generation of Z define getZ
def getZ(h_n):
    # Get A Matrix (d,N) consisting of Gaussian N(0,h_n) Variables
    return np.random.normal(0, h_n, (d, N)) # np.random.normal(loc = 0.0, scale = np.sqrt(delta_t))

"Construct EM Method"
# d relates to the dimension of the problem, therefore, is the no. of assets in the market
Y    = S_0*np.ones([d, N]) # initialisiere Y0! und dann überschreibe Y ständig
for i in range(0, (T+1) * n):
    # Y = Y + np.diag(mu) @ Y * dt + np.multiply(np.diag(sigma) @ Y, L @ getZ(dt))
    Y = Y + mu[:, None] * Y * dt + np.multiply(sigma[:, None] * Y, L @ getZ(dt))
    if i % 100 == 0:
        print('Progress: ' + str(i) + '/' + str((T+1)*n) + ' of all EM steps, while ' + str(np.round((time.time() - start_time), 2)) + ' secs passed.' )

"Construct Payoff"
Payoff = np.matmul(alpha, Y)-K
Payoff = np.sum(Payoff[(Payoff > 0)])/N  # other entries would be 0 anyway, therefore its okay to use Payoff[(Payoff>0)]
V = np.exp(-r*T)*Payoff  # Discount Payoff to get the fair price of the Option


"Output"
print('\nIn a market consisting of ' + str(d) + ' stocks, \nwe evaluated a classical basket option, \nusing ' + str(N) + ' MC samples.')
print('The true price of the Option is ' + str(round(V, 5)) + '\nusing the Euler Maruyama Method with ' + str((T+1) * n) + ' steps for approximation')

print("--- %s seconds ---" % np.round((time.time() - start_time), 2))

cПрофиль:

1708 function calls in 46.562 seconds

   Ordered by: standard name



ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      784    0.004    0.000   46.555    0.059 Monte_Carlo_EM.py:45(getZ)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:1966(sum)
        9    0.000    0.000    0.001    0.000 fromnumeric.py:2940(around)
        9    0.000    0.000    0.001    0.000 fromnumeric.py:3373(round_)
        9    0.000    0.000    0.001    0.000 fromnumeric.py:41(_wrapit)
        9    0.000    0.000    0.001    0.000 fromnumeric.py:54(_wrapfunc)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:69(_wrapreduction)
        1    0.000    0.000    0.000    0.000 fromnumeric.py:70(<dictcomp>)
        1    0.000    0.000    0.000    0.000 linalg.py:111(get_linalg_error_extobj)
        1    0.000    0.000    0.000    0.000 linalg.py:116(_makearray)
        2    0.000    0.000    0.000    0.000 linalg.py:121(isComplexType)
        1    0.000    0.000    0.000    0.000 linalg.py:134(_realType)
        1    0.000    0.000    0.000    0.000 linalg.py:144(_commonType)
        1    0.000    0.000    0.000    0.000 linalg.py:203(_assertRankAtLeast2)
        1    0.000    0.000    0.000    0.000 linalg.py:209(_assertNdSquareness)
        1    0.000    0.000    0.000    0.000 linalg.py:678(cholesky)
        2    0.000    0.000    0.006    0.003 numeric.py:175(ones)
       10    0.000    0.000    0.000    0.000 numeric.py:469(asarray)
        2    0.000    0.000    0.000    0.000 twodim_base.py:154(eye)
       19    0.000    0.000    0.000    0.000 {built-in method builtins.getattr}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.isinstance}
        3    0.000    0.000    0.000    0.000 {built-in method builtins.issubclass}
       11    0.000    0.000    0.000    0.000 {built-in method builtins.print}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.round}
       12    0.000    0.000    0.000    0.000 {built-in method numpy.array}
        2    0.006    0.003    0.006    0.003 {built-in method numpy.copyto}
        2    0.000    0.000    0.000    0.000 {built-in method numpy.empty}
        2    0.000    0.000    0.000    0.000 {built-in method numpy.zeros}
       10    0.000    0.000    0.000    0.000 {built-in method time.time}
        1    0.000    0.000    0.000    0.000 {method '__array_prepare__' of 'numpy.ndarray' objects}
        1    0.000    0.000    0.000    0.000 {method 'astype' of 'numpy.ndarray' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'get' of 'dict' objects}
        1    0.000    0.000    0.000    0.000 {method 'items' of 'dict' objects}
      784   46.550    0.059   46.550    0.059 {method 'normal' of 'mtrand.RandomState' objects}
        1    0.000    0.000    0.000    0.000 {method 'reduce' of 'numpy.ufunc' objects}
        9    0.000    0.000    0.000    0.000 {method 'round' of 'numpy.ndarray' objects}
...