变量相互作用的计算(矩阵中向量的点积)
Computation of variable interaction (dot product of vectors in a matrix)
如果我将向量 x
(1,n) 与其自身相乘,即 np.dot(x.T, x)
我将得到二次矩阵。
如果我有一个矩阵 Xmat
(k, n),我如何有效地计算行方向点积和 select 仅上三角元素?
所以,自动取款机。我有以下解决方案:
def compute_interaction(x):
xx = np.reshape(x, (1, x.size))
return np.concatenate((x, np.dot(xx.T, xx)[np.triu_indices(xx.size)]))
然后 compute_interaction(np.asarray([2,5]))
产生 array([ 2, 5, 4, 10, 25])
.
当我有一个矩阵时,我使用
np.apply_along_axis(compute_interaction, axis=1, arr = np.asarray([[2,5], [3,4], [8,9]]))
这会产生我想要的结果:
array([[ 2, 5, 4, 10, 25],
[ 3, 4, 9, 12, 16],
[ 8, 9, 64, 72, 81]])
除了使用 apply_along_axis
计算此值之外,还有其他方法吗?也许使用 np.einsum
?
方法 #1
np.triu_indices
的一个解决方案是 -
r,c = np.triu_indices(arr.shape[1])
out = np.concatenate((arr,arr[:,r]*arr[:,c]),axis=1)
方法 #2
slicing
-
速度更快
def pairwise_col_mult(a):
n = a.shape[1]
N = n*(n+1)//2
idx = n + np.concatenate(( [0], np.arange(n,0,-1).cumsum() ))
start, stop = idx[:-1], idx[1:]
out = np.empty((a.shape[0],n+N),dtype=a.dtype)
out[:,:n] = a
for j,i in enumerate(range(n)):
out[:,start[j]:stop[j]] = a[:,[i]] * a[:,i:]
return out
计时 -
In [254]: arr = np.random.randint(0,9,(10000,100))
In [255]: %%timeit
...: r,c = np.triu_indices(arr.shape[1])
...: out = np.concatenate((arr,arr[:,r]*arr[:,c]),axis=1)
1 loop, best of 3: 577 ms per loop
In [256]: %timeit pairwise_col_mult(arr)
1 loop, best of 3: 233 ms per loop
In [165]: arr = np.asarray([[2,5], [3,4], [8,9]])
In [166]: arr
Out[166]:
array([[2, 5],
[3, 4],
[8, 9]])
In [167]: compute_interaction(arr[0])
Out[167]: array([ 2, 5, 4, 10, 25])
就其价值而言,apply_along_axis
只是:
In [168]: np.array([compute_interaction(row) for row in arr])
Out[168]:
array([[ 2, 5, 4, 10, 25],
[ 3, 4, 9, 12, 16],
[ 8, 9, 64, 72, 81]])
apply...
只是一个方便的工具,可以使多个轴上的迭代更清晰(但不会更快)。
如果我将向量 x
(1,n) 与其自身相乘,即 np.dot(x.T, x)
我将得到二次矩阵。
如果我有一个矩阵 Xmat
(k, n),我如何有效地计算行方向点积和 select 仅上三角元素?
所以,自动取款机。我有以下解决方案:
def compute_interaction(x):
xx = np.reshape(x, (1, x.size))
return np.concatenate((x, np.dot(xx.T, xx)[np.triu_indices(xx.size)]))
然后 compute_interaction(np.asarray([2,5]))
产生 array([ 2, 5, 4, 10, 25])
.
当我有一个矩阵时,我使用
np.apply_along_axis(compute_interaction, axis=1, arr = np.asarray([[2,5], [3,4], [8,9]]))
这会产生我想要的结果:
array([[ 2, 5, 4, 10, 25],
[ 3, 4, 9, 12, 16],
[ 8, 9, 64, 72, 81]])
除了使用 apply_along_axis
计算此值之外,还有其他方法吗?也许使用 np.einsum
?
方法 #1
np.triu_indices
的一个解决方案是 -
r,c = np.triu_indices(arr.shape[1])
out = np.concatenate((arr,arr[:,r]*arr[:,c]),axis=1)
方法 #2
slicing
-
def pairwise_col_mult(a):
n = a.shape[1]
N = n*(n+1)//2
idx = n + np.concatenate(( [0], np.arange(n,0,-1).cumsum() ))
start, stop = idx[:-1], idx[1:]
out = np.empty((a.shape[0],n+N),dtype=a.dtype)
out[:,:n] = a
for j,i in enumerate(range(n)):
out[:,start[j]:stop[j]] = a[:,[i]] * a[:,i:]
return out
计时 -
In [254]: arr = np.random.randint(0,9,(10000,100))
In [255]: %%timeit
...: r,c = np.triu_indices(arr.shape[1])
...: out = np.concatenate((arr,arr[:,r]*arr[:,c]),axis=1)
1 loop, best of 3: 577 ms per loop
In [256]: %timeit pairwise_col_mult(arr)
1 loop, best of 3: 233 ms per loop
In [165]: arr = np.asarray([[2,5], [3,4], [8,9]])
In [166]: arr
Out[166]:
array([[2, 5],
[3, 4],
[8, 9]])
In [167]: compute_interaction(arr[0])
Out[167]: array([ 2, 5, 4, 10, 25])
就其价值而言,apply_along_axis
只是:
In [168]: np.array([compute_interaction(row) for row in arr])
Out[168]:
array([[ 2, 5, 4, 10, 25],
[ 3, 4, 9, 12, 16],
[ 8, 9, 64, 72, 81]])
apply...
只是一个方便的工具,可以使多个轴上的迭代更清晰(但不会更快)。