4

これが可能かどうかはわかりませんが、MATLABについての私の理解は確かに良くなる可能性があります。

プログラムにかなりのボトルネックが発生しているため、ベクトル化したいコードがいくつかあります。これは最適化ルーチンの一部であり、実行する短期平均(STA)、長期平均(LTA)、および感度(OnSense)の多くの可能な構成があります。

時間はベクトル形式で、FL2onSSはメインデータ(Nx1 double)、FL2onSSSTAはそのSTA(NxSTA double)、FL2onSSThreshはそのしきい値(NxLTAxOnSense double)です。

アイデアは、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

コードは十分に単純なので、これ以上説明しません。特定の行が何をしているのかを解明する必要がある場合は、私に知らせてください。

4

1 に答える 1

5

秘訣は、主にrepmatpermuteを使用して、すべてのデータを同じ形式にすることです。次に、ロジックは単純な部分です。

最後の部分を実装するには、厄介なトリックが必要でした(条件が満たされない場合は、最後の結果を使用してください)。通常、この種のロジックは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.
于 2010-02-10T08:58:31.857 に答える