不使用索引或循环在Octave中迭代矩阵行

3

我试图理解是否有可能通过移除正在使用的for循环来更有效地使用Octave,以在矩阵X的每行上计算一个公式。

myscalar = 0
for i = 1:size(X, 1),
  myscalar += X(i, :) * y(i) % y is a vector of dimension size(X, 1)
  ...

这个公式比添加到标量更加复杂。真正的问题在于如何在没有索引的情况下迭代X行,以便我可以消除for循环。


我不明白你的代码应该做什么。在每个循环中,它只是将向量 X(i,:) 乘以标量 y(i)。你的 myscalar 实际上是一个向量。除非 X 只有一列,但那么为什么要设置它呢?而且为什么要转置进行乘法运算?此外,没有必要使用 size(X,1),Octave 已经有了 rowscolumns 函数来实现这个目的。 - carandraug
我的问题实际上是关于那个for循环,而不是任何特定的代码。确实,转置很令人困惑,所以我要修复它,但是否有一种方法可以去掉索引和for循环呢? - Robert Kubrick
可能是的,但我无法告诉你原因,因为这段代码毫无意义。myscalar 应该是一个标量吗?是乘法的和吗?还是矩阵?大小是多少?我不明白你想要什么。 - carandraug
好的,我已经修复了myscalar,但我不明白为什么专注于代码是如此重要的。这是一个通用问题,是否有一种方法可以避免在每行或每列应用公式时进行矩阵索引,而不是每个元素(在这种情况下向量化更为明显)? - Robert Kubrick
现在有意义了。之前我不明白myscalar发生了什么,因为你只是在覆盖它而不是添加它(使用=而不是+=)。 - carandraug
1个回答

7

是的,您可以使用广播来实现这一点(需要3.6.0或更高版本)。如果您了解Python,则可以使用相同的方法(来自Python的说明)。只需将矩阵乘以列即可。最后,cumsum执行加法,但我们只想要最后一行。

newx      = X .* y;
myscalars = cumsum (newx, 1) (end,:);

或者在一行中不使用临时变量

myscalars = cumsum (X .* y, 1) (end,:);

如果尺寸正确,则会自动执行广播。例如:
octave> a = [ 1 2 3
              1 2 3
              1 2 3];
octave> b = [ 1 0 2];
octave> a .* b'
warning: product: automatic broadcasting operation applied
ans =

   1   0   6
   1   0   6
   1   0   6

octave> a .* b
warning: product: automatic broadcasting operation applied
ans =

   1   2   3
   0   0   0
   2   4   6

警告的原因是这是一个新功能,可能会让用户感到困惑,并且在Matlab中不存在。您可以通过将warning("off", "Octave:broadcast")添加到您的.octaverc文件中永久关闭它。
对于使用旧版本Octave的人,可以直接调用bsxfun来实现相同的功能。
myscalars = cumsum (bsxfun (@times, X, y), 1) (end,:);

在Octave 3.6版本中是否可以做同样的事情,也许是(2.4)? - Kaha
1
@Kaha,没有2.4版本(版本2.0.16之后是2.9.14)。但只要实现了bsxfun,这也可以完成。我已经编辑了我的答案,展示了旧版本的替代方案。 - carandraug

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接