λ”₯λŸ¬λ‹/Today I learned :

νŒŒμ΄ν† μΉ˜ νŒ¨ν‚€μ§€ κΈ°λ³Έ μ‘°μž‘λ²• 읡히기 2 - python ν–‰λ ¬, ν…μ„œ

주영 🐱 2022. 12. 26. 13:42
728x90
λ°˜μ‘ν˜•

νŒŒμ΄ν† μΉ˜ ν…μ„œ μ„ μ–Έν•˜κΈ°(PyTorch Tensor Allocation)

import torch

 

1) 1D with PyTorch

νŒŒμ΄ν† μΉ˜λ‘œ 1차원 ν…μ„œμΈ 벑터λ₯Ό λ§Œλ“€μ–΄λ΄…μ‹œλ‹€.

t = torch.FloatTensor([0., 1., 2., 3., 4., 5., 6.])
print(t)

dim()을 μ‚¬μš©ν•˜λ©΄ ν˜„μž¬ ν…μ„œμ˜ 차원을 λ³΄μ—¬μ€λ‹ˆλ‹€. shapeλ‚˜ size()λ₯Ό μ‚¬μš©ν•˜λ©΄ 크기λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

print(t.dim())  # rank. 즉, 차원
print(t.shape)  # shape
print(t.size()) # shape
1
torch.Size([7])
torch.Size([7])

ν˜„μž¬ 1차원 ν…μ„œμ΄λ©°, μ›μ†ŒλŠ” 7κ°œμž…λ‹ˆλ‹€. 인덱슀둜 μ ‘κ·Όν•˜λŠ” 것과 μŠ¬λΌμ΄μ‹±μ„ ν•΄λ΄…μ‹œλ‹€. 방법은 Numpy μ‹€μŠ΅κ³Ό κ°™μŠ΅λ‹ˆλ‹€.

print(t[0], t[1], t[-1])  # 인덱슀둜 μ ‘κ·Ό
print(t[2:5], t[4:-1])    # μŠ¬λΌμ΄μ‹±
print(t[:2], t[3:])       # μŠ¬λΌμ΄μ‹±
tensor(0.) tensor(1.) tensor(6.)
tensor([2., 3., 4.]) tensor([4., 5.])
tensor([0., 1.]) tensor([3., 4., 5., 6.])

2) 2D with PyTorch

νŒŒμ΄ν† μΉ˜λ‘œ 2차원 ν…μ„œμΈ 행렬을 λ§Œλ“€μ–΄λ΄…μ‹œλ‹€.

t = torch.FloatTensor([[1., 2., 3.],
                       [4., 5., 6.],
                       [7., 8., 9.],
                       [10., 11., 12.]
                      ])
print(t)
tensor([[ 1.,  2.,  3.],
        [ 4.,  5.,  6.],
        [ 7.,  8.,  9.],
        [10., 11., 12.]])

dim()을 μ‚¬μš©ν•˜λ©΄ ν˜„μž¬ ν…μ„œμ˜ 차원을 λ³΄μ—¬μ€λ‹ˆλ‹€. size()λ₯Ό μ‚¬μš©ν•˜λ©΄ 크기λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

print(t.dim())  # rank. 즉, 차원
print(t.size()) # shape
2
torch.Size([4, 3])

ν˜„μž¬ ν…μ„œμ˜ 차원은 2차원이며, (4, 3)의 크기λ₯Ό κ°€μ§‘λ‹ˆλ‹€. μŠ¬λΌμ΄μ‹±μ„ ν•΄λ΄…μ‹œλ‹€.

print(t[:, 1]) # 첫번째 차원을 전체 μ„ νƒν•œ μƒν™©μ—μ„œ λ‘λ²ˆμ§Έ μ°¨μ›μ˜ 첫번째 κ²ƒλ§Œ κ°€μ Έμ˜¨λ‹€.
print(t[:, 1].size()) # ↑ μœ„μ˜ 경우의 크기
tensor([ 2.,  5.,  8., 11.])
torch.Size([4])

