使用 numpy 生成带状矩阵 [英] Generating banded matrices using numpy
问题描述
我正在使用以下代码从生成器 g
创建带状矩阵:
I'm using the following piece of code to create a banded matrix from a generator g
:
def banded(g, N):
"""Creates a `g` generated banded matrix with 'N' rows"""
n=len(g)
T = np.zeros((N,N+n-1))
for x in range(N):
T[x][x:x+n]=g
return T
用法很简单:
banded([1,2,3], 3)
然后它返回
[1, 2, 3, 0, 0]
[0, 1, 2, 3, 0]
[0, 0, 1, 2, 3]
它主要用于解决具有给定模板的有限差分模型,例如 (-1, 1)
It will used mostly to solve a finite difference model with a given stencil for example (-1, 1)
有没有更好的方法来生成模板?我找不到任何好的 NumPy 函数.
Is there a better way to generate that stencil? I could not find any good NumPy Function for that.
更好的意思是,更快,使用更少的内存,从python中删除循环并发送到Numpy堆栈.其中任何(或全部)都是改进.
By better I mean, faster, using less memory, removing the loop from python and sending to Numpy stack. Any (or all) of those are improvements.
推荐答案
这里有一个 np.lib.stride_tricks.as_strided
给我们一个 2D
视图到一个零填充的 1D
版本的输入,因此内存效率很高,因此也很高效.这个技巧已经被探索过很多次了 - 1
,2
.
Here's one with np.lib.stride_tricks.as_strided
to give us a 2D
view into a zeros padded 1D
version of the input and as such pretty memory efficient and hence performant too. This trick had been explored numerous times - 1
,2
.
因此,实现将是 -
def sliding_windows(a, W):
a = np.asarray(a)
p = np.zeros(W-1,dtype=a.dtype)
b = np.concatenate((p,a,p))
s = b.strides[0]
strided = np.lib.stride_tricks.as_strided
return strided(b[W-1:], shape=(W,len(a)+W-1), strides=(-s,s))
样品运行 -
In [99]: a = [1,2,3]
In [100]: sliding_windows(a, W=3)
Out[100]:
array([[1, 2, 3, 0, 0],
[0, 1, 2, 3, 0],
[0, 0, 1, 2, 3]])
In [101]: a = [1,2,3,4,5]
In [102]: sliding_windows(a, W=3)
Out[102]:
array([[1, 2, 3, 4, 5, 0, 0],
[0, 1, 2, 3, 4, 5, 0],
[0, 0, 1, 2, 3, 4, 5]])
采用相同的理念,但不那么混乱的版本,我们还可以利用 np.lib.stride_tricks.as_strided
基于 scikit-image 的 view_as_windows
获得滑动窗口.有关使用基于 as_strided
的 view_as_windows
的更多信息.
With the same philosophy, but less messier version, we can also leverage np.lib.stride_tricks.as_strided
based scikit-image's view_as_windows
to get sliding windows. More info on use of as_strided
based view_as_windows
.
from skimage.util.shape import view_as_windows
def sliding_windows_vw(a, W):
a = np.asarray(a)
p = np.zeros(W-1,dtype=a.dtype)
b = np.concatenate((p,a,p))
return view_as_windows(b,len(a)+W-1)[::-1]
这篇关于使用 numpy 生成带状矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!