numpy - 带有 3d 数组的 Numpy 点积
问题描述
我有两个数组:
data
形状(2466, 2498, 9)
,尺寸在哪里(asset, date, returns)
。correlation_matrix
形状(2466, 2466)
(对角线上有 0)
我想得到等于预期回报的点积,即returns
每个asset
乘以correlation_matrix
. 它应该给出与 相同的形状data
。
我试过了:
data.transpose([1, 2, 0]) @ correlation_matrix
但这只是挂起我的电脑(已经运行了 10 分钟并数着数)。
我也试过:
np.einsum('ijk,lm->ijk', data, correlation_matrix)
但我不太熟悉einsum
,这也挂起。
我究竟做错了什么?
解决方案
使用您的.transpose((1, 2, 0))
数据,正确的形式是:
"ijs,sk" # -> ijk
因为对于张量A
和B
,我们可以写:
C_{ijk} = Σ_s A_{ijs} * B_{sk}
如果您想避免事先转置数据,您可以置换索引:
"sij,sk" # -> ijk
验证:
p, q, r = 2466, 2498, 9
a = np.random.randint(255, size=(p, q, r))
b = np.random.randint(255, size=(p, p))
c1 = a.transpose((1, 2, 0)) @ b
c2 = np.einsum("sij,sk", a, b)
>>> np.all(c1 == c2)
True
计算shape所需的乘法量为. 在你的情况下,那是乘法。您还需要大约相同数量的添加,这样我们就可以进行近 2700 亿次操作。如果您想要更快的速度,您可以考虑通过cupy使用 GPU 进行计算。(p, q, r)
data
p * np.prod(c.shape) == p * (q * r * p) == p**2 * q * r
136_716_549_192
def with_np():
p, q, r = 2466, 2498, 9
a = np.random.randint(255, size=(p, q, r))
b = np.random.randint(255, size=(p, p))
c1 = a.transpose((1, 2, 0)) @ b
c2 = np.einsum("sij,sk", a, b)
def with_cp():
p, q, r = 2466, 2498, 9
a = cp.random.randint(255, size=(p, q, r))
b = cp.random.randint(255, size=(p, p))
c1 = a.transpose((1, 2, 0)) @ b
c2 = cp.einsum("sij,sk", a, b)
>>> timeit(with_np, number=1)
513.066
>>> timeit(with_cp, number=1)
0.197
这是 2600 倍的加速,包括内存分配、初始化和 CPU/GPU 复制时间!(更现实的基准会提供更大的加速。)
推荐阅读
- javascript - AG-Grid agNumberColumnFilter 不适用于 valueFormatter 中的计算值
- javascript - 拉取firebase文档获取多余数据
- python - 导入csv,每行列数不一致,原始标题使用熊猫
- javascript - NextJS:动态创建的 html 节点不被 css 重绘
- c - 如何从文件中填充和打印结构中的数组?
- php - php遍历由字符串而不是对象组成的数组
- python - 表中的 Python ReportLab 图片
- java - Java SOAP 将命名空间声明添加到 SOAP 主体的子元素
- swift - 来自另一个 viewController Swift 的 reloadData()
- c# - 在客户端中未定义的远程服务器上引发异常会导致“无法找到程序集”异常