μœ„μ˜ κ²°κ³ΌλŠ” 첫번째 차원을 전체 μ„ νƒν•˜κ³ , κ·Έ μƒν™©μ—μ„œ λ‘λ²ˆμ§Έ μ°¨μ›μ˜ 1번 인덱슀 κ°’λ§Œμ„ κ°€μ Έμ˜¨ 경우λ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€. λ‹€μ‹œ 말해 ν…μ„œμ—μ„œ λ‘λ²ˆμ§Έ 열에 μžˆλŠ” λͺ¨λ“  값을 κ°€μ Έμ˜¨ μƒν™©μž…λ‹ˆλ‹€. 그리고 μ΄λ ‡κ²Œ 값을 κ°€μ Έμ˜¨ 경우의 ν¬κΈ°λŠ” 4μž…λ‹ˆλ‹€. (1차원 벑터)

print(t[:, :-1]) # 첫번째 차원을 전체 μ„ νƒν•œ μƒν™©μ—μ„œ λ‘λ²ˆμ§Έ μ°¨μ›μ—μ„œλŠ” 맨 λ§ˆμ§€λ§‰μ—μ„œ 첫번째λ₯Ό μ œμ™Έν•˜κ³  λ‹€ κ°€μ Έμ˜¨λ‹€.
tensor([[ 1.,  2.],
        [ 4.,  5.],
        [ 7.,  8.],
        [10., 11.]])

μœ„μ˜ κ²°κ³ΌλŠ” 첫번째 차원을 전체 μ„ νƒν•œ μƒν™©μ—μ„œ λ‘λ²ˆμ§Έ μ°¨μ›μ—μ„œλŠ” 맨 λ§ˆμ§€λ§‰μ—μ„œ 첫번째λ₯Ό μ œμ™Έν•˜κ³  λ‹€ κ°€μ Έμ˜€λŠ” κ²½μš°μž…λ‹ˆλ‹€.

 

3) λΈŒλ‘œλ“œμΊμŠ€νŒ…(Broadcasting)

두 ν–‰λ ¬ A, Bκ°€ μžˆλ‹€κ³  ν•΄λ΄…μ‹œλ‹€. ν–‰λ ¬μ˜ λ§μ…ˆκ³Ό λΊ„μ…ˆμ— λŒ€ν•΄ μ•Œκ³ κ³„μ‹ λ‹€λ©΄, 이 λ§μ…ˆκ³Ό λΊ„μ…ˆμ„ ν•  λ•Œμ—λŠ” 두 ν–‰λ ¬ A, B의 크기가 κ°™μ•„μ•Όν•œλ‹€λŠ” 것을 μ•Œκ³ κ³„μ‹€κ²λ‹ˆλ‹€. 그리고 두 행렬이 κ³±μ…ˆμ„ ν•  λ•Œμ—λŠ” A의 λ§ˆμ§€λ§‰ 차원과 B의 첫번째 차원이 μΌμΉ˜ν•΄μ•Όν•©λ‹ˆλ‹€.

λ¬Όλ‘ , 이런 κ·œμΉ™λ“€μ΄ μžˆμ§€λ§Œ λ”₯ λŸ¬λ‹μ„ ν•˜κ²Œλ˜λ©΄ λΆˆκ°€ν”Όν•˜κ²Œ 크기가 λ‹€λ₯Έ ν–‰λ ¬ λ˜λŠ” ν…μ„œμ— λŒ€ν•΄μ„œ 사칙 연산을 μˆ˜ν–‰ν•  ν•„μš”κ°€ μžˆλŠ” κ²½μš°κ°€ μƒκΉλ‹ˆλ‹€. 이λ₯Ό μœ„ν•΄ νŒŒμ΄ν† μΉ˜μ—μ„œλŠ” μžλ™μœΌλ‘œ 크기λ₯Ό λ§žμΆ°μ„œ 연산을 μˆ˜ν–‰ν•˜κ²Œ λ§Œλ“œλŠ” λΈŒλ‘œλ“œμΊμŠ€νŒ…μ΄λΌλŠ” κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€.

