본문 바로가기
AI 빅데이터/AI 동향

[GPT-3] GPT-3 FineTuning 하기

by 마고커 2023. 2. 19.


잘 알려져 있다시피 GPT-3는 모델을 공개하지 않아서, Transfer Learnin에 의한 Fine Tuning이 어렵다. 하지만, P-Tuning 등으로 불리는 Prompt Encoder에서의 튜닝 기법으로 어느 정도 파인튜닝 모델을 만들어 낼 수 있다. 오죽하면 gpt-3의 논문제목은 "Language Models are Few-Shot Learners"이겠는가!

 

 

 

챗봇 딥러닝 - 초거대모델의 파인튜닝 방법 - P-tuning과 LoRA

BERT 이후로 딥러닝 자연어처리는 사전훈련 모델(pre-trained model)이 기본이 되었습니다. 보통 위키피디아 같은 데이터로 사전훈련을 하면 언어의 기본적인 특징을 이해하게 됩니다. 그다음 개별 태

aidev.co.kr

 

몇일 전 Toward Data Science에 그 구체적 방법이 나와서 소개한다.

 

 

Unleashing the Power of GPT: How to Fine-Tune Your Model

Step-by-step guide to GPT fine-tuning

towardsdatascience.com

 

위의 포스팅에서의 파인튜닝 절차는 아래와 같다.

 

1. Prompt Engineering에 사용할 데이터셋을 준비한다.
   {age}, {gender}, {power}를 포함하고 있는 가상 캐릭터에 대한 완전하고 자세한 설명을 하도록 GPT-3에 요청한다.
   이렇게 만들어진 데이터 세트는 {age}, {gender},{power}의 prompt 형태로 input이 들어오면 대답의 형식으로 
   사용될 것이다.
2. OpenAI의 API를 사용하여 Fine Tuning한다.
3. Fine Tuning된 모델에 prompt 형태({age}, {gender},{power})로 input을 주어 결과를 확인한다.

 

1) 데이터셋 준비

 

사실 데이터셋 준비하는 과정이 복잡하지만, 최종적으로는 아래의 형식을 갖는 파일을 갖는 것이다.

prompt,completion
"18, man, invisibility","He looks to be in his late teens, with dark eyes and unruly black hair which reach his shoulders. His build is athletic and strong, but not muscular. He often wears clothing that makes him blend in with his surroundings, in order to stay as inconspicuous as possible.He has the ability of invisibility, which he can use to become an invisible observer or to make himself or objects around him disappear from view. He has honed his skills to make himself undetectable, able to even make sounds vanish, allowing him to go unnoticed. His invisibility power is his greatest asset, and he uses it to protect those he cares about."
"18, man, invisibility","18 year-old Jackson is a powerful young man with the incredible power of invisibility. He stands at 6'2 and has a strong athletic frame with wavy brown hair, startling blue eyes and a warm and gentle smile. His strength and agility make him especially good at using his ability. He can become invisible in an instant, moving through walls and other obstacles without being detected. What's more, he can move objects with his mind and use his power to protect those he loves. His power is a blessing and a curse, as it can be abused to do harm. Jackson is a brave and noble person who uses his power to do good and make the world a better place."
.....

 

즉, prompt 형식에 input으로 받을 prompt 형식과, 대답의 형태를 갖는 예제(completion)를 csv형태로 넘겨주면 된다. 원저자는 completion 만들어내는 것조차 gpt-3에게 prompt를 포함해서 아주 상세히 만들어달라고 했다.

 

import os
import openai
import pandas as pd

# openai 패키지를 사용하려면 'pip3 install --upgrade openai' 실행
# shell에서 'export OPENAI_API_KEY=sk-로시작하는 openai api key' 실행
# openai api key는 https://platform.openai.com/account/api-keys 에서 취득
openai.api_key = os.getenv("OPENAI_API_KEY")

