Conversational AI / NLP

맞춤형 언어 모델을 생성하는 방법

Reading Time: 8 minutes

생성형 AI는 지난 몇 년 동안 대중의 관심과 상상력을 사로잡았습니다. 이러한 생성형 모델은 주어진 자연어 프롬프트에서 잘 표현된 동화부터 제품 프로토타입 시각화에 이르기까지 인간 수준의 결과를 생성할 수 있습니다.

이러한 혁명의 중심에는 대규모 언어 모델(LLM)이 있습니다. LLM은 인간의 지식을 코드화하는 범용 언어 이해기로, 수많은 자연어 및 프로그래밍 언어 이해 작업에 즉시 적용할 수 있습니다. 여기에는 요약, 번역, 질문 답변, 코드 주석 달기 및 완성 등이 포함됩니다.

단일 기초 언어 모델로 여러 작업을 완료할 수 있는 능력은 완전히 새로운 AI 소프트웨어 패러다임을 열어주며, 단일 기초 모델을 사용하여 회사 내 모든 부서에서 여러 다운스트림 언어 작업을 처리할 수 있습니다. 이를 통해 AI 소프트웨어 개발, 배포 및 유지보수 비용이 간소화되고 절감됩니다.

맞춤형 대규모 언어 모델 생성 소개

강력하고 잠재력이 있지만, 특정 사용 사례에서 제로 샷(Zero-shot) 또는 소수 샷(Few-shot) 학습을 통한 LLM의 기본 성능과는 여전히 격차가 있습니다. 특히 제로 샷 학습의 성능은 낮고 신뢰할 수 없다는 단점이 있습니다. 반면에 소수 샷 학습은 최적의 이산 프롬프트를 찾는 데 의존하는데, 이는 쉽지 않은 과정입니다.

GPT도 이해한다에 설명된 것처럼, 다운스트림 문제를 해결하는 데 사용되는 프롬프트 템플릿의 사소한 변형이 최종 정확도에 큰 영향을 미칠 수 있습니다. 또한, 소수 샷 추론은 프롬프트가 더 크기 때문에 비용도 더 많이 듭니다.

이 문제를 해결하기 위해 매개변수를 효율적으로 미세 조정하는 기법이 제안되었습니다. 프롬프트 학습은 이러한 기법 중 하나로, 요청에 가상 프롬프트 토큰을 추가합니다. 이러한 가상 토큰은 학습 가능한 파라미터로 표준 최적화 방법을 사용하여 최적화할 수 있는 반면, LLM 파라미터는 고정되어 있습니다.

이 게시물에서는 기초 모델을 훈련, 커스터마이징 및 배포하기 위한 범용 프레임워크인 NVIDIA NeMo 프레임워크를 사용하여 LLM을 커스터마이징하는 프로세스를 안내합니다.

NVIDIA NeMo를 사용한 프롬프트 학습(Prompt learning)

NeMo의 맥락에서 프롬프트 학습은 아래에 자세히 설명된 대로 두 가지 매개변수 효율적인 미세 조정 기술을 의미합니다. 자세한 내용은 비영어 다운스트림 작업 해결을 위한 P-튜닝 적용을 참조하세요.

  • 프롬프트 튜닝에서 소프트 프롬프트 임베딩은 2D 매트릭스로 초기화됩니다. 각 작업에는 연결된 고유한 2D 임베딩 매트릭스가 있습니다. 태스크(Task)는 훈련 또는 추론 중에 파라미터를 공유하지 않습니다. 모든 LLM 파라미터는 고정되며 각 태스크의 임베딩 파라미터만 훈련 중에 업데이트됩니다. NeMo 프롬프트 튜닝 구현은 매개변수 효율적 프롬프트 튜닝을 위한 스케일의 힘을 기반으로 합니다.
  • p-튜닝에서는 가상 토큰 임베딩을 예측하기 위해 LSTM 모델 또는 “프롬프트 인코더”가 사용됩니다. LSTM 파라미터는 p-튜닝을 시작할 때 무작위로 초기화됩니다. 모든 LLM 파라미터는 고정되어 있으며, 각 트레이닝 단계에서 LSTM 가중치만 업데이트됩니다. LSTM 파라미터는 동시에 p-튜닝되는 모든 작업 간에 공유되지만, LSTM 모델은 각 작업에 대해 고유한 가상 토큰 임베딩을 출력합니다. NeMo p-튜닝 구현은 GPT도 이해한다를 기반으로 합니다.

