我不太确定这是否可能,但我对MATLAB的理解肯定会更好。
我有一些代码我希望向量化,因为它在我的程序中造成了相当大的瓶颈。它是优化例程的一部分,优化例程有许多可能的配置,包括短期平均、长期平均和灵敏度(OnSense)。
时间是矢量格式,FL2onSS是主要数据( Nx1双精度),FL2onSSSTA是它的STA (NxSTA双精度),FL2onSSThresh是它的阈值(NxLTAxOnSense双精度)
这个想法是计算红色警报矩阵,它将是4D -整个程序其余部分使用的alarmStatexSTAxLTAxOnSense。
Red = zeros(length(FL2onSS), length(STA), length(LTA), length(OnSense), 'double');
for i=1:length(STA)
for j=1:length(LTA)
for k=1:length(OnSense)
Red(:,i,j,k) = calcRedAlarm(Time, FL2onSS, FL2onSSSTA(:,i), FL2onSSThresh(:,j,k));
end
end
end我目前已经得到了这个重复一个函数,试图获得更快的速度,但显然,如果整个事情都可以矢量化,那就更好了。换句话说,如果有更好的解决方案,我不需要保留这个函数。
function [Red] = calcRedAlarm(Time, FL2onSS, FL2onSSSTA, FL2onSSThresh)
% Calculate Alarms
% Alarm triggers when STA > Threshold
zeroSize = length(FL2onSS);
%Precompose
Red = zeros(zeroSize, 1, 'double');
for i=2:zeroSize
%Because of time chunks being butted up against each other, alarms can
%go off when they shouldn't. To fix this, timeDiff has been
%calculated to check if the last date is different to the current by 5
%seconds. If it isn't, don't generate an alarm as there is either a
%validity or time gap.
timeDiff = etime(Time(i,:), Time(i-1,:));
if FL2onSSSTA(i) > FL2onSSThresh(i) && FL2onSSThresh(i) ~= 0 && timeDiff == 5
%If Short Term Avg is > Threshold, Trigger
Red(i) = 1;
elseif FL2onSSSTA(i) < FL2onSSThresh(i) && FL2onSSThresh(i) ~= 0 && timeDiff == 5
%If Short Term Avg is < Threshold, Turn off
Red(i) = 0;
else
%Otherwise keep current state
Red(i) = Red(i-1);
end
end
end代码很简单,所以我就不再详细解释了。如果您需要说明某一行正在做什么,请让我知道。
发布于 2010-02-10 16:58:32
诀窍是将所有数据转换为相同的表单,主要使用和permute。那么逻辑就是简单的部分。
我需要一个糟糕的技巧来实现最后一部分(如果所有条件都不成立,则使用最后的结果)。通常,这种逻辑是使用cumsum来完成的。我不得不使用另一个2.^n的矩阵来确保使用定义的值(这样+1,+1,-1将真正得到1,1,0) -只要看看代码:)
%// define size variables for better readability
N = length(Time);
M = length(STA);
O = length(LTA);
P = length(OnSense);
%// transform the main data to same dimentions (3d matrices)
%// note that I flatten FL2onSSThresh to be 2D first, to make things simpler.
%// anyway you don't use the fact that its 3D except traversing it.
FL2onSSThresh2 = reshape(FL2onSSThresh, [N, O*P]);
FL2onSSThresh3 = repmat(FL2onSSThresh2, [1, 1, M]);
FL2onSSSTA3 = permute(repmat(FL2onSSSTA, [1, 1, O*P]), [1, 3, 2]);
timeDiff = diff(datenum(Time))*24*60*60;
timeDiff3 = repmat(timeDiff, [1, O*P, M]);
%// we also remove the 1st plain from each of the matrices (the vector equiv of running i=2:zeroSize
FL2onSSThresh3 = FL2onSSThresh3(2:end, :, :);
FL2onSSSTA3 = FL2onSSSTA3(2:end, :, :);
Red3 = zeros(N-1, O*P, M, 'double');
%// now the logic in vector form
%// note the chage of && (logical operator) to & (binary operator)
Red3((FL2onSSSTA3 > FL2onSSThresh3) & (FL2onSSThresh3 ~= 0) & (timeDiff3 == 5)) = 1;
Red3((FL2onSSSTA3 < FL2onSSThresh3) & (FL2onSSThresh3 ~= 0) & (timeDiff3 == 5)) = -1;
%// now you have a matrix with +1 where alarm should start, and -1 where it should end.
%// add the 0s at the begining
Red3 = [zeros(1, O*P, M); Red3];
%// reshape back to the same shape
Red2 = reshape(Red3, [N, O, P, M]);
Red2 = permute(Red2, [1, 4, 2, 3]);
%// and now some nasty trick to convert the start/end data to 1 where alarm is on, and 0 where it is off.
Weights = 2.^repmat((1:N)', [1, M, O, P]); %// ' damn SO syntax highlighting. learn MATLAB already!
Red = (sign(cumsum(Weights.*Red2))+1)==2;
%// and we are done.
%// print sum(Red(:)!=OldRed(:)), where OldRed is Red calculated in non vector form to test this.https://stackoverflow.com/questions/2234609
复制相似问题