GPT-2 구조 분석과 파인튜닝을 해보자
by 병현 on Tue Oct 07 2025
개요
저번 게시글에서는 자연어 처리 발전의 한 획을 그은 트랜스포머 기반의 모델들 ‘GPT-1’과 ‘BERT’에 대하여 살펴보았습니다. 각각 ‘GPT-1’은 트랜스포머의 인코더를 제거하고 디코더만을 이용해 ‘생성’ 능력을 극대화 시켜 문장 생성 기반의 task들을 잘 수행하는 모델이였고, ‘BERT’는 디코더를 제거하고 인코더만을 이용해 인코더의 ‘문맥 파악’능력을 극대화 시켜 문장 감정 분석, 요약, 가려진 단어 맞추기 등 의 작업을 잘 수행하였습니다.
이렇게 ‘GPT’와 ‘BERT’ 모두 트랜스포머로 부터 비롯하여 결국 특정 기술을 극대화 하기 위해 제안된 모델들이였습니다.
하지만 ‘GPT-2’부터 그 양상은 조금씩 달라졌습니다. ‘GPT-2’가 매개변수를 ‘GPT-1’보다 약 10배 많이 추가하면서, 사전학습된 ‘GPT-2’로도 미숙하지만 여러 작업들을 수행할 수 있는 가능성이 보이기 시작했습니다. 그것은 ‘GPT-3’이 ‘GPT-1’보다 약 1500배 많은 파라미터를 추가하면서 완전히 사전학습된 모델만으로도 충분히 여러 작업을 수행할 수 있다는 것이 증명됬습니다.
그렇다면 우리는 ‘GPT-1’이 ‘GPT-3’가 되기 이전까지의 매커니즘 변화를 일으켰던 ‘GPT-2’에 대해서 알아보고, 어떤 점이 다른건지, 그리고 ‘GPT-2’를 파인 튜닝한다면 어떤 모습이 되는것인지 함께 알아보도록 하겠습니다.
참고: 해당 게시글은 이미 작성 시점 GPT-2 구조분석과 파인튜닝 프로젝트를 완료한 상태로, 해당 게시글은 진행했던 일련의 과정에 대한 회고와 조금의 이론들에 대한 자세한 설명들로 구성되었습니다. 정확한 코드를 보기 위해서는 자세한 주석과 코드가 작성된 iamb0ttle/GPT-2-Fine-Tuning 해당 깃허브 레포지토리를 참고해주세요.
GPT-2: ‘Large’ Langauage Model의 신호탄
GPT-2는 GPT-1을 연구한 비영리 단체(논문 발표 시점)였던 Open AI에서 약 1년뒤 2019년에 새로 공개한 모델입니다. 논문 Language Models are Unsupervised Multitask Learners” (2019, Radford et al.) 에서 처음으로 공개되었으며, 이는 약 BERT(October, 2018)가 공개된 이후 4개월 뒤 공개된 논문이였습니다.
BERT는 엄청난 문맥처리 분야 벤치마킹 성능으로 세상에 큰 놀라움을 안겨주었지만, 얼마 지나지 않아 거대한 파라미터를 통해 새로운 혁신을 사람들에게 알린 모델이 된 셈 입니다.
한가지 흥미로운 사실은, GPT-2를 공개할 당시에 OpenAI는 가장 큰 파라미터 갯수를 가지는 15억(1.5B)모델을 공개하지 않았다는 점 입니다. 초기에는 가장 작은 모델 1억 1700만 파라미터(117M)를 공개하고, 다른 연구자들이 비슷한 모델을 제현한 시점에서야 공개하였습니다. 이를 두고 많은 사람들은 여전히 ‘안전을 위한 일종의 가드레일’ vs ‘과장된 위험한 마케팅’ 두 의견으로 갈려 한때 논란이 되기도 햇습니다.
어쨌든 중요한 것은, 결국 GPT-2는 GPT-1보다 많은 파라미터를 사용함으로써 GPT-1에 비해서 여러 task를 잘 수행하고, 일반적인 다음 단어를 예측하는 능력도 눈에 띄게 좋아졌다는 것 입니다.
그렇다면 GPT-1과 GPT-2는 정확히 어떤 차이점을 가지는지 알아보겠습니다.
GPT-1 vs GPT-2
사실 GPT-1와 GPT-2 모두 트랜스포머 모델의 디코더 아키텍처를 기반으로 하고 있기 때문에, 모델의 구조에서는 눈에 띄다할 변화와 차이점이 없습니다. 하지만 몇가지 차이점들이 GPT-1 모델과 GPT-2 모델을 구분하게 만듭니다.
먼저 GPT-1 모델과 GPT-2 모델의 차이점을 테이블로 한눈에 비교해보겠습니다.
| GPT-1 | GPT-2 | |
|---|---|---|
| 목표 | 사전 훈련된 모델 기반의 파인튜닝 | 제로샷 학습 성능 |
| 모델 크기 | 1.17억 파라미터 | 15억 파라미터 |
| 훈련 데이터 | BookCorpus (미출판 도서 7,000권, 1GB) | WebText (레딧 게시물, 40GB) |
| 컨텍스트 크기 | 512 토큰 | 1024 토큰 |
| 어휘 크기 | 약 40,000 | 약 50,257 |
모델 목적: 파인튜닝(Fine-Tuning) vs 제로샷(Zero-shot)
GPT-1과 GPT-2의 차이점을 결정짓는데 큰 영향을 끼쳤다해도 과언이아닌, 모델의 목적입니다.
먼저 GPT-1의 목적은 명확했습니다. “여러 분야에 잘 훈련된 사전학습된 모델을 만들어서, 해당 모델을 파인튜닝해 여러 응용분야에할 수 있도록 하자.” 실제로 GPT-1은 해당 목적을 잘 달성하였고, 특정 모델을 A-Z까지 지도학습 하는게 아니라 비지도 학습된 모델을 파인튜닝을 통해 지도학습으로 특정한 영역에 대한 약간의 정보로 오히려 지도학습된 모델보다 좋은 성능을 내기도 하였습니다. 하지만 파인튜닝하지 않은 바닐라(Vanila)상태의 GPT-1은 어느 분야에도 사용하기 애매하다는 단점이 있었습니다.
하지만 GPT-2는 이러한 접근법을 완전히 변화시켰습니다. GPT-2의 목적은 사전 학습된 모델로도 충분히 제로샷(Zero-sho) 성능을 기대할 수 있는 것을 목적으로 하였습니다. 제로샷이란 모델이 훈련과정에서 한번도 본적 없는 데이터나 유형을 처리하는 것 입니다. 즉, GPT-2가 단순히 Casual LM으로 학습이 됬더라 하더라도, 감정 분석, 번역 등과 같은 문제들을 해결하기를 원하는 것 입니다.
실제로 이 방법은 성공하였습니다. casual LM으로 학습이 된 모델에 프롬포트로 “Translate this sentence to enlgish: 안녕 나는 지피티야”를 입력하면 모델은 출력으로 “Hello, I’m GPT”를 출력하게 됩니다. 하지만 이는 프롬포트가 얼마나 정확하냐에 대한 의존성이 있었고, 이는 프롬포트 엔지니어링을 더욱 흥행하도록 하였습니다. 이는 실제로 우리가 한가지 언어 모델에서 많은 작업을 기대할때 널리 사용하는 방법이기도 합니다.
모델 크기: 모델 크기가 성능으로 직결되다.
GPT-2는 대폭 향상된 모델 크기로 등장하여 많은 사람들에게 충격을 주었습니다. GPT-1의 1억 1700만 매개변수보다 약 10배 더 많은 15억 매개변수로 GPT-2가 출시하였으며, 이는 대규모 언어 모델의 시작을 알리는 신호탄이기도 했습니다. 이후 GPT-3가 1750억 매개변수로 그 피날레를 장식한 것이죠.
실제로 파라미터의 갯수를 대폭 늘리는것은 모델의 성능을 크게 좌우하였습니다. 파라미터가 많다는 것은 결국 모델이 학습할 수 있는 정보의량이 늘어난다는 의미였고, 때문에 WebText라는 Reddit의 많은 사람들의 추천을 받은 고품질 웹사이트 데이터를 약 40GB를 담고있는 데이터셋으로 GPT-2를 학습할 수 있었습니다.
매개변수 크기 뿐만아니라, GPT-2는 다른 부분들에서도 모델의 크기가 늘어났습니다. 컨텍스트 크기는 1024 토큰으로 2배 늘어나 모델이 문맥을 이해하는 능력이 늘어났고, 모델이 알고있는 어휘의 갯수도 약 40000개에서 약 만개정도 늘어나게 되어 50257단어를 알게되었습니다.
아키텍처 변화: Post-LN → Pre-LN

