web-dev-qa-db-ja.com

MATLABで長さが不明な行列?

私は、whileループの結果を出力できる2つの列を持つ可変長のゼロ行列を設定しようとしています(これを使用して、調整された時間ステップでオイラー法のステップデータを格納します)。長さは、ループの反復回数によって決まります。

ループの実行中にこれを行う方法があるのか​​、それとも最初からループを設定する必要があるのか​​、そしてそれをどのように行うのかについて疑問に思っています。

24
Flick

列の数が固定されている場合、行列に行を常に追加できます(ループ内)

例えば.

while (....)
   .....
   new_row =[x y] ; % new row with values x & y
   mat = [mat ; new_row]; 

もちろん、whileループの前の反復回数がわかっている場合は、行列を事前に割り当てる方が効率的です

14
LiorH

スペース効率を維持しながらパフォーマンスを念頭に置いた別のアプローチは、メモリを大きなバッチで事前に割り当て、必要に応じてバッチを追加することです。これは、事前に何個あるかを知らずに多数のアイテムを追加する必要がある場合に適しています。

_BLOCK_SIZE = 2000;                          % initial capacity (& increment size)
listSize = BLOCK_SIZE;                      % current list capacity
list = zeros(listSize, 2);                  % actual list
listPtr = 1;                                % pointer to last free position

while Rand<1-1e-5                           % (around 1e5 iterations on avrg)
  % Push items on list
  list(listPtr,:) = [Rand rand];            % store new item
  listPtr = listPtr + 1;                    % increment position pointer

  % add new block of memory if needed
  if( listPtr+(BLOCK_SIZE/10) > listSize )  % less than 10%*BLOCK_SIZE free slots
    listSize = listSize + BLOCK_SIZE;       % add new BLOCK_SIZE slots
    list(listPtr+1:listSize,:) = 0;
  end
end
list(listPtr:end,:) = [];                   % remove unused slots
_

[〜#〜] edit [〜#〜]:時間の比較として、以下のケースを検討してください:

  1. 上記と同じコードを50000回繰り返しました。
  2. 行列全体を事前に事前割り当てする:list = zeros(50000,2); list(k,:) = [x y];
  3. ベクトルを行列に動的に追加:list = []; list(k,:) = [x y];

私のマシンでは、結果は次のとおりでした。

1)経過時間は0.080214秒です。
2)経過時間は0.065513秒です。
3)経過時間は24.433315秒です。


更新:

コメントでの議論に続いて、最新のR2014bリリースを使用していくつかのテストを再実行しました。結論として、MATLABの最近のバージョンでは、自動配列拡張のパフォーマンスが大幅に向上しています。

ただし、落とし穴があります。配列は最後の次元(2D行列の場合は列)全体で拡大する必要があります。そのため、元々意図したように行を追加することは、事前割り当てなしでは依然として遅すぎます。これは、上記の提案されたソリューションが本当に役立つ場合があります(配列をバッチで拡張することにより)。

テストの完全なセットについては、ここを参照してください: https://Gist.github.com/amroamroamro/0f104986796f2e0aa618

47
Amro

MATLABは、自動メモリ管理で動的型付けを使用します。これは、使用する前に固定サイズの行列を宣言する必要がないことを意味します-進行中に変更でき、MATLABがメモリを動的に割り当てます。

[〜#〜] but [〜#〜]これはway最初に行列にメモリを割り当てる方が効率的であり、次にそれを使用します。しかし、プログラムがこの種の柔軟性を必要とする場合は、それに従ってください。

行列に行を追加し続ける必要があると思います。次のコードが機能するはずです。

_Matrix = [];

while size(Matrix,1) <= 10
    Matrix = [Matrix;Rand(1,2)];
end

disp(Matrix);
_

ここでは、新しい行を追加するたびに、Matrixに必要なスペースを動的に再割り当てしています。たとえば、取得する行数の上限が事前にわかっている場合は、Matrix = zeros(20,2)を宣言してから、各行を増分的に行列に挿入できます。

_% Allocate space using the upper bound of rows (20)
Matrix = zeros(20,2);
k = 1;
for k = 1:10
   Matrix(k,:) = Rand(1,2);
end
% Remove the rest of the dummy rows
Matrix(k+1:end,:) = [];
_
7
Jacob

ジェイコブが投稿した同じものの別の味。

for counter = 1:10
    Matrix(counter,:) = Rand(1,2);
end
disp(Matrix);

これに関する「良い」点の1つは、パフォーマンスを向上させるために最小サイズを推測できることです。

これも興味深いかもしれません: http://www.mathworks.com/help/matlab/math/resizing-and-reshaping-matrices.html#f1-8876

4
ccook