[英]Faster matrix calculation in numpy
给定一个 nxn 矩阵 M 和一个 n 向量 X,是否有一些更快的计算以下矩阵的变体(来自 本文): ?
我目前计算如下:
#M, X are given as numpy arrays
G = np.zeros((n,n))
for i in range(0,n):
for j in range(i,n):
xi = X[i]
if i == j:
G[i,j] = abs(xi)
else:
xi2 = xi*xi
xj = X[j]
xj2 = xj*xj
mij = M[i,j]
mid = (xi2 - xj2)/mij
top = mij*mij + mid*mid + 2*xi2 + 2*xj2
G[i,j] = math.sqrt(top)/2
这非常慢,但我怀疑有一种更好的“numpythonic”方式来代替循环......
编辑:虽然所有答案都有效并且比我幼稚的实现要快得多,但我选择了我基准测试最快的答案。 谢谢!
其实很简单。
import math
import numpy as np
n = 5
M = np.random.rand(n, n)
X = np.random.rand(n)
您的代码和结果:
G = np.zeros((n,n))
for i in range(0,n):
for j in range(i,n):
xi = X[i]
if i == j:
G[i,j] = abs(xi)
else:
xi2 = xi*xi
xj = X[j]
xj2 = xj*xj
mij = M[i,j]
mid = (xi2 - xj2)/mij
top = mij*mij + mid*mid + 2*xi2 + 2*xj2
G[i,j] = math.sqrt(top)/2
array([[0.77847813, 5.26334534, 0.8794082 , 0.7785694 , 0.95799072],
[0. , 0.15662266, 0.88085031, 0.47955479, 0.99219171],
[0. , 0. , 0.87699707, 8.92340836, 1.50053712],
[0. , 0. , 0. , 0.45608367, 0.95902308],
[0. , 0. , 0. , 0. , 0.95774452]])
使用广播:
temp = M**2 + ((X[:, None]**2 - X[None, :]**2) / M)**2 + 2 * (X[:, None]**2) + 2 * (X[None, :]**2)
G = np.sqrt(temp) / 2
array([[0.8284724 , 5.26334534, 0.8794082 , 0.7785694 , 0.95799072],
[0.89251217, 0.25682736, 0.88085031, 0.47955479, 0.99219171],
[0.90047282, 1.10306597, 0.95176428, 8.92340836, 1.50053712],
[0.85131766, 0.47379576, 0.87723514, 0.55013345, 0.95902308],
[0.9879939 , 1.46462011, 0.99516443, 0.95774481, 1.02135642]])
请注意,您没有将公式直接用于对角线元素,而仅针对G
的上三角区域计算。 我只是简单地实现了计算所有G[i, j]
的公式。
注意:如果M
的对角线元素无关紧要并且它们包含一些零,只需添加一些偏移量以避免divide by zero
错误,例如:
M[np.arange(n), np.arange(n)] += 1e-5
# Do calculation to get G
# Assign diagonal to X
G[np.arange(n), np.arange(n)] = abs(X)
首先,您 function 不是您的方程式。 作为这条线
mid = (xi2 - xj2)/mij
应该
mid = (xi - xj)/mij
其次,我使用 numpy 生成您的方程式。
生成测试数据
test_m = np.array(
[
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5],
]
)
test_x = np.array([5, 6, 7, 8, 9])
构建 function
def solve(m, x):
x_size = x.shape[0]
x = x.reshape(1, -1)
reshaped_x = x.reshape(-1, 1)
result = np.sqrt(
m ** 2
+ ((reshaped_x - x) / m) ** 2
+ 2 * np.repeat(reshaped_x, x_size, axis=1) ** 2
+ 2 * np.repeat(x, x_size, axis=0) ** 2
) / 2
return result
跑
print(solve(test_m, test_x))
实际上,结果部分可以像这样简单:
result = np.sqrt(
m ** 2
+ ((reshaped_x - x) / m) ** 2
+ 2 * reshaped_x ** 2
+ 2 * x ** 2
) / 2
用谷歌colab测试:
导入 numba 导入 numpy 作为 np 导入数学
# your implementation
def bench_1(n):
#M, X are given as numpy arrays
G = np.zeros((n,n))
M = np.random.rand(n, n)
X = np.random.rand(n)
for i in range(0,n):
for j in range(i,n):
xi = X[i]
if i == j:
G[i,j] = abs(xi)
else:
xi2 = xi*xi
xj = X[j]
xj2 = xj*xj
mij = M[i,j]
mid = (xi2 - xj2)/mij
top = mij*mij + mid*mid + 2*xi2 + 2*xj2
G[i,j] = math.sqrt(top)/2
return G
%%timeit
n = 1000
bench_1(n)
1 loop, best of 3: 1.61 s per loop
使用Numba编译 function:
@numba.jit(nopython=True, parallel=True)
def bench_2(n):
#M, X are given as numpy arrays
G = np.zeros((n,n))
M = np.random.rand(n, n)
X = np.random.rand(n)
for i in range(0,n):
for j in range(i,n):
xi = X[i]
if i == j:
G[i,j] = abs(xi)
else:
xi2 = xi*xi
xj = X[j]
xj2 = xj*xj
mij = M[i,j]
mid = (xi2 - xj2)/mij
top = mij*mij + mid*mid + 2*xi2 + 2*xj2
G[i,j] = math.sqrt(top)/2
return G
%%timeit
n = 1000
bench_2(n)
The slowest run took 88.13 times longer than the fastest. This could mean that an intermediate result is being cached.
1 loop, best of 3: 9.8 ms per loop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.