未知维度矩阵的索引

Posted

技术标签:

【中文标题】未知维度矩阵的索引【英文标题】:Indexing of unknown dimensional matrix 【发布时间】:2012-04-26 03:03:46 【问题描述】:

我有一个非固定维度矩阵 M,我想从中访问单个元素。 元素的索引包含在向量 J 中。

例如:

M = rand(6,4,8,2);
J = [5 2 7 1];

output = M(5,2,7,1)

这次 M 有 4 个维度,但这是事先不知道的。这取决于我正在编写的算法的设置。也可能是这样的

M = rand(6,4);
J = [3 1];

output = M(3,1)

所以我不能简单地使用

output=M(J(1),J(2))

我正在考虑使用sub2ind,但这也需要它的变量逗号分隔..

@gnovice

这可行,但我打算大量使用这种从矩阵M 中提取的元素。那么如果每次访问M时都必须创建一个临时变量cellJ,这不会极大地减慢计算速度吗??

我也可以写一个单独的函数

function x= getM(M,J)
    x=M(J(1),J(2));
    % M doesn't change in this function, so no mem copy needed = passed by reference
end

并针对算法的不同配置进行调整。这当然是我的问题中没有包含的速度与灵活性的考虑因素。

但是:这仅可用于获取元素,用于设置除了实际使用索引(最好是线性索引)之外别无他法。我仍然认为 sub2ind 是一种选择。我想要的最终结果是这样的:

function idx = getLinearIdx(J, size_M)
    idx = ...
end

结果:

function lin_idx = Lidx_ml( J, M )%#eml
%LIDX_ML converts an array of indices J for a multidimensional array M to
%linear indices, directly useable on M
%
% INPUT
%   J       NxP matrix containing P sets of N indices
%   M       A example matrix, with same size as on which the indices in J
%           will be applicable.
%
% OUTPUT
%   lin_idx Px1 array of linear indices
%

% method 1
%lin_idx = zeros(size(J,2),1);
%for ii = 1:size(J,2)
%    cellJ = num2cell(J(:,ii)); 
%    lin_idx(ii) = sub2ind(size(M),cellJ:); 
%end

% method 2
sizeM = size(M);
J(2:end,:) = J(2:end,:)-1;
lin_idx = cumprod([1 sizeM(1:end-1)])*J;

end

方法 2 比方法 1 快 20(要转换的少量索引集 (=P))到 80(大量索引集 (=P))倍。容易选择

【问题讨论】:

是的,我误解了你的问题,@gnovice 的回答很好地解决了这个问题。 【参考方案1】:

对于J 可以是任意长度的一般情况(我假设它始终与M 中的维数匹配),您有几个选项:

    您可以使用num2cell 函数将J 的每个条目放入元胞数组的一个元胞中,然后使用colon operator 从这个元胞数组创建一个comma-separated list:

    cellJ = num2cell(J);
    output = M(cellJ:);
    

    您可以回避sub2ind 函数并自己用一点数学计算linear index:

    sizeM = size(M);
    index = cumprod([1 sizeM(1:end-1)]) * (J(:) - [0; ones(numel(J)-1, 1)]);
    output = M(index);
    

【讨论】:

刚刚编辑完问题,谢谢!我想如果我在配置时将它编译成一个 emlmex 函数,计算量将是最小的 :) 当我有更多的实现时,我会发布结果 @GuntherStruyf:很高兴能提供帮助,尽管我觉得这可能是一个微优化。我猜你代码中的性能瓶颈不会是索引矩阵所花费的时间,所以这些解决方案中的任何一个都应该是好的。 可能,但欢迎每一个小改进 8 小时的计算时间很长:P @GuntherStruyf:您能做的最好的事情就是使用 MATLAB Profiler 找出花费最多的时间并对其进行优化。数组索引可能只占运行时间的 0.1%。即使您神奇地完全消除了这一成本,您的总运行时间 8 小时也会减少... 30 秒。另一方面,尽可能使用 MATLAB 内置函数(用 C 语言编写),在开始循环之前预先分配数组 - 这些都可以显着提升性能。 我只想让我的代码“干净”,当存在更好的解决方案时我不喜欢快速而肮脏的解决方案(这需要更多的努力)在这种情况下,我认为, num2cell 方法是快速而肮脏的方式,另一种方式是索引计算。我很高兴在这种情况下有这样一个简单而整洁的解决方案。我熟悉分析器,但无论如何感谢您的建议。我正在为优化问题构建一个新的解决框架,因为旧框架充满了如此快速和肮脏的修复,而且总体上很慢:/【参考方案2】:

这里是 gnovices 选项 2) 的一个版本,它允许处理整个下标矩阵,其中每一行包含一个下标。例如 3 个下标:

J = [5 2 7 1 
     1 5 2 7
     4 3 9 2];

sizeM = size(M);
idx = cumprod([1 sizeX(1:end-1)])*(J - [zeros(size(J,1),1) ones(size(J,1),size(J,2)-1)]).';

【讨论】:

以上是关于未知维度矩阵的索引的主要内容,如果未能解决你的问题,请参考以下文章

MATLAB中怎样初始化(创建)二维三维四维以及多维矩阵,各维度的索引顺序是怎样的?

来自库编译器的 Python 包:Matlab 运行时错误:索引超出矩阵维度

将ndarray对象的数据按索引矩阵进行选取的几种方法

如何通过另一个具有位置(索引)的垫子访问opencv中的矩阵数据

(Matlab) 使用 min 函数返回的索引进行维度索引

使用向量作为矩阵的索引