μš°μ„  같은 크기일 λ•Œ 연산을 ν•˜λŠ” 경우λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

m1 = torch.FloatTensor([[3, 3]])
m2 = torch.FloatTensor([[2, 2]])
print(m1 + m2)
tensor([[5., 5.]])

μ—¬κΈ°μ„œ m1,κ³Ό m2의 ν¬κΈ°λŠ” λ‘˜ λ‹€ (1, 2)μž…λ‹ˆλ‹€. κ·Έλž˜μ„œ λ¬Έμ œμ—†μ΄ λ§μ…ˆ 연산이 κ°€λŠ₯ν•©λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” 크기가 λ‹€λ₯Έ ν…μ„œλ“€ κ°„μ˜ 연산을 λ³΄κ² μŠ΅λ‹ˆλ‹€. μ•„λž˜λŠ” 벑터와 μŠ€μΉΌλΌκ°€ λ§μ…ˆ 연산을 μˆ˜ν–‰ν•˜λŠ” 것을 λ³΄μ—¬μ€λ‹ˆλ‹€. λ¬Όλ‘ , μˆ˜ν•™μ μœΌλ‘œλŠ” μ›λž˜ 연산이 μ•ˆ λ˜λŠ”κ²Œ λ§žμ§€λ§Œ νŒŒμ΄ν† μΉ˜μ—μ„œλŠ” λΈŒλ‘œλ“œμΊμŠ€νŒ…μ„ 톡해 이λ₯Ό μ—°μ‚°ν•©λ‹ˆλ‹€.

# Vector + scalar
m1 = torch.FloatTensor([[1, 2]])
m2 = torch.FloatTensor([3]) # [3] -> [3, 3]
print(m1 + m2)
tensor([[4., 5.]])

μ›λž˜ m1의 ν¬κΈ°λŠ” (1, 2)이며 m2의 ν¬κΈ°λŠ” (1,)μž…λ‹ˆλ‹€. 그런데 νŒŒμ΄ν† μΉ˜λŠ” m2의 크기λ₯Ό (1, 2)둜 λ³€κ²½ν•˜μ—¬ 연산을 μˆ˜ν–‰ν•©λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” 벑터 κ°„ μ—°μ‚°μ—μ„œ λΈŒλ‘œλ“œμΊμŠ€νŒ…μ΄ μ μš©λ˜λŠ” 경우λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

# 2 x 1 Vector + 1 x 2 Vector
m1 = torch.FloatTensor([[1, 2]])
m2 = torch.FloatTensor([[3], [4]])
print(m1 + m2)
tensor([4., 5.],
       [5., 6.]])

m1의 ν¬κΈ°λŠ” (1, 2) m2의 ν¬κΈ°λŠ” (2, 1)μ˜€μŠ΅λ‹ˆλ‹€. 이 두 λ²‘ν„°λŠ” μ›λž˜ μˆ˜ν•™μ μœΌλ‘œλŠ” λ§μ…ˆμ„ μˆ˜ν–‰ν•  수 μ—†μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ νŒŒμ΄ν† μΉ˜λŠ” 두 λ²‘ν„°μ˜ 크기λ₯Ό (2, 2)둜 λ³€κ²½ν•˜μ—¬ λ§μ…ˆμ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

# λΈŒλ‘œλ“œμΊμŠ€νŒ… κ³Όμ •μ—μ„œ μ‹€μ œλ‘œ 두 ν…μ„œκ°€ μ–΄λ–»κ²Œ λ³€κ²½λ˜λŠ”μ§€ λ³΄κ² μŠ΅λ‹ˆλ‹€.
[1, 2]
==> [[1, 2],
     [1, 2]]