# prompt는 age, gender, power를 사용
l_age = ['18', '20', '30', '40', '50', '60', '90']
l_gender = ['man', 'woman']
l_power = ['invisibility', 'read in the thoughts', 'turning lead into gold', 'immortality', 'telepathy', 'teleport', 'flight'] 

# gpt-3에게 위의 3가지를 포함한 아래 질문으로 아주 상세한 표현으로 대답을 유도
# 이 대답의 형태를 나중에 fine-tuning된 모델의 대답 형태로 사용할 것임
# 즉, prompt에 age, gender, power의 형태로 질문하면 위에서 얻은 대답 형태로 답을 해 줄 것임
f_prompt = "Imagine a complete and detailed description of a {age}-year-old {gender} fictional character who has the superpower of {power}. Write out the entire description in a maximum of 100 words in great detail:"
f_sub_prompt = "{age}, {gender}, {power}"

# 대답의 다양성(?)을 얻기 위해 각 입력별로 3번의 질문을 gpt-3에게 요청
df = pd.DataFrame()
for age in l_age:
 for gender in l_gender:
  for power in l_power:
   for i in range(3): ## 3 times each
    prompt = f_prompt.format(age=age, gender=gender, power=power)
    sub_prompt = f_sub_prompt.format(age=age, gender=gender, power=power)
    print(sub_prompt)

    # 실제 gpt-3에게 요청하는 부분. gpt-3는 4개의 모델이 있는데 davinci가 가장 큼
    # temperature=1 은 자유도를 제일 높게, 0이면 자유도를 줄이고 주어진 형태로만
    # 최대 단어의 수는 500개로
    response = openai.Completion.create(
     model="text-davinci-003",
     prompt=prompt,
     temperature=1,
     max_tokens=500,
     top_p=1,
     frequency_penalty=0,
     presence_penalty=0
    )
    
    finish_reason = response['choices'][0]['finish_reason']
    response_txt = response['choices'][0]['text']
    
    # 결과 값을 저장. 우리가 최종적으로 얻는 것은 out_openai_completion.csv
    new_row = {
      'age':age, 
      'gender':gender, 
      'power':power, 
      'prompt':prompt, 
      'sub_prompt':sub_prompt, 
      'response_txt':response_txt, 
      'finish_reason':finish_reason}
    new_row = pd.DataFrame([new_row])
    df = pd.concat([df, new_row], axis=0, ignore_index=True)

df.to_csv("out_openai_completion.csv")

 

위의 최종 결과물(out_openai_completion.csv)은 아래와 같다.

 

,age,gender,power,prompt,sub_prompt,response_txt,finish_reason
0,18,man,invisibility,Imagine a complete and detailed description of a 18-year-old man 
fictional character who has the superpower of invisibility. Write out the entire 
description in a maximum of 100 words in great detail:,"18, man, invisibility","

Aiden is a 18-year-old man with an athletic build and sharp facial features. He has a 
mop of neatly combed brown hair that frames his face and a deep tan to contrast his 
grey eyes. He keeps a stern face but with a pleasantly subtle smile that gives away 
his good natured personality. He has the superpower of invisibility, enabling him to 
stay hidden in the shadows and move undetected through any area. This allows him to 
practice his favorite hobby, which is exploring abandoned places, without being 
noticed. But his greatest strength is how he can use his ability to observe situations 
and allow his mind to pick up the smallest details undetected. He has a strong sense 
of justice and uses his power to fight crime and protect the innocent.",stop

 

 

2) Fine-Tuning 하기

 

위의 내용이 다 필요한 것은 아니므로 sub_prompt와 response_txt만 가져오고, 이 데이터로 gpt-3에게 학습 데이터 준비를 하라고 지시한다. 그리고, fine-tuning하라고 명령하면 끝이다.

 

import pandas as pd
import openai
import subprocess

df = pd.read_csv("out_openai_completion.csv")

# sub_prompt와 response_txt만 있으면 된다.
prepared_data = df.loc[:,['sub_prompt','response_txt']]
prepared_data.rename(columns={'sub_prompt':'prompt', 'response_txt':'completion'}, inplace=True)
prepared_data.to_csv('prepared_data.csv',index=False)