이 예제의 신속한 학습은 NeMo 생태계의 두 가지 오픈 소스 구성 요소, 즉 NeMo OSS 툴킷과 공개 NeMo 모델을 사용합니다.

소규모 GPT-3 345M 파라미터 모델에 대한 프롬프트 학습 프로세스는 GitHub의 NeMo 멀티태스크 프롬프트 및 P-튜닝 튜토리얼에 자세히 설명되어 있습니다. 이 튜토리얼에서는 데이터 다운로드 및 전처리, 모델 다운로드, 프롬프트 학습 모델 훈련, 세 가지 애플리케이션에 대한 추론 등 프롬프트 학습의 엔드투엔드 프로세스를 보여 줍니다.

아래 섹션에서는 먼저 노트북을 살펴보면서 주요 개념을 요약합니다. 그런 다음 이 노트북을 확장하여 더 큰 NeMo 모델에 대한 신속한 학습을 수행합니다.

선행 조건

NeMo Docker 컨테이너를 통해 NeMo를 경험할 수 있습니다. 이 컨테이너는 NeMo를 실험할 수 있는 자급자족적이고 재현 가능한 환경을 제공합니다. NeMo 멀티태스크 프롬프트 및 P-튜닝 튜토리얼은 NeMo 23.02 컨테이너로 테스트되었지만 동일한 컨테이너의 이후 릴리스를 사용해 볼 수 있습니다. 다음 스크립트를 사용하여 이 컨테이너를 다운로드하고 실행하세요:

docker run -u $(id -u ${USER}):$(id -g ${USER}) --rm -it --net=host nvcr.io/nvidia/nemo:23.02 bash

그런 다음 컨테이너 대화형 bash 환경 내에서 Jupyter Lab을 시작합니다:

cd /workspace
jupyter lab --ip 0.0.0.0 --allow-root --port=8888

Jupyter lab의 /workspace/nemo/tutorials/nlp/Multitask_Prompt_and_PTuning.ipynb에서 위에서 언급한 노트북을 포함한 NeMo 예제를 찾을 수 있습니다.

또한 더 작은 5B 및 1.3B GPT-3 모델로 작업하려면 하나의 GPU가 필요하고, 4도의 텐서 병렬 처리(TP)가 있는 20B 모델과 작업하려면 4개의 NVIDIA Ampere 아키텍처 또는 NVIDIA Hopper 아키텍처 GPU가 필요합니다.

데이터 준비

이 노트북은 SQuAD 문제 풀이 작업을 위한 데이터 수집 및 전처리 과정을 안내합니다.

데이터 세트는 JSON 객체 모음을 포함하는 .jsonl 형식이어야 합니다. 각 JSON 객체에는 데이터 예제에 해당하는 작업의 문자열 식별자인 필드 작업 이름이 포함되어야 합니다. 또한 불연속형 텍스트 프롬프트의 여러 섹션에 해당하는 필드를 하나 이상 포함해야 합니다. 예는 그림 1을 참조하세요.

그림 1. NeMo 프롬프트 학습을 위한 데이터 세트 형식

프롬프트 템플릿

프롬프트를 구성할 때 패턴을 결정하고 이를 준수해야 합니다. 이 패턴을 프롬프트 템플릿이라고 하며 사용 사례에 따라 달라집니다. 질문과 답변의 예는 다음과 같습니다.

{
"taskname": "squad",
"prompt_template": "<|VIRTUAL_PROMPT_0|> Context: {context}\n\nQuestion: {question}\n\nAnswer:{answer}",
"total_virtual_tokens": 10,
"virtual_token_splits": [10],
"truncate_field": "context",
"answer_only_loss": True,
"answer_field": "answer",
}

프롬프트에는 처음에 10개의 가상 토큰이 모두 포함되며, 그 다음에는 컨텍스트, 질문, 그리고 마지막으로 답변이 표시됩니다. 훈련 데이터 JSON 개체의 해당 필드가 이 프롬프트 템플릿에 매핑되어 완전한 훈련 예제를 구성합니다. NeMo는 모델 토큰 길이 제한을 충족하기 위해 특정 필드를 잘라내는 기능을 지원합니다(일반적으로 HuggingFace GPT-2 토큰화 도구를 사용하는 Nemo 공개 모델의 경우 2,048개의 토큰).

교육

기본 NeMo 프롬프트 튜닝 구성은 yaml 파일로 제공되며, GitHub의 NVIDIA/NeMo를 통해 이용할 수 있습니다. 노트북은 이 yaml 파일을 로드한 다음 345M GPT 모델에 맞게 트레이닝 옵션을 재정의합니다. NeMo p-튜닝을 통해 여러 작업을 동시에 학습할 수 있습니다. NeMo는 PyTorch Lightning 인터페이스를 활용하므로 trainer.fit(model) 문을 호출하는 것만으로 간단하게 학습을 수행할 수 있습니다.

추론

마지막으로, 학습이 완료되면 model.generate(inputs=test_examples) 문을 호출하여 새로운 샘플에 대한 추론("answer_field" 생략)에 모델을 사용할 수 있습니다.

대규모 모델에 대한 신속한 학습

노트북에서 데모로 보여드린 345M GPT-3 모델 프로세스는 최대 13B GPT-35B GPT-3의 대규모 공개 NeMo GPT-3 모델에 적용될 수 있습니다. 이 크기의 모델에는 NVIDIA V100, NVIDIA A100, NVIDIA H100과 같이 충분한 메모리 용량을 갖춘 단일 GPU만 필요합니다. 모델을 다운로드한 후, 특히 다음 셀에 모델 이름을 대체합니다:

# Download the model from NGC gpt_file_name = "megatron_gpt_345m.nemo" !wget --content-disposition https://api.ngc.nvidia.com/v2/models/nvidia/nemo/megatron_gpt_345m/versions/1/files/megatron_gpt_345m.nemo -

NGC에서 345M GPT 모델을 다운로드하는 대신, HuggingFace의 지침에 따라 1.3B GPT-3 또는 5B GPT-3 모델을 다운로드한 다음 gpt_file_name 변수를 .nemo 모델 파일로 가리킵니다.

5B 모델의 경우 TP 정도가 1인 변형(nemo_gpt5B_fp16_tp1.nemo)과 TP=2인 변형(nemo_gpt5B_fp16_tp2.nemo, nemo_gpt5B_bf16_tp2.nemo) 두 가지가 있다는 점에 유의해야합니다. 노트북은 TP=1 변형만 지원할 수 있습니다. 다른 모든 것을 변경하지 않은 상태에서 동일한 노트북을 엔드 투 엔드로 실행할 수 있습니다.

멀티 GPU 프롬프트 학습

Jupyter 노트북 환경의 제한으로 인해 프롬프트 학습 노트북은 단일 GPU 트레이닝만 지원합니다. 더 높은 수준의 TP(예: 20B GPT-3의 경우 4개, 5B GPT-3의 경우 기타 변형의 경우 2개)를 사용하는 더 큰 모델에 멀티 GPU 학습을 활용하려면 다른 NeMo 프롬프트 학습 스크립트를 사용해야 합니다. 이 스크립트는 많은 파라미터의 기본값을 찾을 수 있는 config 파일에서 지원됩니다.

모델

이 섹션에서는 프롬프트 학습 노트북의 일부로 다운로드하고 사전 처리한 보조 데이터 세트에서 여러 GPU를 사용하여 대규모 모델을 프롬프트 학습하는 과정을 보여줍니다.

TP=2인 5B GPT 모델(nemo_gpt5B_fp16_tp2.nemo) 또는 TP=4인 20B GPT-3 모델을 다운로드할 수 있습니다. 이러한 모델은 .nemo zip 아카이브에 저장됩니다. 모델 로딩 속도를 크게 높이려면 미리 모델의 압축을 풀고 이 압축 해제된 폴더를 NeMo 구성에서 사용하세요. 다음 스크립트를 사용합니다:

tar -xvf nemo_gpt5B_fp16_tp2.nemo -C nemo_gpt5B_fp16_tp2.nemo.extracted

그런 다음 압축을 푼 디렉터리 nemo_gpt5B_fp16_tp2.nemo.extracted를 NeMo config에서 사용합니다.

구성

보조 데이터 세트(인텐트 및 슬롯 감지 애플리케이션)에 적합한 구성 파일은 다음과 같습니다:

name: megatron_virtual_prompt_gpt

trainer:
  devices: 2
  accelerator: gpu
  num_nodes: 1
  precision: 16
  logger: False # logger provided by exp_manager
  enable_checkpointing: False
  replace_sampler_ddp: False
  max_epochs: 25 # min 25 recommended
  max_steps: -1 # consumed_samples = global_step * micro_batch_size * data_parallel_size * accumulate_grad_batches
  log_every_n_steps: 10 # frequency with which training steps are logged 
  val_check_interval: 1.0 # If is an int n > 1, will run val every n training steps, if a float 0.0 - 1.0 will run val every epoch fraction, e.g. 0.25 will run val every quarter epoch
  gradient_clip_val: 1.0
  resume_from_checkpoint: null # The path to a checkpoint file to continue the training, restores the whole state including the epoch, step, LR schedulers, apex, etc.
  benchmark: False


exp_manager:
  explicit_log_dir: null
  exp_dir: null
  name: ${name}
  create_wandb_logger: False
  wandb_logger_kwargs:
    project: null
    name: null
  resume_if_exists: True
  resume_ignore_no_checkpoint: True
  create_checkpoint_callback: True
  checkpoint_callback_params:
    monitor: val_loss
    save_top_k: 2
    mode: min
    save_nemo_on_train_end: False # Should be false, correct prompt learning model file is saved at model.nemo_path set below, 
    filename: 'megatron_gpt_prompt_tune--{val_loss:.3f}-{step}'
    model_parallel_size: ${model.tensor_model_parallel_size}
    save_best_model: True

