Skip to main content

lightning

파이토치 라이트닝

그 다음에 우리가 지금 파이토치로 생자로 모든 코드를 다 짜고 있는데 이거는 우리가 배우려는 목적에서 여기 내부가 어떤 식으로 흘러가는가를 보려는 목적이고 사실 매번 그 모든 거를 다 손으로 짜고 있으면 사실 너무 번거롭거든요

그리고 우리가 그렇게까지 내부 원리에 대해서 궁금하진 않기 때문에 궁금하실 분도 있겠지만 사실 그냥 잘 돌아가면 그뿐이지 내부 구조가 어떻게 되는지 알게 뭡니까

그래서 파이토치 라이트닝이라는 툴이 있는데요 이 툴이 해주는 건 뭐냐면 우리가 복잡한 구조 같은 게 있는데 맨날 짜는 거는 맨날 비슷비슷하단 말이에요

예를 들면 여기 Fit 함수 같은 거는 한 번 만들어 놓으면 그냥 계속 쓰는 거거든요

왜냐하면 Fit 함수는 모델이 바뀌어도 똑같아요

매번 똑같은 거를 우리가 직접 매번 짤 필요는 없겠죠

그래서 파이토치 라이트닝이라고 해가지고 이런 거를 효율적으로 짤 수 있게 만들어 놓은 툴이 있습니다

봐 dire wee 자 설치 다들 잘 되시나요?

그래서 라이브러리를 새로 깔았으니까 약간 충돌이 있을 수도 있어서 노트북을 하나 새로 열고요 그 다음에 파이토치 라이트닝은 보통 줄여서 PL이라고 많이 하거든요

파이토치 라이트닝이라서 이렇게 임포트를 해주고요 그 다음에 이제 우리가 모델을 구현을 해주는데 249쪽부터입니다

근데 지금 보시면은 1 3분의 1, 2 3분의 3 이렇게 되는데 이렇게 이게 구현이 좀 길어요

그래서 우리가 앞에랑 비슷한데

이닛이랑 포워드는 똑같은데 뒤에 뭐가 더 붙습니다

뭐가 붙냐면 프로세스 배치랑 컨피규어 옵티마이저랑 트레이닝 스텝이랑 테스트 스텝이 붙는데 별 거는 아니고 프로세스 배치는 뭐냐면 배치 배치는 보통 우리가 데이터를 32개 넣으면 32개 묶음을 배치라고 해요

데이터를 어떻게 처리할 거냐

이 얘기고 컨피규어 옵티마이저는 우리가 이제 알고리즘 설정하는 거 있죠

지금 아담으로 돼 있는데 이때까지 알라 아담 했는데 왜 제가 아담으로 했을까요

알라 아담으로 하셔도 됩니다

이거를 예전에는 밖으로 빼서 했는데 그냥 안으로 넣어서 이렇게 해줍니다

그 다음에 트레이닝 스텝은 트레이닝 할 때 매번 뭘 할 거냐

이 얘기인데 트레이닝 할 때 매번 프로세스 배치를 실행을 해 가지고 결과를 얻은 다음에 결과랑 손실이랑 얻은 다음에 손실을 로그를 설정하고 그 다음에 테스트 스텝은 테스트 할 때 뭐 할 거냐

이걸 정리를 해 주는 거에요

테스트 할 때는 손실을 계산을 한 다음에 그 다음에 Accuracy를 계산을 하고 Accuracy를 로그에 남겨라

이런 얘기입니다

그래서 이제 코드가 길어지긴 했는데 사실 별 얘기는 아니고 그냥 테스트 할 때 트레이닝 할 때 뭘 로그에 남길지 이런 거를 적어 주는 거에요

그래서 이거 보면 이게 이제 테스트 스텝이 아니라

그래서 요거 또 그냥 복사해서 붙여놓으시면 되는데요 주의하셔야 되는 게 페이지가 여러 개라서 붙여 넣으실때 들여쓰기를 잘 맞춰 주셔야 겠죠

제가 그 원본에는 들여쓰기를 맞춰 놨는데 이게 PDF로 만들면 들여쓰기가 계속 깨지더라구요そして

DEF들끼리 줄이 맞도록 맞춰 주셔야 됩니다

그래서 이거는 그냥 복사해서 붙여 넣으시면 된다

그래서 이렇게 모델을 정의해 주셨으면 모델 정의하는 코드가 길어졌지만 학습을 시키는 거는 훨씬 쉬워지는데요

일단 강의 자료에 252쪽에 보면 로깅을 위한 임시 디렉토리 생성 이게 있는데 이거는 굳이 하실 필요는 없는데 이거는 언제든지 언제 필요하냐면 파이토치가 파이토치 라이트닝 로그를 남기잖아요

로그를 현재 폴더에다 남기거든요

근데 이제 import os 해가지고 os.getcwd 이렇게 했을 때 여기 폴더 이름에 중간에 한글이 들어가면 현재 폴더를 인식을 못 해 가지고 저장이 안 됩니다

2024년인데 아직도 한글 지원에 문제가 있는 라이브러리가 있다니 믿을 수 없는데 중간에 한글이 들어가면 로그 저장이 안 되거든요

그래서 getcwd 이렇게 하셔가지고 getcwd는 get current directory 현재 current working directory 현재 작업 중인 디렉토리란 뜻이에요

디렉토리는 폴더랑 똑같은 뜻입니다

현재 작업 중인 폴더랑 똑같은 뜻입니다

현재 작업 중인 폴더랑 똑같은 뜻입니다

현재 작업 중인 폴더랑 똑같은 뜻입니다

이제 작업 중인 폴더가 이름의 중간에 한글이 없다

현재 작업 중인 폴더가 이름의 중간에 한글이 없다 그러면 252쪽에 있는 코드는 넘어가셔도 되는데 가격하면 generated a long ID 그러면 252쪽에 있는 코드는 넘어가셔도 되는데 만약에 중간에 한글 있다 그럴 수 있죠

그러면 어떻게 하면 되느냐 임시 디렉토리를 하나 만들어 주면 됩니다

252쪽에 있는 거는 여기에 템프 파일이라고 해 가지고 임시 디렉토리를 만들어 tug서 임시 디렉tory는 중간에 한글이 안 들어 갈 거거든요

이렇게 했는데도 안 된다 임시 디렉토리도 상위에 어딘가 한글이 들어가거나 이런거에요

그래서 가능하시면 아이디 같은거 만들 때 윈도우 처음 설치하면 자기 아이디 만들잖아요

이름 한글로 쓰지 마세요

영어 약자로 유재명이다 그럼 yjm 이렇게 어디서 한글을 지원 안하는데 프로그램에 걸릴지 모릅니다 서양 사람들이 되게 무식해가지고 세상에 한글이나 한자를 쓴다는 걸 몰라요

다 알파벳 쓰는 줄 알기 때문에 이게 별로 지원하는게 어려운 게 아니거든요

어려운 게 아닌데 한 두줄만 고쳐 주면 되는데 아무 생각이 없기 때문에 서양 사람들이 하여간 문제입니다

그래서 이거는 안 하셔도 되는 거지만 라이트닝 로그스라는 임시 디렉토리를 하나 만들어 주도록 하겠습니다

이거 뭐 만든다고 손해 볼 건 없어요

어차피 임시 디렉토리니까 작업 디렉토리는 똑같고요 로그 저장하는 것만 임시 디렉토리에다 저장합니다

요거 코드는 그냥 시스템 임시 디렉토리 밑에 라이트닝 로그스라는 폴더를 만드는 걸로 그냥 끝이에요 작업 디렉토리는 계속 똑같습니다 해보시면 작업 디렉토리는 계속 여기에요

그래서 이제 여기 로그만 저장하는 데를 임시 디렉토리에다 저장을 해 주는 거예요

아 요거요 요거는 그 로그는 저장하는 데에다 저장하는 거예요

그 로그 dir이라고 쳐보시면 나오는데요

로그 dir c 드라이브에 유저스 유저에 앱데이터 밑에 로컬에 템프에 라이트닝 로그스 여기에다가 저장합니다

이거는 제가 코드로 해 놨는데 사실 그냥 직접 만드셔도 돼요

뭐 그냥 손으로 만드셔도 되는데 손으로 만들려면 또 번잡하니까 코드로 해 놓으면 그냥 복사해서 그냥 붙여 놓으면 그냥 실행하면 되잖아요

그래서 이 얘기는 별 건 아니고 그냥 정리를 연결 할때는 천사원이 그렇게 Euch NORF 뭐 할지 요거를 써주시면 된다

이런 얘기고 고거만 써주면 이제 우리가 할 일은 다 한 겁니다

나머지는 파이토치 라이트닝이 알아서 해 줄 거예요

그래서 253쪽에 보시면 우리가 이제 아까는 fit 함수를 우리가 직접 만들었거든요

지금은 fit 함수를 직접 만들 필요가 없습니다

그냥 파이토치 라이트닝이 이미 구현이 돼 있기 때문에 파이토치 라이트닝에 있는 fit 함수를 그냥 쓸 거고 그 다음에 여기 default rootdir 해가지고 logdir 이게 이제 로그를 저장할 디렉토리인데 사실 이게 없어도 되거든요 없어도 되는데 여러분 작업 디렉토리가 한글이 중간에 들어가면 여기서 에러가 나요

왜냐면 현재 디렉토리 저장을 못해서 그럴 때만 요거를 추가해 주시면 됩니다 무조건 하셔야 되는 건 아니에요

그 다음에 이제 테스트 로더 트레인 로더 요거가 있어야겠죠

데이터 데이터가 불러오는 코드가 요거는 이제 복사해 가지고 가져오면 됩니다

데이터는 이제 아까 그걸 그대로 쓰면 되고 요거 훈련하는 거는 이제 이렇게 할 수 있어요

데이터는 이제 아까 그걸 그대로 쓰면 되고 요거 훈련하는 거는 이제 이렇게 할 수 있어요.

쭉하고 이제 그래프가 올라가는데 이게 이유가 뭔지 모르겠지요?

이거는 제가 다시 찾아서 고쳐놓을게요.

원래는 이제 진행 막대가 이렇게 쭉 올라가는데 진행 막대가 올라가고요 여기 위에 보시면은 보면은 GPU 라든가 TPU 라든가 HPU 라든가 이런 게 다 딥러닝 가속하는 칩이거든요

그래서 우리가 이거를 일일이 찾아주지 않아도 자기가 찾아줍니다

그래서 만약에 이런 게 설치가 돼 있으면은 얘가 알아서 그런 걸 처리를 다 해줘요

그래서 지금 우리 눈에 안 보이긴 하지만 딥러닝을 좀 더 빠르게 하기 위해서 효율적으로 하기 위해 필요한 작업들도 다 구현이 돼 있기 때문에 우리가 그런 부분에 신경을 쓸 필요가 없습니다

그래서 그런 것도 다 자동으로 해주고요 그래프는 왜 안 나올까요

그래서 이렇게 해주고 그다음에 이제 Stop 이러면서 이제 다 끝났다

이러면 이제 테스트를 돌려보면은 테스트 결과도 자기가 이제 돌려 가지고 이렇게 예쁘게 표로 정리를 해서 보여줍니다

그래서 테스트하는 코드도 우리가 따로 짤 필요 없고 그냥 테스트할 때 아까 테스팅 스텝 한 단계 한 단계를 어떻게 하면 되는지 하는지만 정의를 해 주면 되는 거죠

훨씬 쉽게 쓰실 수가 있습니다

import torch.nn.functional as F
import torch
import torch.nn as nn
import pytorch_lightning as pl
from torchmetrics.classification import BinaryAccuracy
class MLPClassifierLight(pl.LightningModule): # 부모 클래스가 바뀜
def __init__(self, input_size=784):
super().__init__()
self.linear1 = nn.Linear(input_size, 16) # 16개의 뉴런을 가진 은닉층
self.linear2 = nn.Linear(16, 1) # 한 개의 출력 뉴런
self.accuracy = BinaryAccuracy()

def forward(self, x):
x = x.view(-1, 784) # Flatten 레이어 없이, 텐서 모양을 (N, 28, 28) → (N, 784)
x = F.relu(self.linear1(x)) # ReLU 활성화 함수
x = F.sigmoid(self.linear2(x)) # 활성화 함수는 __init__에서 정의 X
return x

def process_batch(self, batch): # 배치 처리
images, labels = batch
outputs = self(images).squeeze()
loss = F.binary_cross_entropy(outputs, labels.float())
return outputs, loss

def configure_optimizers(self): # 알고리즘 설정
optimizer = torch.optim.Adam(self.parameters(), lr=0.001)
return optimizer
def training_step(self, batch, batch_idx):
outputs, loss = self.process_batch(batch)
self.log('train_loss', loss)
return loss

def test_step(self, batch, batch_idx):
outputs, loss = self.process_batch(batch)
images, labels = batch
accuracy = self.accuracy(outputs, labels)
self.log('test_accuracy', accuracy)
return loss
import os
os.getcwd() # get current working directory 현재 작업중인 디렉토리(폴더)
output
'C:\\Users\\user\\Desktop\\computer-vision'
import os
import tempfile

system_temp = tempfile.gettempdir() # 시스템 임시 디렉토리
log_dir = os.path.join(system_temp, "lightning_logs") # 밑에 lignthing_logs 폴더
os.makedirs(log_dir, exist_ok=True) # 를 만듦
log_dir
output
'C:\\Users\\user\\AppData\\Local\\Temp\\lightning_logs'
from torchvision import datasets, transforms

BATCH_SIZE = 32
train_dataset = datasets.FashionMNIST(
root='./data', # 데이터 저장 경로
train=True, # 학습용 데이터셋
download=True, # 데이터가 없으면 다운로드
transform=transforms.ToTensor() # 텐서로 변환
)

test_dataset = datasets.FashionMNIST(
root='./data',
train=False, # 테스트용 데이터셋(이 부분만 달라짐)
download=True,
transform=transforms.ToTensor()
)

from torch.utils.data import Dataset

class BinaryMNIST(Dataset):
def __init__(self, dataset, class_1, class_2):
self.dataset = dataset
self.indices = [i for i, (_, label) in enumerate(dataset)
if label in [class_1, class_2]] # 원하는 클래스의 인덱스만
self.class_map = {class_1: 0, class_2: 1} # class_1은 0으로, class_2는 1로

def __len__(self):
return len(self.indices)

def __getitem__(self, idx):
image, label = self.dataset[self.indices[idx]] # idx번째 데이터
return image, torch.tensor(self.class_map[label]) # 레이블 바꾸기
# label.item() -> label

binary_train_dataset = BinaryMNIST(train_dataset, 3, 4) # 2번과 6번의 이항 분류
binary_test_dataset = BinaryMNIST(test_dataset, 3, 4)

from torch.utils.data import DataLoader

BATCH_SIZE = 32

train_loader = DataLoader(
binary_train_dataset, # 훈련 데이터
batch_size=BATCH_SIZE, # 32개씩
shuffle=True) # 섞어서(미니배치마다 조합이 다양하도록)

test_loader = DataLoader(
binary_test_dataset, # 테스트 데이터
batch_size=BATCH_SIZE, # 32개씩
shuffle=False) # 섞지 말고
from pytorch_lightning import Trainer

# 훈련
model = MLPClassifierLight()
trainer = Trainer(max_epochs=3, default_root_dir=log_dir) # 로그 저장할 디렉토리 설정
trainer.fit(model, train_loader)


# 모델 테스트
trainer.test(model, test_loader)

output
C:\Users\user\anaconda3\Lib\site-packages\pytorch_lightning\trainer\connectors\data_connector.py:424: The 'test_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the `num_workers` argument` to `num_workers=23` in the `DataLoader` to improve performance.

Testing: |                                                                                       | 0/? [00:00<…
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃  Test metric  ┃  DataLoader 0  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│  test_accuracy  │  0.9480000138282776  │
└───────────────────────────┴───────────────────────────┘

[{'test_accuracy': 0.9480000138282776}]