# gpt-3에게 위 데이터로 fine-tuning 데이터를 만들라고 지시하고
## prepared_data.csv --> prepared_data_prepared.json
subprocess.run('openai tools fine_tunes.prepare_data --file prepared_data.csv --quiet'.split())

# Fine-Tuning을 시작한다. 만들어지는 모델은 'SuperHero'라고 명명하자
## Start fine-tuning
subprocess.run('openai api fine_tunes.create --training_file prepared_data_prepared.jsonl 
				--model davinci --suffix "SuperHero"'.split())

 

위를 수행하면 아래와 같은 메시지와 함께 파인튜닝이 성공한다. 아래 돈 든다는 메시지 나오는데, 현재는 free-trial 임으로 실제 청구되지는 않는다. Credit Card 정보 입력한 적이 없으니..

 

Upload progress: 100%|███████████████████████| 206k/206k [00:00<00:00, 115Mit/s]
Uploaded file from prepared_data_prepared.jsonl: file-VvqQwitcyaATPQJ4npkiIYvv
Created fine-tune: ft-ikCyeKbsyEuOUATSnKIk0YP2
Streaming events until fine-tuning is complete...

(Ctrl-C will interrupt the stream, but not cancel the fine-tune)
[2023-02-19 20:22:58] Created fine-tune: ft-ikCyeKbsyEuOUATSnKIk0YP2

[2023-02-19 20:26:12] Fine-tune costs $5.20
[2023-02-19 20:26:12] Fine-tune enqueued. Queue number: 2
[2023-02-19 20:26:13] Fine-tune is in the queue. Queue number: 0
[2023-02-19 20:26:13] Fine-tune is in the queue. Queue number: 0
[2023-02-19 20:26:54] Fine-tune started
[2023-02-19 20:30:49] Completed epoch 1/4
[2023-02-19 20:32:32] Completed epoch 2/4
[2023-02-19 20:34:14] Completed epoch 3/4
[2023-02-19 20:35:55] Completed epoch 4/4
[2023-02-19 20:36:34] Uploaded model: davinci:ft-personal:superhero-2023-02-19-11-36-34
[2023-02-19 20:36:36] Uploaded result file: file-lXEgKfyA5CVORmRz2LBd1xLZ
[2023-02-19 20:36:36] Fine-tune succeeded

Job complete! Status: succeeded 🎉
Try out your fine-tuned model:

openai api completions.create -m davinci:ft-personal:superhero-2023-02-19-11-36-34 -p <YOUR_PROMPT>

 

 

3) 파인튜닝된 모델로 테스트하기

 

가장 쉬운 방법은 OpenAI가 제공하는 Play Ground(https://platform.openai.com/playground)를 사용하는 것이다.

 

Model 선택에서 'FINE-TUNES' 항목의 생성된 'superhero' 모델을 선택해주고, stop sequence 항목을 END라고 입력한다.

 

 

그리고 위와 같이, Prompt(50, Man, can eat a lot)를 주면('->'까지 적어준다) 아래의 결과가 수행된다. 참고로, 우리가 학습한 prompt에서 50, Man은 포함하고 있었지만, 능력(power)에 'can eat a lot'은 없었다. 두번째는 형식은 그대로 둔 채 입력 값만 모두 임의의 값으로 바꾸었다.. 세번째는 prompt의 순서를 바꾸고, 네번째는 prompt 입력도 2개만 주었다.

 

 

 

첫번째, 두번째는 어느 정도 우리가 학습한 형태로 결과를 출력해 주고 있지만, 세번째, 네번째는 Prompt Engineering이 되어 있지 않은 형식이기 때문에 'davinci' 모델에서 학습된 형태로 결과를 보여준다.

 

마지막으로 tuning된 모델이 아닌 'davinci' 모델에서 prompt를 실행해보자. 아래와 같이 우리가 학습한 형태로 결과가 출력되지 않음을 확인할 수 있다.



댓글