model:
  seed: 1234
  nemo_path: ${name}.nemo # .nemo filename/absolute path to where the virtual prompt model parameters will be saved
  virtual_prompt_style: 'p-tuning' # one of 'prompt-tuning', 'p-tuning', or 'inference'
  tensor_model_parallel_size: 1 # intra-layer model parallelism
  pipeline_model_parallel_size: 1 # inter-layer model parallelism
  global_batch_size: 8
  micro_batch_size: 4

  restore_path: null # Path to an existing p-tuned/prompt tuned .nemo model you wish to add new tasks to or run inference with
  language_model_path: ??? # Path to the GPT language model .nemo file, always required
  save_nemo_on_validation_end: True # Saves an inference ready .nemo file every time a checkpoint is saved during training. 
  existing_tasks: [] # List of tasks the model has already been p-tuned/prompt-tuned for, needed when a restore path is given
  new_tasks: ['squad'] # List of new tasknames to be prompt-tuned
  


  ## Sequence Parallelism
  # Makes tensor parallelism more memory efficient for LLMs (20B+) by parallelizing layer norms and dropout sequentially
  # See Reducing Activation Recomputation in Large Transformer Models: https://arxiv.org/abs/2205.05198 for more details.
  sequence_parallel: False

  ## Activation Checkpoint 
  activations_checkpoint_granularity: null # 'selective' or 'full' 
  activations_checkpoint_method: null # 'uniform', 'block', not used with 'selective'
  # 'uniform' divides the total number of transformer layers and checkpoints the input activation
  # of each chunk at the specified granularity
  # 'block' checkpoints the specified number of layers per pipeline stage at the specified granularity
  activations_checkpoint_num_layers: null # not used with 'selective'

  task_templates: # Add more/replace tasks as needed, these are just examples
  - taskname: "squad"    
    prompt_template: "<|VIRTUAL_PROMPT_0|> Context: {context}\n\nQuestion: {question}\n\nAnswer:{answer}"
    total_virtual_tokens: 10
    virtual_token_splits: [10]
    truncate_field: null
    answer_only_loss: False
    "answer_field": "answer"

  prompt_tuning: # Prompt tunin specific params
    new_prompt_init_methods: ['text'] # List of 'text' or 'random', should correspond to tasks listed in new tasks
    new_prompt_init_text: ['some init text goes here'] # some init text if init method is text, or None if init method is random

  p_tuning: # P-tuning specific params
    encoder_type: "tpmlp" # ['tpmlp', 'lstm', 'biglstm', 'mlp'] 
    dropout: 0.0
    num_layers: 2  # number of layers for MLP or LSTM layers. Note, it has no effect for tpmlp currently as it always assumes it is two layers.
    encoder_hidden: 2048 # encoder hidden for biglstm and tpmlp
    init_std: 0.023  # init std for tpmlp layers

  data:
    train_ds: ???
    validation_ds: ???
    add_eos: True
    shuffle: True
    num_workers: 8
    pin_memory: True
    train_cache_data_path: null  # the path to the train cache data 
    validation_cache_data_path: null  # the path to the validation cache data 
    test_cache_data_path: null  # the path to the test cache data 
    load_cache: False  # whether to load from the cache data


  optim:
    name: fused_adam
    lr: 1e-4
    weight_decay: 0.01 
    betas: 
    - 0.9
    - 0.98
    sched:
      name: CosineAnnealing
      warmup_steps: 50
      min_lr: 0.0 # min_lr must be 0.0 for prompt learning when pipeline parallel > 1
      constant_steps: 0 # Constant steps should also be 0 when min_lr=0
      monitor: val_loss
      reduce_on_plateau: false

Jupyter Lab 인터페이스를 사용하여 이 콘텐츠로 파일을 생성하고 /workspace/nemo/exples/nlp/language_modeling/conf/megatron_gpt_prompt_learning_squad.yaml에 저장합니다.

config 파일에서 가장 중요한 것은 아래 표시된 프롬프트 템플릿입니다:

prompt_template: "<|VIRTUAL_PROMPT_0|> Context: {context}\n\nQuestion: {question}\n\nAnswer:{answer}"
    total_virtual_tokens: 10
    virtual_token_splits: [10]
    truncate_field: null
    answer_only_loss: False
    "answer_field": "answer"

여기서는 10개의 가상 프롬프트 토큰과 몇 가지 영구 텍스트 마커가 함께 사용됩니다.

트레이닝

훈련을 시작하려면 Jupyter 랩 인터페이스(파일 → 새로 만들기 → 터미널)에서 터미널 창을 엽니다. 그런 다음 bash 명령을 실행합니다:

