You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Numpy沿对角线复制给定数组高效创建矩阵的方法

生成滑动窗口式矩阵的解决方案

嗨,这个问题我之前处理过!确实,常规的numpy.kron或者块对角方法(比如scipy.linalg.block_diag)完全没法生成这种每行向右滑动一位的矩阵,因为它们的逻辑是重复或块填充,和我们要的滑动窗口式移位结构不匹配。

下面给你两种实用的解决方案,从直观到高效都有:

方法一:直观循环填充(适合小矩阵)

这种方法逻辑简单,容易理解,对于小规模的矩阵完全够用:

import numpy as np

a = np.array([1,2,3])
n = 4
rows = n + 1  # 结果矩阵的行数
cols = len(a) + n  # 结果矩阵的列数

# 初始化全零矩阵
result = np.zeros((rows, cols), dtype=a.dtype)

# 逐行填充:第i行把a放到从第i列开始的位置
for i in range(rows):
    result[i, i:i+len(a)] = a

print(result)

运行后会输出你期望的矩阵:

array([[1., 2., 3., 0., 0., 0., 0.],
       [0., 1., 2., 3., 0., 0., 0.],
       [0., 0., 1., 2., 3., 0., 0.],
       [0., 0., 0., 1., 2., 3., 0.],
       [0., 0., 0., 0., 1., 2., 3.]])

方法二:利用Stride Tricks高效生成(适合大矩阵)

如果你的n很大,循环会影响效率,这时候可以用numpy的stride_tricks,它通过直接操作数组的内存步长来生成滑动窗口,不需要复制数据,效率极高:

import numpy as np
from numpy.lib.stride_tricks import as_strided

a = np.array([1,2,3])
n = 4
cols = len(a) + n
rows = n + 1

# 构造一个足够长的填充数组:前后各补n个0
pad_a = np.concatenate([np.zeros(n, dtype=a.dtype), a, np.zeros(n, dtype=a.dtype)])

# 利用步长生成滑动窗口:行方向步长为负(向左滑动),列方向步长为正
stride = pad_a.itemsize
result = as_strided(
    pad_a,
    shape=(rows, cols),
    strides=(-stride, stride),
    writeable=False  # 设为False避免意外修改原数组
)

print(result)

这个方法和循环得到的结果完全一致,但运行速度快很多,尤其当n是几百上千的时候。

为什么常规方法不行?

简单说:

  • numpy.kron是克罗内克积,会把a和另一个矩阵的每个元素做乘法扩展,生成的是重复块结构,不是滑动移位。
  • 块对角方法(比如block_diag)只会把a放在对角线的块里,其他位置全0,无法实现每行向右移位的效果。

内容的提问来源于stack exchange,提问作者Alex Hu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:22:36