4

假设它f是一个参数的函数,它的输出是一个n维 ( m 1  ×  m 2 ... ×  m n ) 数组,它B是一个长度为k的向量,其元素都是 的有效参数f

我正在寻找一个方便的,更重要的是,“形状不可知”的 MATLAB 表达式(或配方),用于生成 ( n +1) 维 ( m 1  ×  m 2  ×…×  m n  ×  k ) 数组“堆叠” k n维数组f(b),其中参数b范围超过B

为此numpy,我将使用如下表达式:

C = concatenate([f(b)[..., None] for b in B], -1)

如果它有任何用处,我将在下面解压缩这个 numpy 表达式(参见附录),但我现在要强调的特征是它完全不知道 和 的形状/ f(b) 大小 B。对于我想到的应用程序类型,编写这种“与形状无关”的代码的能力至关重要。(我强调这一点,因为我在进行这种操作时遇到的许多 MATLAB 代码显然不是“与形状无关的”,而且我不知道如何做到这一点。)


附录

一般来说,如果A是一个 numpy 数组,那么表达式A[..., None]可以被认为是“重塑” A,以便它获得一个额外的、微不足道的维度。因此,如果f(b)是一个n维 ( m 1  ×  m 2 … ×  m n ) 数组,则f(b)[..., None]是对应的 ( n +1) 维 ( m 1  ×  m 2  ×…×  m n  × 1) 数组。(添加这个微不足道的维度的原因将在下面变得清楚。)

有了这个澄清,第一个参数的含义concatenate,即:

[f(b)[..., None] for b in B]

不太难破译。它是一个标准的 Python“列表推导”,它计算为k ( n +1) 维 ( m 1  ×  m 2  ×…×  m n  × 1) 数组的序列f(b)[..., None],因为参数b范围在 vector 上B

to的第二个参数concatenate是要执行连接的“轴”,表示为要连接的数组的相应维度的索引。end在这种情况下,索引 -1 与MATLAB中的关键字所起的作用相同。因此,表达式

concatenate([f(b)[..., None] for b in B], -1)

说“f(b)[..., None]沿它们的最后一个维度连接数组”。正是为了提供这个“最后一个维度”来连接,所以有必要对f(b)数组进行整形(例如,使用f(b)[..., None])。

4

2 回答 2

6

一种方法是:

 % input:
 f=@(x) x*ones(2,2)
 b=1:3;
 %%%%
 X=arrayfun(f,b,'UniformOutput',0);
 X=cat(ndims(X{1})+1,X{:});

也许有更优雅的解决方案?

于 2012-09-19T02:07:57.737 回答
1

形状不可知性是 NumPy 和 Matlab 背后的哲学之间的重要区别。在 Matlab 中比在 NumPy 中更难完成。在我看来,形状不可知论也是一件坏事——矩阵的形状具有数学意义。如果某些函数或类完全忽略输入的形状,或者以不符合数学符号的方式更改它们,那么该函数会破坏语言的部分功能和意图。

用程序员的话来说,它是一个真正有用的功能,旨在防止与形状相关的错误。当然,这通常是“程序上的不便”,但这不是调整语言的理由。这一切都在心态上。

现在,话虽如此,我怀疑 Matlab 中是否存在针对您的问题的优雅解决方案 :) 我的建议是将所有要求填充到函数中,这样您就不必进行任何后处理:

f = @(x) bsxfun(@times, permute(x(:), [2:numel(x) 1]), ones(2,2, numel(x)) )

现在显然这不太正确,因为f(1)它不起作用并且f(1:2)做了除 之外的其他事情f(1:4),所以显然必须进行一些修补。但正如这个单线器的丑陋已经表明的那样,专用功能可能是一个更好的主意。Oli 建议的那个相当不错,只要你将它锁定在它自己的函数中:

function y = f(b)

    g = @(x)x*ones(2,2); %# or whatever else you want

    y = arrayfun(g,b, 'uni',false);
    y = cat(ndims(y{1})+1,y{:});
end

以便f(b)任何b产生正确的输出。

于 2012-09-19T05:10:41.870 回答