Ai tech Day43

Model with Pytorch

Model

"In general, a model is an informative representation of an object, person or system."



Design Model with Pytorch

Low-level, Pythonic, Flexibility

리모콘은 리모콘에 구현되어있는 기능만 사용할 수 있지만, 회로를 통해 직접 리모콘을 만들면 새로운 기능을 추가하거나, 원래 있던 기능을 변경할 수도 있다.

Pytorch는 이처럼 직접 회로를 만들듯이, 원하는 모듈들을 만들고 훈련시킬 수 있다. Keras처럼 정해져 있는 tool이 있어 손쉽게 훈련을 진행할 수는 없지만, 잘 이해한다면 자유도가 굉장히 높다.



nn.Module

Pytorch 모델의 모든 레이어는 nn.Module 클래스를 따른다.

import torch.nn as nn
import torch.nn.functional as F

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.conv1 = nn.Conv2d(3, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))


modules

__init__에서 정의한 또 다른 nn.Modules

a = MyModel()
print(a)

list(a.modules())


forward

이 모델(모듈)이 호출 되었을 때 실행 되는 함수

import torch
x = torch.rand(1, 3, 256, 256)
y = a(x)
y.shape


nn.Module Family

nn.Module을 상속받은 모든 클래스의 공통된 특징

모든 nn.Module은 forward() 함수를 가진다. 내가 정의한 모델의 forward()를 한번만 실행한 것으로 그 모델의 forward에 정의된 모듈 각각의 forward()가 실행된다.


Parameters

모델에 정의되어 있는 modules가 가지고 있는 계산에 쓰일 Parameter

sd = a.state_dict()

params = list(a.parameters())


각 모델 파라미터 들은 data, grad, requires_grad 변수 등을 가지고 있습니다.

for param in a.parameters():
    print(f"required_grad : {param.requires_grad}")
    print(f"grad : {param.grad}")

파라미터들은 Tensor class를 상속받는 구조라서 Tensor의 구조를 갖는다. requires_grad는 gradient를 적용할지 말지 결정하는 boolean 파라미터이다. required_grad를 False로 하면 gradient가 적용되지 않아 원하는 모듈만 학습시키는 것도 가능하다.

grad가 None인 이유는 아직 backward를 통해서 확인한 기울기가 없기 때문이다.


Pytorch의 Pythonic

Pythonic하다는 것의 장점

state_dict()는 파이썬의 dictionary 형식이다. 우리가 이러한 형식과 구조를 미리 알고 있다면 여러가지 응용이 가능할 뿐더러, 발생할 수 있는 에러들도 핸들링 할 수 있다!

다만 자유도가 좋기 때문에 모델 안에 있는 각 layer의 명칭은 사람마다 다를 수 있다. 그러나 모델의 구조를 안다면, 명칭이 다르더라도 python code로써 내 모델에 맞게 명칭을 바꾸어, parameter를 load 시킬 수 있다.






Pretrained Model

Computer Vision의 발전

Computer Vision의 발전으로 현재 상당히 많은 일을 자동화 할 수 있습니다.



ImageNet

획기적인 알고리즘 개발과, 검증을 위해 높은 품질의 데이터 셋은 필수적입니다.

ImageNet이 만들어 지고 나서 알고리즘이 성능이 비약적으로 상승했다.



Pretrained Model

Pretrained Model의 배경

모델 일반화를 위해 매번 수 많은 이미지를 학습시키는 것은 까다롭고 비효율적이다.


이미 공개되어 있는 수 많은 Pretrained Model

미리 학습된 좋은 성능이 검증되어 있는 모델을 사용하면 시간적으로 매우 효율적이다.

왼쪽은 pytorch torchvision.models에 내장된 model들이고, 오른쪽은 좀 더 다양한 모델들의 trained parameter를 갖고 있는 timm 라이브러리이다. timm github에 들어가보면 좀 더 다양한 모델들을 확인할 수 있다.


torchvision.models

너무나도 손쉽게 모델 구조와 Pretrained)Weight를 다운로드 할 수 있습니다.



Transfer Learning

CNN base 모델 구조 (simple)

Input + CNN Backbone + Classifier → Output


Torchvision model 구조

import torchvision.models as models

resnet18 = models.resnet18(pretrained=True)
print(resnet18)

fc == fully connected layer == classifier

모델들은 기본적으로 ImageNet으로 학습을 하기 때문에 1000개의 label로 분류되는 것을 볼 수 있다.



내 데이터, 모델과의 유사성

내가 설정한 문제와 비교


Case by Case

Case 1. 문제를 해결하기 위한 학습 데이터가 충분하다.

보통 CNN Backbone가 이미지들의 Feature를 뽑아내고 이를 Classifier 계층에게 보내서 분류를 한다. CNN Backbone이 Feature Extraction을 한다고 말한다.

학습데이터가 충분한데 ImageNet과 굉장히 유사한 데이터로 학습을 하는 경우 CNN Backbone을 그대로 두고 Classifier만 학습시킨다.

그러나 ImageNet과 학습 데이터가 유사하지 않은 경우에는 CNN Backbone까지 미세하게 조정하며 학습해야 한다. 이를 Fine tunning이라 한다. 그러면 아예 pre-trained 된 파라미터를 안 가져오는 것이 좋다고 생각할 수 있다. 그러나 아무리 학습데이터가 많아도 ImageNet보다는 데이터가 적을 수 밖에 없다. 그렇기 때문에 model이 여러 데이터를 토대로 학습된 parameter로 학습하는 것이 완전 random initialize 된 parameter로 학습하게 되는것보다 더 좋다.

갓난아이에게 어떤 새로운 물건이 무엇인지 알려주는 것과 성인에게 그 물건이 무엇인지 알려주는 것은 굉장히 큰 학습 차이를 보이는 것이 당연하고, 모델에도 이를 적용시켜 이해할 수 있다. 실제로도 실험적으로 전혀 다른 domain이더라도 pre-trained 모델로 학습을 시작하는게 더 좋다고 알려져 있다.


Case 2. 학습 데이터가 충분하지 않다.

학습 데이터가 충분하지 않은 경우에는 Feature를 뽑아내는 CNN Backbone은 유지하고, Classifier만 학습시키는 것이 좋다. 적은 데이터로 Feature도 뽑도록 학습시키는 것은 굉장히 효율이 좋지 못하다.

좋은 웹페이지 즐겨찾기