Fine-tune Qwen3-VL-8B pada skematik elektronik menggunakan LoRA. Pelajari seluruh pipeline dari persiapan data hingga menerbitkan model Anda di Hugging Face Hub.
Qwen3‑VL‑8B adalah model visi‑bahasa paling andal dan paling banyak digunakan dalam seri Qwen, dirancang untuk pemahaman terpadu atas teks, gambar, dan video.
Model ini menghadirkan peningkatan besar dalam pembuatan teks, penalaran visual, persepsi spasial, penanganan konteks panjang, dan interaksi agen, menjadikannya cocok untuk riset maupun penerapan nyata di lingkungan edge dan cloud.
Dalam tutorial ini, kita akan melakukan fine‑tuning Qwen3‑VL‑8B‑Instruct pada diagram skematik elektronik. Dengan melatih model untuk menafsirkan simbol skematik, koneksi, dan relasi spasial, kita memungkinkannya memahami desain rangkaian secara akurat dan menentukan komponen elektronik apa yang perlu ditambahkan dalam rangkaian nyata.
Anda akan mempelajari cara:
Memuat dataset dari Hugging Face dan membersihkannya.
Membuat template chat multimodal untuk pelatihan.
Menyiapkan pipeline visi‑bahasa Qwen3-VL.
Mengonfigurasi LoRA untuk pelatihan yang hemat memori.
Melakukan fine-tuning model dan menyimpan checkpoint.
Menerbitkan adapter terlatih ke Hugging Face.
Membandingkan hasil sebelum dan sesudah fine-tuning.
Jika Anda masih baru dengan Hugging Face, Hugging Face Fundamentals adalah jalur keterampilan untuk Anda!
1. Menyiapkan Lingkungan untuk Fine-Tuning Qwen3-VL-8B
Saat bekerja dengan model visi–bahasa, memori GPU menjadi kendala kritis. Gambar beresolusi tinggi dan encoder multimodal dapat dengan cepat menghabiskan VRAM, sehingga sangat disarankan menggunakan GPU dengan memori yang memadai.
Untuk tutorial ini, kita akan meluncurkan instance RunPod A100 (80GB) dengan image PyTorch terbaru. Setup ini menyediakan ruang VRAM yang cukup untuk pelatihan dan menghindari bottleneck memori yang tidak perlu selama fine-tuning.
Gulir ke bagian Pod Template. Di sini, pilih image PyTorch terbaru. Di sini juga Anda dapat menyesuaikan pengaturan storage dan menambahkan variabel lingkungan.
Klik Edit, lalu lakukan perubahan berikut:
Ukuran disk container: setel ke 40 GB
Ukuran disk volume: setel ke 40 GB
Variabel lingkungan: Tambahkan HF_TOKEN dan atur nilainya ke Hugging Face access token Anda (buat dari Hugging Face Settings)
Setelah selesai, simpan template dan deploy pod.
Setelah pod berjalan:
Buka JupyterLab.
Buat notebook Python baru.
Instal dependensi yang diperlukan.
Untuk menginstal dependensi, jalankan sel kode berikut. Di Jupyter, tanda seru di awal memberi tahu notebook untuk mengeksekusi baris tersebut sebagai perintah shell, bukan kode Python.
Selanjutnya, atur seed acak tetap untuk reprodusibilitas dan aktifkan optimisasi kinerja spesifik A100.
import torch
from transformers import set_seed
set_seed(42)# A100: TF32 gives speedups without changing your bf16 training setup
torch.backends.cuda.matmul.allow_tf32 =True
torch.backends.cudnn.allow_tf32 =Trueprint("CUDA:", torch.cuda.is_available(), torch.cuda.get_device_name(0)if torch.cuda.is_available()elseNone)print("bf16 supported:", torch.cuda.is_available()and torch.cuda.is_bf16_supported())Didukung oleh
CUDA: True NVIDIA A100 80GB PCIe
bf16 supported: TrueDidukung oleh
2. Mengunduh Dataset Open Schematics dari Hugging Face
Sekarang kita akan memuat datasetOpen Schematics dari Hugging Face Hub. Dataset ini berisi gambar skematik elektronik beserta metadata kaya yang mendeskripsikan setiap rangkaian, menjadikannya sangat cocok untuk pelatihan visi–bahasa.
import torch
from datasets import load_dataset
DATASET_ID ="bshada/open-schematics"
ds_all = load_dataset(DATASET_ID, split="train")print(ds_all)Didukung oleh
Dataset ini berisi lebih dari 84 ribu sampel, masing-masing memasangkan gambar skematik dengan informasi terstruktur, seperti daftar komponen dan format yang dapat dibaca mesin (JSON dan YAML).
3. Menjelajahi Struktur Dataset
Mari kita inspeksi satu sampel untuk lebih memahami struktur dataset.
# quick peek
ex = ds_all[0]print("\nSample keys:", ex.keys())print("name:", ex.get("name"))print("type:", ex.get("type"))print("components_used:",(ex.get("components_used")or[])[:10])print("has schematic:",bool(ex.get("schematic")))print("has json/yaml:",bool(ex.get("json")),bool(ex.get("yaml")))print("image:", ex.get("image"))Didukung oleh
Sample keys: dict_keys(['schematic', 'image', 'components_used', 'json', 'yaml', 'name', 'description', 'type'])
name: TiebeDeclercq/Uart-programmer
type: .kicad_sch
components_used: ['Conn_01x01_Pin', 'Conn_01x06_Pin', 'USB_A', 'Conn_02x05_Odd_Even', 'Conn_01x06_MountingPin', 'C', 'Fuse_Small', 'LED', 'R', 'CH340C']
has schematic: True
has json/yaml: True True
image: <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=1123x794 at 0x7FBC6FD060F0>Didukung oleh
Ini menegaskan bahwa setiap sampel menyertakan gambar skematik beresolusi tinggi, daftar komponen, dan representasi terstruktur dari rangkaian.
Kita kini dapat merender gambar skematik langsung di dalam notebook Jupyter.
Daftar komponen ini memberikan kaitan yang jelas antara gambar skematik dan elemen elektronik yang ada pada rangkaian.
4. Membersihkan dan Memfilter Dataset
Sebelum pelatihan, kita bersihkan dan filter dataset untuk memastikan setiap sampel memuat informasi minimum yang diperlukan untuk pembelajaran visi–bahasa. Secara khusus, kita fokus mempertahankan contoh yang memiliki anotasi komponen valid dan gambar skematik yang sesuai.
Pertama, kita periksa berapa banyak sampel yang memiliki entri components_used yang hilang, kosong, atau tidak valid.
need_cols =[c for c in["components_used","schematic","name","type"]if c in ds_all.column_names]
ds_small = ds_all.select_columns(need_cols)
missing_key = none_components = empty_components = missing_any =0
has_schematic_but_missing =0for ex in ds_small:if"components_used"notin ex:
missing_key +=1
missing_any +=1if ex.get("schematic"):
has_schematic_but_missing +=1continue
cu = ex["components_used"]
bad =(cu isNone)or(isinstance(cu,list)andlen(cu)==0)if cu isNone:
none_components +=1elifisinstance(cu,list)andlen(cu)==0:
empty_components +=1if bad:
missing_any +=1if ex.get("schematic"):
has_schematic_but_missing +=1print("\n=== Missing components report ===")print("Total:",len(ds_all))print("Missing key:", missing_key)print("None:", none_components)print("Empty list:", empty_components)print("Missing (any):", missing_any)if"schematic"in need_cols:print("Has schematic but missing components:", has_schematic_but_missing)Didukung oleh
=== Missing components report ===
Total: 84470
Missing key: 0
None: 47558
Empty list: 8
Missing (any): 47566
Has schematic but missing components: 47566Didukung oleh
Ringkasan di atas menunjukkan bahwa sebagian besar sampel berisi data skematik tetapi tidak memiliki anotasi komponen yang dapat digunakan.
Untuk menghindari penggunaan memori yang tidak perlu selama pemfilteran, kita secara eksplisit menonaktifkan decoding gambar. Ini memastikan Hugging Face tidak memuat gambar ke memori saat menerapkan filter.
from datasets.features import Image as HFImage
ds_all = ds_all.cast_column("image", HFImage(decode=False))Didukung oleh
Lalu kita mendefinisikan filter yang hanya mempertahankan sampel dengan daftar komponen tidak kosong dan referensi gambar yang valid.
defkeep_components_and_image(components_used, image):# keep only rows with componentsifnot(isinstance(components_used,list)andlen(components_used)>0):returnFalse# image must existif image isNone:returnFalse# when decode=False, image is dict-like: {"path": ...} or {"bytes": ...}ifisinstance(image,dict):returnbool(image.get("path"))orbool(image.get("bytes"))returnTrueDidukung oleh
Menerapkan filter ini secara signifikan mengurangi dataset menjadi sampel berkualitas tinggi yang sepenuhnya dapat digunakan.
ds_clean = ds_all.filter(
keep_components_and_image,
input_columns=["components_used","image"],)print("Original:",len(ds_all))print("Clean:",len(ds_clean))print("Dropped:",len(ds_all)-len(ds_clean))Didukung oleh
Original: 84470
Clean: 33275
Dropped: 51195Didukung oleh
Setelah pemfilteran, tersisa lebih dari 33 ribu sampel bersih yang memuat gambar skematik valid dan anotasi komponen eksplisit. Dataset yang telah dibersihkan ini menjadi fondasi andal untuk langkah prapemrosesan dan pelatihan model berikutnya.
5. Memuat Model Visi‑Bahasa Qwen3-VL-8B
Sekarang kita memuat model Qwen3-VL-8B-Instruct beserta processornya. Model ini adalah model visi–bahasa skala besar yang mampu menalar gabungan atas gambar dan teks, sehingga sangat cocok untuk tugas pemahaman skematik.
Model dimuat dalam presisi bfloat16 untuk mengurangi penggunaan memori sambil menjaga stabilitas numerik. Kita juga mengaktifkan Flash Attention 2 untuk atensi yang lebih cepat dan lebih hemat memori pada GPU A100. Opsi device_map="auto" secara otomatis menempatkan layer model pada GPU yang tersedia.
from transformers import Qwen3VLForConditionalGeneration, AutoProcessor
MODEL_ID ="Qwen/Qwen3-VL-8B-Instruct"
model = Qwen3VLForConditionalGeneration.from_pretrained(
MODEL_ID,
dtype=torch.bfloat16,
device_map="auto",
attn_implementation="flash_attention_2",)
processor = AutoProcessor.from_pretrained(MODEL_ID)Didukung oleh
6. Merancang Prompt untuk Analisis Rangkaian
Langkah ini mendefinisikan utilitas ringan untuk menyiapkan prompt, target, dan gambar untuk pelatihan visi–bahasa. Satu pipeline digunakan untuk banyak tugas dengan mengganti variabel TASK (komponen, YAML, JSON, atau rekonstruksi skematik).
Batas keamanan dasar diterapkan untuk mengendalikan panjang target dan ukuran gambar, membantu menjaga pelatihan tetap stabil dan hemat memori.
from PIL import Image
TASK ="components"# "components" | "yaml" | "json" | "schematic"
MAX_TARGET_CHARS =5000# safety cap for long targets like schematic/json
MAX_IMAGE_SIDE =1024# bigger side
MAX_IMAGE_PIXELS =1024*1024# safety cap (1.0 MP). raise to 1.5MP if stableDidukung oleh
Membangun prompt
Fungsi build_prompt() menyusun teks instruksi yang diberikan ke model. Fungsi ini menggunakan metadata dataset untuk konteks dan menerapkan batas keluaran ketat guna mengurangi halusinasi serta menjaga supervisi konsisten di seluruh tugas.
defbuild_prompt(example):# Use dataset fields to give better context (name/type are helpful)
name = example.get("name")or"Unknown project"
ftype = example.get("type")or"unknown format"if TASK =="components":return(f"Project: {name}\nFormat: {ftype}\n""From the schematic image, extract all component labels and identifiers exactly as shown ""(part numbers, values, footprints, net labels like +5V/GND).\n""Output only a comma-separated list. Do not generalize or add extra text.")if TASK =="yaml":return(f"Project: {name}\nFormat: {ftype}\n""From the schematic image, produce YAML metadata for the design.\n""Return valid YAML only. No markdown, no explanations.")if TASK =="json":return(f"Project: {name}\nFormat: {ftype}\n""From the schematic image, produce a JSON representation of the schematic structure.\n""Return valid JSON only. No markdown, no explanations.")if TASK =="schematic":return(f"Project: {name}\nFormat: {ftype}\n""From the schematic image, reconstruct the raw KiCad schematic content.\n""Return only the schematic text. No markdown, no explanations.")raise ValueError("Unknown TASK")Didukung oleh
Membangun target
Fungsi build_target() mengekstrak keluaran ground-truth untuk tugas yang dipilih langsung dari dataset. Konten dikembalikan apa adanya untuk melatih model melakukan reproduksi persis, bukan parafrase.
Fungsi clamp_text() menerapkan batas karakter keras pada target. Ini mencegah file JSON, YAML, atau skematik yang terlalu besar menyebabkan masalah memori selama pelatihan.
defclamp_text(s:str, max_chars:int= MAX_TARGET_CHARS)->str:
s =(s or"").strip()return s iflen(s)<= max_chars else s[:max_chars].rstrip()Didukung oleh
Mengubah ukuran gambar
Fungsi _resize_pil() menormalkan dan mengubah ukuran gambar skematik sebelum diproses. Fungsi ini menerapkan panjang sisi maksimum dan jumlah piksel total maksimum, memastikan penggunaan memori GPU yang dapat diprediksi sambil mempertahankan detail visual.
def_resize_pil(pil: Image.Image, max_side:int= MAX_IMAGE_SIDE, max_pixels:int= MAX_IMAGE_PIXELS)-> Image.Image:
pil = pil.convert("RGB")
w, h = pil.size
# Scale down if max side too large
scale_side =min(1.0, max_side /float(max(w, h)))# Scale down if too many pixels (area cap)
scale_area =(max_pixels /float(w * h))**0.5if(w * h)> max_pixels else1.0
scale =min(scale_side, scale_area)if scale <1.0:
nw, nh =max(1,int(w * scale)),max(1,int(h * scale))
pil = pil.resize((nw, nh), resample=Image.BICUBIC)return pilDidukung oleh
7. Menyiapkan Template Chat Multimodal
Pada langkah ini, kita mengubah setiap sampel dataset yang telah dibersihkan menjadi format gaya chat multimodal yang dapat langsung digunakan oleh model visi–bahasa Qwen. Format ini secara eksplisit menyelaraskan gambar skematik dengan instruksi tekstual dan keluaran targetnya.
Kita acak dataset untuk menghapus bias pengurutan dan memilih subset kecil untuk eksperimen awal.
Dataset kemudian dipetakan melalui to_messages() untuk menghasilkan contoh pelatihan multimodal. Terakhir, decoding gambar diaktifkan kembali, sehingga gambar hanya dimuat saat waktu pelatihan, menjaga prapemrosesan tetap ringan dan hemat memori.
# Start small (increase later)
train_ds = ds_clean.shuffle(seed=42).select(range(min(800,len(ds_clean)))).map(to_messages)
train_ds = train_ds.cast_column("image", HFImage(decode=True))Didukung oleh
8. Mengevaluasi Qwen3-VL-8B (Pra-Fine-Tuning)
Sebelum fine-tuning, kita evaluasi performa out‑of‑the‑box model Qwen3‑VL 8B Instruct pada tugas kita. Baseline ini membantu memahami sejauh mana model pralatih dapat mengekstrak informasi dari gambar skematik tanpa adaptasi spesifik tugas.
Fungsi run_inference() melakukan satu forward pass pada satu contoh menggunakan logika prompting dan prapemrosesan gambar yang sama yang nanti digunakan saat pelatihan.
import torch
defrun_inference(model_, example, max_new_tokens=256):
prompt = build_prompt(example)
messages =[{"role":"user","content":[{"type":"image","image": _resize_pil(example["image"])},{"type":"text","text": prompt},],}]
inputs = processor.apply_chat_template(
messages,
tokenize=True,
add_generation_prompt=True,
return_dict=True,
return_tensors="pt",).to(model_.device)with torch.inference_mode():
out = model_.generate(**inputs, max_new_tokens=max_new_tokens, do_sample=False)
gen = out[0][inputs["input_ids"].shape[1]:]return processor.decode(gen, skip_special_tokens=True)
baseline_ex = train_ds.shuffle(seed=120).select(range(1))[0]Didukung oleh
Pertama, kita evaluasi model pada sampel yang dipilih acak dari set pelatihan.
Dalam contoh ini, model dengan benar mengenali beberapa elemen struktural tetapi berlebihan dalam menghasilkan nama pin dan sinyal, sekaligus gagal memulihkan pengenal komponen persis seperti di dataset. Pola yang sama saya temukan pada lebih banyak contoh saat saya mengevaluasinya.
Secara keseluruhan, hasil baseline ini menunjukkan bahwa meskipun model memiliki pemahaman visual dan tekstual yang kuat, model kurang selaras dengan anotasi komponen spesifik dataset. Perilaku ini menyoroti perlunya fine-tuning untuk mengurangi halusinasi keluaran dan meningkatkan presisi.
9. Membangun Data Collator Visi‑Bahasa untuk Pelatihan
Bagian ini mendefinisikan data collator khusus yang menyiapkan batch bergaya chat multimodal untuk pelatihan. Collator mengonversi setiap contoh menjadi tensor siap model dengan melakukan enkode teks dan gambar secara bersama, sambil memastikan loss hanya dihitung pada respons asisten.
Collator membangun dua versi teks chat: versi penuh (prompt dan target) untuk enkode input, dan versi hanya prompt untuk menghitung panjang token prompt. Dengan panjang ini, semua token prompt dan padding dimask pada label, sehingga hanya keluaran asisten yang berkontribusi pada loss. Gambar diubah ukurannya secara konsisten, dan panjang urutan maksimum tetap diterapkan untuk kontrol memori.
from typing import List, Dict, Any
import torch
MAX_LEN =1500defcollate_fn(batch: List[Dict[str, Any]]):# 1) Build full chat text (includes assistant answer)
full_texts =[
processor.apply_chat_template(
ex["messages"],
tokenize=False,
add_generation_prompt=False,)for ex in batch
]# 2) Build prompt-only text (up to user turn; generation prompt on)
prompt_texts =[
processor.apply_chat_template(
ex["messages"][:-1],
tokenize=False,
add_generation_prompt=True,)for ex in batch
]# 3) Images
images =[_resize_pil(ex["image"])for ex in batch]# 4) Tokenize full inputs ONCE (text + images)
enc = processor(
text=full_texts,
images=images,
return_tensors="pt",
padding=True,
truncation=True,
max_length=MAX_LEN,)
input_ids = enc["input_ids"]
pad_id = processor.tokenizer.pad_token_id
# 5) Compute prompt lengths with TEXT-ONLY tokenization (much cheaper than text+images)
prompt_ids = processor.tokenizer(
prompt_texts,
return_tensors="pt",
padding=True,
truncation=True,
max_length=MAX_LEN,
add_special_tokens=False,# chat template already includes special tokens)["input_ids"]# Count non-pad tokens in prompt
prompt_lens =(prompt_ids != pad_id).sum(dim=1)# 6) Labels: copy + mask prompt tokens + mask padding
labels = input_ids.clone()
bs, seqlen = labels.shape
for i inrange(bs):
pl =int(prompt_lens[i].item())
pl =min(pl, seqlen)
labels[i,:pl]=-100# Mask padding positions too
labels[labels == pad_id]=-100# If your processor produces pixel_values / image_grid_thw, keep them
enc["labels"]= labels
return encDidukung oleh
Collator ini memungkinkan supervisi yang efisien dan tepat untuk fine-tuning visi–bahasa.
10. Mengonfigurasi LoRA untuk Fine-Tuning Qwen3-VL-8B yang Efisien
Sekarang kita akan mengonfigurasi LoRA (Low-Rank Adaptation) untuk melakukan fine-tuning model Qwen3‑VL secara efisien tanpa memperbarui seluruh bobot model. LoRA menyisipkan matriks berperingkat rendah yang dapat dilatih ke layer proyeksi terpilih, secara signifikan mengurangi penggunaan memori sambil mempertahankan performa.
from peft import LoraConfig, TaskType, get_peft_model
lora = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type=TaskType.CAUSAL_LM,
target_modules=["q_proj","k_proj","v_proj","o_proj","gate_proj","up_proj","down_proj"],)Didukung oleh
Lalu kita mendefinisikan konfigurasi pelatihan menggunakan SFTConfig, menetapkan batch size, laju pembelajaran, presisi, dan opsi logging yang sesuai untuk fine-tuning stabil pada GPU A100.
Setelah pelatihan dimulai, Anda dapat memantau dasbor telemetri RunPod. Pada instance A100 80GB, proses ini biasanya menggunakan sekitar 40–45 GB VRAM dan mencapai pemanfaatan GPU hampir penuh, menandakan penggunaan perangkat keras yang efisien.
Seiring berjalannya pelatihan, Anda akan melihat loss pelatihan menurun secara stabil sebelum stabil. Dalam kasus kami, loss berkonvergensi dan plateau di sekitar 6,5, yang menjadi indikator baseline bahwa model telah beradaptasi dengan tugas ekstraksi komponen skematik.
Pada titik ini, adapter LoRA berhasil di‑fine‑tune dan siap untuk evaluasi serta ekspor.
12. Menerbitkan Model yang Telah Di‑Fine‑Tune ke Hugging Face Hub
Setelah fine-tuning selesai, pertama-tama kita simpan adapter LoRA terlatih dan processor terkait secara lokal.
out_dir = trainer.args.output_dir # from your SFTConfig/TrainingArguments
trainer.save_model(out_dir)# saves model/adapters into output_dir
processor.save_pretrained(out_dir)# save processor (tokenizer + image processor)Didukung oleh
Berikutnya, kita terbitkan model yang telah di‑fine‑tune ke Hugging Face Hub. Ini memungkinkan adapter dan processor digunakan kembali untuk inferensi atau fine-tuning lanjutan.
import os
repo_id ="kingabzpro/qwen3vl-open-schematics-lora"# replace with your username/repo# Push model/adapters
trainer.model.push_to_hub(
repo_id,
token=os.getenv("HF_TOKEN"),)# Push processor
processor.push_to_hub(
repo_id,
token=os.getenv("HF_TOKEN"),)Didukung oleh
Setelah unggahan selesai, adapter LoRA dan processor yang telah di‑fine‑tune tersedia publik di repositori yang ditentukan.
12. Mengevaluasi Model Qwen3-VL-8B yang Telah Di‑Fine‑Tune
Setelah fine-tuning, kita memuat ulang model dan processor langsung dari Hugging Face Hub. Ini memastikan evaluasi dilakukan menggunakan adapter LoRA yang diekspor, persis seperti penggunaannya dalam pengaturan inferensi nyata.
model = Qwen3VLForConditionalGeneration.from_pretrained(
repo_id,
dtype=torch.bfloat16,
device_map="auto",
attn_implementation="flash_attention_2",)
processor = AutoProcessor.from_pretrained(repo_id)
```
We now repeat the same inference procedure used during the baseline evaluation, allowing for a direct comparison between pre-fine-tuning and post-fine-tuning behavior.
```python
baseline_ex = train_ds.shuffle(seed=120).select(range(1))[0]print("\n--- FINETUNED OUTPUT ---\n", run_inference(model, baseline_ex))print("\n--- TARGET (dataset) ---\n", clamp_text(build_target(baseline_ex),1500))Didukung oleh
Dibandingkan baseline, model yang telah di‑fine‑tune menghasilkan keluaran yang jauh lebih pendek dan fokus, menghindari produksi berlebihan nama pin dan sinyal yang terinferensi.
Meski prediksi masih belum lengkap dan mengandung kesalahan kecil, hasil ini menunjukkan pergerakan jelas menuju pengenal komponen yang selaras dengan dataset.
Sekarang kita akan mengevaluasi contoh kedua untuk mengonfirmasi perilaku ini.
Di sini, model yang telah di‑fine‑tune dengan benar mengidentifikasi komponen inti seperti mikrokontroler dan net daya, serta secara signifikan mengurangi halusinasi di tingkat sinyal yang tidak relevan. Namun, model masih mengabstraksi atau menggeneralisasi beberapa komponen alih‑alih mereproduksi pengenal spesifik dataset secara persis.
Secara keseluruhan, hasil ini menunjukkan bahwa fine-tuning berhasil menekan over‑generation dan meningkatkan keselarasan dengan ekstraksi komponen pada tingkat skematik. Walau presisi dapat ditingkatkan lagi dengan epoch tambahan, set pelatihan yang lebih besar, atau batas keluaran yang lebih ketat, perilaku pasca‑fine‑tuning merepresentasikan peningkatan yang jelas dan terukur dibanding baseline.
Jika Anda menemui kendala saat menjalankan kode dalam tutorial ini, silakan merujuk ke notebook pendamping.
Pemikiran Akhir
Model visi–bahasa pada dasarnya berbeda dari model berbasis teks saja, dan memperlakukannya sama hampir selalu menghasilkan hasil yang buruk.
Jika tidak hati-hati, sangat mudah mengalami error kehabisan memori bahkan dengan ukuran batch satu, atau melakukan fine-tuning pada model yang tampak berlatih tetapi gagal benar-benar mempelajari tugas. Ini sesuatu yang saya pelajari dengan cara sulit.
Yang pada akhirnya membuat perbedaan adalah memperhatikan detail yang penting khusus untuk pelatihan multimodal.
Mengubah ukuran gambar ke batas aman, membersihkan dataset untuk menghapus sampel rusak atau tidak dapat digunakan, dan memastikan hanya pasangan gambar–teks yang valid yang diberikan ke model adalah langkah-langkah esensial. Melewatkan salah satunya dengan cepat menyebabkan ketidakstabilan atau komputasi terbuang.
Di sisi pemodelan, hanya menggunakan layer target LoRA yang relevan membantu menjaga pelatihan tetap efisien dan terfokus, sementara penalaan cermat argumen pelatihan meningkatkan konvergensi tanpa menambah tekanan memori.
Optimalisasi untuk GPU A100, mengaktifkan Flash Attention, dan menggunakan bfloat16 memungkinkan pelatihan tetap stabil sambil secara signifikan mengurangi waktu proses. Dalam praktiknya, optimisasi ini memangkas waktu pelatihan hampir setengahnya tanpa mengorbankan kualitas.
Hasil akhir menunjukkan bahwa bahkan model visi–bahasa pralatih yang kuat pun sangat diuntungkan dari fine-tuning spesifik domain. Dengan prapemrosesan yang tepat, konfigurasi yang benar, dan optimisasi yang sadar perangkat keras, adaptasi model multimodal besar dapat dilakukan secara andal dan efisien.
Jika Anda tertarik untuk lebih mempraktikkan fine-tuning, saya merekomendasikan mengikuti kursus Fine-Tuning with Llama 3.
Sebagai data scientist tersertifikasi, saya bersemangat memanfaatkan teknologi mutakhir untuk menciptakan aplikasi machine learning yang inovatif. Dengan latar belakang kuat di pengenalan ucapan, analisis dan pelaporan data, MLOps, conversational AI, dan NLP, saya mengasah keterampilan dalam mengembangkan sistem cerdas yang berdampak nyata. Selain keahlian teknis, saya juga komunikator andal yang mampu menyederhanakan konsep kompleks menjadi bahasa yang jelas dan ringkas. Karena itu, saya menjadi blogger yang dicari di bidang data science, membagikan wawasan dan pengalaman kepada komunitas profesional data yang terus berkembang. Saat ini, saya berfokus pada pembuatan dan penyuntingan konten, bekerja dengan large language model untuk mengembangkan konten yang kuat dan menarik agar membantu bisnis dan individu memaksimalkan data mereka.
Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Temukan model AI open-source terbaru, dataset, dan aplikasi, bangun agen AI, dan sesuaikan model bahasa besar (LLMs) dengan Hugging Face. Bergabunglah dengan komunitas AI terbesar hari ini!
Gunakan PyTorch pada gambar dan terapkan model deep learning untuk deteksi objek dengan kotak batas (bounding boxes) dan pembangkitan segmentasi gambar.
Qwen3‑VL‑8B adalah model visi‑bahasa paling andal dan paling banyak digunakan dalam seri Qwen, dirancang untuk pemahaman terpadu atas teks, gambar, dan video.
Model ini menghadirkan peningkatan besar dalam pembuatan teks, penalaran visual, persepsi spasial, penanganan konteks panjang, dan interaksi agen, menjadikannya cocok untuk riset maupun penerapan nyata di lingkungan edge dan cloud.
Dalam tutorial ini, kita akan melakukan fine‑tuning Qwen3‑VL‑8B‑Instruct pada diagram skematik elektronik. Dengan melatih model untuk menafsirkan simbol skematik, koneksi, dan relasi spasial, kita memungkinkannya memahami desain rangkaian secara akurat dan menentukan komponen elektronik apa yang perlu ditambahkan dalam rangkaian nyata.
Anda akan mempelajari cara:
Jika Anda masih baru dengan Hugging Face, Hugging Face Fundamentals adalah jalur keterampilan untuk Anda!
1. Menyiapkan Lingkungan untuk Fine-Tuning Qwen3-VL-8B
Saat bekerja dengan model visi–bahasa, memori GPU menjadi kendala kritis. Gambar beresolusi tinggi dan encoder multimodal dapat dengan cepat menghabiskan VRAM, sehingga sangat disarankan menggunakan GPU dengan memori yang memadai.
Untuk tutorial ini, kita akan meluncurkan instance RunPod A100 (80GB) dengan image PyTorch terbaru. Setup ini menyediakan ruang VRAM yang cukup untuk pelatihan dan menghindari bottleneck memori yang tidak perlu selama fine-tuning.
Gulir ke bagian Pod Template. Di sini, pilih image PyTorch terbaru. Di sini juga Anda dapat menyesuaikan pengaturan storage dan menambahkan variabel lingkungan.
Klik Edit, lalu lakukan perubahan berikut:
HF_TOKENdan atur nilainya ke Hugging Face access token Anda (buat dari Hugging Face Settings)Setelah selesai, simpan template dan deploy pod.
Setelah pod berjalan:
Untuk menginstal dependensi, jalankan sel kode berikut. Di Jupyter, tanda seru di awal memberi tahu notebook untuk mengeksekusi baris tersebut sebagai perintah shell, bukan kode Python.
Selanjutnya, atur seed acak tetap untuk reprodusibilitas dan aktifkan optimisasi kinerja spesifik A100.
2. Mengunduh Dataset Open Schematics dari Hugging Face
Sekarang kita akan memuat dataset Open Schematics dari Hugging Face Hub. Dataset ini berisi gambar skematik elektronik beserta metadata kaya yang mendeskripsikan setiap rangkaian, menjadikannya sangat cocok untuk pelatihan visi–bahasa.
Dataset ini berisi lebih dari 84 ribu sampel, masing-masing memasangkan gambar skematik dengan informasi terstruktur, seperti daftar komponen dan format yang dapat dibaca mesin (JSON dan YAML).
3. Menjelajahi Struktur Dataset
Mari kita inspeksi satu sampel untuk lebih memahami struktur dataset.
Ini menegaskan bahwa setiap sampel menyertakan gambar skematik beresolusi tinggi, daftar komponen, dan representasi terstruktur dari rangkaian.
Kita kini dapat merender gambar skematik langsung di dalam notebook Jupyter.
Terakhir, kita inspeksi daftar lengkap komponen yang digunakan dalam skematik ini.
Daftar komponen ini memberikan kaitan yang jelas antara gambar skematik dan elemen elektronik yang ada pada rangkaian.
4. Membersihkan dan Memfilter Dataset
Sebelum pelatihan, kita bersihkan dan filter dataset untuk memastikan setiap sampel memuat informasi minimum yang diperlukan untuk pembelajaran visi–bahasa. Secara khusus, kita fokus mempertahankan contoh yang memiliki anotasi komponen valid dan gambar skematik yang sesuai.
Pertama, kita periksa berapa banyak sampel yang memiliki entri
components_usedyang hilang, kosong, atau tidak valid.Ringkasan di atas menunjukkan bahwa sebagian besar sampel berisi data skematik tetapi tidak memiliki anotasi komponen yang dapat digunakan.
Untuk menghindari penggunaan memori yang tidak perlu selama pemfilteran, kita secara eksplisit menonaktifkan decoding gambar. Ini memastikan Hugging Face tidak memuat gambar ke memori saat menerapkan filter.
Lalu kita mendefinisikan filter yang hanya mempertahankan sampel dengan daftar komponen tidak kosong dan referensi gambar yang valid.
Menerapkan filter ini secara signifikan mengurangi dataset menjadi sampel berkualitas tinggi yang sepenuhnya dapat digunakan.
Setelah pemfilteran, tersisa lebih dari 33 ribu sampel bersih yang memuat gambar skematik valid dan anotasi komponen eksplisit. Dataset yang telah dibersihkan ini menjadi fondasi andal untuk langkah prapemrosesan dan pelatihan model berikutnya.
5. Memuat Model Visi‑Bahasa Qwen3-VL-8B
Sekarang kita memuat model Qwen3-VL-8B-Instruct beserta processornya. Model ini adalah model visi–bahasa skala besar yang mampu menalar gabungan atas gambar dan teks, sehingga sangat cocok untuk tugas pemahaman skematik.
Model dimuat dalam presisi bfloat16 untuk mengurangi penggunaan memori sambil menjaga stabilitas numerik. Kita juga mengaktifkan Flash Attention 2 untuk atensi yang lebih cepat dan lebih hemat memori pada GPU A100. Opsi
device_map="auto"secara otomatis menempatkan layer model pada GPU yang tersedia.6. Merancang Prompt untuk Analisis Rangkaian
Langkah ini mendefinisikan utilitas ringan untuk menyiapkan prompt, target, dan gambar untuk pelatihan visi–bahasa. Satu pipeline digunakan untuk banyak tugas dengan mengganti variabel
TASK(komponen, YAML, JSON, atau rekonstruksi skematik).Batas keamanan dasar diterapkan untuk mengendalikan panjang target dan ukuran gambar, membantu menjaga pelatihan tetap stabil dan hemat memori.
Membangun prompt
Fungsi
build_prompt()menyusun teks instruksi yang diberikan ke model. Fungsi ini menggunakan metadata dataset untuk konteks dan menerapkan batas keluaran ketat guna mengurangi halusinasi serta menjaga supervisi konsisten di seluruh tugas.Membangun target
Fungsi
build_target()mengekstrak keluaran ground-truth untuk tugas yang dipilih langsung dari dataset. Konten dikembalikan apa adanya untuk melatih model melakukan reproduksi persis, bukan parafrase.Fungsi
clamp_text()menerapkan batas karakter keras pada target. Ini mencegah file JSON, YAML, atau skematik yang terlalu besar menyebabkan masalah memori selama pelatihan.Mengubah ukuran gambar
Fungsi
_resize_pil()menormalkan dan mengubah ukuran gambar skematik sebelum diproses. Fungsi ini menerapkan panjang sisi maksimum dan jumlah piksel total maksimum, memastikan penggunaan memori GPU yang dapat diprediksi sambil mempertahankan detail visual.7. Menyiapkan Template Chat Multimodal
Pada langkah ini, kita mengubah setiap sampel dataset yang telah dibersihkan menjadi format gaya chat multimodal yang dapat langsung digunakan oleh model visi–bahasa Qwen. Format ini secara eksplisit menyelaraskan gambar skematik dengan instruksi tekstual dan keluaran targetnya.
Kita acak dataset untuk menghapus bias pengurutan dan memilih subset kecil untuk eksperimen awal.
Dataset kemudian dipetakan melalui
to_messages()untuk menghasilkan contoh pelatihan multimodal. Terakhir, decoding gambar diaktifkan kembali, sehingga gambar hanya dimuat saat waktu pelatihan, menjaga prapemrosesan tetap ringan dan hemat memori.8. Mengevaluasi Qwen3-VL-8B (Pra-Fine-Tuning)
Sebelum fine-tuning, kita evaluasi performa out‑of‑the‑box model Qwen3‑VL 8B Instruct pada tugas kita. Baseline ini membantu memahami sejauh mana model pralatih dapat mengekstrak informasi dari gambar skematik tanpa adaptasi spesifik tugas.
Fungsi
run_inference()melakukan satu forward pass pada satu contoh menggunakan logika prompting dan prapemrosesan gambar yang sama yang nanti digunakan saat pelatihan.Pertama, kita evaluasi model pada sampel yang dipilih acak dari set pelatihan.
Dalam contoh ini, model dengan benar mengenali beberapa elemen struktural tetapi berlebihan dalam menghasilkan nama pin dan sinyal, sekaligus gagal memulihkan pengenal komponen persis seperti di dataset. Pola yang sama saya temukan pada lebih banyak contoh saat saya mengevaluasinya.
Secara keseluruhan, hasil baseline ini menunjukkan bahwa meskipun model memiliki pemahaman visual dan tekstual yang kuat, model kurang selaras dengan anotasi komponen spesifik dataset. Perilaku ini menyoroti perlunya fine-tuning untuk mengurangi halusinasi keluaran dan meningkatkan presisi.
9. Membangun Data Collator Visi‑Bahasa untuk Pelatihan
Bagian ini mendefinisikan data collator khusus yang menyiapkan batch bergaya chat multimodal untuk pelatihan. Collator mengonversi setiap contoh menjadi tensor siap model dengan melakukan enkode teks dan gambar secara bersama, sambil memastikan loss hanya dihitung pada respons asisten.
Collator membangun dua versi teks chat: versi penuh (prompt dan target) untuk enkode input, dan versi hanya prompt untuk menghitung panjang token prompt. Dengan panjang ini, semua token prompt dan padding dimask pada label, sehingga hanya keluaran asisten yang berkontribusi pada loss. Gambar diubah ukurannya secara konsisten, dan panjang urutan maksimum tetap diterapkan untuk kontrol memori.
Collator ini memungkinkan supervisi yang efisien dan tepat untuk fine-tuning visi–bahasa.
10. Mengonfigurasi LoRA untuk Fine-Tuning Qwen3-VL-8B yang Efisien
Sekarang kita akan mengonfigurasi LoRA (Low-Rank Adaptation) untuk melakukan fine-tuning model Qwen3‑VL secara efisien tanpa memperbarui seluruh bobot model. LoRA menyisipkan matriks berperingkat rendah yang dapat dilatih ke layer proyeksi terpilih, secara signifikan mengurangi penggunaan memori sambil mempertahankan performa.
Lalu kita mendefinisikan konfigurasi pelatihan menggunakan
SFTConfig, menetapkan batch size, laju pembelajaran, presisi, dan opsi logging yang sesuai untuk fine-tuning stabil pada GPU A100.Terakhir, kita inisialisasi
SFTTrainer, menggabungkan model, dataset, collator khusus, dan konfigurasi LoRA untuk memulai supervised fine-tuning.11. Melakukan Fine-Tuning Qwen3‑VL-8B pada Dataset Open Schematics
Sekarang kita mulai proses fine-tuning menggunakan trainer yang telah dikonfigurasi.
Setelah pelatihan dimulai, Anda dapat memantau dasbor telemetri RunPod. Pada instance A100 80GB, proses ini biasanya menggunakan sekitar 40–45 GB VRAM dan mencapai pemanfaatan GPU hampir penuh, menandakan penggunaan perangkat keras yang efisien.
Seiring berjalannya pelatihan, Anda akan melihat loss pelatihan menurun secara stabil sebelum stabil. Dalam kasus kami, loss berkonvergensi dan plateau di sekitar 6,5, yang menjadi indikator baseline bahwa model telah beradaptasi dengan tugas ekstraksi komponen skematik.
Pada titik ini, adapter LoRA berhasil di‑fine‑tune dan siap untuk evaluasi serta ekspor.
12. Menerbitkan Model yang Telah Di‑Fine‑Tune ke Hugging Face Hub
Setelah fine-tuning selesai, pertama-tama kita simpan adapter LoRA terlatih dan processor terkait secara lokal.
Berikutnya, kita terbitkan model yang telah di‑fine‑tune ke Hugging Face Hub. Ini memungkinkan adapter dan processor digunakan kembali untuk inferensi atau fine-tuning lanjutan.
Setelah unggahan selesai, adapter LoRA dan processor yang telah di‑fine‑tune tersedia publik di repositori yang ditentukan.
12. Mengevaluasi Model Qwen3-VL-8B yang Telah Di‑Fine‑Tune
Setelah fine-tuning, kita memuat ulang model dan processor langsung dari Hugging Face Hub. Ini memastikan evaluasi dilakukan menggunakan adapter LoRA yang diekspor, persis seperti penggunaannya dalam pengaturan inferensi nyata.
Dibandingkan baseline, model yang telah di‑fine‑tune menghasilkan keluaran yang jauh lebih pendek dan fokus, menghindari produksi berlebihan nama pin dan sinyal yang terinferensi.
Meski prediksi masih belum lengkap dan mengandung kesalahan kecil, hasil ini menunjukkan pergerakan jelas menuju pengenal komponen yang selaras dengan dataset.
Sekarang kita akan mengevaluasi contoh kedua untuk mengonfirmasi perilaku ini.
Di sini, model yang telah di‑fine‑tune dengan benar mengidentifikasi komponen inti seperti mikrokontroler dan net daya, serta secara signifikan mengurangi halusinasi di tingkat sinyal yang tidak relevan. Namun, model masih mengabstraksi atau menggeneralisasi beberapa komponen alih‑alih mereproduksi pengenal spesifik dataset secara persis.
Secara keseluruhan, hasil ini menunjukkan bahwa fine-tuning berhasil menekan over‑generation dan meningkatkan keselarasan dengan ekstraksi komponen pada tingkat skematik. Walau presisi dapat ditingkatkan lagi dengan epoch tambahan, set pelatihan yang lebih besar, atau batas keluaran yang lebih ketat, perilaku pasca‑fine‑tuning merepresentasikan peningkatan yang jelas dan terukur dibanding baseline.
Jika Anda menemui kendala saat menjalankan kode dalam tutorial ini, silakan merujuk ke notebook pendamping.
Pemikiran Akhir
Model visi–bahasa pada dasarnya berbeda dari model berbasis teks saja, dan memperlakukannya sama hampir selalu menghasilkan hasil yang buruk.
Jika tidak hati-hati, sangat mudah mengalami error kehabisan memori bahkan dengan ukuran batch satu, atau melakukan fine-tuning pada model yang tampak berlatih tetapi gagal benar-benar mempelajari tugas. Ini sesuatu yang saya pelajari dengan cara sulit.
Yang pada akhirnya membuat perbedaan adalah memperhatikan detail yang penting khusus untuk pelatihan multimodal.
Mengubah ukuran gambar ke batas aman, membersihkan dataset untuk menghapus sampel rusak atau tidak dapat digunakan, dan memastikan hanya pasangan gambar–teks yang valid yang diberikan ke model adalah langkah-langkah esensial. Melewatkan salah satunya dengan cepat menyebabkan ketidakstabilan atau komputasi terbuang.
Di sisi pemodelan, hanya menggunakan layer target LoRA yang relevan membantu menjaga pelatihan tetap efisien dan terfokus, sementara penalaan cermat argumen pelatihan meningkatkan konvergensi tanpa menambah tekanan memori.
Optimalisasi untuk GPU A100, mengaktifkan Flash Attention, dan menggunakan bfloat16 memungkinkan pelatihan tetap stabil sambil secara signifikan mengurangi waktu proses. Dalam praktiknya, optimisasi ini memangkas waktu pelatihan hampir setengahnya tanpa mengorbankan kualitas.
Hasil akhir menunjukkan bahwa bahkan model visi–bahasa pralatih yang kuat pun sangat diuntungkan dari fine-tuning spesifik domain. Dengan prapemrosesan yang tepat, konfigurasi yang benar, dan optimisasi yang sadar perangkat keras, adaptasi model multimodal besar dapat dilakukan secara andal dan efisien.
Jika Anda tertarik untuk lebih mempraktikkan fine-tuning, saya merekomendasikan mengikuti kursus Fine-Tuning with Llama 3.