열심히 코딩 하숭!

2. 파이토치의 기본 기능 | 파이토치 딥러닝 프로그래밍 본문

프로그래밍 책/파이토치 딥러닝 프로그래밍

2. 파이토치의 기본 기능 | 파이토치 딥러닝 프로그래밍

채숭이 2024. 4. 16. 14:27

2. 파이토치의 기본 기능

2.2 텐서

1) 텐서(Tensor)의 개념

  • 파이토치에의 고유 클래스로, 데이터를 표현한다
  • 파이토치의 연산 대상 데이터는 모두 Tensor라는 고유의 형식으로 되어있어야 한다
  • 0계 텐서(스칼라) / 1계 텐서(벡터), 2계 텐서(행렬)

2) 다양한 계수의 텐서 만들기

  • torch.tensor (값 대입)
    • 뒤에 float을 붙여 강제로 float32로 변환하기 (대부분의 계산에 dtype=float32를 사용한다)
    • (그렇지 않으면 float64로 설정되고 이는 nn.Linear 같은 부분에서 에러를 발생시킨다)
r0 = torch.tensor(1.0).float()
  • tensor 확인
print(type(r0)) # 변수 자체의 타입 확인
print(r0.dtype) # 텐서 내의 데이터 타입 확인
print(r0.shape) # 차원 확인
print(r0.data) # 값 확인

## 결과 ##
<class 'torch.Tensor'>
torch.float32
torch.Size([])
tensor(1.)
  • 1계/2계 텐서 - np.array를 활용
    • 텐서넘파이서로 변환이 가능하다
## 1계 텐서 ##
r1_np = np.array([1,2,3,4,5])
r1 = torch.tensor(r1_np).float()

print(r1_np.shape)
print(r1.dtype)
print(r1.shape)
print(r1.data)

## 결과 ##
(5, )
torch.float32
torch.Size([5])
tensor([1., 2., 3., 4., 5.])
## 2계 텐서 ##
r2_np = np.array([[1,5,6],[4,3,2]])
r2 = torch.tensor(r2_np).float()

print(r2_np.shape)
print(r2.shape)
print(r2.data)

## 결과 ##
(2, 3)
torch.Size([2, 3])
tensor([1., 5., 6.],
			 [4., 3., 2.])
  • 3계/4계 텐서- torch.randn / torch.ones를 활용
## 3계 텐서 ##
torch.manual_seed(123) # 난수 seed 초기화
r3 = torch.randn((3, 2, 2)) # shape=[3, 2, 2]인 정규분포 텐서 작성
## 4계 텐서 ##
r4 = torch.ones((2,3,2,2)) # 요소가 모두 1인 shape=[2,3,2,2] 텐서 작성

 

3) 정수값을 가지는 텐서 만들기

  • long 함수 사용
    • 다중분류에서 사용하는 손실함수 nn.CrossEntropyLoss와 nn.NLLLoss에서 사용한다고 한다…(자세히는 아직 모르겠다)
r5 = r1.long()

 

4) view 함수

  • 넘파이의 reshape 함수와 같이, view 함수계수 변환이 가능하다
r3 = torch.randn((3, 2, 2))
r6 = r3.view(3, -1)
print(r6.shape)

## 결과 ##
torch.Size([3, 4])
  • 1계 텐서로 변환하거나, 자동 변환을 하려면 -1로 지정하면 된다
r7 = r3.view(-1)

 

5) item 함수

  • 0계 텐서의 경우 item 함수로 값을 꺼낼 수 있다
    • 주의: 1계 이상의 텐서에 사용하면 오류가 난다
    • 예외: shape이 [1]이나 [1,1]일 경우 사용 가능하다
item = r0.item()
print(type(item))
print(item)

## 결과 ##
<class 'float'>
1.0

 

6) max/min/mean 함수

  • 최대값을 반환
print(r2.max())
print(r2.min())
print(r2.mean())

 

7) torch.max(r2, 1) 함수

  • 기준이 되는 축을 설정하고, 축마다의 max값을 모아서 볼 수 있다
print(torch.max(r2, 1), "\\n")
print(torch.max(r2, 1) # 인덱스 가져오기

## 결과 ##
torch.return_types.max(
values=tensor([6., 4.]),
indices=tensor([2, 0]))

tensor([2, 0])

 

8) 텐서에서 넘파이로 변환

  • .data.numpy() 사용
r2_np = r2.data.numpy()

2.3 자동 미분 기능

 

1) 경사 계산용 변수 정의

  • 경사(미분) 계산을 해야 하는 변수는 텐서 변수로 정의한다
  • 이 때, requires_grad 속성을 True로 설정해야 한다
x = torch.tensor(x_np, **requires_grid**=**True**, dtype=torch.float32)

 

2) 텐서 변수 간의 계산

  • 다른 텐서 변수와 연산을 할 때, 계산 식을 통해 값을 계산한다
y = 2*x**2 + 2 
# y도 자동적으로 텐서 변수가 된다 (**requires_grid**=**True 속성도 가질 수 있다)**
  • 경사 계산 대상의 함수는 스칼라일 필요가 있으므로, y 값을 sum 함수로 모두 더한 다음 그 결과를 새로운 텐서 변수 z에 대입한다 (=> 손실함수가!!!! 스칼라 값이어야 하니까!!!)
z = y.sum()

 

3) 계산 그래프 시각화

  • 계산 그래프는 make_dot 함수를 통해 시각화 할 수 있다
from torchviz import make_dot

g = make_dot(z, params={'x':x})
display(g)

 

4) 경사 계산

  • 계산 결과를 저장한 텐서 변수에 backward 함수를 호출한다
  • 이 때, 파이토치 내부에서 수치 미분이 작용해서 경사 계산이 이뤄진다
z.backward()

 

5) 경삿값 가져오기

  • 수치 미분의 결과를 파이토치에서 ‘경삿값’이라고 부른다
  • 경삿값은 텐서 변수의 grad 속성으로 가져올 수 있다
print(x.grad)

 

6) 경삿값의 초기화

  • grad 속성에 저장된 경사값은, 사용이 끝나면 값을 초기화해야 한다
  • x.grad는 최신 경사 계산 결과가 그대로 입력되는 것이 아니라, 지금까지의 경사 계산 결과를 합산한 값이 입력되기 때문이다
x.grad.zero_()