MedGemma là bộ sưu tập các biến thể Gemma 3 được thiết kế để vượt trội trong việc hiểu văn bản và hình ảnh y khoa. Bộ sưu tập hiện gồm hai biến thể mạnh mẽ: phiên bản đa phương thức 4B và phiên bản chỉ văn bản 27B.
Mô hình MedGemma 4B kết hợp bộ mã hoá hình ảnh SigLIP, được tiền huấn luyện trên các bộ dữ liệu y khoa đa dạng, đã được ẩn danh như X-quang ngực, ảnh da liễu, ảnh nhãn khoa và lát cắt mô bệnh học, cùng với một mô hình ngôn ngữ lớn (LLM) được huấn luyện trên lượng dữ liệu y khoa phong phú.
Trong hướng dẫn này, chúng ta sẽ học cách tinh chỉnh mô hình MedGemma 4B trên một bộ dữ liệu MRI não cho bài toán phân loại ảnh. Mục tiêu là điều chỉnh mô hình MedGemma 4B nhỏ hơn để phân loại hiệu quả các ảnh chụp MRI não và dự đoán ung thư não với độ chính xác và hiệu quả cao hơn.
Thiết lập môi trường
RunPod là nền tảng tuyệt vời để chạy khối lượng công việc dùng GPU, cung cấp môi trường cấu hình sẵn với hỗ trợ JupyterLab. Điều này cho phép bạn khởi chạy một pod và bắt đầu viết mã ngay bằng trình soạn thảo ưa thích. Cách thiết lập môi trường như sau:
1. Thiết lập RunPod
Đăng nhập vào RunPod và tạo một pod với GPU A100 và image PyTorch mới nhất. Sau đó, nhấp nút "Deploy On-Demand" để khởi chạy pod.
Chỉnh sửa pod và thêm các biến môi trường sau để tích hợp với Hugging Face và Kaggle:
HF_TOKEN
KAGGLE_USERNAME
KAGGLE_KEY
Tăng dung lượng lưu trữ lên 100GB để chứa bộ dữ liệu và checkpoint mô hình
2. Cài đặt các gói Python
Khi pod đã chạy, mở JupyterLab bằng cách nhấp nút "Connect". Tạo một notebook Python mới và cài đặt các gói cần thiết bằng lệnh sau:
Chúng ta sẽ dùng bộ dữ liệu MRI Brain Cancer từ Kaggle.
3. Tải bộ dữ liệu
Tải và giải nén bộ dữ liệu bằng Kaggle CLI:
!kaggle datasets download -d orvile/brain-cancer-mri-dataset --unzipĐược hỗ trợ bởi
Dataset URL: https://www.kaggle.com/datasets/orvile/brain-cancer-mri-dataset
License(s): CC-BY-SA-4.0
Downloading brain-cancer-mri-dataset.zip to /workspace
90%|████████████████████████████████████▉ | 130M/144M [00:00<00:00, 231MB/s]100%|█████████████████████████████████████████| 144M/144M [00:01<00:00, 108MB/s]Được hỗ trợ bởi
4. Nạp bộ dữ liệu
Nạp bộ dữ liệu dưới dạng bộ dữ liệu Hugging Face, chia thành tập huấn luyện và tập validation, và hiển thị cấu trúc:
from datasets import load_dataset
data_dir ="./Brain_Cancer raw MRI data/Brain_Cancer"# Define proportions for train and validation splits
train_size =0.8
validation_size =0.2
data = load_dataset("imagefolder", data_dir=data_dir, split="train")# Split the dataset into train and validation sets
data = data.train_test_split(
train_size=train_size,
test_size=validation_size,
shuffle=True,
seed=42,)# Rename the 'test' split to 'validation'
data["validation"]= data.pop("test")# Display dataset detailsprint(data)Được hỗ trợ bởi
Trước khi xử lý bộ dữ liệu, điều quan trọng là kiểm tra tên các nhãn để đảm bảo xử lý đúng bài toán phân loại.
BRAIN_CANCER_CLASSES = data["train"].features["label"].names
print("Detected classes:", BRAIN_CANCER_CLASSES)Được hỗ trợ bởi
Các lớp được phát hiện là: ['brain_glioma', 'brain_menin', 'brain_tumor'].
Detected classes:['brain_glioma','brain_menin','brain_tumor']Được hỗ trợ bởi
Để nâng cao quá trình phân loại, chúng ta sẽ chỉnh sửa các nhãn lớp này bằng cách thêm tiền tố (A, B, C) để tổ chức tốt hơn và phù hợp với định dạng prompt tuỳ chỉnh.
Tiếp theo, chúng ta tạo một prompt tuỳ chỉnh để hướng dẫn mô hình trong quá trình tinh chỉnh. Prompt này bao gồm các nhãn lớp đã cập nhật.
options ="\n".join(BRAIN_CANCER_CLASSES)
PROMPT =f"What is the most likely type of brain cancer shown in the MRI image?\n{options}"Được hỗ trợ bởi
Để chuẩn bị bộ dữ liệu cho tinh chỉnh, chúng ta sẽ tạo cột mới tên "messages". Cột này chứa dữ liệu có cấu trúc gồm truy vấn của người dùng (prompt) và phản hồi của trợ lý (nhãn đúng).
defformat_data(example:dict[str,any])->dict[str,any]:
example["messages"]=[{"role":"user","content":[{"type":"image",},{"type":"text","text": PROMPT,},],},{"role":"assistant","content":[{"type":"text","text": BRAIN_CANCER_CLASSES[example["label"]],},],},]return example
# Apply the formatting to the dataset
formatted_data = data.map(format_data)Được hỗ trợ bởi
Để kiểm tra định dạng, chúng ta có thể xem cột message từ mẫu đầu tiên:
[{'content':[{'text':None,'type':'image'},{'text':'What is the most likely type of brain cancer shown in the MRI image?\nA: brain glioma\nB: brain menin\nC: brain tumor','type':'text'}],'role':'user'},{'content':[{'text':'B: brain menin','type':'text'}],'role':'assistant'}]Được hỗ trợ bởi
Tinh chỉnh MedGemma trên bộ dữ liệu MRI não
Trong phần này, chúng ta sẽ tinh chỉnh mô hình MedGemma 4B Instruct trên bộ dữ liệu MRI não. Quy trình gồm tải mô hình và processor, thiết lập bộ điều hợp LoRA, cấu hình trainer và bắt đầu huấn luyện.
6. Nạp mô hình và tokenizer
Vì MedGemma là mô hình có kiểm soát quyền truy cập, bạn cần đăng nhập Hugging Face CLI bằng API key. Điều này cũng cho phép bạn lưu mô hình đã tinh chỉnh lên Hugging Face Hub. Xem lại khoá học Làm việc với Hugging Face: Hướng dẫn sử dụng Hub nếu bạn cần ôn lại.
from huggingface_hub import login
import os
hf_token = os.environ.get("HF_TOKEN")
login(hf_token)Được hỗ trợ bởi
Chúng ta dùng thư viện Transformers để nạp mô hình MedGemma 4B Instruct và processor của nó. Mô hình được cấu hình dùng độ chính xác bfloat16 để tính toán hiệu quả trên GPU.
import torch
from transformers import AutoProcessor, AutoModelForImageTextToText, BitsAndBytesConfig
model_id ="google/medgemma-4b-it"# Check if GPU supports bfloat16if torch.cuda.get_device_capability()[0]<8:raise ValueError("GPU does not support bfloat16, please use a GPU that supports bfloat16.")
model_kwargs =dict(
attn_implementation="eager",
torch_dtype=torch.bfloat16,
device_map="auto",)
model = AutoModelForImageTextToText.from_pretrained(model_id,**model_kwargs)
processor = AutoProcessor.from_pretrained(model_id)# Use right padding to avoid issues during training
processor.tokenizer.padding_side ="right"Được hỗ trợ bởi
7. Thiết lập mô hình
Để tinh chỉnh hiệu quả MedGemma 4B Instruct, chúng ta sẽ dùng Low-Rank Adaptation (LoRA), một phương pháp tinh chỉnh hiệu quả theo tham số.
LoRA cho phép điều chỉnh các mô hình lớn bằng cách chỉ huấn luyện một lượng nhỏ tham số bổ sung, giúp giảm đáng kể chi phí tính toán mà vẫn duy trì hiệu năng.
from peft import LoraConfig
peft_config = LoraConfig(
lora_alpha=16,
lora_dropout=0.05,
r=16,
bias="none",
target_modules="all-linear",
task_type="CAUSAL_LM",
modules_to_save=["lm_head","embed_tokens",],)Được hỗ trợ bởi
Để xử lý đồng thời đầu vào hình ảnh và văn bản trong quá trình huấn luyện, chúng ta định nghĩa một hàm gom lô tuỳ chỉnh. Hàm này xử lý các ví dụ trong bộ dữ liệu thành định dạng phù hợp với mô hình, bao gồm token hoá văn bản và chuẩn bị dữ liệu hình ảnh.
defcollate_fn(examples:list[dict[str,any]]):
texts =[]
images =[]for example in examples:
images.append([example["image"]])
texts.append(
processor.apply_chat_template(
example["messages"], add_generation_prompt=False, tokenize=False).strip())# Tokenize the texts and process the images
batch = processor(text=texts, images=images, return_tensors="pt", padding=True)# The labels are the input_ids, with the padding and image tokens masked in# the loss computation
labels = batch["input_ids"].clone()# Mask image tokens
image_token_id =[
processor.tokenizer.convert_tokens_to_ids(
processor.tokenizer.special_tokens_map["boi_token"])]# Mask tokens that are not used in the loss computation
labels[labels == processor.tokenizer.pad_token_id]=-100
labels[labels == image_token_id]=-100
labels[labels ==262144]=-100
batch["labels"]= labels
return batchĐược hỗ trợ bởi
Chúng ta dùng lớp SFTConfig từ thư viện trl để định nghĩa các tham số huấn luyện. Những tham số này điều khiển quá trình tinh chỉnh, bao gồm kích thước batch, learning rate và số bước tích luỹ gradient.
SFTTrainer đơn giản hoá quá trình tinh chỉnh bằng cách kết hợp mô hình, bộ dữ liệu, bộ gom dữ liệu, tham số huấn luyện và cấu hình LoRA vào một quy trình duy nhất, giúp thao tác gọn gàng và thân thiện.
from trl import SFTTrainer
trainer = SFTTrainer(
model=model,
args=args,
train_dataset=formatted_data["train"],
eval_dataset=formatted_data["validation"].shuffle().select(range(50)),
peft_config=peft_config,
processing_class=processor,
data_collator=collate_fn,)Được hỗ trợ bởi
8. Huấn luyện mô hình
Khi mô hình, bộ dữ liệu và cấu hình huấn luyện đã sẵn sàng, chúng ta có thể bắt đầu tinh chỉnh. SFTTrainer giúp bước này trở nên đơn giản, cho phép huấn luyện chỉ với một lệnh:
Quá trình huấn luyện mất khoảng 1 giờ 8 phút để hoàn thành. Trong thời gian này, loss huấn luyện và loss validation giảm đều theo từng bước, cho thấy mô hình học hiệu quả.
Sau khi huấn luyện xong, mô hình đã tinh chỉnh có thể được lưu cục bộ và đẩy lên Hugging Face Hub bằng phương thức save_model().
Để đánh giá hiệu năng của MedGemma 4B, chúng ta sẽ kiểm thử cả mô hình gốc và mô hình đã tinh chỉnh trên tập validation. Quy trình gồm giải phóng bộ nhớ, chuẩn bị dữ liệu kiểm thử, sinh phản hồi và tính các chỉ số chính như accuracy và F1.
Trước khi bắt đầu đánh giá, ta loại bỏ thiết lập huấn luyện để giải phóng bộ nhớ GPU và đảm bảo môi trường sạch cho kiểm thử
del model
del trainer
torch.cuda.empty_cache()Được hỗ trợ bởi
9. Thiết lập để kiểm thử mô hình
Chúng ta định dạng lại tập validation để khớp với cấu trúc đầu vào mô hình yêu cầu. Điều này bao gồm tạo cột "messages" chứa prompt cho mỗi ví dụ.
defformat_test_data(example:dict[str,any])->dict[str,any]:
example["messages"]=[{"role":"user","content":[{"type":"image",},{"type":"text","text": PROMPT,},],},]return example
test_data = data["validation"]
test_data = test_data.map(format_test_data)Được hỗ trợ bởi
Để đánh giá hiệu năng mô hình, chúng ta dùng thư viện evaluate, cung cấp sẵn các chỉ số cho bài toán phân loại. Sau khi import và nạp các chỉ số cần thiết, chúng ta trích xuất nhãn ground-truth từ tập kiểm thử. Một hàm hỗ trợ compute_metrics được định nghĩa để tính accuracy và F1 bằng cách so sánh dự đoán với các nhãn này.
Để đảm bảo nhất quán trong xử lý nhãn, chúng ta ép cột "label" của bộ dữ liệu sang kiểu ClassLabel. Điều này cho phép ánh xạ hiệu quả giữa chỉ số nhãn và tên tương ứng. Ngoài ra, chúng ta định nghĩa ánh xạ nhãn thay thế để xử lý biến thể định dạng nhãn trong hậu xử lý.
from datasets import ClassLabel
test_data = test_data.cast_column("label",
ClassLabel(names=BRAIN_CANCER_CLASSES))
LABEL_FEATURE = test_data.features["label"]
ALT_LABELS =dict([(label,f"({label.replace(': ',') ')}")for label in BRAIN_CANCER_CLASSES
])Được hỗ trợ bởi
Để ánh xạ dự đoán của mô hình sang nhãn lớp đúng, chúng ta định nghĩa hàm postprocess. Hàm này đảm bảo dự đoán được khớp với nhãn phù hợp, tính đến cả định dạng nhãn chuẩn và thay thế.
defpostprocess(prediction, do_full_match:bool=False)->int:ifisinstance(prediction,str):
response_text = prediction
else:
response_text = prediction[0]["generated_text"]if do_full_match:return LABEL_FEATURE.str2int(response_text)for label in BRAIN_CANCER_CLASSES:# accept canonical or alternative wordingif label in response_text or ALT_LABELS[label]in response_text:return LABEL_FEATURE.str2int(label)return-1Được hỗ trợ bởi
10. Hiệu năng mô hình gốc
Để đánh giá hiệu năng mô hình gốc, chúng ta nạp mô hình và processor đã tiền huấn luyện, cấu hình tham số sinh, và chuẩn bị prompt cùng hình ảnh để kiểm thử.
import torch
from transformers import AutoModelForImageTextToText, AutoProcessor
model_kwargs =dict(
torch_dtype=torch.bfloat16,
device_map="auto",)
model = AutoModelForImageTextToText.from_pretrained(
model_id,**model_kwargs
)from transformers import GenerationConfig
gen_cfg = GenerationConfig.from_pretrained(model_id)
gen_cfg.update(
do_sample =False,
top_k =None,
top_p =None,
cache_implementation ="dynamic")
model.generation_config = gen_cfg
processor = AutoProcessor.from_pretrained(args.output_dir)
tok = processor.tokenizer
model.config.pad_token_id = tok.pad_token_id
model.generation_config.pad_token_id = tok.pad_token_id
defchat_to_prompt(chat_turns):return processor.apply_chat_template(
chat_turns,
add_generation_prompt=True,# tells the model "your turn"
tokenize=False# we want raw text, not ids)
prompts =[chat_to_prompt(c)for c in test_data["messages"]]
images = test_data["image"]# already a list of PIL imagesassertlen(prompts)==len(images),"1 prompt must match 1 image!"Được hỗ trợ bởi
Chúng ta đã tạo hàm batch_predict để xử lý tập kiểm thử theo lô. Hàm này sinh dự đoán cho từng cặp prompt-hình ảnh và áp dụng hậu xử lý để ánh xạ đầu ra về nhãn đúng.
import torch
from typing import List, Any, Callable
defbatch_predict(
prompts,
images,
model,
processor,
postprocess,*,
batch_size=64,
device="cuda",
dtype=torch.bfloat16,**gen_kwargs
):
preds =[]for i inrange(0,len(prompts), batch_size):
texts = prompts[i : i + batch_size]
imgs =[[img]for img in images[i : i + batch_size]]
enc = processor(text=texts, images=imgs, padding=True, return_tensors="pt").to(
device, dtype=dtype
)
lens = enc["attention_mask"].sum(dim=1)with torch.inference_mode():
out = model.generate(**enc,
disable_compile=True,**gen_kwargs
)for seq, ln inzip(out, lens):
ans = processor.decode(seq[ln:], skip_special_tokens=True)
preds.append(postprocess(ans))return predsĐược hỗ trợ bởi
Chúng ta sẽ dùng hàm batch_predict để sinh dự đoán cho mô hình gốc trên tập kiểm thử. Các dự đoán sau đó được đánh giá bằng hàm compute_metrics.
bf_preds = batch_predict(
model = model,
processor = processor,
prompts = prompts,
images = images,
batch_size =64,
max_new_tokens=40,# forwarded to generate
postprocess= postprocess,# your label-mapping function)
bf_metrics = compute_metrics(bf_preds)print(f"Baseline metrics: {bf_metrics}")Được hỗ trợ bởi
Kết quả không ấn tượng. Độ chính xác đạt 33%, khá thấp.
Baseline metrics:{'accuracy':0.33745874587458746,'f1':0.1737287617650654}Được hỗ trợ bởi
Để hiểu rõ hơn hành vi của mô hình, chúng ta có thể sinh dự đoán cho một ví dụ đơn lẻ từ bộ dữ liệu. Điều này liên quan đến việc tạo một hàm hỗ trợ để xử lý đầu vào và trả về phản hồi của mô hình.
Hàm predict_one nhận prompt và hình ảnh làm đầu vào, xử lý bằng processor của mô hình và sinh phản hồi. Hàm đảm bảo đầu ra của mô hình được giải mã thành văn bản dễ đọc.
Chúng ta sẽ dùng predict_one để sinh phản hồi cho mẫu thứ 11 trong bộ dữ liệu. Việc này bao gồm chuẩn bị prompt và chạy hàm dự đoán.
idx =10
chat = test_data["messages"][idx]
prompt = processor.apply_chat_template(
chat,
add_generation_prompt=True,
tokenize=False)# run the one-sample helper
answer = predict_one(
prompt = prompt,
image = test_data["image"][idx],
model = model,
processor= processor,
max_new_tokens =40)print("Model answer:", answer)Được hỗ trợ bởi
Kết quả là chúng ta nhận được một câu dài giải thích lý do chọn glioma. Phản hồi hoàn toàn sai, kể cả phân loại cũng sai.
Model answer: Based on the MRI image, the most likely type of brain cancer is**A: brain glioma**.
Here's why:***Gliomas** are a common type of brain tumorĐược hỗ trợ bởi
11. Hiệu năng mô hình đã tinh chỉnh
Để đánh giá mô hình đã tinh chỉnh, chúng ta lặp lại quy trình đánh giá bằng cách nạp mô hình từ thư mục đầu ra, sinh dự đoán và tính các chỉ số.
Chúng ta nạp mô hình và processor đã tinh chỉnh từ thư mục đầu ra, chạy hàm batch_predict và tính toán các chỉ số.
model = AutoModelForImageTextToText.from_pretrained(
args.output_dir,**model_kwargs
)
model.generation_config = gen_cfg
processor = AutoProcessor.from_pretrained(args.output_dir)
tok = processor.tokenizer
model.config.pad_token_id = tok.pad_token_id
model.generation_config.pad_token_id = tok.pad_token_id
af_preds = batch_predict(
model = model,
processor = processor,
prompts = prompts,
images = images,
batch_size =64,
max_new_tokens=40,# forwarded to generate
postprocess= postprocess,# your label-mapping function)
af_metrics = compute_metrics(af_preds)print(f"Fine-tuned metrics: {af_metrics}")Được hỗ trợ bởi
Các kết quả cho thấy sự cải thiện đáng kể so với mô hình gốc, nhấn mạnh hiệu quả của tinh chỉnh. Độ chính xác tăng từ 33% lên 89% chỉ với 1 epoch.
Fine-tuned metrics:{'accuracy':0.8927392739273927,'f1':0.892641793935792}Được hỗ trợ bởi
Để phân tích sâu hơn hiệu năng của mô hình đã tinh chỉnh, chúng ta sinh dự đoán cho một ví dụ đơn lẻ từ tập kiểm thử.
idx =10
chat = test_data["messages"][idx]
prompt = processor.apply_chat_template(
chat,
add_generation_prompt=True,
tokenize=False)# run the one-sample helper
answer = predict_one(
prompt = prompt,
image = test_data["image"][idx],
model = model,
processor= processor,
max_new_tokens =40# any generate-kwargs you need)print("Model answer:", answer)Được hỗ trợ bởi
Mô hình đưa ra kết quả rõ ràng và chính xác, phần phân loại đúng và trình bày gọn gàng.
MedGemma đại diện cho một bước tiến đáng kể trong việc ứng dụng AI cho khoa học y tế. Bằng cách hỗ trợ bác sĩ đưa ra quyết định nhanh và chính xác hơn, nó giúp chẩn đoán kịp thời và lập kế hoạch điều trị hiệu quả cho bệnh nhân.
Tinh chỉnh các mô hình ngôn ngữ-thị giác như MedGemma 4B Instruct cho phép thích ứng trên nhiều tác vụ y khoa, từ phân loại ảnh đến tích hợp khả năng suy luận.
Trong hướng dẫn này, chúng ta đã học cách tinh chỉnh một mô hình ngôn ngữ-thị giác trên bộ dữ liệu MRI não để phân loại ung thư não. Kết quả rất ấn tượng, độ chính xác của mô hình tăng từ 33% lên 89%, một bước nhảy lớn cho thấy tiềm năng của tinh chỉnh trong các ứng dụng AI y tế.
Nếu bạn quan tâm tìm hiểu thêm, tôi khuyến nghị xem các tài nguyên sau:
Là một nhà khoa học dữ liệu được chứng nhận, tôi đam mê tận dụng công nghệ tiên tiến để tạo ra các ứng dụng học máy đổi mới. Với nền tảng vững chắc về nhận dạng giọng nói, phân tích và báo cáo dữ liệu, MLOps, AI hội thoại và NLP, tôi đã rèn giũa kỹ năng phát triển các hệ thống thông minh có thể tạo ra tác động thực sự. Bên cạnh chuyên môn kỹ thuật, tôi cũng là một người truyền đạt tốt, có khả năng chắt lọc các khái niệm phức tạp thành ngôn ngữ rõ ràng, súc tích. Nhờ đó, tôi trở thành một blogger được nhiều người quan tâm trong lĩnh vực khoa học dữ liệu, chia sẻ góc nhìn và kinh nghiệm với cộng đồng các chuyên gia dữ liệu ngày càng lớn. Hiện tại, tôi tập trung vào sáng tạo và biên tập nội dung, làm việc với các mô hình ngôn ngữ lớn để phát triển nội dung mạnh mẽ và hấp dẫn, giúp doanh nghiệp và cá nhân tận dụng tối đa dữ liệu của mình.
MedGemma là bộ sưu tập các biến thể Gemma 3 được thiết kế để vượt trội trong việc hiểu văn bản và hình ảnh y khoa. Bộ sưu tập hiện gồm hai biến thể mạnh mẽ: phiên bản đa phương thức 4B và phiên bản chỉ văn bản 27B.
Mô hình MedGemma 4B kết hợp bộ mã hoá hình ảnh SigLIP, được tiền huấn luyện trên các bộ dữ liệu y khoa đa dạng, đã được ẩn danh như X-quang ngực, ảnh da liễu, ảnh nhãn khoa và lát cắt mô bệnh học, cùng với một mô hình ngôn ngữ lớn (LLM) được huấn luyện trên lượng dữ liệu y khoa phong phú.
Trong hướng dẫn này, chúng ta sẽ học cách tinh chỉnh mô hình MedGemma 4B trên một bộ dữ liệu MRI não cho bài toán phân loại ảnh. Mục tiêu là điều chỉnh mô hình MedGemma 4B nhỏ hơn để phân loại hiệu quả các ảnh chụp MRI não và dự đoán ung thư não với độ chính xác và hiệu quả cao hơn.
Thiết lập môi trường
RunPod là nền tảng tuyệt vời để chạy khối lượng công việc dùng GPU, cung cấp môi trường cấu hình sẵn với hỗ trợ JupyterLab. Điều này cho phép bạn khởi chạy một pod và bắt đầu viết mã ngay bằng trình soạn thảo ưa thích. Cách thiết lập môi trường như sau:
1. Thiết lập RunPod
Đăng nhập vào RunPod và tạo một pod với GPU A100 và image PyTorch mới nhất. Sau đó, nhấp nút "Deploy On-Demand" để khởi chạy pod.
Chỉnh sửa pod và thêm các biến môi trường sau để tích hợp với Hugging Face và Kaggle:
Tăng dung lượng lưu trữ lên 100GB để chứa bộ dữ liệu và checkpoint mô hình
2. Cài đặt các gói Python
Khi pod đã chạy, mở JupyterLab bằng cách nhấp nút "Connect". Tạo một notebook Python mới và cài đặt các gói cần thiết bằng lệnh sau:
Nạp và xử lý bộ dữ liệu
Chúng ta sẽ dùng bộ dữ liệu MRI Brain Cancer từ Kaggle.
3. Tải bộ dữ liệu
Tải và giải nén bộ dữ liệu bằng Kaggle CLI:
4. Nạp bộ dữ liệu
Nạp bộ dữ liệu dưới dạng bộ dữ liệu Hugging Face, chia thành tập huấn luyện và tập validation, và hiển thị cấu trúc:
Đầu ra:
Kiểm tra ảnh đầu tiên và nhãn tương ứng từ tập huấn luyện:
5. Xử lý bộ dữ liệu
Trước khi xử lý bộ dữ liệu, điều quan trọng là kiểm tra tên các nhãn để đảm bảo xử lý đúng bài toán phân loại.
Các lớp được phát hiện là: ['brain_glioma', 'brain_menin', 'brain_tumor'].
Để nâng cao quá trình phân loại, chúng ta sẽ chỉnh sửa các nhãn lớp này bằng cách thêm tiền tố (A, B, C) để tổ chức tốt hơn và phù hợp với định dạng prompt tuỳ chỉnh.
Tiếp theo, chúng ta tạo một prompt tuỳ chỉnh để hướng dẫn mô hình trong quá trình tinh chỉnh. Prompt này bao gồm các nhãn lớp đã cập nhật.
Để chuẩn bị bộ dữ liệu cho tinh chỉnh, chúng ta sẽ tạo cột mới tên "messages". Cột này chứa dữ liệu có cấu trúc gồm truy vấn của người dùng (prompt) và phản hồi của trợ lý (nhãn đúng).
Để kiểm tra định dạng, chúng ta có thể xem cột message từ mẫu đầu tiên:
Điểm dữ liệu đã định dạng trông như sau:
Tinh chỉnh MedGemma trên bộ dữ liệu MRI não
Trong phần này, chúng ta sẽ tinh chỉnh mô hình MedGemma 4B Instruct trên bộ dữ liệu MRI não. Quy trình gồm tải mô hình và processor, thiết lập bộ điều hợp LoRA, cấu hình trainer và bắt đầu huấn luyện.
6. Nạp mô hình và tokenizer
Vì MedGemma là mô hình có kiểm soát quyền truy cập, bạn cần đăng nhập Hugging Face CLI bằng API key. Điều này cũng cho phép bạn lưu mô hình đã tinh chỉnh lên Hugging Face Hub. Xem lại khoá học Làm việc với Hugging Face: Hướng dẫn sử dụng Hub nếu bạn cần ôn lại.
Chúng ta dùng thư viện Transformers để nạp mô hình MedGemma 4B Instruct và processor của nó. Mô hình được cấu hình dùng độ chính xác bfloat16 để tính toán hiệu quả trên GPU.
7. Thiết lập mô hình
Để tinh chỉnh hiệu quả MedGemma 4B Instruct, chúng ta sẽ dùng Low-Rank Adaptation (LoRA), một phương pháp tinh chỉnh hiệu quả theo tham số.
LoRA cho phép điều chỉnh các mô hình lớn bằng cách chỉ huấn luyện một lượng nhỏ tham số bổ sung, giúp giảm đáng kể chi phí tính toán mà vẫn duy trì hiệu năng.
Để xử lý đồng thời đầu vào hình ảnh và văn bản trong quá trình huấn luyện, chúng ta định nghĩa một hàm gom lô tuỳ chỉnh. Hàm này xử lý các ví dụ trong bộ dữ liệu thành định dạng phù hợp với mô hình, bao gồm token hoá văn bản và chuẩn bị dữ liệu hình ảnh.
Chúng ta dùng lớp SFTConfig từ thư viện trl để định nghĩa các tham số huấn luyện. Những tham số này điều khiển quá trình tinh chỉnh, bao gồm kích thước batch, learning rate và số bước tích luỹ gradient.
SFTTrainer đơn giản hoá quá trình tinh chỉnh bằng cách kết hợp mô hình, bộ dữ liệu, bộ gom dữ liệu, tham số huấn luyện và cấu hình LoRA vào một quy trình duy nhất, giúp thao tác gọn gàng và thân thiện.
8. Huấn luyện mô hình
Khi mô hình, bộ dữ liệu và cấu hình huấn luyện đã sẵn sàng, chúng ta có thể bắt đầu tinh chỉnh. SFTTrainer giúp bước này trở nên đơn giản, cho phép huấn luyện chỉ với một lệnh:
Quá trình huấn luyện mất khoảng 1 giờ 8 phút để hoàn thành. Trong thời gian này, loss huấn luyện và loss validation giảm đều theo từng bước, cho thấy mô hình học hiệu quả.
Sau khi huấn luyện xong, mô hình đã tinh chỉnh có thể được lưu cục bộ và đẩy lên Hugging Face Hub bằng phương thức
save_model().Mô hình hiện có tại kingabzpro/medgemma-brain-cancer · Hugging Face
Nguồn kingabzpro/medgemma-brain-cancer
Đánh giá mô hình
Để đánh giá hiệu năng của MedGemma 4B, chúng ta sẽ kiểm thử cả mô hình gốc và mô hình đã tinh chỉnh trên tập validation. Quy trình gồm giải phóng bộ nhớ, chuẩn bị dữ liệu kiểm thử, sinh phản hồi và tính các chỉ số chính như accuracy và F1.
Trước khi bắt đầu đánh giá, ta loại bỏ thiết lập huấn luyện để giải phóng bộ nhớ GPU và đảm bảo môi trường sạch cho kiểm thử
9. Thiết lập để kiểm thử mô hình
Chúng ta định dạng lại tập validation để khớp với cấu trúc đầu vào mô hình yêu cầu. Điều này bao gồm tạo cột "messages" chứa prompt cho mỗi ví dụ.
Để đánh giá hiệu năng mô hình, chúng ta dùng thư viện evaluate, cung cấp sẵn các chỉ số cho bài toán phân loại. Sau khi import và nạp các chỉ số cần thiết, chúng ta trích xuất nhãn ground-truth từ tập kiểm thử. Một hàm hỗ trợ
compute_metricsđược định nghĩa để tính accuracy và F1 bằng cách so sánh dự đoán với các nhãn này.Để đảm bảo nhất quán trong xử lý nhãn, chúng ta ép cột "label" của bộ dữ liệu sang kiểu
ClassLabel. Điều này cho phép ánh xạ hiệu quả giữa chỉ số nhãn và tên tương ứng. Ngoài ra, chúng ta định nghĩa ánh xạ nhãn thay thế để xử lý biến thể định dạng nhãn trong hậu xử lý.Để ánh xạ dự đoán của mô hình sang nhãn lớp đúng, chúng ta định nghĩa hàm
postprocess. Hàm này đảm bảo dự đoán được khớp với nhãn phù hợp, tính đến cả định dạng nhãn chuẩn và thay thế.10. Hiệu năng mô hình gốc
Để đánh giá hiệu năng mô hình gốc, chúng ta nạp mô hình và processor đã tiền huấn luyện, cấu hình tham số sinh, và chuẩn bị prompt cùng hình ảnh để kiểm thử.
Chúng ta đã tạo hàm
batch_predictđể xử lý tập kiểm thử theo lô. Hàm này sinh dự đoán cho từng cặp prompt-hình ảnh và áp dụng hậu xử lý để ánh xạ đầu ra về nhãn đúng.Chúng ta sẽ dùng hàm
batch_predictđể sinh dự đoán cho mô hình gốc trên tập kiểm thử. Các dự đoán sau đó được đánh giá bằng hàmcompute_metrics.Kết quả không ấn tượng. Độ chính xác đạt 33%, khá thấp.
Để hiểu rõ hơn hành vi của mô hình, chúng ta có thể sinh dự đoán cho một ví dụ đơn lẻ từ bộ dữ liệu. Điều này liên quan đến việc tạo một hàm hỗ trợ để xử lý đầu vào và trả về phản hồi của mô hình.
Hàm
predict_onenhận prompt và hình ảnh làm đầu vào, xử lý bằng processor của mô hình và sinh phản hồi. Hàm đảm bảo đầu ra của mô hình được giải mã thành văn bản dễ đọc.Chúng ta sẽ dùng
predict_oneđể sinh phản hồi cho mẫu thứ 11 trong bộ dữ liệu. Việc này bao gồm chuẩn bị prompt và chạy hàm dự đoán.Kết quả là chúng ta nhận được một câu dài giải thích lý do chọn glioma. Phản hồi hoàn toàn sai, kể cả phân loại cũng sai.
11. Hiệu năng mô hình đã tinh chỉnh
Để đánh giá mô hình đã tinh chỉnh, chúng ta lặp lại quy trình đánh giá bằng cách nạp mô hình từ thư mục đầu ra, sinh dự đoán và tính các chỉ số.
Chúng ta nạp mô hình và processor đã tinh chỉnh từ thư mục đầu ra, chạy hàm
batch_predictvà tính toán các chỉ số.Các kết quả cho thấy sự cải thiện đáng kể so với mô hình gốc, nhấn mạnh hiệu quả của tinh chỉnh. Độ chính xác tăng từ 33% lên 89% chỉ với 1 epoch.
Để phân tích sâu hơn hiệu năng của mô hình đã tinh chỉnh, chúng ta sinh dự đoán cho một ví dụ đơn lẻ từ tập kiểm thử.
Mô hình đưa ra kết quả rõ ràng và chính xác, phần phân loại đúng và trình bày gọn gàng.
Nếu bạn gặp vấn đề khi chạy mã trên, vui lòng tham khảo notebook kèm theo: Fine_tuning_MedGemma.ipynb
Kết luận
MedGemma đại diện cho một bước tiến đáng kể trong việc ứng dụng AI cho khoa học y tế. Bằng cách hỗ trợ bác sĩ đưa ra quyết định nhanh và chính xác hơn, nó giúp chẩn đoán kịp thời và lập kế hoạch điều trị hiệu quả cho bệnh nhân.
Tinh chỉnh các mô hình ngôn ngữ-thị giác như MedGemma 4B Instruct cho phép thích ứng trên nhiều tác vụ y khoa, từ phân loại ảnh đến tích hợp khả năng suy luận.
Trong hướng dẫn này, chúng ta đã học cách tinh chỉnh một mô hình ngôn ngữ-thị giác trên bộ dữ liệu MRI não để phân loại ung thư não. Kết quả rất ấn tượng, độ chính xác của mô hình tăng từ 33% lên 89%, một bước nhảy lớn cho thấy tiềm năng của tinh chỉnh trong các ứng dụng AI y tế.
Nếu bạn quan tâm tìm hiểu thêm, tôi khuyến nghị xem các tài nguyên sau: