【问题标题】:Vectorize MATLAB code向量化 MATLAB 代码
【发布时间】:2016-04-21 18:46:08
【问题描述】:

假设我们有三个大小相等的 m×n 矩阵:ABC

C 中的每一列代表一个时间序列。
AC 中每个时间序列的运行最大值(在固定窗口长度上)。
B 是运行最小值C中每个时间序列的(在固定窗口长度上)。

有没有办法以矢量化的方式确定T

[nrows, ncols] = size(A);
T = zeros(nrows, ncols);
for row = 2:nrows                           %loop over the rows (except row #1).
    for col = 1:ncols                       %loop over the columns.
        if     C(row, col) > A(row-1, col)
            T(row, col) =  1;
        elseif C(row, col) < B(row-1, col)
            T(row, col) = -1;
        else
            T(row, col) = T(row-1, col);
        end
    end
end

这是我目前想出的:

T = zeros(m, n);
T(C > circshift(A,1)) =  1;
T(C < circshift(B,1)) = -1;

【问题讨论】:

  • 您能否举例说明T 的预期值?发现有点难以遵循代码...您还可以提供示例输入矩阵吗?
  • @rayryeng 我编辑了问题并将循环索引变量名称从m 更改为row,从n 更改为col。我希望这能让事情变得更清楚。我仍在努力想出一个很好的例子来说明 T 应该是什么样子。
  • 我会自己编写代码,看看我是否能理解它。
  • @rayryeng 为了更好地理解,我刚刚删除了一个不必要的变量。所以现在只剩下三个输入矩阵:ABC。我还添加了一个描述 w.r.t.这些矩阵代表什么。

标签: matlab vectorization


【解决方案1】:

嗯,问题在于与条件语句的 ELSE 部分的依赖关系。所以,经过长时间的脑力锻炼,我总结出一种方法来矢量化 hell-outta 一切。

现在,这种方法基于映射。我们得到与ELSE 部分的2D 掩码相对应的列式运行或1s 岛,并为它们分配相同的标签。然后,我们沿着每个此类运行的每一列转到start-1 并存储该值。最后,用这些标记的数字对每个这样的start-1 进行索引,这将作为映射索引为我们提供要在新输出中设置的所有元素。

这是实现所有这些愿望的实现 -

%// Store sizes
[m1,n1] = size(A);

%// Masks corresponding to three conditions
mask1 = C(2:nrows,:) > A(1:nrows-1,:);
mask2 = C(2:nrows,:) < B(1:nrows-1,:);
mask3 = ~(mask1 | mask2);

%// All but mask3 set values as output
out = [zeros(1,n1) ; mask1 + (-1*(~mask1 & mask2))];

%// Proceed if any element in mask3 is set
if any(mask3(:))

    %// Row vectors for appending onto matrices for matching up sizes
    mask_appd = false(1,n1);
    row_appd = zeros(1,n1);

    %// Get 2D mapped indices
    df = diff([mask_appd ; mask3],[],1)==1;
    cdf = cumsum(df,1);

    offset = cumsum([0 max(cdf(:,1:end-1),[],1)]);
    map_idx = bsxfun(@plus,cdf,offset);
    map_idx(map_idx==0) = 1;

    %// Extract the values to be used for setting into new places
    A1 = out([df ; false(1,n1)]);

    %// Map with the indices obtained earlier and set at places from mask3
    newval = [row_appd ; A1(map_idx)];
    mask3_appd = [mask_appd ; mask3];
    out(mask3_appd) = newval(mask3_appd);

end

【讨论】:

  • 亲爱的上帝。我不知道你到底是怎么想出来的。 +1。
  • @rayryeng 正是几个小时的精神折磨;)
  • 天哪,太不可思议了!! +1
  • @bluebox 感谢您的称赞,有些工作! :D
【解决方案2】:

进行矢量化处理相当困难,因为当前行的输出取决于前一行的输出。进行矢量化操作通常意味着每个元素都应该使用独立于围绕它的其他元素的某种关系独立出来。

我没有任何关于在没有for 循环的情况下如何实现这一点的意见,但我可以帮助您将操作减少到一个而不是两个。您可以对每行进行矢量化分配,但我看不出您如何一次性完成所有操作。

因此,请尝试以下方法:

[nrows, ncols] = size(A);
T = zeros(nrows, ncols);
for row = 2:nrows                           
    out = T(row-1,:); %// Change - Make a copy of the previous row
    out(C(row,:) > A(row-1,:)) = 1; %// Set those elements of C 
                                    %// in the current row that are larger
                                    %// than the previous row of A to 1
    out(C(row,:) < B(row-1,:)) = -1; %// Same logic but for B now and it's 
                                     %// less than and the value is -1 instead
    T(row,:) = out; %// Assign to the output
end

我目前正在研究如何使用任何循环来做到这一点。我会及时通知你。

【讨论】:

  • 谢谢,这很有帮助! +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多