2.3.2 브로드캐스팅

2.3.1 원소별 연산 | 목차 | 2.3.3 텐서 점곱

 

앞서 살펴본 단순한 덧셈 구현인 naive_add는 동일한 크기의 2D 텐서만 지원합니다. 하지만 이전에 보았던 Dense 층에서는 2D 텐서와 벡터를 더했습니다. 크기가 다른 두 텐서가 더해질 때 무슨 일이 일어날까요?

모호하지 않고 실행 가능하다면 작은 텐서가 큰 텐서의 크기에 맞추어 브로드캐스팅broadcasting됩니다. 브로드캐스팅은 두 단계로 이루어집니다.

  1. 큰 텐서의 ndim에 맞도록 작은 텐서에 (브로드캐스팅 축이라고 부르는) 축이 추가됩니다.
  2. 작은 텐서가 새 축을 따라서 큰 텐서의 크기에 맞도록 반복됩니다.

구체적인 예를 살펴보겠습니다.

X의 크기는 (32, 10)이고 y의 크기는 (10,)라고 가정합시다. 먼저 y에 비어 있는 첫 번째 축을 추가하여 크기를 (1, 10)으로 만듭니다. 그런 다음 y를 이 축에 32번 반복하면 텐서 Y의 크기는 (32, 10)이 됩니다. 여기에서 Y[i, :] == y for i in range(0, 32)입니다. 이제 XY의 크기가 같으므로 더할 수 있습니다.

구현 입장에서는 새로운 텐서가 만들어지면 매우 비효율적이므로 어떤 2D 텐서도 만들어지지 않습니다. 반복된 연산은 완전히 가상적입니다. 이 과정은 메모리 수준이 아니라 알고리즘 수준에서 일어납니다. 하지만 새로운 축을 따라 벡터가 32번 반복된다고 생각하는 것이 이해하기 쉽습니다. 다음은 단순하게 구현한 예입니다.

def naive_add_matrix_and_vector(x, y):
    assert len(x.shape) == 2   # x는 2D 넘파이 배열입니다.
    assert len(y.shape) == 1   # y는 넘파이 벡터입니다.
    assert x.shape[1] == y.shape[0]
    x = x.copy()               # 입력 텐서 자체를 바꾸지 않도록 복사합니다.
    for i in range(x.shape[0]):
        for j in range(x.shape[1]):
            x[i, j] += y[j]
    return x

(a, b, .. . n, n + 1, .. . m) 크기의 텐서와 (n, n + 1, .. . m) 크기의 텐서 사이에 브로드캐스팅으로 원소별 연산을 적용할 수 있습니다. 이때 브로드캐스팅은 a부터 n – 1까지의 축에 자동으로 일어납니다.

다음은 크기가 다른 두 텐서에 브로드캐스팅으로 원소별 maximum 연산을 적용하는 예입니다.

import numpy as np
x = np.random.random((64, 3, 32, 10)) # x는 (64, 3, 32, 10) 크기의 랜덤 텐서입니다.
y = np.random.random((32, 10))        # y는 (32, 10) 크기의 랜덤 텐서입니다.
z = np.maximum(x, y)                  # 출력 z 크기는 x와 동일하게 (64, 3, 32, 10)입니다.

 


 

2.3.1 원소별 연산 | 목차 | 2.3.3 텐서 점곱

 

이 글은 도서출판 길벗에서 출간한  “케라스 창시자에게 배우는 딥러닝“의 1장~3장입니다. 이 책의 저작권은 (주)도서출판 길벗에 있으므로 무단 복제 및 무단 전제를 금합니다.

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

This site uses Akismet to reduce spam. Learn how your comment data is processed.