[3]
[4]
==> [[3, 3],
     [4, 4]]

λΈŒλ‘œλ“œμΊμŠ€νŒ…μ€ νŽΈλ¦¬ν•˜μ§€λ§Œ, μžλ™μœΌλ‘œ μ‹€ν–‰λ˜λŠ” κΈ°λŠ₯μ΄λ―€λ‘œ μ‚¬μš©μž μž…μž₯μ—μ„œ ꡉμž₯히 μ£Όμ˜ν•΄μ„œ μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄ A ν…μ„œμ™€ B ν…μ„œκ°€ μžˆμ„ λ•Œ, μ‚¬μš©μžλŠ” 이 두 ν…μ„œμ˜ 크기가 κ°™λ‹€κ³  μ°©κ°ν•˜κ³  λ§μ…ˆ 연산을 μˆ˜ν–‰ν–ˆλ‹€κ³  κ°€μ •ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ‹€μ œλ‘œ 이 두 ν…μ„œμ˜ ν¬κΈ°λŠ” λ‹¬λžκ³  λΈŒλ‘œλ“œμΊμŠ€νŒ…μ΄ μˆ˜ν–‰λ˜μ–΄ λ§μ…ˆ 연산이 μˆ˜ν–‰λ˜μ—ˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½, 두 ν…μ„œμ˜ 크기가 λ‹€λ₯΄λ‹€κ³  μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚¨λ‹€λ©΄ μ‚¬μš©μžλŠ” 이 연산이 잘λͺ»λ˜μ—ˆμŒμ„ λ°”λ‘œ μ•Œ 수 μžˆμ§€λ§Œ λΈŒλ‘œλ“œμΊμŠ€νŒ…μ€ μžλ™μœΌλ‘œ μˆ˜ν–‰λ˜λ―€λ‘œ μ‚¬μš©μžλŠ” λ‚˜μ€‘μ— μ›ν•˜λŠ” κ²°κ³Όκ°€ λ‚˜μ˜€μ§€ μ•Šμ•˜λ”λΌλ„ μ–΄λ””μ„œ λ¬Έμ œκ°€ λ°œμƒν–ˆλŠ”μ§€ μ°ΎκΈ°κ°€ ꡉμž₯히 μ–΄λ €μšΈ 수 μžˆμŠ΅λ‹ˆλ‹€.

 

4) 자주 μ‚¬μš©λ˜λŠ” κΈ°λŠ₯λ“€

1) ν–‰λ ¬ κ³±μ…ˆκ³Ό κ³±μ…ˆμ˜ 차이(Matrix Multiplication Vs. Multiplication)

ν–‰λ ¬λ‘œ κ³±μ…ˆμ„ ν•˜λŠ” 방법은 크게 두 가지가 μžˆμŠ΅λ‹ˆλ‹€. λ°”λ‘œ ν–‰λ ¬ κ³±μ…ˆ(.matmul)κ³Ό μ›μ†Œ 별 κ³±μ…ˆ(.mul)μž…λ‹ˆλ‹€.
νŒŒμ΄ν† μΉ˜ ν…μ„œμ˜ ν–‰λ ¬ κ³±μ…ˆμ„ λ³΄κ² μŠ΅λ‹ˆλ‹€. μ΄λŠ” matmul()을 톡해 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

m1 = torch.FloatTensor([[1, 2], [3, 4]])
m2 = torch.FloatTensor([[1], [2]])
print('Shape of Matrix 1: ', m1.shape) # 2 x 2
print('Shape of Matrix 2: ', m2.shape) # 2 x 1
print(m1.matmul(m2)) # 2 x 1
Shape of Matrix 1:  torch.Size([2, 2])
Shape of Matrix 2:  torch.Size([2, 1])
tensor([[ 5.],
        [11.]])

