근황 토크 및 자유게시판/TIL

[Pytorch] 네부캠 day-10

scone 2023. 11. 16. 07:38

Hook


  • Hook 예시
def program_A(x):
    print('program A processing!')
    return x + 3

def program_B(x):
    print('program B processing!')
    return x - 3

class Package(object):
    """프로그램 A와 B를 묶어놓은 패키지 코드"""
    def __init__(self):
        self.programs = [program_A, program_B]

        # hooks
        self.pre_hooks = []
        self.hooks = []

    def __call__(self, x):
        for program in self.programs:

            # pre_hook : 프로그램 실행 전에 날리는 훅
            if self.pre_hooks:
                for hook in self.pre_hooks:
                    output = hook(x)    # 메소드가 return 값을 갖는 경우
                    if output:
                        x = output

            x = program(x)

            # hook : 프로그램 실행 이후 날리는 훅
            if self.hooks:
                for hook in self.hooks:
                    output = hook(x)
                    if output:
                        x = output

        return x

# Hook - 프로그램의 실행 로직 분석 사용 예시
def hook_analysis(x):
    print(f'hook for analysis, current value is {x}')

# 생성된 패키지에 hook 추가
package.hooks = []
package.hooks.append(hook_analysis)

 

  • 이제 패키지 안의 program들이 실행 될 때마다, 실행 이후 current value인 x 값을 알려줄 것입니다. 앞으로는 디버깅 절대 이렇게 해야겠어요!!!!

 

torch.nn.Module


  • torch.nn.Module
    • 딥러닝을 구성하는 Layer의 base class
    • Input, Output, Forward, Backward 정의
    • parameter 정의
  • nn.Parameter
    • Tensor 객체의 상속 객체
    • AutoGrad의 대상
      • nn.Module 내에서 attribute가 될 때는 required_grad=True 로 지정되어 학습 대상이 되는 Tensor
    • 대부분의 layer에는 weights 값들이 지정되어 있기 때문에 우리가 지정할 일은 많지 않다.
  • Backward
    • Layer에 있는 Parameter들의 미분을 수행
    • Foward의 결과값 (model의 output=예측치)과 실제값 간의 차이(loss)에 대해 미분을 수행
    • 해당 값으로 Parameter 업데이트
    for epoch in range(epochs):
        # Clear gradient buffers, 이전의 학습에 의해 영향받지 않기 위해
        opitimizer.zero_grad()
        
        # y hat
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        
        # get gradients w.r.t. to parameters
        loss.backward()
        
        # update parameters
        optimizer.step()
    
    • 실제 backward는 Module 단계에서 직접 지정 가능하다.
    • Module 에서 backward와 optimizer 오버라이딩
    • 사용자가 직접 미분 수식을 써야하는 부담. → 순서에 대한 이해가 필요.

Dataset & DataLoader


  • Feeding data

  • Dataset
    • 데이터의 입력 형태를 정의하는 클래스
    • 데이터를 입력하는 방식의 표준화
    • Image, Text, Audio 등 데이터 타입에 따른 입력 정의.
    import torch
    from torch.utils.data import Dataset
    
    class CustomDataset(Dataset):
        def __init__(self, text, labels):
            self.labels = labels
            self.data = text
            self.length = len(labels)
        
        def __len__(self):
            return self.length
    
        def __getitem__(self, idx):
            label = self.labels[idx]
            text = self.data[idx]
            sample = {"Text":text, "Class":label}
            return sample
    
    • 유의점
      • 데이터 형태에 따라 각 함수를 다르게 정의함 (데이터 마다 다른 특징)
      • 모든 것을 데이터생성 시점에 처리할 필요는 없음.
      • image의 Tensor 변화는 학습에 필요한 시점에 변화.
        • CPU에서는 데이터 변환을 해주고, GPU에서는 학습을 처리
        • 학습을 하는 시점에 transform 메소드를 통해 변환 처리
      • 데이터 셋에 대한 표준화된 처리방법 제공 필요
        • 후속 연구자 또는 동료들에게 빛과 같은 존재
      • 최근에는 HuggingFace, FAST API 등 표준화된 라이브러리 사용.
  • DataLoader
    • Data의 Batch 생성
    • 학습 직전(GPU에 feed하기 전) 데이터의 변환을 책임
    • Tensor로 변환 + Batch 처리가 메인 업무.
    • 병렬적인 데이터 전처리 코드의 고민 필요.
    # Dataset 생성
    MyDataset = CustomDataset(text, labels)
    
    # DataLoader Generator
    MyDataLoader = MyDataLoader(MyDataset, batch_size=2, shuffle=True)
    next(iter(MyDataLoader))
    # {'Text': ['Glum', 'Sad'], 'Class':['Negative', Negative']}
    
  • DataLoader Parameter
    • sampler
    • batch_sampler
    • collate_fn
      • text와 같이 variable의 길이가 다를 때, 각각에 0으로 패딩을 동일하게 정의하고자 할 때 정의한다.
      • sequence 형 데이터를 처리할 때.