【发布时间】:2010-12-15 20:39:58
【问题描述】:
我想使用 NumPy 执行以下 MATLAB 代码的等效代码:repmat([1; 1], [1 1 1])。我将如何做到这一点?
【问题讨论】:
我想使用 NumPy 执行以下 MATLAB 代码的等效代码:repmat([1; 1], [1 1 1])。我将如何做到这一点?
【问题讨论】:
Matlab:
repmat(a, 2, 3)
麻木:
numpy.kron(numpy.ones((2,3)), a)
Numpy 中的 Matlib (numpy.matlib.repmat()):
numpy.matlib.repmat(a, 2, 3)
【讨论】:
>>> import numpy as np
>>> np.repeat(['a','b'], [2,5])
array(['a', 'a', 'b', 'b', 'b', 'b', 'b'], dtype='<U1')
>>> np.repeat([1,2], [2,5])
array([1, 1, 2, 2, 2, 2, 2])
>>> np.repeat(np.array([1,2]), [3]).reshape(2,3)
array([[1, 1, 1],
[2, 2, 2]])
>>> np.repeat(np.array([1,2]), [2,4]).reshape(3,2)
array([[1, 1],
[2, 2],
[2, 2]])
>>> np.repeat(np.matrix('1 2; 3 4'), [2]).reshape(4,2)
matrix([[1, 1],
[2, 2],
[3, 3],
[4, 4]])
【讨论】:
这里有一个更好的(官方)NumPy for Matlab Users 链接 - 恐怕mathesaurus 已经过时了。
repmat(a, m, n) 的 numpy 等效项是 tile(a, (m, n))。
这适用于多个维度,并提供与 matlab 类似的结果。 (如您所料,Numpy 提供了一个 3d 输出数组 - matlab 出于某种原因提供了 2d 输出 - 但内容是相同的)。
Matlab:
>> repmat([1;1],[1,1,1])
ans =
1
1
Python:
In [46]: a = np.array([[1],[1]])
In [47]: np.tile(a, [1,1,1])
Out[47]:
array([[[1],
[1]]])
【讨论】:
a 提升到 tile 参数的维度,方法是根据需要 preending 新轴。 Matlab 似乎以另一种方式工作。同样,使用 4d 平铺时,您将需要两次 newaxis...所以np.tile(a[:,newaxis,newaxis],[1,2,3,4]) = size(repmat(a,[1 2 3 4])) 根据需要...
numpy.matlib 有一个repmat 函数,其接口与matlab 函数类似
from numpy.matlib import repmat
repmat( np.array([[1],[1]]) , 1, 1)
【讨论】:
这就是我通过一些摆弄来理解它的方式。很高兴得到纠正,希望对您有所帮助。
假设您有一个由 2x3 元素组成的矩阵 M。这显然有两个维度。
在要求沿矩阵已有的维度操作输入矩阵时,我看不出 Matlab 和 Python 之间没有区别。 因此这两个命令
repmat(M,m,n) % matlab
np.tile(M,(m,n)) # python
对于秩为 2(二维)的矩阵实际上是等价的。
当您要求在比输入矩阵更多的维度上重复/平铺时,事情就会违反直觉。回到秩为 2 且形状为 2x3 的矩阵 M,看看输出矩阵的大小/形状发生了什么就足够了。假设现在的操作顺序是 1,1,2。
在 Matlab 中
> size(repmat(M,1,1,2))
ans =
2 3 2
它复制了输入矩阵的前两个维度(行和列),并在新的第三个维度中重复了一次(即复制了两次)。与重复矩阵的命名 repmat 一致。
在 Python 中
>>> np.tile(M,(1,1,2)).shape
(1, 2, 6)
它应用了不同的程序,因为我认为序列 (1,1,2) 的读取方式与在 Matlab 中不同。从右向左读取列、行和平面外尺寸方向的份数。生成的对象具有与 Matlab 不同的形状。不能再断言repmat 和tile 是等效的指令。
为了让tile 表现得像repmat,在Python 中必须确保输入矩阵的维度与序列中的元素一样多。例如,这是通过一些预处理和创建相关对象 N
N = M[:,:,np.newaxis]
然后,在输入端有N.shape = (2,3,1) 而不是M.shape = (2,3) 在输出端
>>> np.tile(N,(1,1,2)).shape
(2, 3, 2)
这是size(repmat(M,1,1,2)) 的答案。我想这是因为我们已经引导 Python 将第三维添加到 (2,3) 的右侧而不是左侧,以便 Python 按照 Matlab 中的预期计算出序列 (1,1,2)阅读方式。
N 的 Python 答案中 [:,:,0] 中的元素将包含与 M 的 Matlab 答案中的元素 (:,:,1) 相同的值。
最后,当有人使用 Kronecker 产品时,我似乎找不到 repmat 的等价物
>>> np.kron(np.ones((1,1,2)),M).shape
(1, 2, 6)
除非我将 M 置于 N 中,如上。所以我认为最通用的方法是使用np.newaxis 的方式。
当我们考虑 3 阶(三个维度)的矩阵 L 和输出矩阵中没有添加新维度的简单情况时,游戏变得更加棘手。这两条看似等效的指令不会产生相同的结果
repmat(L,p,q,r) % matlab
np.tile(L,(p,q,r)) # python
因为行、列、平面外的方向是 Matlab 中的 (p,q,r) 和 Python 中的 (q,r,p),这对于 rank-2 数组是不可见的。在那里,必须小心,使用两种语言获得相同的结果需要更多的预处理。
我知道这种推理可能并不普遍,但我只能到此为止。希望这会邀请其他人对其进行更严格的测试。
【讨论】:
知道tile 和repeat。
x = numpy.arange(5)
print numpy.tile(x, 2)
print x.repeat(2)
【讨论】:
请注意,您需要使用 MATLAB 的 repmat 的一些原因由 NumPy 的 broadcasting 机制处理,该机制允许您对形状相似的数组进行各种类型的数学运算。因此,如果您有一个表示 3 色图像的 1600x1400x3 数组,您可以(按元素)将其乘以 [1.0 0.25 0.25] 以减少每个像素的绿色和蓝色数量。有关详细信息,请参阅上面的链接。
【讨论】:
bsxfun,Matlab 也不能做这种广播。