μœ„μ˜ κ²°κ³ΌλŠ” 2 x 2 ν–‰λ ¬κ³Ό 2 x 1 ν–‰λ ¬(벑터)의 ν–‰λ ¬ κ³±μ…ˆμ˜ κ²°κ³Όλ₯Ό λ³΄μ—¬μ€λ‹ˆλ‹€.

ν–‰λ ¬ κ³±μ…ˆμ΄ μ•„λ‹ˆλΌ element-wise κ³±μ…ˆμ΄λΌλŠ” 것이 μ‘΄μž¬ν•©λ‹ˆλ‹€. μ΄λŠ” λ™μΌν•œ 크기의 행렬이 λ™μΌν•œ μœ„μΉ˜μ— μžˆλŠ” μ›μ†ŒλΌλ¦¬ κ³±ν•˜λŠ” 것을 λ§ν•©λ‹ˆλ‹€. μ•„λž˜λŠ” μ„œλ‘œ λ‹€λ₯Έ 크기의 행렬이 λΈŒλ‘œλ“œμΊμŠ€νŒ…μ΄ 된 후에 element-wise κ³±μ…ˆμ΄ μˆ˜ν–‰λ˜λŠ” 것을 λ³΄μ—¬μ€λ‹ˆλ‹€. μ΄λŠ” * λ˜λŠ” mul()을 톡해 μˆ˜ν–‰ν•©λ‹ˆλ‹€.

m1 = torch.FloatTensor([[1, 2], [3, 4]])
m2 = torch.FloatTensor([[1], [2]])
print('Shape of Matrix 1: ', m1.shape) # 2 x 2
print('Shape of Matrix 2: ', m2.shape) # 2 x 1
print(m1 * m2) # 2 x 2
print(m1.mul(m2))
Shape of Matrix 1:  torch.Size([2, 2])
Shape of Matrix 2:  torch.Size([2, 1])
tensor([[1., 2.],
        [6., 8.]])
tensor([[1., 2.],
        [6., 8.]])

m1 ν–‰λ ¬μ˜ ν¬κΈ°λŠ” (2, 2)μ΄μ—ˆμŠ΅λ‹ˆλ‹€. m2 ν–‰λ ¬μ˜ ν¬κΈ°λŠ” (2, 1)μ˜€μŠ΅λ‹ˆλ‹€. μ΄λ•Œ element-wise κ³±μ…ˆμ„ μˆ˜ν–‰ν•˜λ©΄, 두 ν–‰λ ¬μ˜ ν¬κΈ°λŠ” λΈŒλ‘œλ“œμΊμŠ€νŒ…μ΄ 된 후에 κ³±μ…ˆμ΄ μˆ˜ν–‰λ©λ‹ˆλ‹€. 더 μ •ν™•νžˆλŠ” μ—¬κΈ°μ„œ m2의 크기가 λ³€ν™˜λ©λ‹ˆλ‹€.

# λΈŒλ‘œλ“œμΊμŠ€νŒ… κ³Όμ •μ—μ„œ m2 ν…μ„œκ°€ μ–΄λ–»κ²Œ λ³€κ²½λ˜λŠ”μ§€ λ³΄κ² μŠ΅λ‹ˆλ‹€.
[1]
[2]
==> [[1, 1],
     [2, 2]]

2) 평균(Mean)

평균을 κ΅¬ν•˜λŠ” 방법도 μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” Numpyμ—μ„œμ˜ μ‚¬μš©λ²•κ³Ό 맀우 μœ μ‚¬ν•©λ‹ˆλ‹€.
μš°μ„  1차원인 벑터λ₯Ό μ„ μ–Έν•˜μ—¬ .mean()을 μ‚¬μš©ν•˜μ—¬ μ›μ†Œμ˜ 평균을 κ΅¬ν•©λ‹ˆλ‹€.

t = torch.FloatTensor([1, 2])
print(t.mean())
tensor(1.5000)

