使用 numpy 生成带状矩阵

Lin*_*Lin 5 python numpy matrix

我正在使用以下代码从生成器创建带状矩阵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
Run Code Online (Sandbox Code Playgroud)

用法很简单:

banded([1,2,3], 3)
Run Code Online (Sandbox Code Playgroud)

它返回

[1, 2, 3, 0, 0]
[0, 1, 2, 3, 0]
[0, 0, 1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

例如,它将主要用于解决具有给定模板的有限差分模型 (-1, 1)

有没有更好的方法来生成模板?我找不到任何好的 NumPy 函数。

我的意思是,更快,使用更少的内存,从 python 中删除循环并发送到 Numpy 堆栈。其中任何(或全部)都是改进。

Div*_*kar 5

这是一个np.lib.stride_tricks.as_strided让我们2D了解输入的零填充1D版本的视图,因此内存效率很高,因此也很高效。这一招已经探索了无数次- ,。12

因此,实施将是 -

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))
Run Code Online (Sandbox Code Playgroud)

样品运行 -

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]])
Run Code Online (Sandbox Code Playgroud)

使用相同的理念,但不那么混乱的版本,我们还可以利用np.lib.stride_tricks.as_stridedbasedscikit-image's view_as_windows来获得滑动窗口。有关使用as_stridedbased 的更多信息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]
Run Code Online (Sandbox Code Playgroud)