본문 바로가기

TECH/AI

역전파 알고리즘 (backpropagation)

앞서 학습했던, RNN, CNN, LSTM, GRU 뿐 아니라 GAN, Transformer 등 모두 이 역전파 알고리즘을 바탕으로 학습됩니다.

 

먼저 AI 전 후, 패러다임의 변화를 알고 가면 이해하기 쉬울 것 같아요.

 

인공지능이 아닌 프로그램은 Rule을 기반으로 처리가 됩니다.

 

1(Data) + 2(Rule) = y(Solution) 우리는 y를 알기 위해서 rule을 직접 작성했어요. 

Input(Rules, Data) -> Proccess -> Output (Solution)

 

그런데 AI는 Rule을 직접 깨닫습니다.  Data와 Solution을 통해 Rule을 알도록 하는 것이죠.

Input(Data, Solution) -> Proccess -> Output(Rules)

 

이 과정을 위해서 수학적 관계를 형성합니다.

layer를 만들고,

layer에는 node가 있으며,

node에는 weight이라는 가중치가,

그 노드들을 연결하는 edge에는 bias가 존재하죠. 

 

모델은 저희가 원하는 대답을 뱉어내기 위해서 weight와 bias를 수정해요. 바로 역전파 알고리즘을 통해서 말이죠.

그 과정에는 Forwad와 Backward가 있습니다.

Forward Pass(순전파): 입력 데이터를 신경망의 입력층에서 출력층까지 순차적으로 전달하는 과정

  • 입력층에서 데이터를 받아 각 뉴런의 가중치와 편향을 적용합니다.
  • 활성화 함수를 통해 각 뉴런의 출력을 계산합니다.
  • 이 과정을 각 층에서 반복하여 최종 출력을 생성합니다.

Backward Pass(역전파): 계산된 오차를 출력층에서 입력층 방향으로 전파하며 가중치를 조정하는 과정

  • 출력층에서 실제값과 예측값의 차이(오차)를 계산합니다.
  • 이 오차를 이용해 출력층부터 시작하여 각 층의 가중치에 대한 손실 함수의 그래디언트를 계산합니다.
  • 계산된 그래디언트를 사용하여 각 가중치를 조정합니

 

따라서, Forward에서는 현재 학습이 진행된 weight, bias에 의해서 y*를 예측하고 Backward에서 정답 y와 비교하여 loss를 계산한 후, 기울기를 계산하여 weight, bias를 업데이트하는 과정을 역전파 알고리즘이라고 합니다.

 

RNN을 기본으로 한 코드 예시입니다. 

def forward(self, x, state = None):
    # 은닉 상태 초기화(0으로 초기화)
    if state == None :
        state = torch.zeros(x.size(0),self.hidden_size)
    else :
        if state is not None and isinstance(state, tuple):
            state, = state

    # RNN forward 연산
    for i in range(x.size(0)):
        state = torch.tanh(torch.matmul(x[i, :],self.wxh)+torch.matmul(state,self.whh)+self.bh)
        out = torch.matmul(state,self.wh_output) + self.bo


    return out, state

 

현재 입력 x와 과거 상태 state를 바탕으로 output을 출력하고 있습니다. 그리고 아래 코드의 주석을 따라가면 backward 과정을 알 수 있습니다.

for epoch in range(num_epochs):
    random.shuffle(train_dataset)
    total_loss = 0
    for i, (name, label) in enumerate(train_dataset):
        hidden = torch.zeros(1, hidden_size)  # 은닉 상태 0으로 초기화

        for char in name:
            output, hidden = model(char, hidden)  # 각 문자에 대한 출력과 은닉 상태 계산
        loss = criterion(output, label)  # 최종 출력과 레이블 간의 손실 계산
        optimizer.zero_grad()  # 그래디언트 초기화
        loss.backward()  # 역전파를 통한 그래디언트 계산
        optimizer.step()  # 파라미터 업데이트

        total_loss += loss.item()

        if (i + 1) % print_interval == 0:
            print(
                f"Epoch [{epoch + 1}/{num_epochs}], "
                f"Step [{i + 1}/{len(train_dataset)}], "
                f"Loss: {loss.item():.4f}"
            )

    train_losses.append(total_loss / len(train_dataset))  # 에폭당 평균 손실 저장

 

'TECH > AI' 카테고리의 다른 글

Seq2Seq에서 Transformer로의 전환  (0) 2024.11.27
DEBUG with gcc : wheel package 다운로드 실패 해결 (Goliath)  (3) 2024.11.15
Introducing DEEPLABCUT  (2) 2024.11.11
Multi CUDA - ubuntu 24.04  (1) 2024.09.25
CNN : CV #1  (0) 2024.09.21