首页 > 解决方案 > 是否有与这些递归方程等效的矩阵(numpy)?

问题描述

我想在 Python 中实现以下递归方程
(背景是金融市场):

这很容易使用循环按顺序完成:

def compute(x, y, χ, γ, a0, b0):
    a = [a0]
    b = [b0]

    α = [a[0]]
    β = [b[0]]

    for i in range(len(x)):
        a.append(-α[i]*x[i] + β[i]*y[i]*γ[i])
        b.append(-β[i]*y[i] + α[i]*x[i]*χ[i])

        α.append(α[-1] + a[-1])
        β.append(β[-1] + b[-1])
    return α, β

一个小数组示例:

x = np.array([0.6, 0.4, 0., 0., 0.9])
y = np.array([0., 0., 0.3, 0.9, 0.])

χ = np.arange(100., 105., 1.)
γ = 1. / (χ - 1.)

print(np.array(compute(x, y, χ, γ, 1., 0.)))

会产生

>>> [[ 1.          0.4         0.24        0.46621782  0.93661782  0.09366178]  
     [ 0.         60.         76.16       53.312       5.3312     92.99862812]]

有没有办法在 NumPy 中做到这一点(我希望能显着加快计算速度)?

换句话说:在不使用循环的情况下计算整个 a 和 b 向量,只使用 NumPy 函数?

标签: pythonnumpy

解决方案


首先要明确一点:我不知道如何使用 numpy. 所以这不是你的问题的答案

但是:您可以使用以下方法实现一些加速numba

from numba import jit
import numpy as np

N = 1000000

x = np.random.rand(N)
y = np.random.rand(N)
gamma = np.random.rand(N)
chi = np.random.rand(N)

a = [.2]
b = [.3]
alpha = [a[0]]
beta = [b[0]]

def compute_in_python():
    for i in range(len(x)):
        a.append(-alpha[i]*x[i] + beta[i]*y[i]*gamma[i])
        b.append(-beta[i]*y[i] + alpha[i]*x[i]*chi[i])

        alpha.append(alpha[-1]+a[-1])
        beta.append(beta[-1]+b[-1])


@jit(nopython=True)
def compute_with_numba(x,y,gamma,chi,a0, b0, alpha0, beta0):
    N = len(x)
    a = np.empty(N+1)
    b = np.empty(N+1)
    alpha = np.empty(N+1)
    beta = np.empty(N+1)
    a[0] = a0
    b[0] = b0
    alpha[0] = alpha0
    beta[0] = beta0
    for i in range(N):
        a[i+1] = -alpha[i] * x[i] + beta[i] * y[i] * gamma[i]
        b[i+1] = -beta[i] * y[i] + alpha[i] * x[i] * chi[i]

        alpha[i+1] = alpha[i]+a[i+1]
        beta[i+1] = beta[i]+b[i+1]

    return a,b,alpha,beta

香草蟒蛇循环:

In [23]: %time compute_in_python()
CPU times: user 1.6 s, sys: 24.8 ms, total: 1.63 s
Wall time: 1.63 s

麻木:

In [42]: %time res = compute_with_numba(x,y,gamma,chi,a[0], b[0], alpha[0], beta[0])
CPU times: user 13 ms, sys: 3.36 ms, total: 16.4 ms
Wall time: 16.4 ms

请注意,第一次调用compute_with_numba将触发 jit,因此您应该测量第二次调用的运行时间。

同样,这不是您问题的答案,但它仍然快大约 100 倍。


推荐阅读