使用 numpy 生成带状矩阵 [英] Generating banded matrices using numpy

查看:87
本文介绍了使用 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_stridedview_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