수색…


요소 별 작업

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. 불일치 한 차원은 두 배열 중 하나에서 싱글 톤 (예 : 크기가 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 비교하여 암시 적 확장은 실행 속도가 빨라지고 메모리 사용이 향상되고 코드의 가독성이 향상됩니다.


관련 읽기 :

둘 이상의 인수로 된 함수 값 얻기

많은 응용 프로그램에서 두 개 이상의 인수의 함수를 계산해야합니다.

전통적 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 . 따라서 메모리 나 속도 중 하나를 선택해야합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow