PyTorch_1

YJ·2023년 6월 30일
0

▷ 오늘 학습 계획: 파이토치 강의

📖 Chapter 01_Tensor 다루기

1. Tensor 다루기

  • Tensor type: Variable과 Constant 포함
data = [[1,2], [3,4]]
data_tensor = torch.tensor(data)
arr = np.array([[1,2], [3,4]])
arr_tensor = torch.tensor(arr)
arr_from_numpy = torch.from_numpy(arr)

속성값 확인

data_tensor.shape
data_tensor.size()

torch를 numpy 배열로 바꾸기

data_tensor.numpy()
arr_from_numpy.numpy()
# torch.from_numpy(values).float() numpy → float

특정한 값의 Tensor 생성

torch.arange(10)
torch.ones(5), torch.zeros(5)
torch.ones_like(data_tensor) # tensor 입력하기
torch.linspace(0, 10, 5)
torch.logspace(0, 10, 5)

난수 생성

torch.rand(5) # 균등 분포
torch.randn(5) # Normal 분포
torch.randint(10, size=(5,))
# seed 조절하기
torch.manual_seed(0)

data type

torch.randint(10, size=(5,), dtype=torch.float32)
a = torch.randint(10, size=(5,))
print(a.type(torch.float64))
# a의 값 자체가 변하는게 아님. type이 변화된 a를 return

GPU 사용하기

  • tensorflow에서는 사용 가능한 gpu가 있으면 자동으로 사용됨
torch.cuda.is_available()
# True/False

1) device 설정하기

# device 설정
x = torch.ones(2, 2, device='cuda')
# 여러개의 GPU 중에 할당할 GPU 정하기
# nvidia-smi 명령으로 GPU 번호를 찾을 수 있다.
x = torch.ones(2, 2, device = 'cuda:0')
# device 객체 입력
x = torch.ones(2, 2, device = torch.device('cuda'))

2) tensor_var.cuda()

a = torch.rand(10)
a = a.cuda()

3) tensor_var.to(device)

a = torch.rand(2)
a = a.to('cuda')
a = a.to(torch.device('cuda'))
  • 자주 사용되는 방법
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
a = torch.rand(2)
a = a.to(device)

2. Tensor 연산

기본 연산

x = torch.arange(0,5)
y = torch.arange(1,6)
x + y
torch.add(x,y)
x.add(y)

여러가지 연산

  • torch.abs: 절댓값
  • torch.sign: 부호
  • torch.round
  • torch.ceil
  • torch.floor
  • torch.squre: 제곱
  • torch.sqrt: 제곱근
  • torch.maximum
  • torch.minimum
  • torch.cumsum
  • torch.cumprod: 누적곱

차원 축소 연산

  • PyTorch는 기본이 reduce 연산

행렬 연산

  • torch.matmul(torch.mm): 내적
  • torch.linalg.inv: 역행렬

크기 및 차원 바꾸기

  • torch.reshape
  • .view → torch.view로는 쓰지 않는다.
    (view 함수가 있어서 expand_dim과 같은 함수는 필요 없다.)
  • torch.transpose
  • torch.squeeze: 차원 축소
  • torch.unsqueeze: 차원 늘리기

텐서 나누기, 합치기

  • torch.chunk, torch.split
torch.chunk(c, 3, dim=1) # 3개로 나누기
torch.split(c, 2, dim=0) # 2개씩 나누기
  • torch.cat, torch.stack, torch.tile
torch.cat([a,b], dim=0)
  • 함수 끝에 '_' → inplace 명령(예외 있음)

  • RuntimeError
    transpose 하고 view 했을 때 데이터의 물리적 위치와 index가 일치하지 않으면 발생 → contiguous() 함수를 호출하거나 reshape

  • 이전 결과값과 같은 shape로 맞추는 명령

# a를 b와 같은 shape로
a.view_as(b)
a.reshape_as(b)

📖 Chapter 02_최적화

1. 자동미분

autograd

PyTorch에서 핵심적인 기능을 담당하는 하부 패키지로, 텐서의 연산에 대해 자동으로 미분값을 구해주는 기능을 한다.

  • 텐서 자료를 생성할 때, requires_grad 인수를 True로 설정 하거나 .requires_grad_(True) 실행
  • .backward() 함수: 자동으로 미분값을 계산, requires_grad 인수가 True로 설정된 변수의 grad 속성의 값을 갱신
  • retain_graph: 미분을 연산하기 위해 사용했던 임시 그래프를 유지 할 것인지 설정(기본값 False)
  • torch.autograd.grad() 함수로 tf.GradientTape처럼 사용 가능
  • .detach() 함수나 with torch.no_grad()를 이용하면 계산이 멈춘다.

PyTorch 손실 함수

torch.nn.BCELoss(이진 분류)
torch.nn.CrossEntropyLoss(다중 클래스 분류)
torch.nn.MSELoss(회귀)

2. linear regression

  • loss값 출력
# 1
loss.detach().numpy()
# 2
with torch.no_grad():
	print(loss.numpy())
# 3
loss.item()
  • assign 대신 data에 접근해서 값 수정
tensor.data
  • optimizer
opt = torch.optim.Adam([w,b], lr=0.0001)
opt.step()
opt.zero_grad()  # 0으로 초기화

📖 Chapter 03_간단한 모델 학습

PyTorch는 TensorFlow와 이미지를 표현하는데 차이가 있다.

  • TensorFlow: (batch, height, width, channel)
  • PyTorch: (batch, channel, height, width)

모델 정의