1κ³Ό 2의 평균인 1.5κ°€ λ‚˜μ˜΅λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” 2차원인 행렬을 μ„ μ–Έν•˜μ—¬ .mean()을 μ‚¬μš©ν•΄λ΄…μ‹œλ‹€. μš°μ„  2차원 행렬을 μ„ μ–Έν•©λ‹ˆλ‹€.

t = torch.FloatTensor([[1, 2], [3, 4]])
print(t)
tensor([[1., 2.],
        [3., 4.]])

2차원 행렬이 μ„ μ–Έλ˜μ—ˆμŠ΅λ‹ˆλ‹€. 이제 .mean()을 μ‚¬μš©ν•©λ‹ˆλ‹€.

print(t.mean())
tensor(2.5000)

4개의 μ›μ†Œμ˜ 평균인 2.5κ°€ λ‚˜μ™”μŠ΅λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” dim. 즉, 차원(dimension)을 인자둜 μ£ΌλŠ” 경우λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

print(t.mean(dim=0))
tensor([2., 3.])

dim=0μ΄λΌλŠ” 것은 첫번째 차원을 μ˜λ―Έν•©λ‹ˆλ‹€. ν–‰λ ¬μ—μ„œ 첫번째 차원은 'ν–‰'을 μ˜λ―Έν•©λ‹ˆλ‹€. 그리고 인자둜 dim을 μ€€λ‹€λ©΄ ν•΄λ‹Ή 차원을 μ œκ±°ν•œλ‹€λŠ” μ˜λ―Έκ°€ λ©λ‹ˆλ‹€. λ‹€μ‹œ 말해 ν–‰λ ¬μ—μ„œ 'μ—΄'λ§Œμ„ λ‚¨κΈ°κ² λ‹€λŠ” μ˜λ―Έκ°€ λ©λ‹ˆλ‹€. κΈ°μ‘΄ ν–‰λ ¬μ˜ ν¬κΈ°λŠ” (2, 2)μ˜€μ§€λ§Œ 이λ₯Ό μˆ˜ν–‰ν•˜λ©΄ μ—΄μ˜ μ°¨μ›λ§Œ λ³΄μ‘΄λ˜λ©΄μ„œ (1, 2)κ°€ λ©λ‹ˆλ‹€. μ΄λŠ” (2,)와 κ°™μœΌλ©° λ²‘ν„°μž…λ‹ˆλ‹€. μ—΄μ˜ 차원을 λ³΄μ‘΄ν•˜λ©΄μ„œ 평균을 κ΅¬ν•˜λ©΄ μ•„λž˜μ™€ 같이 μ—°μ‚°ν•©λ‹ˆλ‹€.

# μ‹€μ œ μ—°μ‚° κ³Όμ •
t.mean(dim=0)은 μž…λ ₯μ—μ„œ 첫번째 차원을 μ œκ±°ν•œλ‹€.

[[1., 2.],
 [3., 4.]]

1κ³Ό 3의 평균을 κ΅¬ν•˜κ³ , 2와 4의 평균을 κ΅¬ν•œλ‹€.
κ²°κ³Ό ==> [2., 3.]

μ΄λ²ˆμ—λŠ” 인자둜 dim=1을 μ£Όκ² μŠ΅λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” λ‘λ²ˆμ§Έ 차원을 μ œκ±°ν•©λ‹ˆλ‹€. 즉, 열이 제거된 ν…μ„œκ°€ λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

print(t.mean(dim=1))
tensor([1.5000, 3.5000])

μ—΄μ˜ 차원이 μ œκ±°λ˜μ–΄μ•Ό ν•˜λ―€λ‘œ (2, 2)의 ν¬κΈ°μ—μ„œ (2, 1)의 크기가 λ©λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” 1κ³Ό 2의 평균을 κ΅¬ν•˜κ³  3κ³Ό 4의 평균을 κ΅¬ν•˜κ²Œ λ©λ‹ˆλ‹€. κ·Έλ ‡λ‹€λ©΄ κ²°κ³ΌλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

