LLM( 대형 언어 모델 )은 ChatGPT 출시 이후 소프트웨어 개발 분야의 화두가 되었습니다. 인간과 자연스러운 대화를 나누는 능력은 빙산의 일각에 불과합니다. LangChain 또는 Semantic Kernel과 같은 도구로 강화된 LLM은 사용자가 소프트웨어와 상호 작용하는 방식을 완전히 바꿀 수 있는 잠재력을 가지고 있습니다. 즉, LLM은 기능과 데이터 소스 간의 시너지 효과를 창출하고 보다 효율적이고 직관적인 사용자 경험을 제공할 수 있습니다.
예를 들어, 많은 사람들이 이미 차세대 바이럴 동영상에 AI 기반 콘텐츠 제작 도구를 사용하고 있습니다. 일반적인 비디오 제작 파이프라인에는 스크립팅, 실행 계획, 스토리보드, 편집, 마케팅 등이 포함됩니다. 프로세스를 간소화하기 위해 LLM은 콘텐츠 제작자가 대본을 작성하는 동안 조사하고, 촬영을 위한 소품을 구매하고, 대본을 기반으로 스토리보드를 생성하고(이미지 생성을 위해 안정적인 확산이 필요할 수 있음), 편집 프로세스를 촉진하고, 눈길을 끄는 제목을 작성하는 데 도움을 줄 수 있습니다. /소셜 미디어에서 조회수를 유도하기 위한 동영상 설명입니다. LLM은 이 모든 것을 조율하는 핵심이지만 LLM을 소프트웨어 제품에 통합할 때 몇 가지 우려 사항이 있을 수 있습니다.
OpenAI의 API를 사용하면 이 서비스에 너무 의존하게 될까요? 가격이 오르면 어떻게 되나요? 서비스 가용성이 변경되면 어떻게 되나요?
OpenAI가 콘텐츠를 검열하거나 특정 사용자 입력에 대해 비건설적인 피드백을 제공하는 방식이 마음에 들지 않습니다. (또는 그 반대: OpenAI 검열이 내 사용 사례에서 민감한 특정 사항을 무시하는 방식이 마음에 들지 않습니다.)
내 고객이 프라이빗 클라우드 또는 온프레미스 배포를 선호하는 경우 어떤 ChatGPT 대안이 있습니까?
나는 단지 통제권을 갖고 싶습니다. LLM을 맞춤화해야 하는데 저렴하게 하고 싶습니다.
이러한 우려 때문에 OpenAI의 GPT 모델과 동등한 오픈 소스 모델이 있을 수 있는지 궁금합니다. 다행히도 훌륭한 오픈 소스 커뮤니티에서는 이미 매우 유망한 솔루션을 공유하고 있습니다. 나는 자신의 LLM을 훈련하기 위한 매개변수 효율적인 미세 조정 방법인 alpaca-lora를 시험해 보기로 결정했습니다. 이 블로그 게시물에서는 프로세스, 제가 직면한 문제, 해결 방법 및 다음에 일어날 수 있는 일에 대해 설명합니다. 자신의 LLM 교육에도 이 기술을 사용하고 싶다면 이 정보가 도움이 되기를 바랍니다.
의 시작하자!
LLaMA 는 Meta AI의 기초 언어 모델 모음입니다. 이러한 자기회귀 모델은 7B~65B 범위의 매개변수 개수를 가지며 연구 목적으로만 사용할 수 있습니다. Meta는 최근 일부 제한을 두고 상업적으로 사용할 수 있는 LLaMA 2를 출시했습니다. LLaMA 모델 계열을 특별하게 만드는 것은 훈련 코퍼스와 성능입니다. Meta에서는 LLaMA가 공개적으로 사용 가능한 데이터세트를 사용하여 훈련되었다고 명시합니다. 13B 변형은 대부분의 벤치마크에서 GPT-3(175B 모델)과 비슷한 성능을 달성합니다.
알파카 는 LLaMA를 기반으로 지시에 따른 LLM을 구축하려는 스탠포드의 시도입니다. 다음과 같이 작동합니다:
명령어-입력-응답 삼중항을 생성하도록 언어 모델에 요청하세요.
LLaMA 미세 조정을 위해 생성된 데이터를 사용합니다.
미세 조정 후에 LLaMA는 사용자의 지시를 따르고 그에 따라 응답할 수 있습니다.
다음은 바닐라 LLaMA의 응답과 미세 조정된 LLaMA 응답을 비교한 것입니다.
{ "instruction": "Answer user's question.", "input": "Can you put a medium voltage circuit breaker in a low voltage switchgear? Why? Explain in detail.", "vanilla LLaMA": { "answer": "Yes, you can put a medium voltage circuit breaker in a low voltage switchgear. The medium voltage circuit breaker can be put in a low voltage switchgear because the medium voltage circuit breaker can be put in a low voltage switchgear because the medium voltage circuit breaker can be put in a low voltage switchgear because the medium voltage circuit breaker can be put....(repetition continues)" }, "fine-tuned LLaMA": { "answer": "No, it is not possible to put a medium voltage circuit breaker in a low voltage switchgear. This is because low voltage switchgear is designed to handle voltages up to 1 kV, while medium voltage switchgear is designed to handle voltages from 1 kV to 38 kV. The circuit breakers, contacts, and other components in low voltage switchgear are not suitable for the higher voltages and currents of medium voltage switchgear. Using a medium voltage circuit breaker in a low voltage switchgear could result in damage to the components and could pose a safety hazard." } }
보시다시피 미세 조정은 LLM 동작을 상당히 크게 변경합니다. 바닐라 모델이 반복 루프에 갇혀 있습니다. 미세 조정된 모델이 100% 정확한 응답을 산출하지는 못했지만 적어도 그 대답은 "아니요"입니다. 미세 조정은 사용 가능한 LLM을 생성하는 데 필요한 단계입니다. 많은 경우에는 미세 조정된 오픈 소스 LLM을 배포하는 것만으로도 충분합니다. 그러나 일부 맞춤형 비즈니스 사용 사례에서는 도메인별 데이터 세트에 대한 모델을 미세 조정하는 것이 더 나을 수 있습니다.
알파카의 가장 큰 단점은 리소스 요구 사항입니다. GitHub 페이지에는 다음과 같이 명시되어 있습니다.
간단히 말해서 7B 모델을 미세 조정하려면 약 7 x 4 x 4 = 112GB의 VRAM이 필요합니다.
이는 A100 80GB GPU가 처리할 수 있는 것보다 더 많은 VRAM입니다. LoRA를 사용하면 VRAM 요구 사항을 우회할 수 있습니다.
LoRA는 다음과 같이 작동합니다.
추가된 가중치에는 몇 가지 특별한 속성이 있습니다. 이 논문 에서 영감을 받은 Edward Hu et al. 원래 모델 가중치 $W_o\in R^{d \times k}$에 대해 다운스트림 작업에 대해 미세 조정된 가중치 $W_o'=W_o+BA$를 생성할 수 있음을 보여주었습니다. 여기서 $B\in R^{d \times r}$ , $A \in R^{r \times k}$ 및 $r\ll min(d, k)$는 어댑터 가중치의 "내재 순위"입니다. $r$가 작을수록 모델 성능이 낮아지고 $r$가 클수록 비례적인 성능 향상 없이 어댑터 무게 크기가 증가하므로 어댑터 무게에 대해 적절한 $r$를 설정하는 것이 중요합니다.
이 기술은 행렬을 여러 개의 작은 행렬로 분해하고 가장 큰 특이값 몇 개만 유지하여 행렬을 근사화하는 절단된 SVD와 유사합니다. $W_o\in R^{100 \times 100}$를 가정하면 전체 미세 조정으로 10,000개의 매개변수가 변경됩니다. $r=8$을 사용한 LoRA 미세 조정은 미세 조정된 가중치를 $B\in R^{100 \times 8}$ 및 $A\in R^{8 \times 100}$의 두 부분으로 분해합니다. 부품에는 800개의 매개변수가 포함되어 있습니다(총 1600개의 매개변수). 훈련 가능한 매개변수의 수가 6.25배 감소합니다.
LoRA로 모델을 변환한 후 훈련 가능한 가중치가 ~1%에 불과한 모델을 얻었지만 특정 영역에서는 성능이 크게 향상되었습니다. 이를 통해 RTX 4090 또는 V100과 같이 보다 접근하기 쉬운 하드웨어에서 7B 또는 13B 모델을 훈련할 수 있습니다.
GPU 가속 VM 인스턴스( p2s.2xlarge
, 8vCPU, 64GB RAM, 1x V100 32GB VRAM)를 사용하여 Huawei Cloud에서 실험을 실행했습니다. V100은 bfloat16 데이터 유형을 지원하지 않으며 해당 텐서 코어는 int8을 지원하지 않는 것으로 알려져 있습니다. 가속. 이러한 2가지 제한은 혼합 정밀도 훈련 속도를 늦추고 혼합 정밀도 훈련 중에 수치 오버플로를 일으킬 수 있습니다. 나중에 논의할 때 이 점을 염두에 두겠습니다.
finetune.py
와 generate.py
가 프로젝트의 핵심입니다. 첫 번째 스크립트는 LLaMA 모델을 미세 조정하고, 두 번째 스크립트는 미세 조정된 모델을 사용하여 사용자와 채팅합니다. 먼저 finetune.py
의 주요 흐름을 살펴보겠습니다.
model = LlamaForCausalLM.from_pretrained( base_model, # name of a huggingface compatible LLaMA model load_in_8bit=True, torch_dtype=torch.float16, device_map=device_map, )
tokenizer = LlamaTokenizer.from_pretrained(base_model) tokenizer.pad_token_id = ( 0 # unk. we want this to be different from the eos token ) tokenizer.padding_side = "left" # Allow batched inference
훈련 템플릿을 기반으로 tokenize
및 generate_and_tokenize_prompt
라는 두 가지 함수를 사용하여 모델 입력을 준비합니다.
Huggingface의 PEFT를 사용하여 LoRA 적응 모델 생성
config = LoraConfig( r=lora_r, # the lora rank lora_alpha=lora_alpha, # a weight scaling factor, think of it like learning rate target_modules=lora_target_modules, # transformer modules to apply LoRA to lora_dropout=lora_dropout, bias="none", task_type="CAUSAL_LM", ) model = get_peft_model(model, config)
trainer = transformers.Trainer( model=model, train_dataset=train_data, eval_dataset=val_data, args=transformers.TrainingArguments( ...
이것은 매우 간단합니다.
마지막에 스크립트는 체크포인트, 어댑터 가중치 및 어댑터 구성이 포함된 모델 폴더를 생성합니다.
다음으로 generate.py
의 주요 흐름을 살펴보겠습니다 .
model = LlamaForCausalLM.from_pretrained( base_model, device_map={"": device}, torch_dtype=torch.float16, ) model = PeftModel.from_pretrained( model, lora_weights, device_map={"": device}, torch_dtype=torch.float16, )
generation_config = GenerationConfig( temperature=temperature, top_p=top_p, top_k=top_k, num_beams=num_beams, **kwargs, ) generate_params = { "input_ids": input_ids, "generation_config": generation_config, "return_dict_in_generate": True, "output_scores": True, "max_new_tokens": max_new_tokens, }
if stream_output: # streaming ... # Without streaming with torch.no_grad(): generation_output = model.generate( input_ids=input_ids, generation_config=generation_config, return_dict_in_generate=True, output_scores=True, max_new_tokens=max_new_tokens, ) s = generation_output.sequences[0] output = tokenizer.decode(s) yield prompter.get_response(output)
gr.Interface( ...
프로젝트의 README.md
에는 다음과 같은 미세 조정 설정을 통해 Stanford 알파카에 필적하는 성능을 갖춘 LLaMA 7B가 생성된다고 명시되어 있습니다. "공식적인" 알파카로라 무게는 포옹 얼굴에 공유되었습니다.
python finetune.py \ --base_model='decapoda-research/llama-7b-hf' \ --num_epochs=10 \ --cutoff_len=512 \ --group_by_length \ --output_dir='./lora-alpaca' \ --lora_target_modules='[q_proj,k_proj,v_proj,o_proj]' \ --lora_r=16 \ --micro_batch_size=8
그러나 내 경험상 사용 가능한 모델이 나오지 않았습니다. V100에서 실행하면 다음과 같은 중단 문제가 발생합니다.
load_in_8bit
로 모델을 로드하면 데이터 유형 오류가 발생합니다.decapoda-research/llama-7b-hf
모델은 분명히 잘못된 토크나이저를 사용했습니다. 패드 토큰, bos 토큰, eos 토큰은 LLaMA 공식 토크나이저와 다릅니다.training loss = 0.0
및 eval loss = NaN
과 같은 예상치 못한 동작이 발생합니다.
여러 VM 시간을 탐색하고 낭비한 끝에 단일 V100에서 교육 작업을 수행하는 데 필요한 변경 사항을 찾았습니다.
... # do not use decapoda-research/llama-7b-hf as base_model. use a huggingface LLaMA model that was properly converted and has a correct tokenizer, eg, yahma/llama-7b-hf or huggyllama/llama-7b. # decapoda-research/llama-7b-hf is likely to cause overflow/underflow on V100. train loss goes to 0 and eval loss becomes NaN. using yahma/llama-7b-hf or huggyllama/llama-7b somehow mitigates this issue model = LlamaForCausalLM.from_pretrained( base_model, load_in_8bit=True, # only work for 7B LLaMA. On a V100, set True to save some VRAM at the cost of slower training; set False to speed up training at the cost of more VRAM / smaller micro batch size torch_dtype=torch.float16, device_map=device_map, ) ... # comment out the following line if load_in_8bit=False model = prepare_model_for_int8_training(model) ... # set legacy=False to avoid unexpected tokenizer behavior. make sure no tokenizer warning was raised during tokenizer instantiation tokenizer = LlamaTokenizer.from_pretrained(base_model, legacy=False) ... # the following binding script results in invalid adapter. simply comment them out old_state_dict = model.state_dict model.state_dict = ( lambda self, *_, **__: get_peft_model_state_dict( self, old_state_dict() ) ).__get__(model, type(model)) ... # if load_in_8bit=True, need to cast data type during training with torch.autocast('cuda'): trainer.train(resume_from_checkpoint=resume_from_checkpoint)
이러한 변경을 수행한 후 이러한 학습 인수는 사용 가능한 모델을 생성합니다.
{ "args": [ "--base_model", "yahma/llama-7b-hf", "--num_epochs=10", "--data_path", "yahma/alpaca-cleaned", "--output_dir", "./your output dir", "--cutoff_len=512", "--lora_target_modules=[q_proj,k_proj,v_proj,o_proj]", "--lora_r=16", "--micro_batch_size=2", "--batch_size=16", "--wandb_project", "your wandb project name" ], }
학습 스크립트는 "최상의" 모델(평가 손실이 가장 낮은 체크포인트)뿐만 아니라 몇 가지 체크포인트도 저장합니다. 추가 분석을 위해 wandb를 사용하여 훈련/평가 손실을 기록했습니다.
나는 미세 조정된 모델에 무작위로 질문을 던진다. 그것은 합리적인 반응을 낳습니다.
다음은 한 가지 예입니다.
지침: 사용자의 질문에 주의 깊게 대답하십시오.
입력: 개폐기 회로 차단기 트럭을 랙에 장착하면 어떻게 되나요?
응답: 스위치기어 회로 차단기 트럭이 "랙아웃"된 경우 이는 트럭의 모든 회로 차단기가 개방되었으며 트럭에 전원이 공급되지 않은 상태임을 의미합니다. 이는 일반적으로 트럭을 정비, 수리 또는 검사할 때 수행됩니다. 회로 차단기를 분리한 후에는 트럭을 안전하게 작업할 수 있으며 필요한 유지 관리 또는 수리가 완료되면 다시 전원을 공급받을 수 있습니다.
이 예에서는 LLM의 내부 지식을 쿼리합니다. 그 모델은 배전반에 대해 많은 것을 알고 있는 것 같았습니다. 그러나 추론 능력을 경험적으로 테스트하려고 시도했을 때 매우 이상한 결과가 나왔습니다.
지침:
프로젝트에 대한 아래 정보가 주어지면 질문에 답하세요. Chinese-Llama-2 프로젝트는 중국어로 된 대형 언어 모델 Llama-2의 이해, 생성, 번역 능력을 향상시키는 것을 목표로 합니다. LoRA 미세 조정, 전체 매개변수 명령어 미세 조정, 2차 사전 학습 등의 방법을 적용하여 관련 데이터세트, 학습 가이드, 모델 매개변수를 다운로드하여 활용하시기 바랍니다.
입력: 이 프로젝트에서는 어떤 방법이 사용됩니까?
대응: Chinese-Llama-2 프로젝트는 중국어로 된 대형 언어 모델 Llama-2의 이해, 생성, 번역 능력을 향상시키는 것을 목표로 합니다. LoRA 미세 조정, 전체 매개변수 명령 미세 조정, 2차 사전 학습 등의 방법을 적용하여 관련 데이터세트, 학습 가이드, 모델 매개변수를 다운로드하여 활용하시기 바랍니다.</s>
보시다시피 모델은 프롬프트를 반복하는 것을 좋아합니다. 나는 이것을 프롬프트-반복기 모델이라고 부르는데, 다른 개발자들도 저장소 문제 에서 이 동작을 보고했습니다. 질문에 대답하는 능력은 보다 신중하게 설계된 프롬프트를 통해서만 향상됩니다. 다양한 모델에서 즉각적인 효과를 보장할 수 없기 때문에 이러한 동작은 생산 시스템에서 우리가 원하는 것이 아닙니다. 모델은 프롬프트에 덜 민감해야 합니다. 우리는 이 LLM의 성능을 어떻게든 향상시키고 싶습니다.
다음 세션에서는 이러한 문제가 발생한 원인과 미세 조정 결과를 개선하는 방법에 대해 논의하겠습니다.
미세 조정 결과를 개선하기 위해 제가 시도한 세 가지 사항은 다음과 같습니다.
프롬프트에서 손실을 마스킹합니다(프롬프트 반복을 방지하는 데 도움이 됨).
group-by-length
옵션 끄기(성능 향상에 도움이 되고 손실 곡선이 더 부드러워 보이도록 함)
평가 손실 곡선을 신뢰하지 마십시오. 평가 손실이 "최고" 체크포인트보다 높을 수 있더라도 훈련 손실이 낮은 체크포인트를 사용하세요. (여기서는 평가 손실이 최고의 매트릭스가 아니기 때문에 성능 향상에 도움이 됩니다)
이 3가지 사항을 하나씩 설명해보자.
나는 이 게시물 과 공식 lora Weights 커밋 메시지를 발견하기 전까지 프롬프트 반복의 원인을 찾고 있었습니다. 그들은 손실 계산에서 프롬프트를 제외해야 한다고 제안했습니다. 기본적으로 모델이 프롬프트 토큰을 출력하도록 권장하고 싶지는 않습니다. 훈련 중에 프롬프트를 가리면 모델이 프롬프트 토큰을 반복하도록 장려되지 않습니다. 아래 차트는 이를 설명합니다. 3번의 훈련 실행 중에서 stoic-star-6
은 훈련 중에 프롬프트를 가리지 않은 유일한 실행입니다. 따라서 처음에는 훈련 손실이 더 높습니다. 나는 a) 손실을 계산할 때 프롬프트가 가려지지 않고 b) 훈련이 불충분하다면 모델이 지침을 따르기보다는 프롬프트를 반복할 가능성이 더 높다고 생각합니다.
소스 코드에서 손실 마스킹은 프롬프트 토큰을 -100으로 설정하여 수행됩니다.
인덱스가
-100
으로 설정된 토큰은 무시되고(마스크됨), 손실은[0, ..., config.vocab_size]
에 레이블이 있는 토큰에 대해서만 계산됩니다.
group-by-length
옵션 끄기 group-by-length
옵션을 사용하면 Huggingface의 Trainer
비슷한 길이의 입력을 일괄 처리로 그룹화할 수 있습니다. 이는 입력 시퀀스를 패딩할 때 VRAM 사용량을 줄이는 데 도움이 됩니다. 그러나 단일 배치 내에서 샘플 분산이 크게 줄어듭니다. 훈련 과정에서 우리는 일반적으로 모델을 다양한 훈련 샘플에 노출시키는 것을 선호합니다. group-by-length
False
로 설정하면 샘플 변동이 줄어듭니다. 또한 훈련 중에 손실 변동이 발생합니다(예를 들어 두 개의 연속 배치에는 10과 50의 패딩 길이가 있습니다. 짧은 배치는 손실이 낮고, 긴 배치는 손실이 높습니다. 이로 인해 그림에 표시된 것처럼 진동하는 손실 곡선이 생성됩니다. 아래에).
반면, group-by-length
배치 내 샘플 변동을 감소시키기 때문에 모델 성능도 이로 인해 저하될 수 있다고 생각됩니다. 아래 그림은 group-by-length
유무에 따른 훈련 손실을 비교합니다. group-by-length
활성화된 peach-violet-19
실행의 경우 평균 손실이 더 높다는 것이 분명합니다.
나는 모든 실행에서 훈련 손실과 평가 손실이 서로 다른 것을 관찰했습니다.
예는 다음과 같습니다.
이 예에서 최적의 체크포인트는 epoch=2
부근에서 발생합니다. 원래 repo 에서 제안한 대로 최적의 체크포인트를 로드하면 이전 세션에서 언급한 프롬프트-반복기 모델을 얻을 가능성이 가장 높습니다.
훈련이 끝날 무렵에 모델 체크포인트를 로드하여 더 성능이 좋은 모델을 얻었습니다. 이전과 동일한 질문을 했고 모델이 정답을 반환했습니다.
지침:
프로젝트에 대한 아래 정보가 주어지면 질문에 답하세요. Chinese-Llama-2 프로젝트는 중국어로 된 대형 언어 모델 Llama-2의 이해, 생성, 번역 능력을 향상시키는 것을 목표로 합니다. LoRA 미세 조정, 전체 매개변수 명령어 미세 조정, 2차 사전 학습 등의 방법을 적용하여 관련 데이터세트, 학습 가이드, 모델 매개변수를 다운로드하여 활용하시기 바랍니다.
입력: 이 프로젝트에서는 어떤 방법이 사용됩니까?
응답: Chinese-Llama-2 프로젝트는 LoRA 미세 조정, 전체 매개변수 명령 미세 조정, 2차 사전 훈련과 같은 방법을 사용합니다.</s>
그러나 평가 손실로 판단하면 이 모델의 성능은 더 나빠질 것입니다. 딜레마의 원인은 무엇입니까?
평가 손실은 대규모 언어 모델 성능을 측정하기 위한 좋은 매트릭스가 아니라고 생각합니다. LLaMA는 훈련 및 평가 손실을 위해 CrossEntropyLoss
사용합니다.
# modelling_llama.py from transformers library ... # forward function under LlamaForCausalLM class if labels is not None: # Shift so that tokens < n predict n shift_logits = logits[..., :-1, :].contiguous() shift_labels = labels[..., 1:].contiguous() # Flatten the tokens loss_fct = CrossEntropyLoss() loss = loss_fct(shift_logits.view(-1, self.config.vocab_size), shift_labels.view(-1))
평가 세트를 테스트할 때 모델은 다른 표현으로 동일한 답변을 생성할 수 있습니다.
{ "evaluation prompt": "What is 1 + 3?" "evaluation answer": "4." "prediction answer": "The answer is 4." }
두 답 모두 정답이지만, 예측 답이 평가 답과 정확히 일치하지 않으면 평가 손실이 커집니다. 이 경우 모델 성능을 측정하려면 더 나은 평가 매트릭스가 필요합니다. 적절한 평가에 대해서는 나중에 고민하도록 하겠습니다. 지금은 훈련 손실이 가장 낮은 모델이 가장 좋은 모델이라고 가정하겠습니다.
13B 모델을 V100에서 미세조정해보았습니다. V100은 7B 모델에서 int8 및 fp16 교육을 모두 처리할 수 있지만 13B 모델에서는 int8 교육을 처리할 수 없습니다. load_int_8bit = True
이면 13B 모델은 training_loss = 0.0
생성합니다. 일부 디버깅 도구를 사용하여 이러한 일이 발생하는 이유를 이해할 수 있습니다( 스포일러 경고: 오버플로/언더플로로 인해 발생함).
훈련 중에 매개변수를 검사하기 위해 Huggingface의 DebugUnderflowOverflow
도구를 사용했습니다. 첫 번째 순방향 패스에서는 inf/nan 값을 감지했습니다.
보다 구체적으로, DebugUnderflowOverflow
아래 그림과 같이 LlamaDecoderLayer
의 두 번째 입력에서 음의 무한대 값을 포착했습니다. 두 번째 입력은 attention_mask
입니다. 나는 좀 더 깊이 파고들어 attention_mask
패딩 요소에 대해 매우 큰 음수 값을 가져야 한다는 것을 알아냈습니다. 우연히도 음의 무한대 값은 모든 시퀀스의 시작 부분에 있습니다. 이 관찰을 통해 저는 음의 무한대 값이 이 레이어에서 발생한다고 믿게 되었습니다. 또한 추가 조사를 통해 무한대 값이 다음 몇 개의 레이어에서 더 많은 무한대 값을 발생시키지 않는 것으로 나타났습니다. 따라서 LlamaDecoderLayer
의 오버플로는 비정상적인 훈련 손실의 근본 원인이 아닐 가능성이 높습니다.
다음으로 각 레이어의 출력을 검사했습니다. 아래 그림과 같이 최종 레이어의 출력이 오버플로되는 것이 매우 분명했습니다. 나는 이것이 int-8 가중치의 제한된 정밀도(또는 float16
의 제한된 범위 때문에 발생한다고 믿습니다. bfloat16
이 문제를 피할 수 있을 가능성이 높습니다).
오버플로 문제를 해결하기 위해 훈련 중에 float16을 사용했습니다. V100에는 몇 가지 트릭을 사용하지 않는 한 13B 모델을 교육하기에 충분한 VRAM이 없습니다. Hugging Face DeepSpeed는 훈련용 VRAM 사용량을 줄이기 위해 CPU 오프로딩과 같은 여러 가지 방법을 제공합니다. 그러나 가장 간단한 방법은 훈련이 시작되기 전에 model.gradient_checkpointing_enable()
호출하여 그래디언트 체크포인트를 활성화하는 것입니다.
그라데이션 체크포인트는 VRAM 사용량을 줄이기 위해 훈련 속도를 절충합니다. 일반적으로 정방향 전달 중에 활성화가 계산되어 역방향 전달 중에 사용할 수 있도록 메모리에 저장됩니다. 이는 추가 메모리를 차지합니다. 그러나 그래디언트 체크포인트를 사용하면 순방향 패스 중에 활성화를 저장하는 대신 역방향 패스 중에 활성화를 다시 계산하여 VRAM을 절약합니다. 이 기술에 대한 좋은 기사가 있습니다.
float16 및 그래디언트 체크포인트를 활성화하여 Llama 13B를 훈련할 수 있었습니다.
python finetune.py \ --base_model=yahma/llama-13b-hf \ --num_epochs=10 \ --output_dir 'your/output/dir' \ --lora_target_modules='[q_proj,k_proj,v_proj,o_proj]' \ --cutoff_len=1024 \ --lora_r=16 \ --micro_batch_size=4 \ --batch_size=128 \ --wandb_project 'alpaca_lora_13b' \ --train_on_inputs=False
13B 모델은 이름 엔터티 인식과 같은 일부 고급 작업을 처리할 수 있습니다. 테스트를 위해 예시 프롬프트를 사용했는데 이는 13B 모델의 정확한 응답입니다.
모두 괜찮아요! 이것은 흥미로운 시작입니다. 이 모델을 사용하면 LangChain을 사용하여 복잡한 애플리케이션을 만들 수 있습니다.
현재로서는 자동 모델 평가를 위한 도구가 아직 없습니다. 언어 모델 평가 하네스를 사용하여 많은 테스트 사례에서 모델을 평가하거나 자체 테스트 사례를 만들 수도 있습니다. Hugging Face가 Open LLM Leaderboard에 사용하는 것과 동일한 도구입니다. 평가는 LLM 개발의 중요한 측면이지만 이 기사에서는 교육 프로세스에만 중점을 둡니다. 향후 기사에서 평가에 대해 논의할 수도 있습니다.
이 기사에서는 LFM(대형 기초 모델)의 개념과 LFM이 원하는 대로 작동하도록 만드는 몇 가지 미세 조정 방법을 소개했습니다. 그런 다음 LFM 미세 조정을 위한 매개변수 효율적인 방법인 LoRA에 중점을 두고 미세 조정 코드와 성능 개선 기술을 설명했습니다. 마지막으로 우리는 한 단계 더 나아가 V100 GPU에서 Llama 13B 모델을 성공적으로 훈련했습니다. 13B 모델 훈련에서 몇 가지 문제가 발생했지만 이러한 문제는 하드웨어 제한으로 인해 발생한다는 것을 발견하고 해결책을 제시했습니다. 결국 우리는 작동하는 미세 조정된 LLM을 얻었지만 아직 LLM의 성능을 정량적으로 평가하지 않았습니다.
저자 소개
안녕! 제 이름은 웨이입니다. 저는 전담 문제 해결사이자 ABB 의 수석 AI 전문가이자 분석 프로젝트 리더이며, 머신러닝 Google 개발자 전문가입니다 . 저는 미네소타 트윈 시티 대학교에서 기계 공학 석사 학위를 취득했고, 일리노이 대학교 어바나-샴페인에서 기계 공학 학사 학위를 받았습니다.
내 기술 스택은 Python/C# 프로그래밍, 컴퓨터 비전, 기계 학습, 알고리즘 및 마이크로 서비스에 중점을 두고 있지만 게임 개발(Unity), 프런트/백엔드 개발, 기술 리더십, 단일 보드 컴퓨터와 로봇공학을 만지작거립니다.
이 글이 사람들에게 어떤 식으로든 도움이 되기를 바랍니다. 읽어주셔서 감사합니다. 즐거운 문제 해결이 되시길 바랍니다!