pytorch - model, nn.module 제대로 이해하기 재활치료

1. model이란 무엇인가

 

data preprocessing에서 Vanilla data가 모델을 거칠 수 있도록 데이터를 변환했음

 

어떤 데이터를 사용하여 어떤 결과를 만들지 문제 해결 과정을 잘 정의했다면?

 

modeling에서 preprocessing한 image를 넣어 원하는 형태의 output이 나오는 model을 만들어야

 

------------------------------------------------------------------------------

 

여기서 말하는 model이란?

 

“일반적으로 model은 object, person, system의 정보적인 표현”

 

object는 노트북이나 핸드폰 모델, person은 패션모델, system이 바로 딥러닝

 

여기서는 딥러닝을 말하고 싶으니까..

 

“시스템의 모형을 디자인하겠다”

 

------------------------------------------------------------------------------

 

system이 뭔데??

 

이미지는 시각적 표현의 인공물로 RGB channel과 가로 세로 차원의 array로 표현할 수 있다

 

어떤 변환을 나타내는 model을 넘어가면 원하는 형태의 category class가 나오게하는 시스템

 

이러한 system을 표현하는 것이 바로 model이다

 

model은 input을 넣어 output이 나오는 하나의 system을 표현하는 것

 

 

2. Pytorch는 왜 유명할까

 

2-1) 특징

 

요즘 대세인 오픈 소스 머신러닝 프레임워크

 

다이나믹한 그래프 정의로 제한점 없이 바로바로 실행에 적용

 

자유롭고, pythonic, 연구하기 좋음

 

쉽지 않은 부분이 분명 있지만 처음 딥러닝을 접한 사람이 공부하기 좋다

 

여러가지를 유연하게 시도해볼 수 있는 장점

 

2-2) 슬로건

 

자신있게 research라는 연구에 적절하다고 내세우는 framework가 없는데 research부터 production까지 자유롭다고 함

 

 

2-3) 예시로 이해하는 pytorch만의 철학

 

low-level , pythonic, flexibility, dynamic graph

 

(아래 그림에서) 완제품 리모컨과 도저히 정체를 모르겠는 오른쪽 그림의 제품의 차이는??

 

 

 

완제품 리모컨은 처음 보는 사람도 조작법만 한번 알려주면 그냥 누구나 쉽게 쓸 수 있음

 

오른쪽에 아무리 봐도 정체를 모르겠는 제품은 아두이노에 올린 하드웨어 실험 키트라는데

 

일단 모르는 사람이 보면 정체를 알기가 어려움

 

작은 버튼, LED 조작 같은 것을 아무도 말을 안해주면 도저히 사용할 수가 없음

 

만약에 전원 버튼 누름과 동시에 sound가 들려야 한다고 하자.

 

왼쪽 리모컨은 전원 눌러도 sound가 들리지 않아

 

이럴 때 수정할 수 있는 방법이 없어…

 

수정하고 싶어서 분해해서 수정한다해도 안에 있는 회로가 어떻게 구성된지 잘 모르니 사실상 불가능

 

high level의 완제품 리모컨은 딱 그런 기능만 가지도록 임팩트하게 구성된 제품이다

 

그러나 오른쪽 회로는 어떤 부분이 전원인지만 이해한다면 그것을 뜯어서 sound 모듈만 추가하면 끝이다

 

LED가 마음에 안든다면 LED 빼서 바꾼다든지 커스터마이징이 굉장히 쉽다.

 

low level의 회로는 변형이 쉽고 다양한 실험이 쉬워, 쉽게 기능들이 분리되어 있어서 응용 잠재력이 높다

 

epochs = 50

callbacks = [
    keras.callbacks.ModelCheckpoint("save_at_{epoch}.h5"),
]

model.compile(
    optimizer = keras.optimizers.Adam(1e-3),
    loss = "binary_crossentropy",
    metrics = ["accuracy"],
)

model.fit(
    train_ds, epochs = epochs, callbakcs = callbacks, validation_data = val_ds,
)

 

위 코드는 케라스 코드

 

