4

Sの時点で行われたN個の測定値のセットがあります(時点は測定ごとに異なります)。私は2つの行列を持っています:

V-測定値を表すNxSマトリックス

T-測定時間を表すNxSマトリックス

時間TIで線形補間された測定値を表す行列VIを生成したいと思います。ベクトル化されていないバージョンのコードは次のとおりです。

tic;
VI = zeros([size(V,1), size(TI,2)]);
for j = 1:size(V,1)
    VI(j,:) = interp1(T(j,:),V(j,:),TI);
end
toc;

このコードを書き直してforループを削除し、行列演算と関数を使用して実装されるようにします。ベクトル化できますか?

4

4 に答える 4

2

データがなく、プロファイラーを実行していないと言うのは難しいですが、データが並べ替えられている場合は、データのチェックを行わないinterp1qの代わりに使用できます。interp

Matlabヘルプから取得:

interp1qが正しく機能するには、xが単調に増加する列ベクトルである必要があります。Yは、length(x)行の列ベクトルまたは行列である必要があります。xiは列ベクトルでなければなりません

于 2012-09-20T07:50:15.107 に答える
1

あなたが言うように、すべての測定の測定時間が異なる場合 (T は行列であり、ベクトルではありません)、次のように arrayfun を 1 回呼び出すだけで、必要なことを行うことができます。

VI = arrayfun(@(x)(interp1(T(x,:),V(x,:),TI)), 1:size(V, 1), 'UniformOutput', false);
VI = cell2mat(VI');

arrayfun はループに似ていますが、内部の matlab 関数であるため、より高速な場合があります。これはベクトルのセルを返すため、2 行目で出力として行列があることを確認します。あなたはそれを必要としないかもしれません-それは後でデータをどうするかによって異なります.

一方、N の異なる値に対して測定値が同時に取得された場合 (T はサイズ S のベクトルであり、行列ではありません。つまり、T のすべての行が等しい場合)、1 回の呼び出しで補間できます。 interp1 へ。

VI = interp1(T(1,:), V', TI)

ここでは、interp1 が列内で補間されるため、V を転置する必要があります。これは、MATLAB が行列を列単位で格納するためです (列はメモリ内で連続しています)。V を SxN 行列として渡すと、すべての CPU がより効率的な方法でメモリにアクセスできるため、interp1 のより効率的な並列化が可能になる可能性があります。したがって、もちろん、パフォーマンス上の理由でこの正確なデータ レイアウトを別の場所に依存しない限り、コード全体で行列を転置することをお勧めします。

編集行列の列レイアウトのため、行列を転置して列ごとに作業することで元のコードを改善できます。次のバージョンは、N=1000、S=10000、TI が 10000 要素の場合、私のコンピューターで約 20% 高速です。メモリ帯域幅の使用効率が向上するため、システム サイズとともに大きくなる可能性があります。

tic;
VI = zeros(size(TI,2), size(V,2));
for j = 1:size(V,2)
    VI(:,j) = interp1(T(:,j),V(:,j),TI);
end
toc;
于 2012-09-20T07:39:07.367 に答える
1

Matlab はデータを行ではなく列にパックするため、ループを行から列へと変更するだけで速度が向上すると思われます。

[N, S] = size(V);

VT = V';                             % Value series in columns
TT = T';                             % Time series in columns
VIT = zeros(length(TI), N);          % Interpolated value series in columns

for j = 1:N
    VIT(:, j) = interp1(VT(:, j), TT(:, j), TI);
end

VI = VIT';                           % Interpolated value series in rows

残念ながら、異なる値シリーズには関連する時系列がないため、このコードのパフォーマンスをさらに改善するためにできることはあまりないと思います。Tでベクトルに折りたたむことができるように、それらが同じ時間を持っている場合、これlength(T) = Sを行うのは簡単です。

VIT = interp1(VT, T, TI);            % (see VIT and VT from above)
于 2012-09-20T04:45:37.820 に答える
0

私は仕事をしているので、慣れる時間がありませんinterp1(これまで使用したことがありません)。次の回答が不適切である場合は、事前にお詫び申し上げます。

そうは言っても、ループの反復は互いに依存しないため、ベクトル化が可能になるはずです。mat2cellandを使用して明示的なループを取り除くことができるように思えますcellfun

私が意味することの簡単な例は次のとおりです。

NumRow = 4;
NumCol = 3;
V = randn(NumRow, NumCol);
VCell = mat2cell(V, ones(NumRow, 1), NumCol);
A = cellfun(@sum, VCell);

もちろん、私が行ったことは と同等sum(V, 2)です。しかし、私が使用した方法はあなたの状況にも当てはまると思います。この関数はセルの列ベクトルにmat2cell変換します。ここで、各セルには V の行が含まれます。次に、 の呼び出しにより関数がの各セルに適用され、結果が に返されます。もちろん、入力を適切に調整して、単に置き換えることができる場合があります。VcellfunsumVCellA@sum@interp1cellfun

うまくいかない場合はお知らせください。家に帰ったら、より明確なものをまとめてみます。また、動作するようになったとしても、速度があまり速くならない場合は、それを知りたいので、結果をここに投稿してください。

于 2012-09-20T03:02:56.043 に答える