从行向量创建块矩阵的最佳方法是什么?
What is the best way to create a block matrix form a row vector?
我有以下 numpy 行矩阵。
X = np.array([1,2,3])
我想创建一个分块矩阵如下:
1 0 0
2 1 0
3 2 1
0 3 2
0 0 3
如何使用 numpy 执行此操作?
如果您自上而下,然后从左到右读取所需的输出矩阵,您会看到模式 1,2,3, 0,0,0, 1,2,3, 0,0,0, 1 ,2,3。您可以使用该模式轻松创建线性阵列,然后将其重塑为二维形式:
import numpy as np
X = np.array([1,2,3])
N = len(X)
zeros = np.zeros_like(X)
m = np.hstack((np.tile(np.hstack((X,zeros)),N-1),X)).reshape(N,-1).T
print m
给予
[[1 0 0]
[2 1 0]
[3 2 1]
[0 3 2]
[0 0 3]]
方法 #1: 使用 np.lib.stride_tricks.as_strided
-
from numpy.lib.stride_tricks import as_strided as strided
def zeropad_arr_v1(X):
n = len(X)
z = np.zeros(len(X)-1,dtype=X.dtype)
X_ext = np.concatenate(( z, X, z))
s = X_ext.strides[0]
return strided(X_ext[n-1:], (2*n-1,n), (s,-s), writeable=False)
请注意,这将创建一个 read-only
输出。如果您以后需要写入,只需在末尾附加 .copy()
即可制作副本。
方法 #2: 使用零连接然后 clipping/slicing -
def zeropad_arr_v2(X):
n = len(X)
X_ext = np.concatenate((X, np.zeros(n,dtype=X.dtype)))
return np.tile(X_ext, n)[:-n].reshape(-1,n,order='F')
作为基于步幅的方法的方法 #1 在性能上应该非常有效。
样品运行 -
In [559]: X = np.array([1,2,3])
In [560]: zeropad_arr_v1(X)
Out[560]:
array([[1, 0, 0],
[2, 1, 0],
[3, 2, 1],
[0, 3, 2],
[0, 0, 3]])
In [561]: zeropad_arr_v2(X)
Out[561]:
array([[1, 0, 0],
[2, 1, 0],
[3, 2, 1],
[0, 3, 2],
[0, 0, 3]])
运行时测试
In [611]: X = np.random.randint(0,9,(1000))
# Approach #1 (read-only)
In [612]: %timeit zeropad_arr_v1(X)
100000 loops, best of 3: 8.74 µs per loop
# Approach #1 (writable)
In [613]: %timeit zeropad_arr_v1(X).copy()
1000 loops, best of 3: 1.05 ms per loop
# Approach #2
In [614]: %timeit zeropad_arr_v2(X)
1000 loops, best of 3: 705 µs per loop
# @user8153's solution
In [615]: %timeit hstack_app(X)
100 loops, best of 3: 2.26 ms per loop
另一个可写的解决方案:
def block(X):
n=X.size
zeros=np.zeros((2*n-1,n),X.dtype)
zeros[::2]=X
return zeros.reshape(n,-1).T
尝试:
In [2]: %timeit block(X)
600 µs ± 33 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我有以下 numpy 行矩阵。
X = np.array([1,2,3])
我想创建一个分块矩阵如下:
1 0 0
2 1 0
3 2 1
0 3 2
0 0 3
如何使用 numpy 执行此操作?
如果您自上而下,然后从左到右读取所需的输出矩阵,您会看到模式 1,2,3, 0,0,0, 1,2,3, 0,0,0, 1 ,2,3。您可以使用该模式轻松创建线性阵列,然后将其重塑为二维形式:
import numpy as np
X = np.array([1,2,3])
N = len(X)
zeros = np.zeros_like(X)
m = np.hstack((np.tile(np.hstack((X,zeros)),N-1),X)).reshape(N,-1).T
print m
给予
[[1 0 0]
[2 1 0]
[3 2 1]
[0 3 2]
[0 0 3]]
方法 #1: 使用 np.lib.stride_tricks.as_strided
-
from numpy.lib.stride_tricks import as_strided as strided
def zeropad_arr_v1(X):
n = len(X)
z = np.zeros(len(X)-1,dtype=X.dtype)
X_ext = np.concatenate(( z, X, z))
s = X_ext.strides[0]
return strided(X_ext[n-1:], (2*n-1,n), (s,-s), writeable=False)
请注意,这将创建一个 read-only
输出。如果您以后需要写入,只需在末尾附加 .copy()
即可制作副本。
方法 #2: 使用零连接然后 clipping/slicing -
def zeropad_arr_v2(X):
n = len(X)
X_ext = np.concatenate((X, np.zeros(n,dtype=X.dtype)))
return np.tile(X_ext, n)[:-n].reshape(-1,n,order='F')
作为基于步幅的方法的方法 #1 在性能上应该非常有效。
样品运行 -
In [559]: X = np.array([1,2,3])
In [560]: zeropad_arr_v1(X)
Out[560]:
array([[1, 0, 0],
[2, 1, 0],
[3, 2, 1],
[0, 3, 2],
[0, 0, 3]])
In [561]: zeropad_arr_v2(X)
Out[561]:
array([[1, 0, 0],
[2, 1, 0],
[3, 2, 1],
[0, 3, 2],
[0, 0, 3]])
运行时测试
In [611]: X = np.random.randint(0,9,(1000))
# Approach #1 (read-only)
In [612]: %timeit zeropad_arr_v1(X)
100000 loops, best of 3: 8.74 µs per loop
# Approach #1 (writable)
In [613]: %timeit zeropad_arr_v1(X).copy()
1000 loops, best of 3: 1.05 ms per loop
# Approach #2
In [614]: %timeit zeropad_arr_v2(X)
1000 loops, best of 3: 705 µs per loop
# @user8153's solution
In [615]: %timeit hstack_app(X)
100 loops, best of 3: 2.26 ms per loop
另一个可写的解决方案:
def block(X):
n=X.size
zeros=np.zeros((2*n-1,n),X.dtype)
zeros[::2]=X
return zeros.reshape(n,-1).T
尝试:
In [2]: %timeit block(X)
600 µs ± 33 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)