본문 바로가기

AI

HuggingFace Autotrain - 단 한 줄의 코드로 LLM 파인튜닝하기

  🤗 AutoTrain

Huggingface의 AutoTrain은 자연어 처리(NLP) 작업, 컴퓨터 비전(CV) 작업, 음성 작업, 표 형식 작업 등을 위한 최첨단 모델을 훈련하기 위한 코드가 필요 없는 툴입니다.

코드 없이 UI에서 스페이스를 생성하여 사용할수도 있고, 개발자는 autotrain-advanced 패키지를 설치하고 파이썬 API를 사용하여 최소한의 코드로 학습을 진행할 수 있습니다.

이번 글에서는 제가 autotrain으로 학습 가능한 다양한 태스크 중 LLM Finetuning을 수행한 과정에 대해 공유하고자 합니다.

 

  LLM Finetuning

AutoTrain을 사용하면 자체 데이터에서 대규모 언어 모델(LLM)을 쉽게 미세 조정할 수 있습니다.

AutoTrain은 아직 CLM의 파인튜닝만 지원하고 있고, MLM 파인튜닝은 아직 개발중인 것 같습니다.

  • Causal Language Modeling (CLM)
  • Masked Language Modeling (MLM) [곧 출시 예정]

 

  Data Preparation

LLM 미세 조정은 CSV 형식의 데이터를 허용합니다.

 

Supervised Fine-Tuning (SFT) / Generic Trainer

기본 모델을 선택할 때에는 하고자 하는 태스크가 무엇인지를 생각해야합니다. GPT, Llama2 또는 T5와 같은 다양한 모델이 생성되는 방식에 따라 다릅니다. Llama2 모델은 instruction 기반 작업에 능숙합니다. GPT는 다음 토큰을 예측하는 텍스트 생성에 좋습니다. 따라서 이를 기반으로 필요한 작업에 따라 기본 모델을 선택해야합니다.

그 다음 학습에 맞게 데이터셋을 준비해야합니다. 프롬프트의 형식은 human / bot의 대화 쌍으로 이루어져있으면 됩니다. 좀 더 모델이 이해하기 쉬운 형태로 주입하려면 ### 세 개의 해시를 사용하는 것이 좋다고 합니다.

1. 알파카 형식

https://huggingface.co/datasets/royboy0416/ko-alpaca

 

알파카 형식에는 기본적으로 instruction , input , output 이 있습니다. 입력(input)은 선택사항이며 제공할 수도 있고 제공하지 않을 수도 있습니다.

우리가 파인튜닝 시에 제공하는 것은 세 가지가 모두 합쳐진 프롬프트입니다. 각 형식을 구분하는 것은 앞서 말한대로 ### 세 개의 해시이며, 이 해시는 모델이 각 작업을 이해하도록 특별히 설계된 special token입니다.

그리고 해당 프롬프트의 칼럼명을 제공하면 됩니다.

 

2. 과나코 형식

https://huggingface.co/datasets/timdettmers/openassistant-guanaco

공식 문서에서 예제로 제공한 데이터 형식입니다. Human → Assistant → Human의 쌍으로 이루어져있습니다.

 

  Parameters

아래 명령을 사용하면 사용 가능한 모든 옵션을 얻을 수 있고, 각 parameter argumets의 default값은 여기에서 확인할 수 있습니다.

!autotrain --help

 

train 주요 파라미터

파인튜닝을 수행할 경우는 --train 으로 지정하고 추론만 할 경우 --inference 로 지정합니다.

--train 으로 설정한 경우 필수인자 및 선택 인자는 아래와 같습니다.

각 인자의 default 설정은 여기에서 확인 가능합니다.

[required argument]

  • --model : base 모델 경로
  • --project-name : 학습의 고유한 프로젝트 이름을 할당
    • 향후 해당 프로젝트명으로 결과 폴더가 생성됨
  • --data-path : 훈련 데이터의 위치 지정
    • 허깅페이스의 저장소이거나 로컬 데이터의 경로
    • 위에서 언급했던 것처럼 데이터 형식은 text 컬럼 명을 가진 csv 파일이어야하고, text 컬럼은 alpaka 또는 guanako 형식의 템플릿을 따르는 프롬프트면 좋습니다.

[설정하지 않을 경우 default로 지정되는 argument]

  • --lr: 학습률 지정 (default: 3e-5)
  • --batch-size: 학습시 사용할 배치 사이즈 (default: 2)
  • –-epochs: 학습할 에폭 수 (default: 1)
  • –-block-size: 훈련 중 처리를 위해 데이터를 분할하는 블록 크기를 설정 (default: -1)
  • –-warmup-ratio: 훈련 시작 시 학습률을 점차 높여 안정성을 높이는 워밍업 비율을 설정 (default: 0.1)
  • –-weight-decay: 가중치 감쇠 (default: 0.0)
    • loss function에 weight가 커질 경우에 대한 패널티 부여하는 방법
  • –-gradient-accumulation: gradient를 누적할 step 수 (default: 1)
    • oom 방지를 위해 그래디언트를 누적시킨 후 한번에 업데이트하는 방법
  • –-mixed-precision: 혼합 정밀도 훈련을 활성화하여 계산 효율성을 향상 (default: None)
    • fp16, bf16, or None

 

PEFT 사용을 위한 파라미터

peft를 수행할 경우 –-peft 로 지정하고 아래 인자를 설정합니다.

  • –-quantization: 모델 크기를 줄이고 추론 속도를 향상시키는 기술인 양자화를 활성화 (default: None)
    • int4, int8 or None
  • –-target-modules: 양자화를 위한 특정 대상 모듈을 식별합니다. 이 경우 q_proj 및 v_proj에 중점을 둡니다. (default: all-linear)
  • –-lora-r: LoRA가 훈련 중에 사용할 수 있는 훈련 가능한 매개변수의 양과 관련 (default: 16)
    • 4, 8과 같이 낮은 값은 모델에 새로운 정보나 높은 개념을 가르치려는 것이 아니라 기본적인 출력 형식을 지정하는 스타일을 알려주는 것
    • 이 값이 증가하면 업데이트해야 하는 추가 매개변수의 수가 증가합니다.
    • 직관적으로 r이 낮을수록 훈련 프로세스가 더 빠르고 계산 집약적이지 않을 수 있지만, 이렇게 생성된 모델의 품질에 영향을 미칠 수 있습니다.
    • 그러나 r을 특정 값 이상으로 높여도 모델 출력의 품질이 눈에 띄게 향상되지 않을 수 있습니다.
  • –-lora-alpha: LoRA의 스케일링 매개변수 (default: 32)
    • r과 alpha가 같을 경우 가중치를 1.0으로 조정
    • alpha가 2*r 이 될 경우 새로 학습된 가중치를 모델의 가중치보다 “더 크게” 만들기 위한 것
  • –-lora-dropout: LoRA의 드롭아웃 비율을 지정하여 과적합에 대한 네트워크의 저항에 영향을 줍니다. (default: 0.05)

주어진 설정이 실제 코드에서 적용되는 부분은 아래와 같습니다. (원본코드)

logger.info("loading model...")
if config.peft:
        if config.quantization == "int4":
            bnb_config = BitsAndBytesConfig(
                load_in_4bit=True,
                bnb_4bit_quant_type="nf4",
                bnb_4bit_compute_dtype=torch.float16,
                bnb_4bit_use_double_quant=False,
            )
        elif config.quantization == "int8":
            bnb_config = BitsAndBytesConfig(load_in_8bit=True)
        else:
            bnb_config = None

...
if config.peft:
        logger.info("preparing peft model...")
        if config.quantization is not None:
            model = prepare_model_for_kbit_training(
                model,
                use_gradient_checkpointing=not config.disable_gradient_checkpointing,
            )
         ...
        peft_config = LoraConfig(
                r=config.lora_r,
                lora_alpha=config.lora_alpha,
                lora_dropout=config.lora_dropout,
                bias="none",
                task_type="CAUSAL_LM",
                target_modules=utils.get_target_modules(config),
            )
        model = get_peft_model(model, peft_config)

 

  적용 사례

  Task: 브랜드/논브랜드 키워드 분류

저는 현재 SEO를 위하여 검색어 내의 사용자의 의도를 분석하는 프로젝트를 진행하고 있습니다. 그 과정에서 검색자가 키워드를 검색할 때 특정 브랜드를 생각하고 검색한 의도가 있는지를 확인하는 브랜드/논브랜드 분류 프로세스가 필요했고, 단순히 검색어만 봐서는 해당 키워드가 브랜드를 포함하고 있는지 확인이 어려운 경우가 있습니다.

그러나 검색결과를 확인하면 브랜드가 명시되어있는 경우가 많으므로 해당 정보를 참고하면 브랜드/논브랜드 분류 및 어떤 브랜드인지도 특정하는 것이 가능해집니다.

🔎 논브랜드 키워드 예: “seo 최적화”

 

🔎 브랜드 키워드 예: “mdz-27-aa”

  • 검색결과 확인 시 “샤오미” 브랜드의 제품인 것을 확인할 수 있음

 

  학습 및 평가 데이터 셋 생성

Train / Test

  • 학습셋
    • 31개의 도메인에 대해 약 100개씩 총 9443 개의 데이터 생성
  • 평가셋
    • 13개의 도메인에 대해 약 100개씩 총 1368 개의 데이터 생성

 

 

프롬프트 구성

  • keyword에 대해 검색결과 콘텐츠 수집 후 top1 결과에 대해 사이트명, 타이틀, 스니펫 추출
  • 키워드/ 브랜드와 검색결과 텍스트로 프롬프트 생성

### Instruction:
검색어를 보고 사용자가 제품의 특정 브랜드를 생각하고 검색한 의도가 없다면 '없음'이라고 말합니다. 그게 아니라면 검색결과로부터 브랜드를 추출합니다. 반드시 검색어를 먼저 보도록 합니다.

검색어:
mdz-27-aa

검색결과:
```
# sitename or domain link
케이에이치프라자

# title
[국내정품]샤오미 TV 스틱 4K MDZ-27-AA 유튜브 넷플릭스 ...

# snippet
기본 정보. 상품명, [국내정품]샤오미 TV 스틱 4K MDZ-27-AA 유튜브 넷플릭스 미라캐스트 크롬캐스트 안드로이드 셋탑 리모컨포함(대량견적/세금계산서가능) 정발 ...

```
### Response:
샤오미

 

  Train

테스트 대상이 될 base 모델들은 아래와 같이 추렸습니다.

gemma

solar

Llama2

 

4bit 양자화된 base모델로 lora를 적용시켜 학습하도록 파라미터는 아래와 같이 project-name과 model만 바꾸고 전체 일괄 적용하였습니다.

!autotrain llm --train \
    --project-name "hyjin-solar-7b-instruct-finetune" \
    --model "upstage/SOLAR-10.7B-Instruct-v1.0" \
    --data-path "/data1/share/notebooks/hy.jin-notebooks/brand/train" \
    --text-column "text" \
    --peft \
    --lr 2e-4 \
    --train-batch-size 16 \
    --gradient-accumulation 4 \
    --epochs 5 \
    --lora_r 16 \
    --lora-alpha 16 \
    --lora-dropout 0.05 \
    --block-size 256 \
    --warmup-ratio 0.1 \
    --weight-decay 0.01 \
    --mixed-precision "fp16" \
    --quantization "int4" \
    --model_max_length 1024 \
    --trainer sft 

tesla v100 pcie 32gb 2장으로 solar 10.7B 모델은 약 5시간정도 걸리네요.

Generating train split: 9443 examples [00:00, 13090.07 examples/s]
🚀 INFO   | 2024-03-14 15:59:07 | __main__:process_input_data:109 - Train data: Dataset({
    features: ['keyword', 'input', 'output', 'text'],
    num_rows: 9443
})
🚀 INFO   | 2024-03-14 15:59:07 | __main__:process_input_data:110 - Valid data: None
`low_cpu_mem_usage` was None, now set to True since model is quantized.
`low_cpu_mem_usage` was None, now set to True since model is quantized.
Loading checkpoint shards: 100%|██████████████████| 5/5 [01:51<00:00, 22.36s/it]
Loading checkpoint shards: 100%|██████████████████| 5/5 [01:51<00:00, 22.32s/it]
🚀 INFO   | 2024-03-14 16:01:01 | __main__:train:321 - Using block size 256
🚀 INFO   | 2024-03-14 16:01:01 | __main__:train:383 - creating trainer
{'loss': 1.5877, 'grad_norm': 0.37086018919944763, 'learning_rate': 0.00019271356783919598, 'epoch': 0.66}
 20%|███████▍                             | 177/885 [1:01:40<4:06:45, 20.91s/it]
{'loss': 1.0304, 'grad_norm': 0.3623475134372711, 'learning_rate': 0.00016306532663316583, 'epoch': 1.33}
{'loss': 0.9616, 'grad_norm': 0.3897276520729065, 'learning_rate': 0.0001334170854271357, 'epoch': 1.99}
 40%|██████████████▊                      | 355/885 [2:03:40<3:04:26, 20.88s/it]
{'loss': 0.9164, 'grad_norm': 0.39801955223083496, 'learning_rate': 0.00010376884422110554, 'epoch': 2.66}
 60%|██████████████████████▎              | 533/885 [3:05:39<2:02:38, 20.91s/it]
{'loss': 0.8912, 'grad_norm': 0.41495198011398315, 'learning_rate': 7.412060301507539e-05, 'epoch': 3.32}
{'loss': 0.8688, 'grad_norm': 0.4467140734195709, 'learning_rate': 4.4472361809045225e-05, 'epoch': 3.98}
 80%|█████████████████████████████▋       | 711/885 [4:07:43<1:00:33, 20.88s/it]
{'loss': 0.8513, 'grad_norm': 0.43965277075767517, 'learning_rate': 1.4824120603015077e-05, 'epoch': 4.65}
{'train_runtime': 18503.6103, 'train_samples_per_second': 6.143, 'train_steps_per_second': 0.048, 'train_loss': 1.003699833929202, 'epoch': 4.98}
100%|███████████████████████████████████████| 885/885 [5:08:23<00:00, 20.91s/it]
🚀 INFO   | 2024-03-14 21:09:31 | __main__:train:521 - Finished training, saving model...

 

  Evaluation

