有没有更有效(即更快)的方法来计算相关的随机游走?

Is there a more efficient (i.e. faster) way to compute correlated random walks?

有什么方法可以矢量化或以其他方式加速吗?我已经在使用 numba 来解决它了,但它仍然是一个主要瓶颈。使用 numba 在一维 numpy 数组上对我的函数进行 jit 会导致代码速度提高几个数量级,但在下面的二维数组上使用 numba 时基本上可以忽略不计的改进。 decomposition是一个numpy矩阵,表示相关矩阵的cholesky分解,x和n是常量,nrand是numpy.random

@jit
def generate_random_correlated_walks(decomposition, x, n):

    uncorrelated_walks = np.empty((2*x, n))

    for i in range(x):
        # Generate the random uncorrelated walks
        wv = nrand.normal(loc=0, scale=1, size=n)
        ws = nrand.normal(loc=0, scale=1, size=n)
        uncorrelated_walks[2*i] = wv
        uncorrelated_walks[(2*i) + 1] = ws

    # Create a matrix out of these walks
    uncorrelated_walks = np.matrix(uncorrelated_walks)

    m, n = uncorrelated_walks.shape
    correlated_walks = np.empty((m, n))

    # Go through column and correlate the walk values
    for i in range(n):
        correlated_timestep = np.transpose(uncorrelated_walks[:, i]) * decomposition
        correlated_walks[:, i] = correlated_timestep

    return correlated_walks

编辑:我已经做了建议的更改,现在我的代码如下,但不幸的是仍然是一个主要瓶颈。有什么想法吗?

@jit
def generate_random_correlated_walks(self, decomposition, x, n):

    rows = 2*x

    uncorrelated_walks = np.random.normal(loc=0, scale=1, size=(rows, n))

    correlated_walks = np.empty((rows, n))

    for i in range(n):
        correlated_timestep = np.dot(np.transpose(uncorrelated_walks[:, i]), decomposition)
        correlated_walks[:, i] = correlated_timestep

    return correlated_walks

您可以改进的第一件事是删除 for 循环。如果您认为 np.random.normal 确实会生成随机数,那么使用相同的输入参数多次调用 np.random.normal 并没有任何好处。

而不是使用 np.matrix, use np.array。当您认为上一项可用于将函数的整个第一部分缩短为一个步骤时,这将使您的生活更轻松。

您当然可以通过简单的矩阵乘法完全删除最终循环:uncorrelated_walks.T @ decomposition 将为您提供当前 correlated_walks 的转置。您可以通过更改参数的顺序来避免 transposes 之一。

你最终会得到这样的结果:

def generate_random_correlated_walks(decomposition, x, n):
    uncorrelated_walks = nrand.normal(loc=0, scale=1, size=(2*x, n))
    correlated_walks = np.dot(decomposition.T, uncorrelated_walks)
    return correlated_walks

不确定这对您有多大帮助,但删除 Python 级循环应该是一种提升,因为它会减少多个 numpy 调用的开销。

您可以牺牲易读性来将整个内容变成一行:

def generate_random_correlated_walks(decomposition, x, n):
    return np.dot(decomposition.T, nrand.normal(loc=0, scale=1, size=(2*x, n)))