[PyTorch] Tensor의 산술, 비교, 논리 연산 + in-place 연산

beaver.zip·2024년 8월 11일
0

in-place 연산

  • 연산 결과를 새로운 텐서에 저장하는 것이 아닌 기존 텐서에 업데이트하는 방식
  • 일반적으로 in-place 연산은 메서드 이름 뒤에 언더바(_)를 붙여 표시함.
  • 메모리 효율성↑, 그러나 autograd와 호환성 문제를 일으킬 수 있음.
  • PyTorch Tutorial에도 권장하지 않는다고 적혀있음.

In-place operations save some memory, but can be problematic when computing derivatives because of an immediate loss of history. Hence, their use is discouraged.

In-place 연산은 메모리를 절약할 수 있으나, 즉각적인 history 손실로 인해 미분 계산 시 문제를 일으킬 수 있다. 따라서 권장되지 않는다

산술 연산

더하기 - add()

  • 텐서-텐서, 텐서-스칼라 간의 합을 구함
  • 두 텐서의 크기가 다를 시 작은 텐서의 크기를 확장
x = torch.tensor([[1, 2], [3, 4]])
y = torch.tensor([1, 1])

# 일반적인 덧셈
z = torch.add(x, y)  # y를 [[1, 1], [1, 1]]로 확장
print(z)  # tensor([[2, 3], [4, 5]])

# in-place 덧셈
x.add_(y)
print(x)  # tensor([[2, 3], [4, 5]])

빼기 - sub()

  • 텐서-텐서, 텐서-스칼라 간의 차를 구함
  • 두 텐서의 크기가 다를 시 작은 텐서의 크기를 확장
x = torch.tensor([[1, 2], [3, 4]])
y = torch.tensor([1, 1])

# 일반적인 뺄셈
z = torch.sub(x, y)  # y를 [[1, 1], [1, 1]]로 확장
print(z)  # tensor([[0, 1], [2, 3]])

# in-place 뺄셈
x.sub_(y)
print(x)  # tensor([[0, 1], [2, 3]])

곱하기 - mul()

  • 텐서-텐서, 텐서-스칼라 간의 곱을 구함
  • 두 텐서의 크기가 다를 시 작은 텐서의 크기를 확장
x = torch.tensor([[1, 4], [7, 8]])
y = torch.tensor([2, 3])

# 일반적인 곱셈
z = torch.mul(x, y)  # y를 [[2, 3], [2, 3]]로 확장
print(z)  # tensor([[2, 12], [14, 24]])

# in-place 곱셈
x.mul_(y)
print(x)  # tensor([[2, 12], [14, 24]])

나누기 - div()

  • 두 텐서를 요소별로 나눔
  • 두 텐서의 크기가 다를 시 작은 텐서의 크기를 확장
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6])

z = torch.div(x, y)
print(z)  # tensor([0.2500, 0.4000, 0.5000])

거듭제곱 - pow()

  • 텐서의 각 요소를 주어진 지수(스칼라 or 벡터)로 거듭제곱
x = torch.tensor([1, 2, 3])
z = torch.pow(x, 2)
print(z)  # tensor([1, 4, 9])

제곱근 - pows()

  • 텐서의 각 요소에 대한 n제곱근을 계산
x = torch.tensor([1, 4, 9])
z = torch.pows(x, 2)
print(z)  # tensor([1, 2, 3])

내적 - dot()

  • 두 벡터(=1-D Tensor)의 내적을 계산
  • NumPy와는 달리 행렬 곱셈은 미지원
x = torch.tensor([1, 2, 3])
y = torch.tensor([4, 5, 6])

dot_product = torch.dot(x, y)
print(dot_product)  # 32 (1*4 + 2*5 + 3*6)

행렬 곱셈 - matmul(), @, mm()

  • 두 행렬(=2-D Tensor)의 행렬 곱셈
  • matmul() = @: broadcasting 지원(디버깅에 불리) + 3차원부터는 텐서곱(외적)
  • mm(): broadcasting 미지원(디버깅에 유리)
A = torch.tensor([[1, 2],
                  [3, 4]])
B = torch.tensor([[5, 6],
                  [7, 8]])

product = torch.mm(A, B)
print(product)

# tensor([[19, 22],
#        [43, 50]])

비교 연산

같음 - eq()

  • 두 텐서의 요소별로 같은지 비교
x = torch.tensor([1, 2, 3])
y = torch.tensor([1, 2, 4])

z = torch.eq(x, y)
print(z)  # tensor([True, True, False])

다름 - ne()

  • 두 텐서의 요소별로 다른지 비교
x = torch.tensor([1, 2, 3])
y = torch.tensor([1, 2, 4])

z = torch.ne(x, y)
print(z)  # tensor([False, False, True])

gt, ge, lt, le()

  • 두 텐서의 요소별로 크기를 비교
  • gt: 크다 (greater than)
  • ge: 크거나 같다 (greater or equal)
  • lt: 작다 (less than)
  • le: 작거나 같다(less or equal)

논리 연산

논리곱 - logical_and()

  • 두 텐서의 요소별로 논리곱(AND)
x = torch.tensor([True, False, True])
y = torch.tensor([True, True, False])

z = torch.logical_and(x, y)
print(z)  # tensor([True, False, False])

논리합 - logical_or()

  • 두 텐서의 요소별로 논리합(OR)
x = torch.tensor([True, False, True])
y = torch.tensor([True, True, False])

z = torch.logical_or(x, y)
print(z)  # tensor([True, True, True])

배타적 논리합 - logical_xor()

x = torch.tensor([True, False, True])
y = torch.tensor([True, True, False])

z = torch.logical_xor(x, y)
print(z)  # tensor([False, True, True])

Outro

더 읽어볼 것

참고 자료

profile
NLP 일짱이 되겠다.

0개의 댓글