# μ‹€μ œ μ—°μ‚° κ²°κ³ΌλŠ” (2 × 1)
[1. 5]
[3. 5]

ν•˜μ§€λ§Œ (2 × 1)은 κ²°κ΅­ 1μ°¨μ›μ΄λ―€λ‘œ (1 × 2)와 같이 ν‘œν˜„λ˜λ©΄μ„œ μœ„μ™€ 같이 [1.5, 3.5]둜 좜λ ₯λ©λ‹ˆλ‹€. μ΄λ²ˆμ—λŠ” dim=-1λ₯Ό μ£ΌλŠ” 경우λ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€. μ΄λŠ” λ§ˆμ§€λ§‰ 차원을 μ œκ±°ν•œλ‹€λŠ” 의미이고, κ²°κ΅­ μ—΄μ˜ 차원을 μ œκ±°ν•œλ‹€λŠ” μ˜λ―Έμ™€ κ°™μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ μœ„μ™€ 좜λ ₯ κ²°κ³Όκ°€ κ°™μŠ΅λ‹ˆλ‹€.

print(t.mean(dim=-1))
tensor([1.5000, 3.5000])

3) λ§μ…ˆ(Sum)

λ§μ…ˆ(Sum)은 평균(Mean)κ³Ό μ—°μ‚° λ°©λ²•μ΄λ‚˜ μΈμžκ°€ μ˜λ―Έν•˜λŠ” λ°”λŠ” μ •ν™•νžˆ λ™μΌν•©λ‹ˆλ‹€. λ‹€λ§Œ, 평균이 μ•„λ‹ˆλΌ λ§μ…ˆμ„ ν•  λΏμž…λ‹ˆλ‹€.

t = torch.FloatTensor([[1, 2], [3, 4]])
print(t)
tensor([[1., 2.],
        [3., 4.]])
print(t.sum()) # λ‹¨μˆœνžˆ μ›μ†Œ μ „μ²΄μ˜ λ§μ…ˆμ„ μˆ˜ν–‰
print(t.sum(dim=0)) # 행을 제거
print(t.sum(dim=1)) # 열을 제거
print(t.sum(dim=-1)) # 열을 제거
tensor(10.)
tensor([4., 6.])
tensor([3., 7.])
tensor([3., 7.])

4) μ΅œλŒ€(Max)와 μ•„κ·Έλ§₯슀(ArgMax)

μ΅œλŒ€(Max)λŠ” μ›μ†Œμ˜ μ΅œλŒ€κ°’μ„ λ¦¬ν„΄ν•˜κ³ , μ•„κ·Έλ§₯슀(ArgMax)λŠ” μ΅œλŒ€κ°’μ„ 가진 인덱슀λ₯Ό λ¦¬ν„΄ν•©λ‹ˆλ‹€.
(2, 2) 크기의 행렬을 μ„ μ–Έν•˜κ³  Maxλ₯Ό μ‚¬μš©ν•΄λ΄…μ‹œλ‹€.

t = torch.FloatTensor([[1, 2], [3, 4]])
print(t)
tensor([[1., 2.],
        [3., 4.]])

μš°μ„  (2, 2) 행렬을 μ„ μ–Έν•˜μ˜€μŠ΅λ‹ˆλ‹€. 이제 .max()λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

print(t.max()) # Returns one value: max
tensor(4.)

μ›μ†Œ 쀑 μ΅œλŒ€κ°’μΈ 4λ₯Ό λ¦¬ν„΄ν•©λ‹ˆλ‹€.
μ΄λ²ˆμ—λŠ” 인자둜 dim=0을 μ£Όκ² μŠ΅λ‹ˆλ‹€. 첫번째 차원을 μ œκ±°ν•œλ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€.

print(t.max(dim=0)) # Returns two values: max and argmax
(tensor([3., 4.]), tensor([1, 1]))

