LoRA의 또 다른 이점은 사전 훈련된 가중치가 고정된 상태로 유지되기 때문에 생성된 어댑터가 가볍고 휴대가 간편하며 쉽게 보관할 수 있다는 것입니다.
이 튜토리얼에서는 LLaMa Factory를 사용합니다. LLaMa Factory는 대규모 언어 모델(LLM) 훈련 및 로우 및 노코드 미세 조정 플랫폼으로, 사용자가 사용자 지정 데이터 세트에서 LLM을 조정하고 성능을 평가하며 모델을 제공할 수 있습니다. 사용하기 쉽고 100개 이상의 LLM을 지원하는 웹 UI와 CLI를 모두 갖추고 있습니다. 이 플랫폼은 Alpaca 및 ShareGPT 형식의 데이터 세트를 지원합니다. LLaMa Factory만이 대규모 언어 모델(LLM)을 미세 조정하는 유일한 방법은 아닙니다. 매개변수 효율적 미세 조정(PEFT)을 위한 PEFT 라이브러리 역시 대규모 모델을 업데이트하는 또 다른 옵션입니다. PEFT는 양자화된 LoRA(QLoRA)를 수행하여 미세 조정된 모델을 더욱 압축할 수 있는 기능을 제공합니다. 이 튜토리얼에서는 양자화되지 않은 버전의 Granite 3.3을 사용합니다.
LLaMa Factory는 광범위한 컴퓨팅 리소스를 사용하지 않고도 실행할 수 있지만 GPU와 상당한 메모리 리소스가 필요합니다. 이 튜토리얼에서는 watsonx에서 LLaMa Factory를 사용하여 생성된 어댑터에 대한 GPU 리소스 및 스토리지를 제공합니다.
Watson Studio 구성
a. IBM® Cloud 계정을 사용하여 watsonx.ai에 로그인합니다.
b. watsonx.ai 프로젝트를 생성합니다. 프로젝트 > 관리 > 일반 > 프로젝트 ID에서 프로젝트 ID를 기록해 둡니다.
이 튜토리얼을 진행하기 위해 이 ID가 필요합니다.
c. watsonx.ai 런타임 서비스 인스턴스를 생성합니다. 이 튜토리얼에서는 GPU에 액세스하려면 유료 인스턴스를 만들어야 합니다.
d. watsonx 애플리케이션 프로그래밍 인터페이스(API 키)를 생성합니다.
e. watsonx.ai 런타임 서비스를 watsonx.ai에서 생성한 프로젝트에 연결합니다.
Cloud Object Storage
a. 노트북용으로 Cloud Object Storage를 만들려면 https://cloud.ibm.com/으로 이동한 후 '인스턴스 생성'을 선택합니다.
b. 요금제를 선택할 수 있는 생성 대화 상자로 이동합니다. 이 튜토리얼에서는 표준 요금제로 충분합니다.
c. 그런 다음 Cloud Object Storage 인스턴스에 이름을 지정합니다.
d. 인스턴스를 생성했으면 프로젝트로 돌아가서 '새 자산'을 선택한 다음 '데이터 소스에 연결'을 선택합니다.
e. 'Cloud Object Storage'를 선택합니다.
f. 다음 대화 상자에서 a~d 단계에서 생성한 인스턴스를 이름별로 선택합니다.
g. '만들기'를 선택합니다.
Jupyter Notebook을 만듭니다.
a. 프로젝트 환경에서 자산 탭을 선택합니다.
b. 새 자산을 클릭합니다.
c. 왼쪽 패널에서 모델 작업 옵션을 선택합니다.
d. Python 및 R 노트북을 사용하여 데이터 및 모델 작업을 클릭합니다.
e. 이름 필드에 노트북의 이름을 입력합니다. 런타임 23.1 on Python(4 vCPU 16GB RAM)을 선택하여 구성을 정의합니다.
f. 생성을 선택합니다.
다음으로 런타임에 종속성을 설치합니다. 먼저 llama-factory를 사용하여 하위 어댑터를 생성한 다음 Pandas를 사용하여 데이터 세트를 Alpaca 형식으로 포맷합니다.
!pip install -q llamafactory 2>/dev/null
# pandas needed to format the dataset
!pip install -q --upgrade pandas 2>/dev/null
다음으로 LLaMa-Factory를 사용하는 데 필요한 Torch 호환 GPU를 watsonx 환경에서 제공하는지 확인합니다.
import torch
try:
assert torch.cuda.is_available() is True
except AssertionError:
print("No GPU found, please set up a GPU before using LLaMA Factory.")
위 코드 스니펫에 'GPU를 찾을 수 없음'이 표시되지 않으면 정상입니다.
다음으로 라이브러리를 가져와서 데이터를 조작하고 학습에 사용되는 LLaMa Factory 구성 파일을 생성합니다.
# Import libraries
import pandas as pd
import json
import yaml
이 튜토리얼에서는 MedReason 데이터 세트의 일부를 사용합니다. MeDreason은 LLM에서 설명 가능한 의학적 문제 해결을 지원하도록 설계된 대규모 고품질 의료 추론 데이터 세트입니다. MedReason은 모델의 추론과 모델이 사용하는 생각의 연결고리를 검증하는 데 중점을 두지만, 이 경우 IBM® Granite 3.3의 학습 데이터에 포함하기에는 너무 최근의 데이터 세트를 제공하는 것도 도움이 됩니다.
Granite 3.3은 미세 조정을 통해 학습하도록 설계되었으며, 두 가지 모두 LLaMa Factory와 함께 실행됩니다. Granite 모델은 제한된 컴퓨팅 리소스로도 효율적으로 미세 조정할 수 있습니다.
GitHub에서 일부 MedReason 데이터 세트를 로드합니다.
from datasets import load_dataset
training = pd.read_json("https://raw.githubusercontent.com/UCSC-VLAA/MedReason/refs/heads/main/eval_data/medbullets_op4.jsonl", lines=True)
LLaMa Factory에서는 데이터 세트를 Alpaca 또는 ShareGPT 형식으로 미리 포맷해야 합니다. 따라서 원본 법적 데이터 세트의 질문과 답변 필드의 형식을 Alpaca 형식에 따라 명령어, 입력 및 아웃풋 필드를 포함하도록 다시 포맷합니다.
Alpaca는 명령어, 사용자 입력 및 시스템 아웃풋을 다음과 같이 표현하는 JSON 형식입니다.
{
"instruction": "user instruction (required)",
"input": "user input (optional)",
"output": "model response (required)",
"system": "system prompt (optional)",
}
MedReason은 Alpaca 형식이 아니므로 다음 셀에 Alpaca 데이터 세트를 생성합니다.
!mkdir -p data
# Format Med Dataset to Alpaca Format
formatted_data = [
{
"instruction": row["question"] + str(row["options"]),
"input": "",
"output": row["answer"]
}
for _, row in training.iterrows()
]
# output formatted MedReason dataset
with open("data/med.json", "w", encoding="utf-8") as f:
json.dump(formatted_data, f, indent=2, ensure_ascii=False)
Llama Factory는 특정 파일을 사용하여 학습용 데이터 세트를 로드하는 방법을 이해합니다. 이 파일은 data/dataset_info.json 경로에 존재해야 합니다. 따라서 데이터 세트에 액세스하려면 Llama Factory CLI를 위해 생성한 새 형식의 의료 데이터 세트 경로가 포함된 dataset_info.json 파일을 만들어야 합니다. dataset_info.json 파일에 대한 자세한 내용은 문서를 참조하세요. Llama Factory 리포지토리에는 사용할 수 있는 데이터 세트가 있지만, 자체 사용자 지정 데이터 세트를 사용하고 있기 때문에 데이터 세트를 JSON 파일에 추가해야 합니다.
# "med" will be the identifier for the dataset
# which points to the local file that contains the dataset
dataset_info = {
"med": {
"file_name": "med.json",
}
}
# Create dataset_info.json with legal dataset so can reference with llama factory
with open("data/dataset_info.json", "w", encoding="utf-8") as f:
json.dump(dataset_info, f, indent=2, ensure_ascii=False)
이제 Alpaca 형식의 JSON 객체가 환경에 저장되었으므로 교육을 시작할 준비가 되었습니다.
다음 단계는 훈련 구성을 설정한 다음 LLaMa-Factory가 훈련을 실행하는 데 사용하는 YAML 파일에 구성을 작성하는 것입니다.
이제 MedReason 데이터 세트의 하위 집합에 대해 SFT(감독 미세 조정)를 실행합니다. LLaMa Factory는 여러 가지 유형의 훈련을 지원합니다. 가장 일반적으로 사용되는 것 중 일부는 다음과 같습니다.
사전 훈련: 광범위한 데이터 세트를 사용하여 모델이 기본적인 언어와 아이디어에 대한 응답을 생성하는 초기 훈련을 거치는 유형입니다.
감독형 미세 조정(SFT): 특정 기능이나 특정 주제에 대한 정확도를 높이기 위해 주석이 달린 데이터로 모델에 추가 훈련을 제공하는 유형입니다.
보상 모델링: 모델이 특정 인센티브 또는 보상을 달성하는 방법에 대한 지식을 습득하여 아웃풋 프록시멀 정책 최적화(PPO)에 정보를 제공하는 유형입니다.
훈련: 특정 환경에서 모델의 효과를 높이기 위해 정책 경사 기법을 통해 모델을 더욱 연마하는 강화 학습(RL) 기법입니다.
LoRA를 구성하는 데 사용되는 설정은 여러 가지가 있지만 가장 중요하고 일반적으로 사용되는 몇 가지 설정은 다음과 같습니다.
학습 속도(LR): 학습 속도는 훈련을 반복할 때마다 각 모델 파라미터가 얼마나 크게 업데이트되는지를 결정합니다. LR이 높을수록 더 큰 업데이트를 허용하여 수렴 속도를 높일 수 있지만 최적의 솔루션을 초과하거나 그 주변에서 진동할 위험이 있습니다. LR이 낮을수록 수렴은 느리지만 더 안정적이어서 최적 솔루션 근처에서 불안정성의 위험을 줄입니다.
loraplus_lr_ratio: 학습률의 비율을 설정하는 단계입니다. 일반적으로 1>이어야 하지만 loraplus_lr_ratio의 최적 선택은 모델 및 작업에 따라 다릅니다. 지침으로, 작업이 더 어렵고 모델이 잘 학습하기 위해 기능을 업데이트해야 할 때 loraplus_lr_ratio는 더 커야 합니다. 이 경우 학습 속도를 일반적인 LoRA 학습률보다 약간 작게(예: 2배) 만드는 것이 도움이 됩니다.
유효 배치 크기: 배치 크기를 올바르게 구성하는 것은 훈련 안정성과 사용 중인 GPU의 VRAM 제한 사이의 균형을 맞추는 데 중요합니다. 유효 배치 크기는 per_device_train_batch_size * gradient_accumulation_steps의 곱으로 설정됩니다. 일반적으로 유효 배치 크기가 클수록 더 부드럽고 안정적인 훈련이 가능하지만 GPU에 포함된 것보다 더 많은 VRAM이 필요할 수도 있습니다. 유효 배치 크기가 작을수록 더 많은 편차가 발생할 수 있습니다.
학습을 구성하는 코드는 다음과 같습니다.
# setup training configurations
args = dict(
stage="sft", # do supervised fine-tuning
do_train=True, # we're actually training
model_name_or_path="ibm-granite/granite-3.3-2b-instruct", # use IBM Granite 3.3 2b instruct model
dataset="med", # use medical datasets we created
template="granite3", # use granite3 prompt template
finetuning_type="lora", # use LoRA adapters to save memory
lora_target="all", # attach LoRA adapters to all linear layers
loraplus_lr_ratio=16.0, # use LoRA+ algorithm with lambda=16.0
output_dir="granite3_lora", # the path to save LoRA adapters
per_device_train_batch_size=4, # the batch size
gradient_accumulation_steps=2, # the gradient accumulation steps
learning_rate=1e-4, # the learning rate
num_train_epochs=3.0, # the epochs of training
max_samples=500, # use 500 examples in each dataset
fp16=True, # use float16 mixed precision training
report_to="none", # disable wandb logging
)
# create training config file to run with llama factory
with open("train_granite3_lora_med.yaml", "w", encoding="utf-8") as file:
yaml.dump(args, file, indent=2)
다음 셀은 모델을 학습시키고 실행하는 데 최대 10분이 걸릴 수 있습니다.
!llamafactory-cli train train_granite3_lora_med.yaml;
다음으로 IBM® Cloud Object Storage에서 데이터를 업로드하고 다운로드하는 두 가지 메서드를 만듭니다.
from ibm_botocore.client import Config
import ibm_boto3
def upload_file_cos(credentials, local_file_name, key):
cos = ibm_boto3.client(service_name='s3',
ibm_api_key_id=credentials['IBM_API_KEY_ID'],
ibm_service_instance_id=credentials['IAM_SERVICE_ID'],
ibm_auth_endpoint=credentials['IBM_AUTH_ENDPOINT'],
config=Config(signature_version='oauth'),
endpoint_url=credentials['ENDPOINT'])
try:
res=cos.upload_file(Filename=local_file_name, Bucket=credentials['BUCKET'],Key=key)
except Exception as e:
print(Exception, e)
else:
print(' File Uploaded')
def download_file_cos(credentials,local_file_name,key):
cos = ibm_boto3.client(service_name='s3',
ibm_api_key_id=credentials['IBM_API_KEY_ID'],
ibm_service_instance_id=credentials['IAM_SERVICE_ID'],
ibm_auth_endpoint=credentials['IBM_AUTH_ENDPOINT'],
config=Config(signature_version='oauth'),
endpoint_url=credentials['ENDPOINT'])
try:
res=cos.download_file(Bucket=credentials['BUCKET'],Key=key,Filename=local_file_name)
except Exception as e:
print(Exception, e)
else:
print('File Downloaded')
다음 셀에는 Cloud Object Storage의 자격 증명이 포함됩니다.
노트북에서 오른쪽 구석의 코드 스니펫 탭을 클릭하세요. 이 단계에서는 생성된 코드 스니펫에 대한 여러 옵션이 있는 메뉴가 열립니다. "데이터 읽기"를 선택합니다.
이 단계에서는 데이터 파일을 선택할 수 있는 메뉴가 열립니다. Cloud Object Storage 인스턴스에 아무것도 업로드하지 않은 경우 자격 증명을 생성하기 위해 무언가를 업로드해야 하며, 이는 wine.csv와 같은 일반적인 데이터 세트일 수 있습니다.
'선택'을 클릭한 후 '다른 이름으로 로드' 옵션에서 자격 증명 스니펫을 생성할 수 있습니다. '셀에 코드 삽입'을 선택합니다.
이 단계에서는 올바른 ID와 엔드포인트가 포함된 자격 증명이 포함된 다음과 같은 셀이 생성됩니다.
# @hidden_cell
# The following code contains metadata for a file in your project storage.
# You might want to remove secret properties before you share your notebook.
storage_metadata = {
'IAM_SERVICE_ID': '',
'IBM_API_KEY_ID': '',
'ENDPOINT': '',
'IBM_AUTH_ENDPOINT': '',
'BUCKET': '',
'FILE': ''
}
이제 zip 폴더에 어댑터와 어댑터 자체에 대한 정보가 포함됩니다.
!zip -r "granite3_lora.zip" "granite3_lora"
zip이 올바르게 생성되었는지 확인합니다.
!ls
이제 추론을 실행할 차례입니다. 추론은 PyTorch를 사용하여 텍스트 생성을 위한 model.generate() 메서드를 제공하는 HuggingFace 생성을 통해 뒷받침됩니다.
이 튜토리얼에서는 기본 모델에 MedReason 데이터 세트에서 가져온 의료 관련 질문을 하는 방법을 보여 줍니다. 기본 모델은 대규모의 다양한 데이터 세트에서 학습된 범용 모델이기 때문에 이 질문에 답하지 못하는 것은 당연합니다.
먼저 추론 구성을 설정합니다.
# setup inference configurations
args = dict(
model_name_or_path="ibm-granite/granite-3.3-2b-instruct", # use IBM Granite 3.3 2b instruct model
template="granite3", # set to the same one used in training, template for constructing prompts
infer_backend="huggingface" # choices: [huggingface, vllm]
)
# create inference config file to run with llama factory
with open("inference_config.yaml", "w", encoding="utf-8") as file:
yaml.dump(args, file, indent=2)
이제 챗봇에게 MedReason 데이터 세트의 질문 중 하나를 물어봅니다.
from llamafactory.chat import ChatModel
chat_model = ChatModel(args)
messages = []
# run inference chatbot
question = '''
A 1-year-old girl is brought to a neurologist due to increasing seizure frequency over the past 2 months.
She recently underwent a neurology evaluation which revealed hypsarrhythmia on electroencephalography (EEG) with a mix of slow waves, multifocal spikes, and asynchrony.
Her parents have noticed the patient occasionally stiffens and spreads her arms at home. She was born at 38-weeks gestational age without complications.
She has no other medical problems. Her medications consist of lamotrigine and valproic acid. Her temperature is 98.3\u00b0F (36.8\u00b0C), blood pressure is 90/75 mmHg, pulse is 94/min, and respirations are 22/min.
Physical exam reveals innumerable hypopigmented macules on the skin and an irregularly shaped, thickened, and elevated plaque on the lower back.
Which of the following is most strongly associated with this patient's condition?"
"A": "Cardiac rhabdomyoma", "B": "Glaucoma", "C": "Optic glioma", "D": "Polyostotic fibrous dysplasia"
'''
질문을 사용하여 새 메시지를 만들어 기본 모델에 전달합니다.
messages.append({"role": "user", "content": question})
response = ""
for new_text in chat_model.stream_chat(messages):
response += new_text
print(response)
messages.append({"role": "assistant", "content": response})
다음은 기본 Granite 3.3 모델의 샘플 아웃풋입니다.
사용자:
A 1-year-old girl is brought to a neurologist due to increasing seizure frequency over the past 2 months.
She recently underwent a neurology evaluation which revealed hypsarrhythmia on electroencephalography (EEG) with a mix of slow waves, multifocal spikes, and asynchrony.
Her parents have noticed the patient occasionally stiffens and spreads her arms at home. She was born at 38-weeks gestational age without complications.
She has no other medical problems. Her medications consist of lamotrigine and valproic acid. Her temperature is 98.3\F (36.8\C), blood pressure is 90/75 mmHg, pulse is 94/min, and respirations are 22/min.
Physical exam reveals innumerable hypopigmented macules on the skin and an irregularly shaped, thickened, and elevated plaque on the lower back.
Which of the following is most strongly associated with this patient's condition?"
"A": "Cardiac rhabdomyoma", "B": "Glaucoma", "C": "Optic glioma", "D": "Polyostotic fibrous dysplasia"
응답:
The most strongly associated condition with this patient's condition is "C": "Optic glioma".
The patient's symptoms of hypsarrhythmia on EEG, seizure frequency increase, and the presence of hypopigmented macules and a thickened plaque on the lower back are indicative of a neurological disorder. Optic glioma is a type of brain tumor that can present with these symptoms, including seizures and visual disturbances.
Option A, "Cardiac rhabdomyoma", typically presents with cardiac involvement and is not associated with the described EEG findings or skin manifestations.
Option B, "Glaucoma", is an eye disease that can lead to vision loss but is not associated with the EEG findings or skin lesions described.
Option D, "Polyostotic fibrous dysplasia", is a bone disorder characterized by multiple bone lesions and is not associated with the neurological symptoms and EEG findings presented.
Therefore, based on the clinical presentation, the most likely diagnosis is an optic glioma.
데이터 세트의 올바른 응답은 다음과 같습니다.
answer: Cardiac rhabdomyoma
따라서 기본 모델은 올바른 답을 생성하지 않습니다.
기본 모델과 LoRA 조정된 어댑터로 실행하여 결과를 비교합니다. 그런 다음 동일한 질문을 통해 법률 데이터 세트를 사용하여 모델이 의료 문제를 더 잘 이해하고 이에 대한 답을 얻을 수 있는 방법을 살펴봅니다.
동일한 세션에서 LoRA를 수행한 경우 다음 셀이 필요하지 않습니다. 하지만 Jupyter Notebook으로 돌아가 재학습을 원하지 않는 경우 COS 인스턴스에서 미세 조정된 어댑터를 다운로드할 수 있습니다.
download_file_cos(credentials, "granite3_lora.zip", "granite3_lora.zip")
!unzip granite3_lora.zip
이제 어댑터를 통합할 수 있도록 ChatModel에 대한 옵션을 구성합니다.
# setup inference configurations
args = dict(
model_name_or_path="ibm-granite/granite-3.3-2b-instruct", # use IBM Granite 3.3 2b instruct model
adapter_name_or_path="granite3_lora", # load the saved LoRA adapters
template="granite3", # set to the same one used in training, template for constructing prompts
finetuning_type="lora", # which fine-tuning technique used in training
infer_backend="huggingface" # choices: [huggingface, vllm]
)
# create inference config file to run with llama factory
with open("inference_config.yaml", "w", encoding="utf-8") as file:
yaml.dump(args, file, indent=2)
from llamafactory.chat import ChatModel
chat_model = ChatModel(args)
이제 미세 조정된 모델에 대해 동일한 추론 과제를 테스트할 수 있습니다.
messages = []
# run inference chatbot
question = '''
A 1-year-old girl is brought to a neurologist due to increasing seizure frequency over the past 2 months.
She recently underwent a neurology evaluation which revealed hypsarrhythmia on electroencephalography (EEG) with a mix of slow waves, multifocal spikes, and asynchrony.
Her parents have noticed the patient occasionally stiffens and spreads her arms at home. She was born at 38-weeks gestational age without complications.
She has no other medical problems. Her medications consist of lamotrigine and valproic acid. Her temperature is 98.3\u00b0F (36.8\u00b0C), blood pressure is 90/75 mmHg, pulse is 94/min, and respirations are 22/min.
Physical exam reveals innumerable hypopigmented macules on the skin and an irregularly shaped, thickened, and elevated plaque on the lower back.
Which of the following is most strongly associated with this patient's condition?"
"A": "Cardiac rhabdomyoma", "B": "Glaucoma", "C": "Optic glioma", "D": "Polyostotic fibrous dysplasia"
'''
질문을 사용하여 새 메시지를 만들고 미세 조정된 모델에 전달합니다.
messages.append({"role": "user", "content": question})
response = ""
for new_text in chat_model.stream_chat(messages):
response += new_text
print(response)
messages.append({"role": "assistant", "content": response})
Cardiac rhabdomyoma
사용자:
A 1-year-old girl is brought to a neurologist due to increasing seizure frequency over the past 2 months.
She recently underwent a neurology evaluation which revealed hypsarrhythmia on electroencephalography (EEG) with a mix of slow waves, multifocal spikes, and asynchrony.
Her parents have noticed the patient occasionally stiffens and spreads her arms at home. She was born at 38-weeks gestational age without complications.
She has no other medical problems. Her medications consist of lamotrigine and valproic acid. Her temperature is 98.3\u00b0F (36.8\u00b0C), blood pressure is 90/75 mmHg, pulse is 94/min, and respirations are 22/min.
Physical exam reveals innumerable hypopigmented macules on the skin and an irregularly shaped, thickened, and elevated plaque on the lower back.
Which of the following is most strongly associated with this patient's condition?"
"A": "Cardiac rhabdomyoma", "B": "Glaucoma", "C": "Optic glioma", "D": "Polyostotic fibrous dysplasia"
응답:
Cardiac rhabdomyoma
이번에는 학습된 어댑터 덕분에 모델이 정답을 생성했습니다.
한 가지 주목할 점은 모델이 더 이상 추론으로 응답하지 않는다는 것입니다. 이 결과는 LoRa에 사용된 데이터 세트가 예상 모델 아웃풋으로 정답만 가지고 있기 때문입니다. LoRA 미세 조정은 새로운 정보를 제공할 뿐만 아니라 모델에 응답 방법을 지시하는 데에도 사용할 수 있습니다.
이 튜토리얼에서는 새로운 의학 지식과 대응 방법에 대한 자세한 템플릿으로 LoRA가 IBM Granite-3.3-2b-Instruct 모델을 미세 조정했습니다. 소규모 모델과 데이터 세트의 제한된 샘플로도 Granite 3.3의 학습 능력을 확인했습니다.
watsonx 포트폴리오의 IBM 파운데이션 모델 라이브러리에 대해 자세히 알아보고 비즈니스를 위한 생성형 AI를 자신 있게 확장하세요.
업계 최고의 AI 전문성과 솔루션 포트폴리오를 보유한 IBM과 함께 AI를 비즈니스에 활용하세요.
AI 추가를 통해 중요한 워크플로와 운영을 혁신함으로써 경험, 실시간 의사 결정 및 비즈니스 가치를 극대화하세요.