MATLAB Language
벡터화
수색…
요소 별 작업
MATLAB은 벡터 및 행렬에서 벡터화 된 연산을 지원합니다 (장려하십시오).
예를 들어, 우리가 가정 와 A
B
두 개의 n
-by- 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;
- MATLAB에서 요소 단위의 곱셈에 대한 자세한 내용은
times
대한 문서를 참조하십시오. - 배열과 행렬 연산의 차이점에 대한 자세한 내용은 MATLAB 문서의 배열 대 행렬 연산을 참조하십시오.
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)
위의 모든 함수는 한 차원에서만 작동하지만 전체 행렬을 합산하려면 어떻게해야합니까? 다음을 사용할 수 있습니다.
s = sum(sum(A))
하지만 ND 배열이 있다면? 적용 sum
에 sum
에 sum
대신 사용, 최선의 선택하지 않는 것 같아요 ... :
배열을 벡터화 운영자 :
s = sum(A(:))
그리고 이것은 당신의 모든 배열의 합계 인 하나의 숫자가 될 것이고 얼마나 많은 차원을 가지고 있든지 관계 없습니다.
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
을 사용하면 한 줄에서 똑같은 일을 깔끔하고 쉽게 할 수 있습니다.
A = bsxfun(@minus, B, mean(B));
여기서 @minus
는 minus
연산자 ( -
)에 대한 함수 핸들 이며 두 행렬 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
로 복제하는 것입니다 (이렇게 하지 마십시오 ).
>> v = repmat(v,3,1)
v =
1 2 3
1 2 3
1 2 3
>> B = A + v;
대신이 작업을 위해 bsxfun
을 사용 bsxfun
.
>> B = bsxfun(@plus, A, v);
B =
9 3 9
4 7 10
5 11 5
통사론
bsxfun(@fun, A, B)
여기서 @fun
은 지원되는 함수 중 하나이며 두 개의 배열 A
와 B
는 아래의 두 조건을 @fun
.
이름의 bsxfun
기능의 작동 방식을 이해하는 데 도움이 S의 ingleton 전자 X의 펜션과 B inary 재미있는 ction을 의미합니다. 다른 말로하면 :
- 두 배열은 하나를 제외하고는 같은 차원을 공유합니다.
- 불일치 한 차원은 두 배열 중 하나에서 싱글 톤 (예 : 크기가
1
)입니다.
싱글 톤 차원이있는 배열이 다른 배열의 차원과 일치하도록 확장됩니다. 확장 후 2 진 함수가 두 배열에 elementwise 적용됩니다.
예를 들어, A
M
-by- N
-by K
배열로, B
를 M
-by- N
배열로 가정합니다. 첫 번째로, 처음 두 치수는 해당 크기를가집니다. 둘째, A
는 K
레이어를 가지고 B
는 암시 적으로 1
만을 가지므로 싱글 톤입니다. 모든 조건이 충족되고, B
의 3 차원에 맞게 복제됩니다 A
.
다른 언어에서는 이것을 일반적으로 브로드 캐스팅 이라고하며 파이썬 (numpy) 및 옥타브에서 자동으로 발생합니다.
@fun
함수는 반드시 2 개의 입력을 받아야하는 이진 함수 여야합니다.
비고
내부적으로 bsxfun
은 배열을 복제하지 않고 효율적인 루프를 실행합니다.
논리 마스킹
MATLAB은 for 루프 또는 if 문을 사용하지 않고 행렬에 대한 선택을 수행하기 위해 논리적 마스킹을 지원합니다.
논리 마스크는 오직 1
과 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
. 이론적으로 무한한 양의 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 st 어레이 크기 | 2 번째 배열 크기 | 결과 크기 |
---|---|---|---|
벡터와 스칼라 | [3x1] | [1x1] | [3x1] |
행 및 열 벡터 | [1x3] | [2x1] | [2x3] |
벡터 및 2D 행렬 | [1x3] | [5x3] | [5x3] |
ND 및 KD 어레이 | [1x3x3] | [5x3x1x4x2] | [5x3x3x4x2] |
호환되지 않는 크기의 예 :
기술 | 1 st 어레이 크기 | 2 번째 배열 크기 | 가능한 해결 방법 |
---|---|---|---|
벡터가 다른 배열의 같은 차원의 배수 인 벡터입니다. | [1x2] | [1x8] | transpose |
서로 배수 인 차원의 배열. | [2x2] | [8x8] | repmat , reshape |
싱글 톤 차원이 적당하지만 잘못된 순서 (# 1)의 ND 배열. | [2x3x4] | [2x4x3] | permute |
싱글 튼 차원의 올바른 양을 가지고 있지만 그것들은 잘못된 순서 (# 2)의 ND 배열. | [2x3x4x5] | [5x2] | permute |
중대한:
이 규칙에 의존하는 코드는 MATLAB의 이전 버전과 이전 버전과 호환되지 않습니다. 따라서 이전 MATLAB 버전에서 코드를 실행해야하는 경우 bsxfun
1 , 2 (명시 적으로 동일한 효과가 발생 함)를 명시 적으로 호출해야합니다. 이러한 우려가 없으면 MATLAB R2016 릴리스 노트 는 bsxfun
에서 사용자로 전환하도록 권장합니다.
bsxfun
을 사용하는bsxfun
비교하여 암시 적 확장은 실행 속도가 빨라지고 메모리 사용이 향상되고 코드의 가독성이 향상됩니다.
관련 읽기 :
- " 기본 연산을위한 호환 배열 크기 "에 대한 MATLAB 문서
- NumPy 's Broadcasting 1 , 2 .
-
bsxfun
사용하는 컴퓨팅 속도와 암시 적 어레이 확장을 비교 한 것 입니다.
둘 이상의 인수로 된 함수 값 얻기
많은 응용 프로그램에서 두 개 이상의 인수의 함수를 계산해야합니다.
전통적 for
-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과 같이 열 단위로 저장됩니다. 따라서 앞서 언급 한 두 가지 모델을 구현하기 위해 MATLAB에 두 개의 simular 함수 ndgrid
와 meshgrid
가 있습니다. meshgrid
의 경우 함수를 시각화하기 위해 다음을 사용할 수 있습니다.
surf(y,x,f)
Note2 - 메모리 소비 : x
또는 y
크기를 1000이라고합시다. 따라서 비 벡터화 된 코드 1에 대해 1000*1000+2*1000 ~ 1e6
요소를 저장해야합니다. 그러나 벡터화 된 코드 2 의 경우 3*(1000*1000) = 3e6
요소가 필요합니다. (하자 3D 경우 z
같은 크기 갖는다 x
또는 y
), 메모리 소비가 증가 과장 : 4*(1000*1000*1000)
(~ 복식 32기가바이트) VS 벡터화 CODE2의 경우 ~1000*1000*1000
(단지 ~ 8 기가 바이트)의 경우 code1 . 따라서 메모리 나 속도 중 하나를 선택해야합니다.