Tensor 생성
리스트(list) 또는 NumPy 배열(ndarray)로부터 Tensor 생성 ( list도 가능하다)
import torch
import numpy as np
# 리스트로부터 Tensor 생성
list_data = [1, 2, 3]
tensor_data = torch.tensor(list_data)
# NumPy 배열로부터 Tensor 생성
ndarray_data = np.array([[1, 2], [3, 4]])
tensor_data = torch.tensor(ndarray_data)
Tensor Operation
기본적으로 numpy 연산과 같다.
data = [[3,5,20],[10,5,50],[1,5,10]]
x_data = torch.tensor(data)
x_data[1:,]
x_data.flatten() #tensor([ 3, 5, 20, 10, 5, 50, 1, 5, 10])
torch.zeros_like(x_data)
#tensor([[0, 0, 0],
# [0, 0, 0],
# [0, 0, 0]])
x_data.numpy()
#array([[ 3, 5, 20],
# [10, 5, 50],
# [ 1, 5, 10]], dtype=int64)
x_data.shape
#torch.Size([3, 3])
x_data.dtype
#torch.int64
tensor GPU에서 사용하기
import torch
# CUDA 디바이스가 사용 가능한지 확인
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Tensor를 생성하고 GPU로 올리기
x = torch.Tensor([1, 2, 3]).to(device)
# GPU에서 연산하기
y = x + 2
# 결과 출력하기
print(y)
먼저, torch.cuda.is_available() 함수를 사용하여 CUDA 디바이스가 사용 가능한지 확인합니다. 그런 다음 torch.device() 함수를 사용하여 디바이스를 선택하고, Tensor를 to() 메소드를 사용하여 GPU에 올립니다. 그리고 나서 GPU에서 연산을 수행할 수 있습니다.
view() vs reshape() - contiguity(접근) 보장의 차이
view() 메소드는 Tensor를 새로운 shape로 변경하는 뷰를 반환합니다. 뷰는 원래 Tensor의 데이터를 참조하며, 새로운 shape에서 데이터를 재배열하는 것이 아니므로 연산이 비용이 거의 없습니다. 하지만, 반환된 뷰를 수정하면 원래 Tensor도 변경됩니다. 즉, 뷰와 원래 Tensor는 동일한 데이터를 참조하기 때문입니다.
import torch
x = torch.randn(3, 4, 5) # 3x4x5 Tensor
y = x.view(2, 6, 5) # 2x6x5 뷰 반환
print(x.shape) # torch.Size([3, 4, 5])
print(y.shape) # torch.Size([2, 6, 5])
y[0, 0, 0] = 1.0 # 뷰 수정
print(x[0, 0, 0]) # 1.0 출력 (x의 데이터도 변경됨)
reshape() 메소드는 Tensor를 새로운 shape로 변경하는 새로운 Tensor를 반환합니다. 따라서 메모리에 새로운 Tensor를 할당하고, 데이터를 새로운 shape로 재배열합니다. 이것은 view와 달리 연산 비용이 조금 더 큽니다.
import torch
x = torch.randn(3, 4, 5) # 3x4x5 Tensor
y = x.reshape(2, 6, 5) # 2x6x5 Tensor 반환
print(x.shape) # torch.Size([3, 4, 5])
print(y.shape) # torch.Size([2, 6, 5])
y[0, 0, 0] = 1.0 # y 수정
print(x[0, 0, 0]) # 원래 Tensor인 x는 변경되지 않음
squeeze, unsqueeze
squeeze() 메소드는 Tensor에서 크기가 1인 차원을 제거합니다. 예를 들어, (1, 3, 1, 5) 크기의 Tensor가 있다면 squeeze()를 사용하여 (3, 5) 크기의 Tensor를 만들 수 있습니다. 이때, 제거할 차원을 인자로 지정할 수도 있습니다.
import torch
x = torch.randn(1, 3, 1, 5) # 1x3x1x5 Tensor
y = x.squeeze() # 3x5 Tensor 반환
z = x.squeeze(0) # 3x1x5 Tensor 반환 (0번째 차원 제거)
print(x.shape) # torch.Size([1, 3, 1, 5])
print(y.shape) # torch.Size([3, 5])
print(z.shape) # torch.Size([3, 1, 5])
unsqueeze() 메소드는 Tensor의 차원을 추가합니다. 인자로 차원을 지정하면 해당 위치에 크기가 1인 차원이 추가됩니다.
import torch
x = torch.randn(3, 5) # 3x5 Tensor
y = x.unsqueeze(0) # 1x3x5 Tensor 반환 (0번째 차원에 추가)
z = x.unsqueeze(-1) # 3x5x1 Tensor 반환 (마지막 차원에 추가)
print(x.shape) # torch.Size([3, 5])
print(y.shape) # torch.Size([1, 3, 5])
print(z.shape) # torch.Size([3, 5, 1])
squeeze()와 unsqueeze() 메소드는 모델에서 입력 Tensor의 shape를 맞추는데 매우 유용합니다. 또한, 차원을 추가하거나 제거하여 Tensor의 shape를 변경할 수 있습니다.
행렬 곱셈 연산 - dot이 아닌 mm,matmul 사용
matmul 과 mm 의차이- broadcasting
mm() 함수는 두 개의 2차원 Tensor를 입력으로 받아 행렬곱 연산을 수행합니다. 따라서, 이 함수는 2차원 Tensor 간의 행렬곱 연산에 최적화되어 있습니다. mm() 함수는 다음과 같이 사용됩니다.
import torch
x = torch.randn(3, 4) # 3x4 Tensor
y = torch.randn(4, 5) # 4x5 Tensor
z = torch.mm(x, y) # 3x5 Tensor 반환
print(z.shape) # torch.Size([3, 5])
matmul() 함수는 두 개의 Tensor를 입력으로 받아 행렬곱 연산을 수행합니다. matmul() 함수는 입력 Tensor의 차원이 2차원 이상일 경우에도 동작할 수 있습니다. 따라서, 다차원 Tensor 간의 행렬곱 연산을 수행할 수 있습니다. matmul() 함수는 다음과 같이 사용됩니다.
import torch
x = torch.randn(3, 4, 5) # 3x4x5 Tensor
y = torch.randn(3, 5, 6) # 3x5x6 Tensor
z = torch.matmul(x, y) # 3x4x6 Tensor 반환
print(z.shape) # torch.Size([3, 4, 6])
nn.functional 모듈 - 다양한 수식 변환 지원
nn.functional 모듈은 PyTorch에서 제공하는 신경망 함수들을 모아놓은 모듈입니다. 이 모듈은 nn.Module을 상속받지 않는 함수들을 제공하며, 이러한 함수들은 일반적으로 간단한 계산을 수행하기 위한 함수들입니다.
import torch.nn as nn
import torch.nn.functional as F
nn.functional 모듈에서 제공하는 함수들은 다음과 같습니다.
- nn.functional.relu(input, inplace=False): ReLU(Rectified Linear Unit) 함수를 계산합니다. inplace 매개변수가 True로 설정되면 입력 Tensor 자체가 수정됩니다.
- nn.functional.sigmoid(input): 시그모이드 함수를 계산합니다.
- nn.functional.tanh(input): 하이퍼볼릭 탄젠트 함수를 계산합니다.
- nn.functional.softmax(input, dim=None, _stacklevel=3, dtype=None): 소프트맥스 함수를 계산합니다. dim 매개변수를 통해 계산할 차원을 지정할 수 있습니다.
- nn.functional.one_hot(x) : one hot encoding으로 변환
Autograd - 자동미분
backward() 함수는 Autograd를 사용하여 자동으로 계산된 기울기를 역전파하는 함수입니다. 이 함수는 손실 함수를 모델의 출력에 대해 미분한 결과를 모델의 입력으로 전달하여 각 매개변수에 대한 기울기를 계산합니다.
import torch
# 입력값 x 생성
x = torch.tensor(2.0, requires_grad=True)
# 계산 그래프 생성
y = 3*x**2 + 2*x + 1
# 기울기 계산
y.backward()
# x의 기울기 출력
print(x.grad)
#tensor(14.)
tensor 안의 requires_grad의 의미
requires_grad는 PyTorch에서 Tensor 객체가 Autograd를 사용하여 자동 미분을 수행해야 하는지 여부를 나타내는 부울 값입니다. 기본값은 False입니다.
만약 requires_grad를 True로 설정하면, 해당 Tensor를 포함한 계산 그래프가 생성될 때 PyTorch는 해당 Tensor에 대한 모든 연산을 추적하여 이 Tensor를 사용하여 계산된 결과 Tensor의 기울기(gradient)를 자동으로 계산할 수 있습니다.
예를 들어, 신경망 모델을 학습할 때 모델의 매개변수(Parameter)들은 항상 requires_grad=True로 설정해야 합니다. 그렇지 않으면 Autograd가 해당 매개변수들의 기울기를 계산하지 않으므로 학습이 제대로 이루어지지 않습니다.
requires_grad의 값은 Tensor 객체 생성시 requires_grad=True로 지정하거나, requires_grad_() 메서드를 사용하여 변경할 수 있습니다. 또한 detach() 메서드를 사용하여 기울기 추적을 멈출 수 있습니다.
만약 다수의 x에 대한 기울기를 구하고 싶다면??
import torch
x = torch.tensor([2.0,3.0,4.0],requires_grad = True)
y = 3*x**2 + 2*x + 1
external_grad = torch.tensor([1.0,1.0,1.0]) #external_grad -> output gradient값의 크기지정
y.backward(gradient = external_grad)
x.grad
#tensor([14., 20., 26.])
미분 결과가 여러개가 나오므로 external_grad의 크기를 지정해주어 backward함수의 파라미터로 넘겨준다.
'AI > Pytorch' 카테고리의 다른 글
모듈 분석,Docstring,repr (0) | 2023.03.16 |
---|---|
Custom Model, Conatiner, Module (0) | 2023.03.16 |
PyTorch Document 2 (0) | 2023.03.16 |
PyTorch Document 1 (0) | 2023.03.14 |
PyTorch 개요 (0) | 2023.03.12 |
Tensor 생성
리스트(list) 또는 NumPy 배열(ndarray)로부터 Tensor 생성 ( list도 가능하다)
import torch
import numpy as np
# 리스트로부터 Tensor 생성
list_data = [1, 2, 3]
tensor_data = torch.tensor(list_data)
# NumPy 배열로부터 Tensor 생성
ndarray_data = np.array([[1, 2], [3, 4]])
tensor_data = torch.tensor(ndarray_data)
Tensor Operation
기본적으로 numpy 연산과 같다.
data = [[3,5,20],[10,5,50],[1,5,10]]
x_data = torch.tensor(data)
x_data[1:,]
x_data.flatten() #tensor([ 3, 5, 20, 10, 5, 50, 1, 5, 10])
torch.zeros_like(x_data)
#tensor([[0, 0, 0],
# [0, 0, 0],
# [0, 0, 0]])
x_data.numpy()
#array([[ 3, 5, 20],
# [10, 5, 50],
# [ 1, 5, 10]], dtype=int64)
x_data.shape
#torch.Size([3, 3])
x_data.dtype
#torch.int64
tensor GPU에서 사용하기
import torch
# CUDA 디바이스가 사용 가능한지 확인
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Tensor를 생성하고 GPU로 올리기
x = torch.Tensor([1, 2, 3]).to(device)
# GPU에서 연산하기
y = x + 2
# 결과 출력하기
print(y)
먼저, torch.cuda.is_available() 함수를 사용하여 CUDA 디바이스가 사용 가능한지 확인합니다. 그런 다음 torch.device() 함수를 사용하여 디바이스를 선택하고, Tensor를 to() 메소드를 사용하여 GPU에 올립니다. 그리고 나서 GPU에서 연산을 수행할 수 있습니다.
view() vs reshape() - contiguity(접근) 보장의 차이
view() 메소드는 Tensor를 새로운 shape로 변경하는 뷰를 반환합니다. 뷰는 원래 Tensor의 데이터를 참조하며, 새로운 shape에서 데이터를 재배열하는 것이 아니므로 연산이 비용이 거의 없습니다. 하지만, 반환된 뷰를 수정하면 원래 Tensor도 변경됩니다. 즉, 뷰와 원래 Tensor는 동일한 데이터를 참조하기 때문입니다.
import torch
x = torch.randn(3, 4, 5) # 3x4x5 Tensor
y = x.view(2, 6, 5) # 2x6x5 뷰 반환
print(x.shape) # torch.Size([3, 4, 5])
print(y.shape) # torch.Size([2, 6, 5])
y[0, 0, 0] = 1.0 # 뷰 수정
print(x[0, 0, 0]) # 1.0 출력 (x의 데이터도 변경됨)
reshape() 메소드는 Tensor를 새로운 shape로 변경하는 새로운 Tensor를 반환합니다. 따라서 메모리에 새로운 Tensor를 할당하고, 데이터를 새로운 shape로 재배열합니다. 이것은 view와 달리 연산 비용이 조금 더 큽니다.
import torch
x = torch.randn(3, 4, 5) # 3x4x5 Tensor
y = x.reshape(2, 6, 5) # 2x6x5 Tensor 반환
print(x.shape) # torch.Size([3, 4, 5])
print(y.shape) # torch.Size([2, 6, 5])
y[0, 0, 0] = 1.0 # y 수정
print(x[0, 0, 0]) # 원래 Tensor인 x는 변경되지 않음
squeeze, unsqueeze
squeeze() 메소드는 Tensor에서 크기가 1인 차원을 제거합니다. 예를 들어, (1, 3, 1, 5) 크기의 Tensor가 있다면 squeeze()를 사용하여 (3, 5) 크기의 Tensor를 만들 수 있습니다. 이때, 제거할 차원을 인자로 지정할 수도 있습니다.
import torch
x = torch.randn(1, 3, 1, 5) # 1x3x1x5 Tensor
y = x.squeeze() # 3x5 Tensor 반환
z = x.squeeze(0) # 3x1x5 Tensor 반환 (0번째 차원 제거)
print(x.shape) # torch.Size([1, 3, 1, 5])
print(y.shape) # torch.Size([3, 5])
print(z.shape) # torch.Size([3, 1, 5])
unsqueeze() 메소드는 Tensor의 차원을 추가합니다. 인자로 차원을 지정하면 해당 위치에 크기가 1인 차원이 추가됩니다.
import torch
x = torch.randn(3, 5) # 3x5 Tensor
y = x.unsqueeze(0) # 1x3x5 Tensor 반환 (0번째 차원에 추가)
z = x.unsqueeze(-1) # 3x5x1 Tensor 반환 (마지막 차원에 추가)
print(x.shape) # torch.Size([3, 5])
print(y.shape) # torch.Size([1, 3, 5])
print(z.shape) # torch.Size([3, 5, 1])
squeeze()와 unsqueeze() 메소드는 모델에서 입력 Tensor의 shape를 맞추는데 매우 유용합니다. 또한, 차원을 추가하거나 제거하여 Tensor의 shape를 변경할 수 있습니다.
행렬 곱셈 연산 - dot이 아닌 mm,matmul 사용
matmul 과 mm 의차이- broadcasting
mm() 함수는 두 개의 2차원 Tensor를 입력으로 받아 행렬곱 연산을 수행합니다. 따라서, 이 함수는 2차원 Tensor 간의 행렬곱 연산에 최적화되어 있습니다. mm() 함수는 다음과 같이 사용됩니다.
import torch
x = torch.randn(3, 4) # 3x4 Tensor
y = torch.randn(4, 5) # 4x5 Tensor
z = torch.mm(x, y) # 3x5 Tensor 반환
print(z.shape) # torch.Size([3, 5])
matmul() 함수는 두 개의 Tensor를 입력으로 받아 행렬곱 연산을 수행합니다. matmul() 함수는 입력 Tensor의 차원이 2차원 이상일 경우에도 동작할 수 있습니다. 따라서, 다차원 Tensor 간의 행렬곱 연산을 수행할 수 있습니다. matmul() 함수는 다음과 같이 사용됩니다.
import torch
x = torch.randn(3, 4, 5) # 3x4x5 Tensor
y = torch.randn(3, 5, 6) # 3x5x6 Tensor
z = torch.matmul(x, y) # 3x4x6 Tensor 반환
print(z.shape) # torch.Size([3, 4, 6])
nn.functional 모듈 - 다양한 수식 변환 지원
nn.functional 모듈은 PyTorch에서 제공하는 신경망 함수들을 모아놓은 모듈입니다. 이 모듈은 nn.Module을 상속받지 않는 함수들을 제공하며, 이러한 함수들은 일반적으로 간단한 계산을 수행하기 위한 함수들입니다.
import torch.nn as nn
import torch.nn.functional as F
nn.functional 모듈에서 제공하는 함수들은 다음과 같습니다.
- nn.functional.relu(input, inplace=False): ReLU(Rectified Linear Unit) 함수를 계산합니다. inplace 매개변수가 True로 설정되면 입력 Tensor 자체가 수정됩니다.
- nn.functional.sigmoid(input): 시그모이드 함수를 계산합니다.
- nn.functional.tanh(input): 하이퍼볼릭 탄젠트 함수를 계산합니다.
- nn.functional.softmax(input, dim=None, _stacklevel=3, dtype=None): 소프트맥스 함수를 계산합니다. dim 매개변수를 통해 계산할 차원을 지정할 수 있습니다.
- nn.functional.one_hot(x) : one hot encoding으로 변환
Autograd - 자동미분
backward() 함수는 Autograd를 사용하여 자동으로 계산된 기울기를 역전파하는 함수입니다. 이 함수는 손실 함수를 모델의 출력에 대해 미분한 결과를 모델의 입력으로 전달하여 각 매개변수에 대한 기울기를 계산합니다.
import torch
# 입력값 x 생성
x = torch.tensor(2.0, requires_grad=True)
# 계산 그래프 생성
y = 3*x**2 + 2*x + 1
# 기울기 계산
y.backward()
# x의 기울기 출력
print(x.grad)
#tensor(14.)
tensor 안의 requires_grad의 의미
requires_grad는 PyTorch에서 Tensor 객체가 Autograd를 사용하여 자동 미분을 수행해야 하는지 여부를 나타내는 부울 값입니다. 기본값은 False입니다.
만약 requires_grad를 True로 설정하면, 해당 Tensor를 포함한 계산 그래프가 생성될 때 PyTorch는 해당 Tensor에 대한 모든 연산을 추적하여 이 Tensor를 사용하여 계산된 결과 Tensor의 기울기(gradient)를 자동으로 계산할 수 있습니다.
예를 들어, 신경망 모델을 학습할 때 모델의 매개변수(Parameter)들은 항상 requires_grad=True로 설정해야 합니다. 그렇지 않으면 Autograd가 해당 매개변수들의 기울기를 계산하지 않으므로 학습이 제대로 이루어지지 않습니다.
requires_grad의 값은 Tensor 객체 생성시 requires_grad=True로 지정하거나, requires_grad_() 메서드를 사용하여 변경할 수 있습니다. 또한 detach() 메서드를 사용하여 기울기 추적을 멈출 수 있습니다.
만약 다수의 x에 대한 기울기를 구하고 싶다면??
import torch
x = torch.tensor([2.0,3.0,4.0],requires_grad = True)
y = 3*x**2 + 2*x + 1
external_grad = torch.tensor([1.0,1.0,1.0]) #external_grad -> output gradient값의 크기지정
y.backward(gradient = external_grad)
x.grad
#tensor([14., 20., 26.])
미분 결과가 여러개가 나오므로 external_grad의 크기를 지정해주어 backward함수의 파라미터로 넘겨준다.
'AI > Pytorch' 카테고리의 다른 글
모듈 분석,Docstring,repr (0) | 2023.03.16 |
---|---|
Custom Model, Conatiner, Module (0) | 2023.03.16 |
PyTorch Document 2 (0) | 2023.03.16 |
PyTorch Document 1 (0) | 2023.03.14 |
PyTorch 개요 (0) | 2023.03.12 |