AI VIDEO BRIEFING

GPT 모델 직접 구현하기 — 레이어 정규화·GELU·잔차 연결·트랜스포머 블록 완전 정리

세바스찬 라시카가 'LLM을 밑바닥부터 만들기' 4장에서 GPT 아키텍처를 코드로 직접 조립한다. 레이어 정규화와 GELU 활성화, 잔차 연결, 트랜스포머 블록에 이어 1억 2400만 파라미터라는 숫자의 정체와 텍스트 생성 과정까지 짚는다.

GPT를 밑바닥부터 조립하기: 레이어 정규화부터 텍스트 생성까지 영상 대표 이미지

핵심 메시지

  • 어텐션이 자동차의 엔진이라면 이 장에서 만드는 것은 바퀴와 핸들, 좌석에 해당한다. 먼저 빈 껍데기 클래스를 만들어 두고 빈칸을 하나씩 채워 나가는 방식으로 전체 구조를 익힌다.
  • 레이어 정규화는 각 샘플의 특성 차원을 평균 0, 분산 1로 맞춘다. 배치 정규화를 쓰지 않는 이유는 여러 GPU로 나눠 학습할 때 GPU당 샘플 수가 적어지면 불안정해지기 때문이다.
  • 잔차(숏컷) 연결은 층을 건너뛰는 뒷문이다. 같은 신경망을 숏컷 없이/있게 돌려 보면 역전파로 전달되는 기울기 값의 크기가 눈에 띄게 달라진다.
  • GPT-2 스몰의 실제 파라미터는 1억 6300만 개인데 흔히 1억 2400만 개로 불린다. 원본 구현이 입력 임베딩과 출력 층의 가중치를 공유해 그만큼을 두 번 세지 않았기 때문이다.
  • 텍스트 생성은 한 번에 한 토큰씩 이뤄진다. 마지막 행의 로짓에서 가장 큰 값의 위치를 찾아 토큰으로 바꾸고, 그것을 입력 뒤에 붙여 다시 모델에 넣는 반복 과정이다.

쉽게 이해하기

세바스찬 라시카의 'LLM을 밑바닥부터 만들기' 강의 시리즈 4장은 앞서 만든 토크나이저와 어텐션을 하나의 GPT 모델로 조립하는 단계다. 그는 어텐션을 자동차 엔진에 비유하며, 이번에는 바퀴와 핸들과 좌석을 붙이는 작업이라고 설명한다. 실습은 실제 코드 대신 자리표시자만 넣은 더미 클래스를 먼저 만들고, 그 빈칸을 한 절씩 진짜 구현으로 교체하는 방식으로 진행된다.

설정값은 GPT-2 스몰을 그대로 따른다. 어휘 크기 50,257개(tiktoken의 GPT-2 토크나이저 기준), 컨텍스트 길이 1,024, 임베딩 차원 768, 어텐션 헤드 12개, 트랜스포머 블록 12개다. 원본 수치를 고집하는 이유는 5장에서 오픈AI가 공개한 가중치를 그대로 불러와 넣기 위해서인데, 차원이 하나라도 어긋나면 가중치를 끼워 넣을 수 없다.

첫 번째 빈칸은 레이어 정규화다. 층의 출력값이 너무 크거나 작으면 기울기 소실·폭발로 학습이 불안정해지므로, 특성 차원 방향으로 평균을 빼고 표준편차로 나눠 평균 0·분산 1로 맞춘다. 여기에 학습 가능한 스케일(초깃값 1)과 시프트(초깃값 0) 파라미터가 붙는데, 이는 정규화가 오히려 방해가 될 때 신경망이 스스로 그 효과를 되돌릴 수 있게 열어 둔 여지다. 0으로 나누는 것을 막는 작은 상수도 분모에 더한다.

두 번째와 세 번째 빈칸은 GELU 활성화와 피드포워드 모듈이다. 선형 층만 쌓으면 아무리 깊어도 결국 하나의 선형 함수가 되므로 비선형 함수가 반드시 필요하고, GELU는 ReLU와 비슷하되 꺾이지 않고 매끄러워 최적화에 유리하다. 피드포워드는 768차원을 4배인 3,072차원으로 부풀렸다가 다시 768로 줄이는 모래시계를 뒤집은 모양이며, 4배라는 숫자 역시 원본 GPT 설계자가 고른 하이퍼파라미터다. 네 번째 빈칸인 잔차 연결은 이미지 인식용 ResNet 논문에서 온 개념으로, 모듈의 출력에 입력을 그대로 더해 깊은 신경망에서도 신호가 끊기지 않게 한다.