python /workspace/nemo/examples/nlp/language_modeling/megatron_gpt_prompt_learning.py \
    	--config-name=megatron_gpt_prompt_learning_squad.yaml \
    	trainer.devices=2 \
    	trainer.num_nodes=1 \
    	trainer.max_epochs=25 \
    	trainer.precision=bf16 \
    	model.language_model_path=/workspace/nemo/tutorials/nlp/nemo-megatron-gpt-5B/nemo_gpt5B_fp16_tp2.nemo.extracted \
    	model.nemo_path=/workspace/nemo/examples/nlp/language_modeling/squad.nemo \
    	model.tensor_model_parallel_size=2 \
    	model.pipeline_model_parallel_size=1 \
    	model.global_batch_size=16 \
    	model.micro_batch_size=1 \
    	model.optim.lr=1e-4 \
    	model.data.train_ds=[/workspace/nemo/tutorials/nlp/data/SQuAD/squad_train.jsonl] \
    	model.data.validation_ds=[/workspace/nemo/tutorials/nlp/data/SQuAD/squad_val.jsonl]

다음 사항에 유의하세요:

  • model.tensor_model_parallel_size는 5B GPT 모델(nemo_gpt5B_fp16_tp2.nemo)의 경우 2로, 20B GPT-3 모델의 경우 4로 설정해야 합니다.
  • trainer.devices는 TP 값의 배수로 설정해야 합니다. 5B 모델의 경우 4인 경우, 각각 두 개의 GPU를 사용하는 두 개의 데이터 병렬 워커가 있습니다.
  • model.language_model_path는 모델 추출 디렉토리의 절대 경로로 설정해야 합니다.
  • model.data.train_ds, model.data.validation_ds는 훈련 및 검증 데이터의 위치로 설정해야 합니다.

추론

마지막으로 학습이 완료되면 다음 스크립트를 사용하여 NeMo에서 추론을 수행합니다:

python /workspace/nemo/examples/nlp/language_modeling/megatron_gpt_prompt_learning_eval.py \
            virtual_prompt_model_file=/workspace/nemo/examples/nlp/language_modeling/intent_n_slot.nemo \
            gpt_model_file=/workspace/nemo/tutorials/nlp/nemo-megatron-gpt-5B/nemo_gpt5B_fp16_tp2.nemo.extracted  \
            inference.greedy=True \
            inference.add_BOS=False \
            inference.tokens_to_generate=128 \
            trainer.devices=2 \
            trainer.num_nodes=1 \
            tensor_model_parallel_size=2 \
            pipeline_model_parallel_size=1 \
            data_paths=["/workspace/nemo/tutorials/nlp/data/SQuAD/squad_test.jsonl"] \
            pred_file_path="test-results.txt"

다음 사항에 유의하세요:

  • model.tensor_model_parallel_size는 5B GPT 모델(nemo_gpt5B_fp16_tp2.nemo)의 경우 2로, 20B GPT-3 모델의 경우 4로 설정해야 합니다.
  • trainer.devices는 TP 값(위)과 같도록 설정해야 합니다.
  • pred_file_path는 테스트 결과가 기록될 파일로, 테스트 샘플당 한 줄입니다.

NeMo를 사용하여 언어 모델 사용자 지정 시작하기

이 게시물에서는 NeMo와 프롬프트 학습과 같은 기술을 사용하여 특정 사용 사례에 맞게 LLM을 사용자 지정하는 프로세스를 안내했습니다. 단일 공개 체크포인트에서 이러한 모델은 매개변수 효율적이고 컴퓨팅 효율적인 프로세스를 통해 수많은 NLP 애플리케이션에 적용할 수 있습니다.

LLM 커스터마이징을 시작하려면 GitHub의 NVIDIA/NeMo를 방문하세요. 오픈 베타에도 초대받으실 수 있습니다.

관련 리소스

이 블로그에 열거된 SDK의 대부분의 독점 액세스, 얼리 액세스, 기술 세션, 데모, 교육 과정, 리소스는 NVIDIA 개발자 프로그램 회원은 무료로 혜택을 받으실 수 있습니다. 지금 무료로 가입하여 NVIDIA의 기술 플랫폼에서 구축하는 데 필요한 도구와 교육에 액세스하시고 여러분의 성공을 가속화 하세요.

Discuss (0)

Tags

답글 남기기