from torch import nn
import torch.nn.functional as F
class Net(nn.Module):
	def __init__(self):
    	super(Net, self).__init__()
    	# forward에서 사용되는 것을 미리 정의
    def forward(self, x):
    	pass  # 실제 모델의 연산
  • PyTorch에서는 model을 Training 모드로 변경 후 Training 할 수 있다.
import torch.optim as optim
opt = optim.SGD(model.parameters(), 0.03)
for epoch in epochs:
# 모델 학습
	model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
    	data, target = data.to(device), target.to(device)
        opt.zero_grad()  # grad 초기화
        output = model(data)
        loss = F.nll_loss(output, target)  # 예측값, 정답 순서로
        loss.backward()
        opt.step()
# 모델 evaluation
    model.eval()
    test_loss = 0
    with torch.no_grad():
    	for data, target in test_loader:
        	output = model(data)
            test_loss += F.nll_loss(output, target).item()
    test_loss /= (len(test_loader.dataset) // batch_size)

📖 Chapter 04_Modeling

  • nn.Sequential
  • Sub-class of nn.Module
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = nn.Sequential(
	nn.Linear(784, 15),
    nn.Sigmoid(),
    nn.Linear(15, 10),
    nn.Sigmoid()
)
# model.children()
# model.modules()
# pip install torchsummary
import torchsummary
torchsummary.summary(model, (784,))

📖 Chapter 05_Model 학습

1. training

Learning Rate Scheduler

  • LambdaLR, StepLR, MultiStepLR, ExponentialLR, CosineAnnealingLR, ReduceLROnPlateau
from torch.optim.lr_scheduler import ReduceLROnPlateau
optimizer = optim.Adam(model.parameters(), lr = 0.03)
scheduler = ReduceLROnPlateau(optimizer, mode='min', verbose=True)
def train_loop(dataloader, model, loss_fn, optimizer, scheduler, epoch):
	model.train()
    size = len(dataloader)
    for batch, (x, y) in enumerate(dataloader):
    # batch size, image height, image width, image channel
    	x, y = x.to(device), y.to(device)
        pred = model(x)
        loss = loss_fn(pred, y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
       	if batch % 100 == 0:
        	loss = loss.item()
            print(f'Epoch {epoch}: [{batch}/{size}] loss: {loss.item()}')
	scheduler.step(loss)
    return loss.item()    
for epoch in range(10):
	loss = train_loop(train_loader, model, F.nll_loss, optimizer, scheduler, epoch)
    print(f'Epoch: {epoch} loss: {loss}')

2. Model save

weight만 저장

torch.save(model.state_dict(), 'model_weights.pth')
model.load_state_dict(torch.load('model_weights.pth')

weight, 구조 함께 저장

torch.save(model, 'model.pth')
model = torch.load('model.pth')

save, load, resume

checkpoint_path = 'checkpoint.pth'
torch.save({
	'epoch' : epoch,
    'model_state_dict' : model.state_dict(),
    'optimizer_state_dict' : optimizer.state_dict(),
    'loss' : loss
}, checkpoint_path)
model = ResNet().to(device)
optimizer = optim.SGD(model.parameters(), lr = 0.003)
checkpoint = torch.load(checkpoint_path)
# checkpoint.keys()
model.load_state_dict(checkpoint['model_state_dict'])
epoch = checkpoint['epoch']
optimizer.load_state_dict(checkpoint['optimizer_state_dict'])
loss = checkpoint['loss']

📖 Chapter 06_Data 다루기

ImageFolder

  • 로컬에 있는 이미지 데이터셋을 불러옴(디렉토리 구조가 같아야 함)
import torch
from torchvision import datasets, transforms
train_dataset = datasets.ImageFolder(
    root = train_dir,
    transform=transforms.Compose([transforms.ToTensor(),
    					 		  transforms.Normalize(0.5, 0.5])
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)

Custom dataset

  • dataset sub-class: torch.utils.data.Dataset 상속 받아서 데이터셋 구현
from PIL import Image

class Dataset(torch.utils.data.Dataset):

	def __init__(self, data_paths, transform):
    	super(Dataset).__init__()
        self.data_paths = data_paths
        self.transform = transforms
       
    def __len__(self,):
    	return len(self.data_paths)
       
    def __getitem__(self, idx):
    	path = self.data_paths[idx]
        image = Image.open(path)
        label_name = path.split('.png')[0].split('_')[-1].strip()
        label = label_list.index(label_name)
       
        if self.transform:
        	image = self.transform(image)
       
        return image, label
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
train_loader = torch.utils.data.DataLoader(
	Dataset(train_paths, transform = transforms.ToTensor()),
    batch_size = 32,
    shuffle = True
)

Transforms

  • 이미지 데이터 변환
transforms.Resize((32,32))(image)
transforms.RandomCrop(size=(64, 64))(image)
# 정해진 사이즈에 맞춰서 랜덤으로 이미지의 조각을 보여준다.
transforms.ColorJitter(brightness=1)(image)
transforms.Grayscale()(image)
transforms.Pad(padding=(20,10))(image)
transforms.RandomAffine(degrees=90)(image)
transform_list = [
	transforms.RandomAffine(degrees=90),
	transforms.Pad(padding=(20,10))
]
# transform_list에서 지정해 놓은 설정을 50%의 확률로 실행한다. 
transforms.RandomApply(transform_list, p=0.5)(image)
# transform_list에서 지정해 놓은 설정에서 랜덤으로 하나 선택
transforms.RandomChoice(transform_list)(image)
transforms.RandomHorizontalFlip(p=0.5)(image)

▷ 다음주 학습 계획: OpenCV 강의

[이 글은 제로베이스 데이터 취업 스쿨의 강의 자료 일부를 발췌하여 작성되었습니다.]

0개의 댓글