수색…


요소 별 작업

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 배열이 있다면? 적용 sumsumsum 대신 사용, 최선의 선택하지 않는 것 같아요 ... : 배열을 벡터화 운영자 :

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));

여기서 @minusminus 연산자 ( - )에 대한 함수 핸들 이며 두 행렬 Bmean(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

또 다른 옵션은 vrepmat 로 복제하는 것입니다 (이렇게 하지 마십시오 ).

>> 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지원되는 함수 중 하나이며 두 개의 배열 AB 는 아래의 두 조건을 @fun .

이름의 bsxfun 기능의 작동 방식을 이해하는 데 도움이 S의 ingleton 전자 X의 펜션과 B inary 재미있는 ction을 의미합니다. 다른 말로하면 :

  1. 두 배열은 하나를 제외하고는 같은 차원을 공유합니다.
  2. 불일치 한 차원은 두 배열 중 하나에서 싱글 톤 (예 : 크기가 1 )입니다.

싱글 톤 차원이있는 배열이 다른 배열의 차원과 일치하도록 확장됩니다. 확장 후 2 진 함수가 두 배열에 elementwise 적용됩니다.

예를 들어, A M -by- N -by K 배열로, BM -by- N 배열로 가정합니다. 첫 번째로, 처음 두 치수는 해당 크기를가집니다. 둘째, AK 레이어를 가지고 B 는 암시 적으로 1 만을 가지므로 싱글 톤입니다. 모든 조건이 충족되고, B 의 3 차원에 맞게 복제됩니다 A .

다른 언어에서는 이것을 일반적으로 브로드 캐스팅 이라고하며 파이썬 (numpy) 및 옥타브에서 자동으로 발생합니다.

@fun 함수는 반드시 2 개의 입력을 받아야하는 이진 함수 여야합니다.

비고

내부적으로 bsxfun 은 배열을 복제하지 않고 효율적인 루프를 실행합니다.

논리 마스킹

MATLAB은 for 루프 또는 if 문을 사용하지 않고 행렬에 대한 선택을 수행하기 위해 논리적 마스킹을 지원합니다.

논리 마스크는 오직 10 으로 구성된 행렬로 정의됩니다.

예 :

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]

논리 마스크를 사용하여 iffor 를 포함하는 복잡한 코드 블록을 줄일 수 있습니다.

벡터화되지 않은 코드 가져 오기 :

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 함수 ndgridmeshgrid 가 있습니다. 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