딥러닝 Deeplearning 2

Bleu·2023년 10월 12일
0

python

목록 보기
18/22

Tensor 생성

  • 파이토치에서 데이터를 저장하는 자료구조
  • ndarray와 성격, 사용법이 유사

원하는 형태(shape) 텐서 생성

  • torch.tensor(자료구조 [, dtype])
    • 지정한 dtype(Data type)에 맞는 Tensor객체를 생성해서 반환

특정 타입의 Tensor를 직접 생성

  • torch.tensor()로 생성하면서 dtype을 지정하면 아래 타입의 Tensor객체가 생성됨
  • 원하는 Type의 Tensor클래스를 이용해 직접 생성해도 됨
  • torch.FloatTensor(자료구조)
    • float32 타입 텐서 생성
  • torch.LongTensor(자료구조)
    • int64 타입 텐서생성
  • 그외
    • BoolTensor(bool), CharTensor(int8), ShortTensor(int16), IntTensor(int32), DoubleTensor(float64)

tensor 상태 조회

  • tensor.shape, tensor.size([축번호])
    • tensor의 shape조회
  • tensor.dtype, tensor.type()
    • tensor 원소들의 데이터타입 조회
    • dtype은 data type을 type()은 tensor 객체의 클래스 타입을 반환
  • tensor.ndim, tensor.dim() : tensor 차원
  • tensor.numel(): 전체 원소 개수
a = torch.tensor([[1,2],[3,4]], dtype=torch.float32)

print("shape:", a.shape, a.size())  #전체 shape
print("축별 크기:", a.shape[0], a.size(0))  # 측별 size
print("type:", a.type(), a.dtype)
print('차원크기:', a.dim(), a.ndim)
print('원소개수:', a.numel())
print("device:", a.device) # 이 값이 cpu에 의해 처리될 수 있는 (ram) 영역에 있다는 뜻
#Float, Double(32, 64bit 실수)/Int, Long(32, 64 bit 정수) type Tensor
b = torch.FloatTensor([1,3,7])  #float32
print(b.dtype)
c = torch.IntTensor([10,20,30]) # int64
print(c.dtype)
d = torch.DoubleTensor([1, 2, 3])  # torch.tensor([], dtype = torch.float64) 와 동일
print(d.dtype)
e = torch.LongTensor([10, 20, 30, 40])  # torch.tensor([], dtype = torch.int64)와 동일
print(e.dtype)

특정 값으로 구성된 Tensor 생성

  • torch.zeros(*size), zeros_like(텐서): 0으로 구성된 tensor 생성
  • torch.ones(*size), ones_like(텐서): 1로 구성된 tensor생성
  • torch.full(*size), full_like(텐서): 지정한 값으로 구성된 tensor생성

동일한 간격으로 떨어진 값들로 구성된 배열생성

  • torch.arange(start=0, end, step=1)
  • torch.linspace(start, end, steps,) : steps - 원소개수
torch.arange(10)  # 0~ 10-1
torch.arange(0, 1, 0.1)  # 0~1, 증감: 0.1
torch.arange(10, 1, -1)  # (reverse-역순) 10~1+1: 증감: -1
torch.linspace(0, 10, 5)  # 0~ 10 등분한 값 5개
torch.linspace(0, 1, 11)  # 0~1, 등분한 값 10개


빈 tensor 생성

  • torch.empty(*size)
    (0 에 가까운 의미 없는 값으로 채워줌)

난수를 이용한 생성

  • torch.rand(*size): 0 ~ 1사이 실수로 구성된 배열을 생성. 각 값은 균등분포를 따름
  • torch.randn(*size): 표준정규분포(평균:0, 표준편차:1)를 따르는 실수로 구성된 배열 생성
  • torch.randint(low=0, high, size): 지정한 범위의 정수로 구성된 배열 생성
  • torch.randperm(n): 0 ~ n 사이의 정수를 랜덤하게 섞은 값을 원소로 가지는 배열 생성

tensor를 상수로 변환

  • tensor객체.item()
    • Scalar(상수) tensor를 python 상수로 변환

ndarray 호환

  • ndarray를 tensor로 생성
    • torch.tensor(ndarray)
    • torch.from_numpy(ndarray)
  • tensor를 ndarray로 변환
    • tensor.numpy()
    • tensor가 gpu에 있을 경우 cpu로 옮긴 뒤 변환해야 함


Tensor gpu/cpu 메모리로 옮기기

  • pytorch는 데이터셋인 tensor를 cpu메모리와 gpu 메모리로 서로 옮길 수 있다.
    • 데이터에 대한 연산처리를 어디서 하느냐에 따라 메모리를 선택한다.
    • 장치는 문자열로 설정한다.
      • CPU 사용: "cpu"
      • nvida GPU: "cuda"
      • Apple m1: "mps"
        • pytorch 1.12 부터 지원
  • 옮기기
    • tensor 생성시 device 파라미터를 이용해 설정
    • tensor.to(device)를 이용해 설정
  • 현재 실행환경에서 어떤 장비를 사용할 수 있는지 확인
    • nvidia gpu 사용가능 확인
      • torch.cuda.is_available() - nvida gpu 사용가능 여부
      • torch.backends.mps.is_available() - M1 사용가능 여부

