LLaMa2 파인튜닝(finetuning) 하기

AI|2024. 2. 3. 13:46

아래 글을 먼저 보세요.

CUDA를 이용한 LlaMa2사용하기

본 블로그에서 alpaca-lora를 가진고 finetuing하는 방법을 공개한적이 있습니다. alpaca-lora는 Llama를 기반으로 LoRa를 지원해서 NVidia 4090에서도 Llama model를 실행할 수 있었습니다. Meta에서 지난 7월에 공개한 LlaMa2를 가지고 finetuing하는 방법을 소개하겠습니다.

먼저 파인튜닝(finetuning)은 뭘까?

GPT나 LlaMa와 같은 대규모 언어 모델(Larget Language Model)은 대량의 텍스트 데이터에서 단어 사이 통계적 연관성을 학습해서 사전 훈련된 머신 러닝 모델로 트랜스포머 아키텍처로 구현되어 있습니다. LLM은 기본적으로 어떤 단어나 문장을 주었을 때, 앞으로 나올 문장을 확률에 따라서 그냥 생성하는 기능만을 갖고 있습니다. 하지만 이 과정을 통해 광범위한 언어를 이해하고 생성하는 능력을 갖게 되고, 다양한 주제와 문맥에 대한 지식을 학습합니다.

아래 처럼 Llama-cpp를 이용해서 codellama 모델을 실행해보면 이래와 같은 int multiply( 이후 함수를 자동으로 작성해줍니다.

llama.cpp$ ./main -m ./models/CodeLlama-7b/ggml-model-f16.gguf -p "int multiply("

int multiply(int n1, int n2) {
        if (n1 == 0 || n2 == 0) { // base case
            return 0;
        } else {
            return add(multiply(n1, n2 - 1), n1);
        }
    }


    public static int multiply2(int n1, int n2) {
        if (n1 == 0 || n2 == 0) { // base case
            return 0;
        } else {
            int result = n1 + multiply2(n1, n2 - 1); // 折半计算
            return result;
        }
    }

    public static void main(String[] args) {
        System.out.println("0 * 1 = " + multiply(0, 1));
        System.out.println("1 * 2 = " + multiply(1, 2));
        System.out.println("1 * 3 = " + multiply(1, 3));
        System.out.println("1 * 4 = " + multiply(1, 4));
        System.out.println("2 * 3 = " + multiply(2, 3));
        System.out.println("2 * 5 = " + multiply(2, 5));
        System.out.println("3 * 10 = " + multiply(3, 10));
        System.out.println("3 * 4 = " + multiply(3, 4));
        System.out.println("4 * 8 = " + multiply(4, 8));
        System.out.println("5 * 6 = " + multiply(5, 6));
        System.out. [end of text]

출처: 열린 소프트웨어 이야기:티스토리

그렇기 때문에 특정 작업이나 도메인에 최적해하려면 파인튜닝(finetuing)하는 작업이 필요합니다. 자, 그러면 LLama2를 이용해서 간단하게 finetuning을 해보겠습니다. 첫번째 글에서 소개된 llama-recipes 저장소를 clone해야합니다.

이 글에서는 alpaca_dataset을 finetunig에 사용하겠습니다. alpaca_dataset은 OpenAI의 text-davinci-003모델에서 생성한 52K의 instruction-response 셋을 갖고 있습니다. 바로 이 파일인 alpaca_data.json을 다운로드 받아서 src/llama_recipes/dataset에 복사합니다. llama-recipe에는 이름에 걸맞게 alapca_data를 LlaMa2에 finetunig하도록 dataset 형식을 바꿔주는 python 코드(src/llama_recipes/datasets/alpaca_dataset.py)가 있기 때문에 별다른 코딩 없이 바로 finetuning을 할 수 있습니다.
아래와 같이 Llama-2-7b-hf 모델로 finetuning을 해보겠습니다.

$ cd ~/git/llama-recipes
$ cp ~/Downloads/alpaca_data.json ~/git/llama-recipes/src/llama_recipes/datasets
$ python -m llama_recipes.finetuning  --use_peft --peft_method lora --quantization --batch_size_training=2 --model_name ../models/Llama-2-7b-hf/ --dataset alpaca_dataset  --output_dir outputs/7b
Training Epoch: 1/3, step 1421/1422 completed (loss: 0.09633808583021164): 100%|███████| 1422/1422 [2:53:14<00:00,  7.31s/it]
Max CUDA memory allocated was 15 GB
Max CUDA memory reserved was 18 GB
Peak active CUDA memory was 15 GB
Cuda Malloc retires : 0
CPU Total Peak Memory consumed during the train (max): 2 GB
evaluating Epoch: 100%|████████████████████████████████████████████████████████████████████████| 9/9 [00:07<00:00,  1.17it/s]
 eval_ppl=tensor(2.3844, device='cuda:0') eval_epoch_loss=tensor(0.8689, device='cuda:0')
we are about to save the PEFT modules
PEFT modules are saved in outputs/7b directory
best eval loss on epoch 1 is 0.8689326643943787
Epoch 1: train_perplexity=2.4760, train_epoch_loss=0.9066, epoch time 10394.590659613s
Training Epoch: 2/3, step 1421/1422 completed (loss: 0.07578233629465103): 100%|███████| 1422/1422 [2:53:12<00:00,  7.31s/it]
Max CUDA memory allocated was 15 GB
Max CUDA memory reserved was 18 GB
Peak active CUDA memory was 15 GB
Cuda Malloc retires : 0
CPU Total Peak Memory consumed during the train (max): 2 GB
evaluating Epoch: 100%|████████████████████████████████████████████████████████████████████████| 9/9 [00:07<00:00,  1.17it/s]
 eval_ppl=tensor(2.3683, device='cuda:0') eval_epoch_loss=tensor(0.8622, device='cuda:0')
we are about to save the PEFT modules
PEFT modules are saved in outputs/7b directory
best eval loss on epoch 2 is 0.8621865510940552
Epoch 2: train_perplexity=2.4086, train_epoch_loss=0.8791, epoch time 10392.544478912998s
Training Epoch: 3/3, step 1421/1422 completed (loss: 0.06521736830472946): 100%|███████| 1422/1422 [2:53:02<00:00,  7.30s/it]
Max CUDA memory allocated was 15 GB
Max CUDA memory reserved was 18 GB
Peak active CUDA memory was 15 GB
Cuda Malloc retires : 0
CPU Total Peak Memory consumed during the train (max): 2 GB
evaluating Epoch: 100%|████████████████████████████████████████████████████████████████████████| 9/9 [00:07<00:00,  1.17it/s]
 eval_ppl=tensor(2.3635, device='cuda:0') eval_epoch_loss=tensor(0.8602, device='cuda:0')
we are about to save the PEFT modules
PEFT modules are saved in outputs/7b directory
best eval loss on epoch 3 is 0.8601586818695068
Epoch 3: train_perplexity=2.3646, train_epoch_loss=0.8606, epoch time 10382.494863348998s
Key: avg_train_prep, Value: 2.4164153734842935
Key: avg_train_loss, Value: 0.8821062048276266
Key: avg_eval_prep, Value: 2.3720779418945312
Key: avg_eval_loss, Value: 0.8637592991193136
Key: avg_epoch_time, Value: 10389.876667291666
Key: avg_checkpoint_time, Value: 0.027448729337872162

위와 같이 3의 epoch를 거치면, 모든 데이터를 3번 학습하면 끝납니다. 이렇게 finetuning할 때, 각 epoch마다 모델은 데이터 세트에 있는 패턴과 특징을 더 잘 학습하고, 이를 통해 예측의 정확도를 높이려고 시도합니다. Epoch 수를 적절하게 설정하는 것은 과적합(overfitting)이나 미적합(underfitting)을 방지하는 데 중요합니다. 너무 많은 epoch는 모델이 트레이닝 데이터에 과적합되어 새로운 데이터에 대한 일반화 성능이 떨어질 수 있으며, 너무 적은 epoch는 모델이 데이터의 중요한 특성을 충분히 학습하지 못하게 만들 수 있습니다. 참고로, Llama receipt에서는 기본적으로 epoch값이 3번으로 정해져있습니다.

Nvidia 4090 GPU기준으로 finetuing하는데 약 5시간 정도 걸리는 것 같습니다.

Inference

여러분이 직접 fintuning한 model로 inference를 해보겠습니다. 먼저 아래와 같이 chatgpt.txt를 작성합니다.

Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.

### Instruction:
Classify the following into animals, plants, and minerals

### Input:
Oak tree, copper ore, elephant

### Response:

이렇게 한 후, 다음 괕이 inference 명령을 실행해봅니다.

cat chatgpt.txt |  python3 examples/inference.py --model_name ../models/Llama-2-7b-hf --peft_model outputs/7b --max_new_tokens 580  --quantization true

아래와 같은 결과가 나오면 성공입니다.

Animals: Elephant
Plants: Oak tree
Minerals: Copper ore

댓글()