for epoch in range(2): #loop over the dataset multiple times
    
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        
        #get the inputs: data is a list of [inputs, labels]
        inputs, labels = data
        
        #zero the parameter gradients
        optimizer.zero_grad()
        
        #forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        
        #print statistics
        running_loss += loss.item()
        
        if i % 2000 == 1999: #print every 2000 mini-batches
            
            print("[%d, %5d] loss: %.3f" %
                   (epoch + 1, i+1, running_loss/2000))
            
            running_loss = 0.0

print("Finished Training")

 

위 코드는 pytorch training code

 

keras가 완제품 리모컨 느낌이고 pytorch가 회로 느낌임

 

keras는 callbacks, compile의 optimizer, loss, metric을 알려주고 fit을 쓰면 training이 가능하다고 알려준다면 누구나 쉽게 training을 시킬 수 있음

 

그런데 pytorch는 처음 보면 도대체 이게 무슨말인가? ‘누가 이것이 training 과정이에요’라고 알려주지 않으면

 

도저히 무슨 과정을 나타내는 것인지 파악하는 것은 쉽지 않다 (사실 내가 처음에 이랬음… 진짜 완전 공감)

 

그러나 keras는 fit 함수를 조종하는 것이 쉽지 않다..

 

fit을 뜯어서 조종할려고해도 도대체 얘는 어디에 있는것인지 찾기도 쉽지 않아

 

반대로 pytorch는 코드만 잘 이해한다면 다음부터는 원하는 행동을 하도록 커스터마이징이 굉장히 쉽다..

 

다양한 변형이 쉬워 응용가능성이 굉장히 크다

 

 

3. nn.Module은 어떤 의미를 가지는가

 

model class가 반드시 가져야하는 함수

 

pytorch의 모든 모델은 nn.Module을 상속받는다.

 

 

model class가 기본적으로 가져야하는 것은 __init__과 forward함수를 정의

 

그리고 __init__ 함수 밑에 super((model명),self).__init__()를 반드시 써야하는데

 

이것은 현재 model의 부모 class인 nn.Module의 __init__을 가져오겠다는 의미다.

 

nn.Module이 가지는 이런 기능들을 가져오겠다는 의미다

 

 

convNd같은 경우는 conv1d, conv2d, conv3d,...들의 부모 class로 이들이 어느정도 공통적인 기능을 가질 수 있도록 만든다

 

물론 이제 이런 conv layer도 결국 nn.Module을 상속받아 이들의 기능을 가진다.

 

 

3-1) modules

 

모델을 정의하고 모델을 선언하면 __init__이 실행

 

모델 객체를 print하면 정의된 모델을 설명하면서 module들이 전부 출력

 

비슷하게 modules()라는 함수가 존재하여 모델에 존재하는 모든 module에 대한 generator

 

modules는 generator라서 list로 씌우면 잘 보임

 

 

modules는 parameter를 저장하고 있는 저장소

 

model의 weight를 가지고 있는 여러 layer들의 합으로 이루어져 있음

 

modules로 찍어낸 모듈들은 model의 parameter를 가지고 있을 수 있다.

 

 

3-2) forward

 

input을 받아 output까지 계산하는 과정을 담은 함수

 

forward에서는 modules에서 담고 있는 parameter를 바탕으로 input으로부터 “원하는” output까지 계산이 이루어짐

 

처음에는 학습이 안되어서 weight가 있더라도 “원하는” output이 안나오고 결과는 이상함

 

training을 거치면서 ground truth와 predict간 loss를 발생시키고

 

loss를 backward로 전파하여 model의 parameter를 업데이트하는 과정은 model에 정의된 modules기반

 

nn.Module을 상속받아서 직접 각각 안찾아가도 training시 parameter가 자동으로 업데이트

 

 

a=MyModel()이라고 선언하면 그냥 y=a(x)라고 calling만 해도 forward 함수가 실행.. 혹은 a.forward(x)라고 해도 실행

 

x = torch.rand((1,3,256,256))

y = a(x) #a.forward(x)

y.shape
torch.size([1,20,248,248])

 

model의 모든 layer는 nn.Module을 상속 받음

 

정의된 model 내부의 module들도 nn.Module을 상속 받아

 

model 내부의 conv든 뭐든 전부 forward를 가지고 있음

 

정의된 모델 객체에 대해 단 1번만 forward 함수를 수행하면

 

model 내부의 모든 module conv1, conv2, … 들에 대해서도 자동적으로 forward가 수행됨

 

TAGS.

Comments