위에서 생성했던 테스트 데이터셋으로 각 모델들의 추론결과에 대해 accuracy를 측정한 결과 upstage/SOLAR-10.7B-Instruct-v1.0 모델이 가장 성능이 좋았습니다.

검색결과 상위 1개로 학습한 결과

모델이 틀린 데이터를 살펴봤을 때 검색결과의 1번째 텍스트에 브랜드명이 없는 케이스가 많았습니다. 이런 경우는사람이 봐도 브랜드를 식별하지 못합니다.

틀린 케이스:

  • 키워드: 미니쿠듀얼 가격
  • 정답: 아이휠
  • 예측: 미니쿠
### Instruction:
검색어를 보고 사용자가 제품의 특정 브랜드를 생각하고 검색한 의도가 없다면 '없음'이라고 말합니다. 그게 아니라면 검색결과로부터 브랜드를 추출합니다. 반드시 검색어를 먼저 보도록 합니다.

검색어:
미니쿠듀얼 가격

검색결과:
```
# sitename or domain link
ipick.kr

# title
전동/전기스쿠터 미니쿠 듀얼.

# snippet
None
```

### Response:

 

그러나 해당 검색어를 검색결과 3개까지 본다면 3번째 결과에서 브랜드가 "아이휠"이라는 정보가 있으므로 모델이 추론가능해집니다.

### Instruction:
검색어를 보고 사용자가 제품의 특정 브랜드를 생각하고 검색한 의도가 없다면 '없음'이라고 말합니다. 그게 아니라면 검색결과로부터 브랜드를 추출합니다. 반드시 검색어를 먼저 보도록 합니다.

검색어:
미니쿠듀얼 가격

검색결과 (연관성 순):
1.
```
# sitename or domain link
ipick.kr

# title
전동/전기스쿠터 미니쿠 듀얼.

# snippet
None
```

2.
```
# sitename or domain link
번개장터

# title
전동스쿠터.

# snippet
아이비 싱글/듀얼 · 아이비 싱글/듀얼. 1,680,000원 ; 전동/전기 스쿠터 미니쿠 듀얼 울트라 · 전동/전기 스쿠터 미니쿠 듀얼 울트라. 1,450,000원 ; 강아지 전동스쿠터 미니비.
```

3.
```
# sitename or domain link
라이드매거진

# title
(세계최초 듀얼 전동스쿠터) 아이휠 미니쿠 듀얼 (새상품).

# snippet
(세계최초 듀얼 전동스쿠터) 아이휠 미니쿠 듀얼 (새상품) 가격: 1650000원 번호판 보험 의무 없는 전동스쿠터 중에 힘이 제일 끝판왕 모델입니다:) 배터리는 하나당.
```
    
### Response:

 

검색결과 상위 3개까지 사용하여 학습한 결과

따라서 위에서 가장 성능이 좋은 upstage/SOLAR-10.7B-Instruct-v1.0 모델로 서프 상위 3개까지 input에 포함하여 학습하였습니다.

그 결과 정확도가 76.32% → 79.39% 로 향상되었습니다. 정확도 계산시 텍스트의 완전일치만 평가한 것이기 때문에 프리고 다이렉트 != 프리고 , kb국민카드 != kb카드 nh농협카드 != nh투자증권 와 같이 거의 정답으로 볼 수 있는 케이스도 평가에 반영한다면 성능은 더 좋게 평가될 것으로 보입니다.

 

 

  Conclusion

대규모 언어 모델을 미세 조정하는 것은 특히 필요한 특정 요구 사항이 있는 경우 비즈니스 프로세스에 도움이 됩니다. 허깅페이스 오토트레인을 사용하면 학습 프로세스를 향상시키고 사전 학습된 모델을 사용하여 모델을 쉽게 미세 조정할 수 있습니다.