들어가며
LLM 이야기를 접하다보면 필수적으로 따라오는 용어 중에 Fine Tuning이라는 것이 있습니다. 우리 말로는 미세조정이라고 번역합니다. 오늘은 Fine Tuning이 무엇이고, 왜 LLM 이야기에 빠지지 않고 등장하는지에 대해 이야기해보려고 합니다.
Pre-trained Model
Fine Tuning에 대해서 이해하려면 Pre-trained Model을 먼저 이야기해야합니다. https://jins-sw.tistory.com/48 에서 Foundation Model이라는 측면의 LLM 이야기를 한 적이 있는데 참고하셔도 좋을 듯 합니다.
예를 들어 어떤 이메일이 스팸인지 아닌지 판단하다는 자연어처리 기능을 만든다고 생각해보겠습니다. 전통적으로 하던 방법은 다음과 같습니다.
- 이메일 데이터를 많이 많이 많이 모읍니다
- 각 이메일이 스팸인지 아닌지 표시합니다
- 이렇게 만든 데이터를 훈련 데이터 삼아서 Machine Learning 모델(Deep Learning도 물론 포함입니다)을 훈련시킵니다
오랜 기간동안 학계, 업계에서 검증된 신뢰도 있고 안정적인 방법입니다. 하지만 당연히 만족스럽지 못한 점들이 있습니다.
- 좋은 성능을 내려면 모아야할 데이터가 아주 아주 아주 많습니다. 특히 각 이메일에 스팸인지 아닌지 표시하는 일은 더더욱 어렵습니다.
- 이렇게 모아도 언어라는 특성상 전 세계의 다양한 이메일을 처리하기에는 한계가 있습니다.
그 때 누군가 아이디어를 냅니다.
- 스팸인지 아닌지 표시된 이메일 데이터를 많이 모으는 것은 어렵다
- 하지만 스팸인지 아닌지 표시 안 된 이메일 데이터를 모은 건 상대적으로 쉽다
- 더 나아가서 이메일인지 아닌지 관계없이 일반 텍스트 데이터는 인터넷에 넘쳐난다
- 문제를 쪼개서 풀어보자
- (스팸인지 아닌지) 아무 레이블링이 안 된 그냥 텍스트를 잔뜩 모아서 언어를 이해하는 모델을 하나 만들고
- 이 모델을 이메일 스팸 기능으로 조금만 특화시키면 비슷한 효과가 나지 않을까? 바닥부터 만들 때보다는 스팸인지 아닌지 표시된 데이터가 훨씬 덜 필요하겠지?
이 아이디어를 실제로 구현해봤더니 전통적인 방법보다 훨씬 적은 이메일 데이터를 쓰고도 효과가 나타났습니다. 여전히 1단계 모델을 만들기 위해서 일반 텍스트 데이터를 모아야했지만, 레이블링 된 데이터를 사람이 만드는 것보다 훨씬 쉬운 일이고요.
문제를 두 단계로 쪼갰으니 이제 각 단계를 부를 이름이 필요합니다.
1단계는 실제 원하는 Task를 훈련시키기 전 단계 훈련이라 Pre-training(사전 학습)이라고하고, 이렇게 만들어진 모델을 Pre-trained Model(사전 학습 모델)이라고 부르기로 합니다.
2단계는 Pre-trained Model을 조금 특화 시켜서 우리가 실제 원하는 Task로 튜닝하는 단계입니다. 여기에 착안해서 2단계를 Fine Tuning(미세 조정)이라고 부르기로 합니다. 아주 많이는 아니고 살짝(Fine) 튜닝한다는 의미를 담고 있습니다.
새 시대의 개막
이렇게 Pre-training과 Fine Tuning으로 나누고 보니 기대 이상의 효과가 나타났습니다.
- (Pre-training 없이) 레이블링된 이메일 데이터만 잔뜩 모아서 훈련했던 기존 방식보다 스팸 판단 성능이 올라갔습니다. 이메일과 직접 관련은 없지만 엄청나게 많은 텍스트 데이터로 Pre-trained Model을 만든 덕에 일반적인 언어 능력이 올라갔기 때문입니다.
- Pre-trained Model은 이메일 스팸 판단용 모델이 아니라 일반적인 언어 모델에 가깝습니다. Pre-trained Model을 용도에 맞게 Fine Tuning하면 다른 Task용으로도 쓸 수 이다는 생각이 듭니다.
하지만 Pre-training과 Fine Tuning으로 나누자 예상치 못했던 문제도 나타났습니다. 바로 Pre-training에 엄청나게 많은 노력, 시간, 돈이 들어간다는 점입니다. Pre-trained Model의 장점이 많다는 사실이 증명되자 사람들은 점점 더 많은 데이터를 넣고(레이블링이 안 된 일반 텍스트 데이터는 정말 많으니까요), 더 큰 모델을 만들기 시작합니다. 모델 크기를 나타내는 파라미터수가 백만 단위에서 십억 단위로 올라가고, 심지어 조 단위로 올라가기 시작합니다.
이쯤 되자 전 세계적으로 진지하게 Pre-trained Model을 만들 수 있는 곳은 손에 꼽히게 됩니다. 수십억 파라미터 급을 제대로 만들 수 있는 여력이 있는 곳도 많지 않고, 수천억 파라미터로 가면 정말 손에 꼽습니다.
많은 사람들은 시간, 인력, 돈같은 현실적인 이유 때문에 Pre-trained Model을 만드는 일에서 손을 놓습니다. 대신 누군가 이미 잘 만들어서 공개해준(또는 팔고 있는) Pre-trained Model을 기반으로 자신만의 Task를 만드는 Fine Tuning에 집중하기 시작합니다. 바야흐로 Fine Tuning의 시대가 열립니다.
Fine Tuning
Pre-training과 Fine-tuning은 Deep Learning 훈련 관점에서 본질적으로 같은 일입니다. 둘 다 Neural Net을 구성하는 파라미터의 값들을 최적화하는 일입니다. 다른 말로 Weights를 훈련시킨다고도 합니다. 실제로 훈련 시에 사용하는 기법도 동일합니다. 그렇다면 Pre-training와 Fine Tuning의 차이는 무엇일까요?
Pre-training은 훈련시킬 Neural Net의 Weight가 0 또는 랜덤인 상태에서 시작합니다. 아무것도 없는 바닥부터 시작하는 것이죠. 엄청나게 많은 텍스트 데이터를 훈련데이터로 넣어주면서 계속 훈련을 하다보면 Neural Net의 Weights가 최적화된 값으로 변합니다. 언어를 이해하고 생성할 수 있는 상태가 된 셈이죠.
Fine Tuning이 하는 일도 같습니다. 예를 들어 이메일 스팸 필터라면, 스팸인지 아닌지 표시된 훈련데이터를 넣어주면서 최적화 Weights를 찾아갑니다. Pre-training과 다른 점이라면 0 또는 랜덤 Weight에서 시작하는 것이 아니라, 이미 Pre-training을 통해 언어 관점에서 최적화된 Weight에서 출발한다느 점입니다.
이런 방식은 두가지 장점이 있습니다.
- 바닥부터 시작하는 것이 아니기 때문에 최적값을 찾기까지 시간이 훨씬 덜 걸립니다. 서울에서 출발해서 부산이나 광주로 간다고 생각해보죠. Pre-training은 나를 대전까지 데려다주는 역할입니다. 부산으로 갈 사람은 대전->부산 만큼만 가면 되고, 광주로 갈 사람은 대전->광주 만큼만 가면 되는 원리입니다.
- 최적값을 찾을 가능성도 더 높습니다. 다르게 말하면 Fine Tuning 한 최종 결과물이 바닥부터 만드는 것보다 성능이 좋을 가능성이 높다는 뜻입니다. 서울에서 부산까지 가야하는데, 나는 대전에서 부산까지 가는 길만 잘 안다고 생각해보겠습니다. 처음부터 서울에서 부산까지 가는 길을 찾는 것보다, 대전까지는 서울->대전 길찾기 전문가의 도움을 받는 같이 훨씬 길찾기 품질이 좋을 가능성이 높습니다.
Pre-trained Model을 직접 만드는 어려움과 Fine Tuning의 장점이 맞물려 다양한 Fine Tuning 기법과 Fine Tuning 된 모델들이 쏟아져 나오기 시작합니다.
또 다른 새 시대의 개막
이렇게 모두가 행복해질 즈음 또다른 문제가 생깁니다. Pre-trained Model이 점점 커지고 강력해지면서 Fine Tuning 또한 매우 어려운 일이 되갑니다.
Fine Tuning은 Pre-training 보다 가벼운 훈련은 맞지만 여전히 모델 전체를 훈련시키는 방식입니다. Pre-training이 70억개의 파라미터를 훈련시켜야한다면, Fine Tuning도 동일하게 70억개의 파라미터를 훈련시켜야합니다. Pre-training 과정에서 70억개의 파라미터가 최적값에 가까워졌기 때문에, Fine Tuning을 위한 최적값을 찾는데 시간이 덜 걸리고, 찾은 최적값의 더 좋은 값을 가능성은 높아졌지만 공짜는 아닙니다. 서울에서 대전까지는 전문가의 도움으로 온다고해도 서울->대전까지 비용은 내야하니까요. 특히 서울->대전 구간 전문가가 뛰어난 사람일수록 비싸겠죠.
Pre-training 보다는 가볍다고는 하지만 Pre-trained Model 자체가 커지면서 Fine Tuning을 위한 시간, 노력, 비용도 기하급수적으로 늘어나기 시작합니다.
또다른 문제도 생깁니다. Fine Tuning 된 모델의 크기는 기본적으로 Pre-trained Model과 같기 때문에 Fine Tuning 된 모델이 늘어날수록 그만큼 비례해서 저장하고, 유지해야할 모델이 늘어납니다. 70억개의 파라미터를 가진 Pre-trained Model을 사용해 스팸 필터, 감정 분류, 요약 기능을 만들었다면 70억 * 3 개에 해당하는 Fine Tuning Model을 유지해야합니다.
이제는 Fine Tuning 조차 왠만한 돈으로는 제대로 하기 힘든 단계에 들어서기 시작합니다. 선택지는 무엇일까요? 옛날처럼 덜 강력하지만 크기가 작은 Pre-trained Model을 사용하는 것입니다. 현실적인 이유 때문에 성능을 포기해하다니 너무나 슬픈 일이죠.
하지만 역시 난세에 영웅이 나오는 법. 이 문제를 해결할 영웅이 나타납니다. 바로 LoRA로 대표되는 Parameter Efficient Fine Tuning 입니다.
Parameter Efficient Fine Tuning (PEFT)
Parameter Efficient Fine Tuning (PEFT)은 이름 그대로 Fine Tuning을 하되 (전체 다 훈련하지 말고) Parameter Efficient 하게 해보자는 아이디어입니다. 핵심 아이디어는 "Fine Tuning 할 때 정말로 Pre-trained Model의 파라미터 전체를 훈련시켜야할까?"에서 시작합니다. 내가 하려는 일은 겨우 이메일이 스팸인지 아닌지 판단하는 일인데 이 거대한 Pre-trained Model 전체가 스팸 판단에 필요할 것 같지는 않은데?라는 생각이죠.
이 아이디어를 기반으로 다양한 PEFT 기법들이 만들어집니다. 그리고 PEFT 중 가장 유명하고 요즘 표준처럼 쓰이는 방법이 바로 LoRA입니다.
LoRA
오늘 글이 LoRA의 수학적인 원리를 설명하는 것은 아니니 이해를 위한 컨셉 측면에서 이야기해보겠습니다. 다른 PEFT 기법들과 마찬가지로 LoRA의 핵심 아이디어는 이렇습니다.
- 훈련할 때
- Fine Tuning 할 때 Pre-trained Model의 Weights는 건드리지 않겠다. 이를 Weight를 Freeze한다고 합니다.
- 대신에 Pre-trained Model의 Weights보다 훨씬 훨씬 훨씬 작은 새로운 Weights를 옆에 붙여서 이 Weights만 훈련시키겠다. 새로 훈련된 아주 작은 Weight를 LoRA Weight라고 부릅니다.
- 해석(Inference)할 때
- 입력을 Pre-trained Model의 Weight와 LoRA Weight에 모두 통과시킵니다. 최종 결과는 Pre-trained Weight를 거친 값과 LoRA Weight를 거친 값을 적절히 섞어서 (Weighted Sum) 사용합니다.
위의 그림에서 왼쪽의 파란 상자가 Freeze 시키는 Pre-trained Model의 Weight이고, 오른쪽의 주황색 사다리꼴 두 개가 새로 훈련시킬 LoRA Weight입니다.
기존 Fine Tuning 처럼 Pre-trained Model 전체를 훈련시키는 것보다 훨씬 작은 LoRA Weight만 훈련시키겠다는거니 훈련할 양이 줄어드는 것은 당연합니다. 그렇다면 실제로 얼마나 줄어들까요?
LoRA 논문에 따르면 GPT-2 Large Full Fine Tuning(774M 파라미터) 대비 약 0.1%의 Weight(0.77M 파라미터)만 훈련시키고도 Full Fine Tuning과 동일하거나 더 좋은 성능을 보인다고 합니다. GPT-3의 Full Fine Tuning(175B) 대비 0.0026%의 Weight(4.7M)만 훈련시켜도 동등한 수준을 얻을 수 있다고 합니다.
이런 놀라운 효과 덕에 Fine Tuning을 고려할 때 LoRA 가 첫번째 기법으로 꼽히곤 합니다. Pre-trained Model 작다면 기존의 Full Fine Tuning도 고려할 수 있지만, Full Fine Tuning과 LoRA의 성능이 같다면 굳이 Full Fine Tuning을 고집할 필요는 없겠죠.
약간 기술적인 이야기
건너뛰어도 무방한 약간 기술적인 이야기를 해보려고합니다.
LoRA는 Low-Rank Adapation을 줄인 말입니다. Adpation은 Pre-trained Model 전체를 다시 훈련시키지 않고 결과를 변형(Adapt)해서 사용한다는 의미입니다. 외국에서 산 전자 제품에 끼우는 돼지코(어탭터)와 같은 개념입니다.
남은 것은 Low-Rank라는 표현인데 Rank Decomposition 이라는 기법을 사용하기 때문에 붙인 이름입니다. 간단히 이야기하면 아주 큰 행렬 W를 좀 더 작은 두 개의 행렬 A와 B로 나눌 수 있다는 이론인데요 (W = A X B). 이때 행렬 A와 B가 W보다 작은 Rank를 가집니다. Rank는 행렬이 선형적으로 독립적인 column을 갖는지 표현하는 값인데, 자세한 이야기는 이 글의 취지를 벗어나기 때문에 생략하겠습니다.
LoRA Weight의 크기를 결정짓는 것은 그림에 r이라고 표현된 값입니다. Pre-trained Weight W의 차원이 500x500이라고 해보겠습니다. 그럼 내부적으로 250,000개의 값(파라미터)을 가집니다. r을 4로 했다고 해보죠. 그럼 A의 차원은 500x4 (2,000개 파라미터), B의 차원은 4x500(2,000개 파라미터)가 됩니다. A, B를 합쳐도 4,000개 파라미터입니다. r=4 일 때 LoRA Weight는 Pre-trained Weight 대비 파라미터가 1.6% (4,000 / 250,000) 뿐 입니다.
r을 2로 줄이면 훈련시킬 파라미터가 더 줄어듭니다. r이 커질수록 원래 Pre-trained Weight와 크기가 비슷해지기 때문에 성능이 올라가고, r이 작을수록 성능은 낮아집니다. 대신 r이 커질수록 LoRA Weight도 커집니다. 실제로 LoRA 훈련시에 r을 몇이로 하느냐가 중요한 실험 세팅입니다.
LoRA의 장점과 단점
다시 한 단계 상위 개념으로 올라와보겠습니다 :)
LoRA의 장점은 무엇일까요?
가장 명확한 점은 Full Fine Tuning 대비 아주 적은 양의 파라미터만 훈련시키면서, Full Fine Tuning과 같거나 심지어 더 좋은 성능을 내기도 한다는 점입니다.
또다른 장점으로 Fine Tuning 한 Task 별로 전체 Weight를 관리할 필요없이 Pre-trained Model은 그대로 두고 LoRA Weight만 바꾸면 된다는 점도 있습니다. 예를 들어 Pre-trained Model은 같은 것을 사용하고 LoRA 기법을 사용해서 이메일 스팸 필터와 감정 분류 Fine Tuning을 했다고 해보겠습니다. 이메일이 스팸인지 아닌지를 알고 싶다면 Pre-trained Model은 그대로 두고 이메일 스팸용 LoRA Weights를 붙이면 됩니다. 그러다가 감정 분류를 하고 싶다면 그 자리에 감정 분류용 LoRA Weight만 갈아 끼우면 됩니다.
별것 아닌 것 같지만 규모가 커지면 이 방식은 엄청난 효과를 보입니다. 예를 들어 제가 GPT-4를 능가하는 LLM을 만들었다고 해보겠습니다. 고객 중 일부가 LLM의 기본 성능에 만족하지 않고 자신의 Task에 맞추어 Fine Tuning을 하고 싶어합니다. 제가 제공하는 LLM은 너무 크기 때문에 저는 LoRA를 사용한 Fine Tuning 서비스를 자연스럽게 제공할 겁니다. 이 Fine Tuning 서비스가 인기가 많아지면서 수천, 수만개의 Fine Tuning 모델이 만들어집니다. Full Fine Tuning 기법을 썼다면 저는 GPT-4급의 Fine Tuning 모델을 수천개, 수만개 유지하고 서비스해야겠죠. 하지만 LoRA 기법을 사용했기 때문에 LLM은 그대로 두고 고객별, Task별 LoRA Weights만 필요 시에 제공하면 됩니다.
LoRA의 단점도 있습니다.
첫번째는 Full Fine Tuning 과 비교해서 추가적인 Weights가 들어가기 때문에 상대적으로 메모리를 더쓰고 추가적인 연산(LoRA Weight를 통과하고 나중에 Pre-trained Weight를 통과한 값과 합치기) 때문에 속도가 느려질 수 있다는 점입니다. 하지만 현실적으로는 앞에서 설명한대로 LoRA Weight가 Pre-trained Weight 대비 무시할 정도로 작은 크기이기 때문에 문제가 크지는 않습니다.
또다른 단점은 LoRA Weight는 Pre-trained Weight에 종속적(Adaptation)이기 때문에 Pre-trained Model의 Weight가 바뀌면 LoRA Weight도 다시 학습해야한다는 점입니다. LoRA로 훈련시킨 Fine Tuned Model 많을수록 다시 훈련시켜야할 LoRA Weight 가 많아지는 셈입니다.
Prompt Engineering
마지막으로 Fine Tuning과 Prompt Engineering의 관계에 대해서 간단히 이야기해보려고 합니다. 더 자세한 이야기는 https://jins-sw.tistory.com/51 에도 있으니 참고해보시면 좋을 듯 합니다.
Fine Tuning과 Prompt Engineering은 둘 다 Pre-trained Model을 내가 원하는 특정 Task에서 성능이 잘 나오게 하기위한 방법입니다. Prompt Engineering이 Fine Tuning과 가장 큰 차이점은 바로 Model의 Weight를 변형하지 않는다는 점입니다.
Prompt Engineering이라고 부르는 기법은 실제로 In-Context Learning을 말합니다. Pre-trained Weight이든 LoRA Weight이든 모델을 다시 훈련시키는 방식입니다. 하지만 In-Context Learning은 대신 Pre-trained Model(LLM)에게 동작 수행에 필요한 정보(Context)와 지시(Instruct)를 입력의 일부로 주는 방식입니다. Prompt Engineering의 작동원리는 https://jins-sw.tistory.com/51 에 적어보았습니다.
그럼 왜 Prompt Engineering 기법이 나왔을까요? LoRA 같은 PEFT 기법들이 나온 이유와 비슷합니다. PEFT가 아무리 효율적이라고 하지만 여전히 모델을 재훈련해야하기 떄문에 시간과 비용이 들어가고, 모델 훈련을 위한 전문적인 지식이 필요합니다. 하지만 Prompt Engineering은 사람의 언어(자연어)를 사용해서 LLM의 성능을 올리기 때문에 보다 직관적이고, 입력에 성능 개선을 위한 정보(Context, Instruct)를 넣기 때문에 별도의 사전 훈련도 필요하지 않습니다.
Full Fine Tuning vs LoRA vs Prompt Engineering
그럼 언제 Full Fine tuning을 쓰고, 언제 LoRA 같은 PEFT를 쓰고, 언제 Prompt Engineering을 사용할까요? 정답은 없지만 현재 학계, 업계의 통용되는 가이드라인을 제시해보면 이렇습니다.
- ChatGPT, GPT-4, PaLM 같이 LLM이 매우 크고 강력하다면 (어림잡아 70B 이상),
- Prompt Engineering을 먼저 시도해보는 것이 좋습니다. 부담없고 값싼 방법입니까요. zero-shot을 시도해보고, 잘 안 되면 few-shot도 시도해봅니다.
- 그래도 잘 안 된다면 LoRA 같은 PEFT를 시도해봅니다.
- 현실적으로 이 정도 크기의 모델을 Full Fine Tuning 하는 것은 매우 어렵습니다.
- 모델이 상대적으로 작다면 (7B ~ 30B급)
- Zero-shot은 작동하지 않은 가능성이 매우 큽니다.
- Task에 따라 다르기는 하지만 솔직히 few-shot도 가능성이 높지는 않습니다. 그래도 비싼 노력은 아니니 시도해볼만 합니다.
- LoRA가 효과가 가장 좋습니다. 7B라고 하더라도 Full Fine Tuing을 하기에는 여전히 큽니다.
- 모델이 작은 경우 (2B 이하)
- few-shot도 안 될 가능성이 매우 큽니다.
- Pre-trained Model의 성능이 상대적으로 낮기 때문에 Fine Tuning에 많이 의지해야합니다.
- 이 정도 크기면 요즘 좋은 GPU에서는 굳이 LoRA를 쓰지 않고 Full Fine Tuning을 해볼 수 있습니다.
- 물론 LoRA는 언제나 Full Fine Tuning 대비 저렴하기 때문에 시도해볼만한 가치가 있습니다.
앞에 말씀드린대로 정답은 없고 Pre-trained Model, Task, 가지고 있는 데이터에 따라 달라지기 때문에 상황에 맞는 엔지니어링이 필요합니다.
마무리
오늘은 Fine Tuning과 LoRA를 LLM 관점에서 다루어보았습니다. 모든 기술이 그렇듯이 만능은 없고 문제 상황에 적절한 도구를 찾아서 사용하는 것이 중요하다고 생각합니다. 이 글이 LLM을 이해하는데 조금이나마 도움이 됐으면 하는 바람입니다.
'Deep Learning' 카테고리의 다른 글
LLM : Context Window (1) | 2024.05.25 |
---|---|
LLM : RAG (3) | 2024.04.28 |
Cross Entropy 이야기 (0) | 2023.05.21 |
LLM : In-Context Learning, 남은 이야기들 (12) | 2023.04.12 |
LLM : LLM을 가능케한 삼박자 (7) | 2023.04.12 |