在Matlab中考虑这个问题:
>> clear M, M(:,:,:,1,:)=rand(10,10,2,1,5); size(M)
ans =
10 10 2 1 5
>> clear M, M(:,:,:,1,:)=rand(10,10,1,1,5); size(M)
ans =
10 10 5
>> clear M, M(:,:,1,1,:)=rand(10,10,1,1,5); size(M)
ans =
10 10 1 1 5
为什么第二行代码的行为与第一行和第三行代码不同?(即保持数组的5D形状)
不允许用冒号来表示单一维度吗?(第二行代码中的第三个维度)
你能在文件中找出相应的段落吗?
3条答案
按热度按时间agxfikkp1#
我找不到任何有关这一问题的具体文档,因此,除了猜测之外,我还将参考Loren Shure的一篇博客文章:“All about the Colon Operator“。大部分内容与这个问题没有密切关系。但有一条特别的信息值得详细说明,我将以她的一句话作为开始:
:
运算符在MATLAB中的行为因其用法不同而不同。这可能会导致混淆。相关信息遵循2-x-2到1-x-1-x-1-x-4的分配。例如:
这个任务是如何完成的呢?Loren解释道:
注意,我只需要在左右两边有相同数量的元素,值从右边注入,就好像数组已经变成了一个列向量。
因此,即使左边和右边的对象大小差别很大,赋值语句中出现的索引-
:
也会强制右边数组的形状,因为存在元素等价性,赋值语句的执行就好像向量被列化了,v
是reshape
-d的原始形状。在继续讨论问题示例之前,我想指出,在MATLAB中,尾随单元素维数(
1
s下标)在所有数组中是无限隐式的。为[赋值时的数组]指定的下标数不超过
ndims(B)
,不包括等于1的尾部下标。我们确实可以看到:
后面的单例,比如乘1或加0,总是在那里。
继续讨论问题示例,我认为在赋值时分配的数组中出现索引-
:
会使MATLAB在考虑到上述灵活性的情况下如何赋值时陷入困境。(给定前面的clear
),但是赋值仍然会把右边的数组强制成列向量的形式,而且强制数组 * 确实 * 有一个形状。更有可能的是,在给定代码的情况下,* 最 * 直观的行为是在将其值赋给
M
时保留右侧的形状,然而,另一个观点可能是尽可能多地保留M
的形状,以最小化赋值结果的大小。第一种行为是通过在赋值中不使用任何索引来立即实现的。我认为后一种行为更符合Loren的说法,即“值从右边注入,就像数组已经变成了列向量一样”。一旦右边被列化,单元素维度就几乎消失了。并且MATLAB将尽可能多地填充每个
:
桶,同时考虑显式维度,如示例中呈现的1
。所以
M(:,:,:,1,:)=rand(10,10,2,1,5);
工作得很好,因为M
的大小是通过匹配右边的大小来最小化的。M(:,:,:,1,:)=rand(10,10,1,1,5); size(M)
将在形状强制过程中删除中间的单例,三个连续的赋值-:
s将像桶一样被10 - 10 - 5数组填充,以最小化输出的大小。而剩下的单元素维度将被忽略,因为它们是隐式存在的。并且M(:,:,1,1,:)=rand(10,10,1,1,5);
的工作方式与第一个完全相同,因为第三个:
桶已经被替换为MATLAB将尊重的显式索引。我不确定在这个行为中是否有一个显式的
squeeze
,或者它只是形状强制的MATLAB引擎中的一个自然结果,所以我认为最好以这样的话结束:如果一个数组的形状很重要,那么应该尽可能地显式地确定它的大小,而不使用赋值索引。hts6caw32#
我认为左右两边的单元素维度匹配是一种误导,根据我的观察,右边的单元素维度被移除,剩下的维度与左手的
:
维度匹配:当然,这只有在我们用赋值语句创建一个新数组时才会发生,左手的
:
必须至少和右边的非单元素维度一样多:这也很有趣:
如果左手的
:
维至少与右侧的总维一样多,则保留单个维。如果少于此数,则删除单个维以尝试匹配维。[请记住,后面的单元素维度是隐式的,永远不会显式显示。因此,这里的第二个赋值语句创建了一个5D数组,但最后两个维度是单元素,因此没有显示。无论从什么Angular 看,该数组看起来都像一个3D数组。但您始终可以索引3D数组的第5个维度,因为它是单元素维度!]
7xzttuei3#
参见matlab中
squeeze
函数的definition:B = squeeze(A)返回与A具有相同元素的数组B,但删除了所有单例维。单例维是size(A,dim)= 1的任何维。二维数组不受squeeze的影响;如果A是行或列向量或标量(1 × 1)值,则B = A。
一种解决方案可能是在核心的源中,在某些情况下,它挤压给定的基质,这在不同的情况下可以变化,并且可以应用于基质的一部分,而不是整个基质。