保持 Numpy 数组 2D
Posted
技术标签:
【中文标题】保持 Numpy 数组 2D【英文标题】:Keep Numpy Arrays 2D 【发布时间】:2022-01-19 12:54:29 【问题描述】:我正在做很多向量代数,并希望使用 numpy 数组来消除对循环的任何需求并运行得更快。
我发现如果我有一个大小为 [N,P] 的矩阵 A,我经常需要使用 np.array([A[:,0]).T
来强制 A[:,0]
成为大小为 (N,1) 的列向量
有没有办法将二维数组的单行或列保持为二维数组,因为它使以下算术变得更加容易。例如,我经常需要将列向量(来自矩阵)与行向量(也从矩阵创建)相乘以创建一个新矩阵:eg
C = A[:,i] * B[j,:]
如果我不必继续使用那就太好了:
C = np.array([A[:,i]]).T * np.array([B[j,:]])
它确实混淆了代码 - 在 MATLAB 中,它只是 C = A[:,i] * B[j,:]
,它更易于阅读并与基础数学进行比较,特别是如果在同一行中有很多这样的术语,但不幸的是我的大部分同事没有 MATLAB 许可证。
请注意,这不是唯一的用例,因此此列 x 行操作的特定函数并没有太大帮助
【问题讨论】:
你考虑过使用 Octave 吗? 总的来说,我的组织大量使用 Python,所以如果我能坚持使用 Python 是最好的 此外,一个最小的可重现示例将包括 Python 将矩阵更改为一维数组的许多单独实例 你误用了matrix
这个词。二维array
不是numpy
中的matrix
。它是一个array
,仍然是array
@选择切片时。您的问题似乎是:我可以将 MATLAB 语法与 numpy 一起使用吗? 答案是:不,您不能,您实际上必须学习 numpy
才能使用 numpy
。
是的,我在数学意义上使用矩阵,其中二维数组是矩阵。问题是,我可以在 numpy 中使用不那么笨重的 numpy 语法吗? MATLAB 是一个不那么笨拙的语法的好例子。
【参考方案1】:
即使是 MATLAB/Octave 也会挤出多余的维度:
>> ones(2,3,4)(:,:,1)
ans =
1 1 1
1 1 1
>> size(ones(2,3,4)(1,:)) # some indexing "flattens" outer dims
ans =
1 12
当我开始使用 MATLAB v3.5 时,二维矩阵就是它所拥有的一切;单元格、结构和更高维度是后来添加的(如上述示例所示)。
你的:
In [760]: A=np.arange(6).reshape(2,3)
In [762]: np.array([A[:,0]]).T
Out[762]:
array([[0],
[3]])
比需要的更复杂。它创建一个列表,然后是一个 (1,N) 数组,最后是一个 (N,1)
A[:,[0]]
、A[:,:,None]
、A[:,0:1]
更直接。甚至A[:,0].reshape(-1,1)
我想不出能将标量和列表索引一视同仁的简单方法。
像np.atleast_2d
这样的函数可以有条件地添加一个新维度,但它将是一个前导(外部)维度。但是根据broadcasting
的规则,前导维度通常是“自动的”。
基本与高级索引
在底层 Python 中,标量不能被索引,列表只能用标量和切片来索引。底层语法允许使用元组进行索引,但列表拒绝这些。 numpy
大大扩展了索引 - 不是语法,而是它如何处理这些元组。
numpy
使用切片和标量进行索引是basic
索引。这就是可能发生尺寸损失的地方。这与列表索引一致
In [768]: [[1,2,3],[4,5,6]][1]
Out[768]: [4, 5, 6]
In [769]: np.array([[1,2,3],[4,5,6]])[1]
Out[769]: array([4, 5, 6])
使用列表和数组进行索引是advanced
索引,没有任何列表对应项。这可能是 MATLAB 和 numpy
之间的差异最丑陋的地方:)
>> A([1,2],[1,2])
产生一个 (2,2) 块。在产生“对角线”的 numpy 中
In [781]: A[[0,1],[0,1]]
Out[781]: array([0, 4])
要获得块,我们必须使用相互“广播”的列表(或数组):
In [782]: A[[[0],[1]],[0,1]]
Out[782]:
array([[0, 1],
[3, 4]])
要在 MATLAB 中获取“对角线”,我们必须使用 sub2ind([2,2],[1,2],[1,2])
来获取 [1,4] 平面索引。
什么样的乘法?
在
np.array([A[:,i]]).T * np.array([B[j,:]])
这是按元素 (.*
) 还是矩阵?
对于 (N,1) 和 (1,M) 对,A*B
和 A@B
产生相同的 (N,M) 结果,但使用 broadcasting
来推广 outer
乘积,并且另一个是内部/矩阵积(带有积和)。
【讨论】:
【参考方案2】:https://numpy.org/doc/stable/reference/generated/numpy.matrix.html
从类似数组的对象或数据字符串中返回一个矩阵。矩阵是一种特殊的二维数组通过运算保留其二维性质。它有一些特殊的运算符,例如*(矩阵乘法)和**(矩阵幂)。
我不知道如何重新实现它,这是一个有趣的练习。
如前所述,矩阵将被弃用。但是从 np.array 中,您可以使用参数 ndim=2 指定维度:
np.array([1, 2, 3], ndmin=2)
【讨论】:
你读过笔记了吗?不再推荐使用np.matrix
。
@MichaelSzczesny 不得不阅读两次并向下滚动并再次阅读两次才能看到它,对不起!
@MichaelSzczesny 我编辑了答案以使用 np.array 添加替代方案
np.matrix
是为任性的 MATLAB 用户设计的,比如这个。 OP 对差异的理解有限。
确实,我喜欢 MATLAB 的东西,就像所有数据都被相同对待在 Python 中,a = 12 和 a = [12] 似乎完全不同,即使基础数据是相同,因此您希望对它们执行的任何功能都是完全明确的,例如查找长度或测试它是否大于 3 - 在 Python 中您必须使用不同的功能......我一直遇到这个并写了很多尴尬的代码而不是 Python 能够以类似 MATLAB 的方式处理它如果 i 和 j 是向量(大小相同),C = A[:, [i]] * B[[j],:] 会起作用吗?谁知道...【参考方案3】:
您可以通过以下方式保持维度(使用@进行矩阵乘法)
C = A[:,[i]] @ B[[j],:]
注意i
和j
周围的括号,否则C 将不是二维矩阵。
【讨论】:
以上是关于保持 Numpy 数组 2D的主要内容,如果未能解决你的问题,请参考以下文章
如何将 2D float numpy 数组转换为 2D int numpy 数组?
python使用numpy中的diagonal函数获取2D numpy数组的对角线元素使用numpy中的diagonal函数和sum函数获取2D numpy数组的迹(matrix trace)