이 조각들을 모으면 트랜스포머 블록이 된다. 레이어 정규화 → 마스크드 멀티헤드 어텐션 → 드롭아웃 → 숏컷 덧셈, 다시 레이어 정규화 → 피드포워드 → 드롭아웃 → 숏컷 덧셈 순서이며, 정규화 층을 두 개 따로 두는 이유는 각자 학습 가능한 파라미터를 갖기 때문이다. 입력과 출력의 형태가 같아 블록을 12번 그대로 쌓을 수 있고, 여기에 임베딩 층과 마지막 정규화, 어휘 크기로 되돌리는 출력 층을 붙이면 GPT가 완성된다.

주요 인사이트

  • 구조를 배우는 가장 빠른 길은 완성된 코드를 읽는 것이 아니라, 빈칸이 뚫린 뼈대를 먼저 세우고 한 칸씩 메우는 것이다. 이 강의는 그 순서 자체를 교육 방법으로 삼는다.
  • GELU를 쓸지, 라마 계열처럼 SwiGLU를 쓸지는 사실 본질이 아니다. 중요한 것은 비선형 함수를 반드시 넣는다는 원칙이고, 나머지는 설계자의 선택에 가깝다는 것이 강사의 설명이다.
  • '1억 2400만 파라미터'라는 유명한 숫자는 모델의 실제 크기가 아니라 가중치 공유를 전제한 계산 결과다. 같은 아키텍처라도 임베딩과 출력 층을 묶느냐 마느냐에 따라 표기가 달라지며, 라마 3·3.1은 묶지 않고 3.2는 묶는다.
  • 잔차 연결의 효과는 이론이 아니라 눈으로 확인할 수 있다. 동일한 5층 신경망을 숏컷 없이/있게 각각 역전파해 기울기를 출력해 보면 값의 크기 차이가 뚜렷하게 드러난다.
  • 학습되지 않은 모델이 만들어 내는 문장은 완전한 횡설수설이다. 아키텍처가 맞게 조립됐는지와 쓸 만한 글이 나오는지는 별개의 문제이며, 후자는 5장의 사전학습 몫이다.

자주 묻는 질문

LLM에서 배치 정규화 대신 레이어 정규화를 쓰는 이유는 무엇인가?

레이어 정규화는 샘플 개수와 무관하게 각 샘플 안에서 정규화하기 때문이다. 큰 신경망을 여러 GPU로 나눠 학습하면 GPU 한 대가 맡는 샘플 수가 적어지는데, 배치 단위로 통계를 내는 배치 정규화는 이때 매우 불안정해진다.

레이어 정규화에 학습 가능한 스케일과 시프트를 왜 붙이는가?

초깃값이 각각 1과 0이라 처음에는 아무 효과가 없지만, 학습 과정에서 신경망이 정규화가 도움이 되지 않는다고 판단하면 그 값을 조정해 평균 빼기와 표준편차 나누기를 되돌릴 수 있다. 즉 정규화를 강제하지 않고 선택지로 남겨 두는 장치다.

출력이 텍스트가 아니라 5만 차원 벡터인데 어떻게 단어가 되는가?

마지막 토큰에 해당하는 행만 꺼내 소프트맥스로 확률로 바꾸고, 가장 큰 값의 인덱스를 찾는다. 그 인덱스가 곧 토큰 ID이므로 토크나이저의 디코드로 단어가 된다. 소프트맥스는 해석을 쉽게 할 뿐 순서를 바꾸지 않으므로 생략해도 결과는 같다.

왜 원본 GPT-2의 설정값을 그대로 따라야 하는가?

다음 장에서 오픈AI가 공개한 사전학습 가중치를 직접 불러와 이 코드에 넣기 때문이다. 임베딩 차원과 층 수, 피드포워드 확장 배수, 심지어 GELU의 근사식까지 원본과 맞춰야 가중치 행렬의 크기가 호환된다.

원문과 출처

이 글은 원본 영상의 자막을 바탕으로 한국어 독자를 위해 요약했습니다. 전체 맥락과 최신 정보는 원문에서 확인하세요.

YouTube 원본 영상 보기 ↗

관련 AI 소식