앞서 언급한 것 처럼, 모델 아키텍처 자체에 대한 변화는 GPT-1이나 GPT-2나 거의 다를 것 없이 동일하다고 하였습니다.
하지만 한가지 차이점이 있다면 GPT-1이 선택한 PostLN 방식에서 GPT-2는 Pre-LN 방식을 사용하였다는 것 입니다.
Pre-LN이란 Laeyr Normalization, 즉, 정규화를 수행하는 레이어를 학습 이전에 배치하여 미리 정규화 한 이후에 학습을 진행하는 것 입니다. 위 사진에서 볼 수 있는 것처럼, 좌측 GPT-1의 구조는 Masked Multihead Self-Attention 이후에 정규화를 수행하는 PostLN 방식을 사용하고 있습니다. 반면 우측의 GPT-2 구조는 미리 정규화를 진행하고 이후에 정규화 된 벡터들을 통해 self-attention을 수행하는, Pre-LN 방식을 사용하였습니다.
GPT-2가 이러한 Pre-LN 방식을 채택한 이유는, 모델의 크기가 커지고 학습해야하는 정보가 늘어남에 따라서, 만약 어텐션을 수행하는 값들이 불안정하면 그 영향력이 학습 전반에 걸쳐서 깊어지기 때문에, 미리 학습을 안정적으로 만들고 변수를 통제하고자 이러한 Pre-LN 방식을 도입한 것 입니다.
이렇게 GPT-2 모델은 GPT-1에 비해 조금씩 변화를 통해 그 매커니즘을 확장시켜 Zero-shot Learning 방법론을 적극적으로 달성하기위해 노력하였습니다. 실제로 hugging face의 transformers 라이브러리에서는 GPT2Model에 Head를 추가해 학습시켜서 문장 감정 분류, 질의응답 등 특정한 Task에 더욱 잘 작동하도록 파인 튜닝한 모델로 제공됩니다. GPT-1에 비해 파인튜닝 성능도 대폭 향상하였으며, GPT-2 모델은 결국 대규모 언어 모델의 신호탄을 쏘아올린 기념비적인 모델이 되었습니다.
PEFT와 LoRA란? Fine-Tuning 기법에 대해 알아보자
GPT-2 구조를 살펴보았으니, 이제 다음으로는 GPT-2를 파인 튜닝해보도록 하겠습니다.
그 전에, 먼저 이번 프로젝트에서 제가 계획했던 목표에 대해서 살펴보고 가겠습니다.
- news 데이터셋으로 GPT-2를 파인튜닝해서 news 스타일의 글을 작성하도록 학습
- joker(batman) 캐릭터의 대사 데이터셋으로 GPT-2를 파인튜닝해서 조커 말투를 따라하는 문장을 생성하도록 학습
따라서 저는 해당 프로젝트를 진행하기 위해서 Fine-Tuning 기법중 하나인 PEFT, 그중에서도 LoRA 기법을 적용하여 파인튜닝 하기로 결정하였습니다.
Full Fine-Tuning vs PEFT
먼저, 크게 파인튜닝 방식에는 두가지 분류로 나누어집니다. 바로 Full Fine-Tuning과 PEFT 입니다.
- Full Fine-Tuning: 모델을 파인튜닝하기 위해서 사전학습 된 모델의 모든 가중치를 새로운 데이터에 대해 업데이트 하는 방법입니다. 가장 전통적인 방식으로, 특정 모델에 대해 강력한 특정 작업의 정확성을 바랄때 주로 사용합니다. 하지만 학습 시켜야 하는 파라미터가 많을 수 있다는 단점이 있습니다.
- PEFT(Parameter-Efiicient Fine-Tuning): PEFT(Parameter-Efiicient Fine-Tuning)는 Full Fine-Tuning처럼 모델의 모든 매개변수를 업데이트 하는 것이 아닌, 일부 매개변수는 동결(freeze)시켜 전체 학습과정에서 절대로 매개변수를 업데이트 시키지 않고, 일부 매개변수에 대해서만 업데이트를 조금씩 수행하거나 새로운 매개변수를 추가하여 업데이트 하는 방식입니다.

쉽게 비유하여 정리하자면, Full Fine-Tuning은 내가 완성한 레고블록의 모습을 조금더 멋있게 바꾸기 위해서 모든 블럭들을 조금씩 조금 더 좋은 블럭들로 교체하는 방법이고, PEFT는 레고블록의 모습을 조금 더 멋지게 하기 위해서 기존 블럭들 중에 일부를 교체하거나, 새로운 블럭들을 기존 블럭들 위에 쌓는 방식을 사용하는 것 입니다.
Full Fine-Tuning의 경우 모델이 우리의 의도대로 조금 더 잘 작동한다는 장점이 있지만, 이는 Large Language Model 시대가 되며 조금씩 변화하기 시작하였습니다. 오히려 파라미터 갯수가 약 15억개 되는 모델을 튜닝하려고 하다보니 복잡성과 시간은 많이 필요하였고, 효율성은 낮아지기 시작하였습니다. 따라서 이 때 PEFT 방법론이 부상하기 시작하면서, 일부 파라미터만 튜닝하거나 추가하는 방식이 오히려 LLM 에게는 낮은 시간과 비용으로 더욱 좋은 성능을 기대하기 좋은 방법이라고 제시되기 시작하였습니다.
그렇게 PEFT의 중요성이 대두되기 시작하던 때, 2021년, Microsoft의 연구팀은 LoRA: Low-Rank Adaptation of Large Language Models라는 논문을 통해 PEFT의 일종인 새로운 메커니즘인 LoRA를 제안하였습니다.
LoRA
LoRA(Low-Rank Adaptation)는 사전 학습 모델의 원본 가중치 행렬에서 낮은 순위(Low-Rank)를 가지는 항목들을 찾는 것이 결국 LoRA의 핵심 목표입니다.
여기서 낮은 순위란 무엇일까요? 이를 이해하기 위해선 잠깐 선형대수학의 세계로 넘어가야합니다.
예를 들어, 다음과 같은 3x3 행렬이 있다고 생각해 봅시다.
[ 1, 2, 3 ]
[ 2, 4, 6 ]
[ 3, 6, 9 ]
해당 행렬은 행이 커질수록 첫번째 열의 값들에 단순히 배수를 취한 값을 다음 행으로 취하는 행렬입니다. 예를 들어 두번째 행렬 [ 2, 4, 6 ]은 첫번째 행렬의 모든 열들의 값들을 2배수 한 값들인 것을 알 수 있죠.
따라서 우리는 해당 행렬에서 가장 대표적이면서 행렬을 잘 설명하는 행을 [ 1, 2, 3 ]로 정의합니다. 그리고 이 행렬은 순위가 낮다(Low-Rank) 라고 할 수 있습니다.
반면, 행렬의 모든 행과 열이 서로 완전히 독립적인 정보를 담고 있다면, 그 행렬은 ‘Full-Rank’ 라고 부릅니다. Full-Rank 행렬은 정보를 압축할 여지가 없는, 정보가 꽉 찬 상태라고 할 수 있습니다.
LoRA는 이러한 원리를 모델의 가중치 행렬에 적용한 것 입니다. 결국 모델의 가중치 행렬은 행렬을 잘 설명하는 낮은 순위의 행렬들로 표현할 수 있기 때문에, 그 낮은 행렬을 모방하여 찾아내고 학습시켜 가중치를 업데이트 하겠다는 것 입니다.