ν–‰μ˜ 차원을 μ œκ±°ν•œλ‹€λŠ” μ˜λ―Έμ΄λ―€λ‘œ (1, 2) ν…μ„œλ₯Ό λ§Œλ“­λ‹ˆλ‹€. κ²°κ³ΌλŠ” [3, 4]μž…λ‹ˆλ‹€.

그런데 [1, 1]μ΄λΌλŠ” 값도 ν•¨κ»˜ λ¦¬ν„΄λ˜μ—ˆμŠ΅λ‹ˆλ‹€. max에 dim 인자λ₯Ό μ£Όλ©΄ argmax도 ν•¨κ»˜ λ¦¬ν„΄ν•˜λŠ” νŠΉμ§• λ•Œλ¬Έμž…λ‹ˆλ‹€. 첫번째 μ—΄μ—μ„œ 3의 μΈλ±μŠ€λŠ” 1μ΄μ—ˆμŠ΅λ‹ˆλ‹€. λ‘λ²ˆμ§Έ μ—΄μ—μ„œ 4의 μΈλ±μŠ€λŠ” 1μ΄μ—ˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ [1, 1]이 λ¦¬ν„΄λ©λ‹ˆλ‹€. μ–΄λ–€ μ˜λ―ΈμΈμ§€λŠ” μ•„λž˜ μ„€λͺ…ν•΄λ΄€μŠ΅λ‹ˆλ‹€.

# [1, 1]κ°€ 무슨 μ˜λ―ΈμΈμ§€ λ΄…μ‹œλ‹€. κΈ°μ‘΄ 행렬을 λ‹€μ‹œ μƒκΈ°ν•΄λ΄…μ‹œλ‹€.
[[1, 2],
 [3, 4]]
첫번째 μ—΄μ—μ„œ 0번 μΈλ±μŠ€λŠ” 1, 1번 μΈλ±μŠ€λŠ” 3μž…λ‹ˆλ‹€.
λ‘λ²ˆμ§Έ μ—΄μ—μ„œ 0번 μΈλ±μŠ€λŠ” 2, 1번 μΈλ±μŠ€λŠ” 4μž…λ‹ˆλ‹€.
λ‹€μ‹œ 말해 3κ³Ό 4의 μΈλ±μŠ€λŠ” [1, 1]μž…λ‹ˆλ‹€.

λ§Œμ•½ 두 개λ₯Ό ν•¨κ»˜ λ¦¬ν„΄λ°›λŠ” 것이 μ•„λ‹ˆλΌ max λ˜λŠ” argmax만 리턴받고 μ‹Άλ‹€λ©΄ λ‹€μŒκ³Ό 같이 리턴값에도 인덱슀λ₯Ό λΆ€μ—¬ν•˜λ©΄ λ©λ‹ˆλ‹€. 0번 인덱슀λ₯Ό μ‚¬μš©ν•˜λ©΄ max κ°’λ§Œ λ°›μ•„μ˜¬ 수 있고, 1번 인덱슀λ₯Ό μ‚¬μš©ν•˜λ©΄ argmax κ°’λ§Œ λ°›μ•„μ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

print('Max: ', t.max(dim=0)[0])
print('Argmax: ', t.max(dim=0)[1])
Max:  tensor([3., 4.])
Argmax:  tensor([1, 1])

μ΄λ²ˆμ—λŠ” dim=1둜 인자λ₯Ό μ£Όμ—ˆμ„ λ•Œμ™€ dim=-1둜 인자λ₯Ό μ£Όμ—ˆμ„ λ•Œλ₯Ό λ³΄κ² μŠ΅λ‹ˆλ‹€.

print(t.max(dim=1))
print(t.max(dim=-1))
(tensor([2., 4.]), tensor([1, 1]))
(tensor([2., 4.]), tensor([1, 1]))
λ°˜μ‘ν˜•