MATLAB Language
ベクトル化
サーチ…
要素的な操作
MATLABはベクトルと行列のベクトル演算をサポートしています。
たとえば、 AとB 2つのn行m列の行列を持ち、 Cを対応する要素の要素ごとの積としたいとします(つまりC(i,j) = A(i,j)*B(i,j) )。
ネスト化されたループを使用した非ベクトル化の方法は、次のとおりです。
C = zeros(n,m);
for ii=1:n
for jj=1:m
C(ii,jj) = A(ii,jj)*B(ii,jj);
end
end
しかし、これを行うベクトル化された方法は、要素ごとの演算子.*を使用すること.*
C = A.*B;
Sum、mean、prod&co
与えられたランダムベクトル
v = rand(10,1);
要素の合計が必要な場合は、ループを使用しないでください
s = 0;
for ii = 1:10
s = s + v(ii);
end
sum()関数のベクトル化された機能を使用します
s = sum(v);
sum() 、 mean() 、 prod()などの関数は、行、列または他の次元に沿って直接操作することができます。
例えば、ランダムな行列
A = rand(10,10);
各列の平均は
m = mean(A,1);
各行の平均は
m = mean(A,2)
上のすべての関数は1次元でしか機能しませんが、行列全体を合計したい場合はどうすればよいでしょうか?あなたが使用することができます:
s = sum(sum(A))
しかし、もしNDアレイを持っていたら?適用sumにsumにsum ...使う代わりに、最良の選択肢のように見えるしていません:オペレーターがあなたの配列をベクトル化します。
s = sum(A(:))
これにより、すべての配列の合計である1つの数値となりますが、次元数には関係ありません。
bsxfunの使用
たいていの場合、コードがforループで記述されている理由は、 '近くのもの'からの値を計算することです。関数bsxfunは、これをより簡潔な方法で行うためにしばしば使用されます。
たとえば、行列Bに対して列方向演算を実行し、その行列の各列の平均を引いたとします。
B = round(randn(5)*10); % Generate random data
A = zeros(size(B)); % Preallocate array
for col = 1:size(B,2); % Loop over columns
A(:,col) = B(:,col) - mean(B(:,col)); % Subtract means
end
このメソッドは、 Bが大きい場合は効率が悪く、MATLABが変数の内容をメモリ内で移動する必要があるためです。 bsxfunを使うbsxfun 、1つのbsxfunで同じ仕事をきちんと簡単に行うことができます:
A = bsxfun(@minus, B, mean(B));
ここで、 @minusはminus演算子( - )の関数ハンドルであり、2つの行列Bとmean(B)要素の間に適用されます。他の関数ハンドル、ユーザー定義の関数ハンドルも可能です。
次に、行列A各行に行ベクトルvを追加するとします。
v = [1, 2, 3];
A = [8, 1, 6
3, 5, 7
4, 9, 2];
素朴なアプローチは、ループを使用することです(これをしないでください ):
B = zeros(3);
for row = 1:3
B(row,:) = A(row,:) + v;
end
もう一つのオプションは、 vをrepmat複製することrepmat ( これを行わないでください )。
>> v = repmat(v,3,1)
v =
1 2 3
1 2 3
1 2 3
>> B = A + v;
代わりに、このタスクにはbsxfunを使用します。
>> B = bsxfun(@plus, A, v);
B =
9 3 9
4 7 10
5 11 5
構文
bsxfun(@fun, A, B)
@funはサポートされている関数の 1つで、2つの配列AとBは以下の2つの条件を尊重します。
名前bsxfun機能がどのように機能するかを理解するのに役立ちます、それはSの Ingletonの電子のXのパンシオンとB inary FUNの ctionの略です。言い換えると、
- 2つの配列は1つを除いて同じ次元を共有する
- 不一致の次元は、2つの配列のいずれかにシングルトン(すなわち、
1サイズを有する)である
シングルトンディメンションの配列は、他の配列のディメンションと一致するように展開されます。展開後、バイナリ関数が2つの配列の要素ごとに適用されます。
例えば、 A M × N × Kアレイ、 BをM × Nアレイとする。まず、最初の2つのディメンションは、対応するサイズを持ちます。第2に、 AはK層を持ち、 Bは暗黙的に1しかないので、シングルトンです。すべての条件が満たされ、 A 3次元と一致するようにBが複製されます。
他の言語では、これは一般にブロードキャストと呼ばれ、Python(numpy)とOctaveで自動的に発生します。
関数@funは2つの入力を必要とすることを意味するバイナリ関数でなければなりません。
備考
内部的には、 bsxfunは配列を複製せず、効率的なループを実行します。
論理マスキング
MATLABは、forループやif文を使用せずに行列の選択を実行するために、論理マスキングの使用をサポートしています。
論理マスクは、 1と0だけからなる行列として定義され0 。
例えば:
mask = [1 0 0; 0 1 0; 0 0 1];
恒等行列を表す論理行列である。
述語を使用して行列を照会する論理マスクを生成することができます。
A = [1 2 3; 4 5 6; 7 8 9];
B = A > 4;
最初に、1から9までの数字を含む3x3行列A作成します。次に、 Aより4より大きい値をクエリし、 Bという新しい行列に結果を格納します。
Bは次の形式の論理行列です。
B = [0 0 0
0 1 1
1 1 1]
述語A > 4が真であった場合は1になります。それが偽であったとき0 。
論理行列を使用して行列の要素にアクセスすることができます。論理行列を使用して要素を選択すると、論理行列に1が現れるインデックスが、選択元の行列で選択されます。
上のものと同じBを使って、次のことができます:
C = [0 0 0; 0 0 0; 0 0 0];
C(B) = 5;
これは、の要素のすべて選択するであろうC B有する1という指標です。 Cこれらのインデックスは、 5設定されます。
私たちのCは次のようになりました:
C = [0 0 0
0 5 5
5 5 5]
論理マスクを使用してifとforを含む複雑なコードブロックを減らすことができます。
ベクトル化されていないコードを取る:
A = [1 3 5; 7 9 11; 11 9 7];
for j = 1:length(A)
if A(j) > 5
A(j) = A(j) - 2;
end
end
これは、論理マスキングを使用して次のコードに短縮できます。
A = [1 3 5; 7 9 11; 11 9 7];
B = A > 5;
A(B) = A(B) - 2;
またはさらに短く:
A = [1 3 5; 7 9 11; 11 9 7];
A(A > 5) = A(A > 5) - 2;
暗黙の配列展開(放送)[R2016b]
MATLAB R2016bは 、スカラー拡張の一般特色1 、 2もあれば、それらの寸法に互換性があるように、異なるサイズのアレイとの間に一定の要素単位操作をサポートするために、機構。暗黙的な展開をサポートする演算子は、 1 :
- 要素ごとの算術演算子:
+、-、.*、.^、.\./.\。 - 関係演算子:
<、<=、>、>=、==、~=。 - 論理演算子:
&、|、xor。 - ビット単位の関数:
bitand、bitor、bitxor。 - 初等数学関数:
max、min、mod、rem、hypot、atan2、atan2d。
前述のバイナリ演算は、 "互換性のあるサイズ"を持つ限り、配列間で使用できます。 1つの配列の各次元が他の配列の同じ次元と正確に等しい場合、または1等しい場合、サイズは "互換"とみなされます。 MATLABでは、理論上無限の量があるにもかかわらず、末尾のシングルトン(サイズ1 )ディメンションはMATLABによって省略されていることに注意してください。つまり、ある配列に表示され、他の配列には表示されないディメンションは、自動的に展開するために暗黙的に適合します。
例えば、 R2016bより前の MATLABでは、これは起こります:
>> magic(3) + (1:3)
Error using +
Matrix dimensions must agree.
R2016bから始めると 、前の操作は成功します。
>> magic(3) + (1:3)
ans =
9 3 9
4 7 10
5 11 5
互換性のあるサイズの例:
| 説明 | 1 番目のアレイのサイズ | 2 番目のアレイサイズ | 結果サイズ |
|---|---|---|---|
| ベクトルとスカラー | [3x1] | [1x1] | [3x1] |
| 行ベクトルと列ベクトル | [1x3] | [2x1] | [2x3] |
| ベクトルと2D行列 | [1x3] | [5x3] | [5x3] |
| NDおよびKDアレイ | [1x3x3] | [5x3x1x4x2] | [5x3x3x4x2] |
互換性のないサイズの例:
| 説明 | 1 番目のアレイのサイズ | 2 番目のアレイサイズ | 考えられる回避策 |
|---|---|---|---|
| ベクトルは、次元が他の配列の同じ次元の倍数である場合に使用します。 | [1x2] | [1x8] | transpose |
| お互いの倍数の次元を持つ配列。 | [2x2] | [8x8] | repmat 、 reshape |
| シングルンディメンションの正しい量を持っているが、順序が間違っているND配列(#1)。 | [2x3x4] | [2x4x3] | permute |
| シングルンディメンションの正しい量を持っているが、順序が間違っているND配列(#2)。 | [2x3x4x5] | [5x2] | permute |
重要:
この規約に基づくコードは、以前のバージョンのMATLABと下位互換性がありません 。したがって、明示的に呼び出しbsxfun 1 、 2コードが古いMATLABバージョンで実行する必要がある場合(同じ効果が得られる)を使用しなければなりません。このような懸念が存在しない場合、 MATLAB R2016のリリースノートでは 、ユーザはbsxfunからの切り替えをbsxfunます。
暗黙的な拡張により、
bsxfunを使用する場合と比較して、実行速度が向上し、メモリ使用率が向上し、コードの可読性が向上します。
関連する読書:
- 「 基本操作のための互換アレイサイズ 」に関するMATLABのドキュメント
- numpyのの放送1 、 2 。
-
bsxfunと暗黙的な配列展開を使用したコンピューティングの速度の比較。
2つ以上の引数の関数の値を取得する
多くのアプリケーションでは、2つ以上の引数の関数を計算する必要があります。
従来は、-loopsに使用forました。たとえば、 f = exp(-x^2-y^2)を計算する必要がある場合( 高速シミュレーションが必要な場合はこれを使用しないでください):
% code1
x = -1.2:0.2:1.4;
y = -2:0.25:3;
for nx=1:lenght(x)
for ny=1:lenght(y)
f(nx,ny) = exp(-x(nx)^2-y(ny)^2);
end
end
しかし、ベクトル化されたバージョンはよりエレガントで高速です:
% code2
[x,y] = ndgrid(-1.2:0.2:1.4, -2:0.25:3);
f = exp(-x.^2-y.^2);
それを視覚化するよりも、
surf(x,y,f)
注1 - グリッド:通常、マトリックスストレージは行ごとに編成されます。しかし、MATLABでは、FORTRANのような列単位の記憶域です。したがって、前述の2つのモデルを実装するために、MATLABに2つのmeshgrid関数ndgridとmeshgridがあります。 meshgridの場合に関数を視覚化するために、以下を使用することができます。
surf(y,x,f)
注2 - メモリ消費量: xまたはyサイズを1000とします。したがって、非ベクトル化コード 1000*1000+2*1000 ~ 1e6 1000〜1e6要素を格納する必要があります。しかし、我々は必要な3*(1000*1000) = 3e6ベクトル化コード2の場合の要素を。ベクトル化されたコード2〜1000 ~1000*1000*1000場合、 4*(1000*1000*1000) ( 倍精度の場合は32GB 4*(1000*1000*1000)メモリ消費量が劇的に増加します( zはxまたはyと同じサイズです) コード1の場合は~1000*1000*1000 (わずか8GB) です 。したがって、メモリまたは速度のいずれかを選択する必要があります。