在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形状)
是否允许冒号代表单身维度? (第二个代码行中的第三维)
您能否在文档中找出相应的段落?
答案 0 :(得分:4)
我无法找到关于此事的任何具体文档,因此,除了推测之外,我将引用Loren Shure的博客文章:" All about the Colon Operator"。其中大部分与这个问题没有密切关系。但是有一条特别值得详细说明的信息,以及我将以其开头的结尾引用:
:
运算符在MATLAB中的行为有所不同,具体取决于其用法。这可能会导致混淆。
相关信息遵循2乘2到1乘1乘4的分配。例如:
>> v(1,1,1,1:4) = 1:4;
>> v(:) = [5,6;7,8]
v(:,:,1,1) =
5
v(:,:,1,2) =
7
v(:,:,1,3) =
6
v(:,:,1,4) =
8
这项任务是如何运作的?洛伦解释说:
请注意,我只需要在左侧和右侧都有相同数量的元素。这些值从右侧排出,就像该数组已被转换为列向量一样。
因此,即使左手和右手的对象具有非常不同的大小,分配中的索引外观 - :
也会强制右手数组的形状,因为存在元素等价。并且将执行赋值,就好像向量是列为列,并且v
为reshape
- d为其原始形状。
在继续讨论问题示例之前,我想指出尾随单例维度(1
s下标)在MATLAB中的所有数组上都是无限隐含的。引用Matrix Indexing:
为[分配时的数组]指定的下标数,不包括等于1的尾随下标,不超过
ndims(B)
。
我们确实可以看到这一点:
>> clear A; A(:,:,1,1,1,1,1,1,1,1,1) = rand(2,2)
A =
0.6355 0.7823
0.8439 0.2646
>> A(2,2,1,1,1,1,1,1,1,1,1)
ans =
0.2646
>> clear A; A = 5; A(1,1,1,1,1,1,1,1,1,1,1,1,1,1)
ans =
5
跟随单身,如乘以1或加零,总是那里。
继续讨论问题的例子,我认为在分配at-assignment的数组中索引的出现 - :
会让MATLAB陷入困境,当涉及到如何分配给定上述灵活性的值。与Loren的例子不同,M
没有形状可以保留(给定前面的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)
将在形状强制期间删除中间单例,三个连续的赋值 - :
将被填充,就像带有十个十五个数组的桶一样,以最小化输出的大小,其余单身尺寸将被忽略,因为它们隐含在那里。 M(:,:,1,1,:)=rand(10,10,1,1,5);
的工作方式与第一个完全相同,因为第三个:
存储桶已被MATLAB所尊重的显式索引替换。
我不确定此行为中是否存在明确的squeeze
,或者它是否只是形状强制的MATLAB引擎中某处的自然结果。所以我认为最好结束时说如果数组的形状很重要,那么应该尽可能明确地调整数组的大小,而不是尽可能地分配索引。
答案 1 :(得分:1)
请参阅matlab中squeeze
函数的definition:
B = squeeze(A)返回一个阵列B,其元素与A相同,但删除了所有单例维度。单个维度是尺寸(A,dim)= 1的任何维度。二维阵列不受挤压的影响;如果A是行或列向量或标量(1乘1)值,则B = A.
一个解决方案可能是核心的来源,在某些情况下会挤压给定的矩阵。这可以在不同的情况下变化,并且可以应用于矩阵的一部分,而不是整个矩阵。