Python 用numpy生成带状矩阵
我使用以下代码从生成器Python 用numpy生成带状矩阵,python,numpy,matrix,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 用法很简单,如下所示: banded([1,2,3], 3) 它回来了 [1, 2, 3, 0,
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)
有更好的方法生成模具吗?我找不到任何好的NumPy函数
我说的更好是指更快,使用更少的内存,从python中删除循环并发送到Numpy堆栈。所有这些都是改进。您可以使用
scipy.sparse.diags
:
输入:
diags([1, 2, 3], [0, 1, 2], shape=(3,5)).toarray()
输出:
array([[ 1., 2., 3., 0., 0.],
[ 0., 1., 2., 3., 0.],
[ 0., 0., 1., 2., 3.]])
array([[1., 2., 1., 0., 0.],
[0., 1., 2., 1., 0.],
[0., 0., 1., 2., 1.],
[0., 0., 0., 1., 2.],
[0., 0., 0., 0., 1.]])
第二个列表[0,1,2]是偏移量列表。它告诉您希望某个元素与对角线的偏移量。这里有一个,它为我们提供了一个2D
视图,进入一个零填充1D
版本的输入,因此内存效率很高,因此性能也很好。这个技巧已经被探索过无数次-
因此,执行工作将是非常重要的-
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]])
同样的理念,但不太混乱的版本,我们也可以利用基于的来获得滑动窗口
您还可以使用scipy的toeplitz函数,它与matlab中的对应函数非常相似。它周围的形状也很灵巧,不用担心它
import scipy.linalg as scl
# define first column and first line
column1 = [1,0,0]
line1 = [1,2,3,0,0]
scl.toeplitz(column1, line1)
如果需要可变大小,请使用大小参数(N)将零动态添加到列和行中。下面是我对最小值为3的有限差分的实现
col = [1,0,0] + [0] * (size -3)
lin = [1,2,1] + [0] * (size -3)
m = scl.toeplitz(col, lin)
输出:
array([[ 1., 2., 3., 0., 0.],
[ 0., 1., 2., 3., 0.],
[ 0., 0., 1., 2., 3.]])
array([[1., 2., 1., 0., 0.],
[0., 1., 2., 1., 0.],
[0., 0., 1., 2., 1.],
[0., 0., 0., 1., 2.],
[0., 0., 0., 0., 1.]])
请定义“更好”。更短的代码?更一般(以什么方式)?更快?消耗更少的内存?能够在更高的维度中工作?更快,消耗更少的内存,从python中删除循环并发送到numpy堆栈。任何(或全部)都更好。真实程序中的真实输入是什么?
g
通常有多长,以及N
有多大?g
不是很大,从2个元素到32个元素不等(是一个常规的有限差分模板)。但是N
可以稍大一些。就像100000
,任何真正决定矩阵大小的N
。而且大小会变大,N**2
@Lin是输入数组还是列表?Joe,是的,scipy sparse是一个想法。真是个好主意。事实上,第二个参数可以是范围
。为了进行比较,我尝试使用稀疏方法和我在示例中使用的方法生成相同的矩阵,稀疏矩阵在矩阵分配(对于100000x1000000)矩阵时稍微快一点。当然,我相信在尝试求逆时,稀疏性是有好处的。只是为了获取信息,我使用了scipy.sparse.diags(g,range(len(g),shape=(N,N+len(g)-1)).toarray()
,其中N
和g
在问题上是相同的。哇!这种方法最快,速度为4个数量级。