【问题标题】:Difference between `eye(2)` and `[1, 0; 0, 1]` in automatic broadcasting`eye(2)` 和 `[1, 0; 0, 1]` 在自动广播中
【发布时间】:2019-12-23 08:37:13
【问题描述】:

我想从 Octave(版本 4.4.1)中单位矩阵的每一列中减去一个向量 v,例如v = [1; 1].

为什么自动广播对命令eye 不起作用?

eye(2) - [1; 1]

error: operator -: nonconformant arguments (op1 is 2x2, op2 is 1x2)

bsxfun(@minus,eye(2),[1; 1])[1, 0; 0, 1] - [1; 1] 都产生了

[0, -1; -1, 0]

为什么 Octave 在自动广播中做出这种区分?为什么eye(2) 不等于[1, 0; 0, 1]


注意:在Matlab R2016a中,我没有自动广播,所以我只能使用bsxfun(@minus,eye(2),[1; 1]),这样是一致的,不会那么混乱。

【问题讨论】:

  • 输入isequal([1, 0; 0, 1], eye(2)),无论他们是否相等,您都会得到答案
  • 我刚刚在工作中检查了 matlab (R2018b),可以确认 eye(2)-[1;1] 产生了预期的广播结果。此外,对于任何感兴趣的人(参考下面我的回答),在 matlab 中,eye(2) 返回一个标准的完整矩阵,而不是像 Octave 中的内存优化对象。
  • @LuisMendo 在 matlab 中,是的。它们都是完整的矩阵。然而,在八度音程中,情况并非如此。第一个创建一个“矩阵”类型的对象(双精度类),而后者创建一个“对角矩阵”类型的对象(双精度类)。创建两者并比较 matlab 和 octave 中的“whos”以了解我的意思。另请参阅下面的我的答案。 typeinfo 函数仅存在于 octave 中,但据我了解,它指的是其他内置对象的类型(而不是用户创建的类,这是一种不同的机制),并暗示这些类型是如何实现的引擎盖。
  • @Tasos 啊,我明白了。我对 Octave 不太熟悉,但我记得冒号表达式创建“范围”对象而不是向量的类似内容
  • @DaveFar:DaveFar 感谢您的补充,但是,我已经恢复了这一点,因为 [ <specialised matrix> ] 语法不能保证将专用矩阵转换为其正常(即“完整”)版本。执行此操作的适当函数是 full 函数(例如 full(eye(2))full(sparse[1,0;0,1]))full(1:10)

标签: matlab matrix octave broadcast


【解决方案1】:

对此(至少在八度音程中)的技术答案是 eye(2) 不会产生与 [1,0;0,1] 相同的类型;它会产生一个内存效率高的对角矩阵,并且 octave 没有为对角矩阵类型实现可广播的减法函数(尚未*)。

> typeinfo([1,0;0,1])
ans = matrix

> typeinfo(eye(2))
ans = diagonal matrix

> diag([1,1])- [1;1]
% error: operator -: nonconformant arguments (op1 is 2x2, op2 is 2x1)

> full( diag([1,1]) ) - [1;1]
% works

事实上,如果你尝试广播等效的稀疏矩阵,你会遇到同样的问题:

> sparse([1,0;0,1]) - [1;1]
%error: operator -: nonconformant arguments (op1 is 2x2, op2 is 2x1)

如果您想在不转换回完整矩阵的情况下执行广播(例如通过full(eye(2)) - [1; 1]),您可以使用bsxfun,这是一个旨在显式执行广播的函数。

话虽如此,bsxfun 的输出是一个普通矩阵,这意味着如果你先从专门的类型中“收集”full 矩阵,然后按预期使用广播,你会得到相同的结果,因此我怀疑在这种情况下,使用 bsxfun 可以提高效率。相反,当 bsxfun 与 bsxfun( @(x,y) x-y, eye(2), [1;1] ) 等计算成本高的反模式一起使用时,可能会导致性能下降(这很常见,但幸好不是你所做的)。


* 话虽如此,如果这不是一个错误,那么它肯定是一个特性。在 octave bugtracker 上打开一张票是值得的(如果还没有的话!)。

【讨论】:

【解决方案2】:

在 R2016b 中,Matlab 更改了 隐式扩展 算法,请参见 blog-post from Loren - on the art of Matlab。还有一个有用的帖子here

基本上,它使 Matlab 对不喜欢编程的人更加用户友好,他们只是想把事情做好,他们主要是工程师(比如我)。因此,如果向量不适合一维矩阵,Matlab 现在将扩展向量(该维度将被扩展)。这既好又坏。您的代码变得更短且更具可读性(因为您不需要使用 repmat 手动扩展它)但它也使您的代码容易出现代码中的缺陷,这些缺陷将被忽略并导致更多奇怪的错误. 在任何情况下,如果涉及代码生成,您仍然需要使用repmat 显式扩展向量。

【讨论】:

  • 严肃地说,在 bsxfun / 隐式扩展和 repmat 之间,扩展更可取。在大多数情况下,repmat 往往会带来巨大的计算损失。
  • 虽然是一堂有趣的历史课,但这似乎并没有解决有关 eye() 的不同处理的问题。
  • 询问为什么 eye(2) - [1,1] 不起作用与隐式扩展完全相关,因为原始 matlab 只能减去相同大小的标量或矩阵(而不是将 1x2 向量隐式扩展为 2x2 矩阵)。因此,它实际上是在回答原始问题@NickJ
  • 但是 MATLAB 在隐式扩展方面赶上 Octave 并不能解决为什么 eye(2) - [1,1] 不起作用而 [1,0;0,1] - [1,1] 起作用的原始问题。
猜你喜欢
  • 2017-11-28
  • 2018-09-26
  • 1970-01-01
  • 2013-07-15
  • 1970-01-01
  • 2014-12-30
  • 1970-01-01
  • 2013-05-29
  • 1970-01-01
相关资源
最近更新 更多