해당 사진은 LoRA의 구조를 도식화 한 그림입니다.
LoRA는 PEFT를 달성하기 위하여 원본 가중치 행렬은 모두 동결하고, 원본 가중치 행렬을 모방하는 새로운 행렬 A, B를 생성하여 학습시킵니다.
예를 들어, 원본 가중치 행렬이 d x k의 크기를 가지는 행렬일 때, 새로운 가중치 행렬 A와 B는 각각 다음과 같은 크기를 가집니다. d x r, r x k. 이 때 Full Fine-Tuning 기법은 원본 가중치 행렬의 학습을 위해서 d x k개의 파라미터를 업데이트 해야합니다. 즉, 가중치 행렬이 1000 x 1000 이면 가중치는 100만개를 업데이트 해야합니다. 하지만 LoRA에서 사용되는 가중치 행렬 A, B는 오직 (d x r) + (r x k)개의 파라미터를 학습시키면 됩니다. 즉, 원본 가중치 행렬을 모방하기 위한 A, B의 크기가 각각 1000 x r, r x 1000이므로 총 2000r 만큼의 파라미터 갯수만 업데이트 하면 됩니다.
여기서 r은 위에서 언급한 Rank로, 이는 LoRA 학습을 적용하는 사용자가 직접 설정 해주어야 하는 값입니다. 보통 2, 4, 8, 16, 32, 64... 이러한 2의 배수 값들로 설정하며 값이 작을수록 더욱 전체행렬을 표현하기 위한 낮은 순위의 값들을 구하기 위해 동작하므로 정보 압축률이 커집니다. 반면 값이 클수록 보다 높은 순위의 값들로 행렬을 표현하기 위해 보다 많은 정보를 남기면서 압축이 가능합니다.
이것이 가능한 이유는 모두 행렬 곱셈(Multiplication of matrices) 덕분인데요, LoRA를 위해 생성된 가중치 행렬 d x r, r x k는 둘이 행렬 곱셈을 수행하면 d x k크기의 하나의 행렬이 됩니다. 즉, 원본 가중치 행렬의 크기와 동일해지며 원본 가중치 행렬을 모방할 수 있는 것 처럼 동작하는 것 입니다. LoRA는 이렇게 만들어진 행렬이 우리가 원했던 ‘변화량’ ΔW와 거의 비슷할 것이라고 보는 것입니다.
이를 달성하기 위한 LoRA의 학습과 추론 과정은 다음과 같이 진행됩니다.
- 학습: Input 값을 원본 가중치 행렬과, LoRA를 적용하여 생긴 두개의 새로운 가중치 행렬에 각각 통과 시킴. 이후 원본 가중치 행렬을 통과한 출력과 새로운 가중치 행렬을 통과한 출력을 합쳐서 모델의 출력으로 결정. Loss 발생시 Backpropogation은 오직 LoRA 가중치 행렬들에 대해서만 적용.
- 추론: 학습과 마찬가지로 Input 값을 원본 가중치 행렬과, LoRA 가중치 행렬에 각각 통과. 이후 출력을 합쳐서 모델의 출력으로 결정.
정리해보면, LoRA는 특정 가중치 행렬을 모방하는 새로운 행렬, 하지만 비교적 정보를 압축하는 새로운 행렬 A, B를 학습시켜서, 마치 원본 행렬의 가중치가 업데이트 되는 것처럼 동작하여 모델의 파인튜닝 성능을 끌어올리는 것이 목표인 학습 방법입니다.
프로젝트 회고
지금까지는 이번 프로젝트를 진행하면서 제가 가장 관심있게 공부한 GPT-2의 구조와 매커니즘, LoRA 파인튜닝 기법에 대해서 살펴보았습니다.
이번 프로젝트를 진행하면서 저는 또 한번 많은 것을 느낄 수 있었는데요. 몇가지 느낀 점을 회고해보려고 합니다.
먼저 결과 부터 말씀드리자면, 계획했던 news 파인튜닝과, 조커 말투 파인튜닝 시도를 해보았고, news 파인튜닝은 성공적인 성과를 얻었으나 조커 말투 파인튜닝은 이렇다할 성과를 얻지 못했습니다.
그 이유가 LoRA의 장/단점에 있다고 생각하는데요.
먼저 LoRA의 장점은, 확실하게 빠르고 쉽고 효율적으로 파인튜닝을 수행할 수 있다는 사실 입니다. 이는 방대한 양의 컴퓨팅 자원을 확보하기 어려운 사람들에게는 더더욱 매력적으로 다가오죠.
또한 이번에 파인튜닝을 진행할때 제가 학습한 매개변수의 갯수는
trainable params: 147,456 || all params: 124,588,032 || trainable%: 0.1184
이렇게 보다시피 약 14만개로, 원본 GPT-2 1.5B의 15억개보다 약 0.11%정도의 값으로 Full Fine-Tuning을 했다면 학습해야할 파라미터의 갯수보다 99.89% 적게 파라미터를 학습할 수 있었습니다.
하지만 그만큼 LoRA의 단점도 명확했습니다.
제가 news 데이터셋으로 모델을 학습할때는, 데이터셋의 갯수가 학습 2000개, 테스트 데이터셋 500개 정도되어서 ephoc을 5번정도 진행하고 점차 ephoc을 감수할수록 loss도 눈에 띄게 감소하는 것을볼 수 있었습니다.
하지만 조커 말투를 흉내내는 GPT-2를 학습하기 위해서는 조커 말투 데이터셋이 필요하였는데, 이는 구하기 쉽지 않았고 어쩔수 없이 LMM Gemini-2.5-Pro를 통해서 약 500개 정도 되는 대사를 직접 생성했습니다.
하지만 이는 모델을 학습하기 충분한 데이터 갯수가 아니였고 결국 학습이 원할하게 진행되지 못하였습니다.
물론 이는 LoRA 모델의 문제점이라기 보다는, 모든 인공지능의 학습에서 문제시 되는 학습데이터의 부족이였습니다.
하지만 LoRA의 단점도 프로젝트에 영향을 미쳤습니다. ‘말투’라는 것은, 그리 쉽게 파악할 수 있는 패턴이 아닙니다. 특히 조커 말투는 더더욱 조금은 특이하면서도 일반적인 문장 구조는 정확히 가지고 있기 때문에 그렇죠.
때문에 이런 경우는 오히려 모델의 전체 파라미터를 미세 조정하는 Full Fine-Tuning이 나을 수도 있겠다는 생각이 들었습니다. LoRA는 일부 파라미터를 모방하여 비교적 적은 파라미터를 학습시켜야 하기 때문에, 복잡한 패턴이나 특정 도메인에 대한 학습이 제대로 이루어지기 어렵기 때문입니다.
하지만 그 과정에서 저는 모델의 성능을 조금이라도 올리기 위해 프라이밍 기법 (Priming Technique)을 시도하는 등의 노력을 하며 조금이나마 성능을 개선시켜보기도 하였습니다.
결국 이번 프로젝트에서는 news 데이터셋을 통한 성공적인 파인튜닝 경험도 해보았고, 좋은 줄만알았던 LoRA의 한계에 직접 부딪혀보며 실패적인 파인튜닝 경험도 쌓을 수 있었던 경험치 두배 이벤트 프로젝트였습니다..!
결론
Seq2Seq Attention과 Self-Attention에서 부터 시작해 GPT-2를 파인튜닝하기 까지 정말 길고 긴 여정이였습니다. 이렇게 학습을하며 NLP 분야의 발전을 직접 체감하니 더욱 즐겁고 흥미로운 느낌이 들었습니다.
사실 이 글을 작성하는 시점인 2025년 10월에는 이미 얼마전 GPT에서 공개한 새로운 오픈소스인 GPT-OSS와 Grok 2.5, Deepseek R1 등 여러 LLM들이 학습할 수 있는 상태입니다.
즉슨 저는 계속해서 학습을 해야한다는 이야기겠죠.. ㅎㅎ
어쨌든 해당 어텐션 메커니즘부터 GPT-2 파인튜닝을 학습 하는데 약 1달정도 소모된 거 같은데, 오랜만에 정말 알찬 1달이 아니였나 싶습니다. 이번 프로젝트는 여기서 마치지만 저는 계속해서 NLP 분야에 대해 학습하고, 더 나아가 많은 인공지능 분야까지 학습해보도록 노력하겠습니다.