원소 조회및 변경 - indexing/slicing

  • 대부분 Numpy 와 동일
    • slicing에서 step을 음수로 지정할 수 없음


Reshape

shape 변경

  • tensor객체.reshape(*shape) / view(*shape) 이용
    • 변환 후 값을 변경하면 원본 배열의 값도 같이 바뀜

      tensor.clone(): tensor를 복제

dummy 축 늘리기

  • None을 이용 (numpy의 newaxis 대신 None을 사용)
  • unsqueeze(dim=축번호)
import torch
a = torch.tensor([[10,20],[10,20]])
print(a.shape)

a1, a2 = a[None, :], a.unsqueeze(dim=0)
print(a1.shape, a2.shape)

a3, a4 = a[:, :, None], a.unsqueeze(dim=-1) 
print(a3.shape, a4.shape)

a5, a6 = a3[:,None,:,:], a3.unsqueeze(dim=1)
print(a5.shape, a6.shape)

# numpy에도 이 문법이 있음

dummy 축 제거

  • squeeze([dim=축번호]) 이용
t = torch.rand(3, 1, 3, 1)
print(t.shape)

r1 = t.squeeze()  #축을 명시하지 않모두 제거
print(r1.shape)

r2 = t.squeeze(dim=1) # 특정 axis 제거
print(r2.shape)

r3 = t.squeeze(dim=[1,3]) # 여러 axis의 dummy 축 제거
print(r3.shape)


tensor 합치기

torch.cat([tensorA, tensorB, ...], dim=0)

값의 위치(index) 변경

  • tensor 원소의 축별 index의 위치를 바꿈
  • tensor.transpose(axis1, axis2)
    • 두 축의 자리만 변경 할 수 있음
  • tensor.permute(axis1, axis2, axis3, ..)
    • 두 개 이상의 축 자리를 변경


tensor 연산 및 주요 함수

element-wise 연산

  • tensor와 상수 연산시, tensor와 tensor간 연산시 원소별로 처리
  • 행렬곱 연산을 제외하고 tensor간 연산시 피연산지 tensor간에 shape이 같아야 함
    • shape이 다를 경우 조건이 맞으면 broadcasting을 한 뒤에 연산
      (size가 다른 축의 경우 한개의 피연산자 size가 1일 경우 복사하여 shape을 맞춤
import torch

a = torch.arange(10).reshape(2,5)
b = torch.arange(10,20).reshape(2,5)
c = torch.arange(50, 55)

print(a)
print(b)
print(c)
y = x + torch.randn((3,3))
# print(y)
print(torch.round(y)) # 반올림
print(torch.round(y, decimals=2)) # 소수점 둘째자리 이하에서 반올림
print(torch.floor(y)) # 내림 
print(torch.ceil(y)) # 올림

행렬곱

  • @ 연산자 또는 torch.matmul(tensor1, tensor2) 함수 이용
import torch

x = torch.FloatTensor([[1, 2],
                       [3, 4],
                       [5, 6]
                      ])

y = torch.FloatTensor([[1, 2],
                       [1, 2],
                      ])
x.size(), y.shape
z1 = x @ y
z2 = torch.matmul(x, y)
print(z1.shape, z2.shape)
print(z1)
print(z2)
# Batch 행렬곱(Batch matrix muliplication) - bmm()
# x, y가 가지는 3개의 2차원 배열 간에 행렬곱을 처리
import torch
x = torch.FloatTensor(3,4,2)
y = torch.FloatTensor(3,2,5)
z = torch.bmm(x, y)
z.shape

torch.nan, torch.inf

  • nan: Not a Number, 주로 결측치를 표현
  • inf: infinit 무한.
    • torch.inf: 양의 무한
    • -torch.inf: 음의 무한
  • torch.isnan(tensor)
    • 원소별 결측치 확인
  • torch.isinf(tensor)
    • 원소별 inf 확인
print(torch.inf > 10, torch.inf < 10)
print(-torch.inf < 10, -torch.inf > 10)
print(torch.log(torch.tensor(-1))) # nan 
print(torch.isnan(torch.tensor([1,2,torch.nan,3,4])))  # nan 여부 확인
print(torch.isinf(torch.tensor([1,2,3,4,torch.inf])))  # inf 여부 확인

autograd(자동미분)

  • 자동 미분을 이용해 gradient를 계산하는 pytorch system.
  • 딥러닝 모델에서 weight와 bias tensor들(Parameter)은 backpropagation(역전파)를 이용해 gradient를 구해서 loss가 줄어드는 방향으로 update를 하게 됨
  • pytorch는 이런 미분 수행을 자동으로 처리해 줌
    • gradient(기울기)를 구한다는 것은 미분을 한다는 것
  • tensor가 미분 가능하려면 requires_grad=True 로 설정되 있어야 함. (default: False)
x = torch.tensor([1.], requires_grad=True)
# x = torch.tensor([1.])
# x.requires_grad = True
print(x)
print(x.requires_grad)

torch.no_grad()

  • no_grad() 구문에서 연산을 할 경우 requires_grad=True로 설정되었다 하더라도 gradient를 update하지 않음
  • 딥러닝 모델 학습이 끝나고 평가할 때는 gradient를 계산할 필요가 없기 때문에 no_grad 구문을 사용

0개의 댓글