Photon-90M Early Instruct
Model bahasa Indonesia dengan arsitektur Dual Sparse custom, dilatih dari nol dan di-finetune untuk instruction following di Google Colab Free T4.
β οΈ Work in Progress β Pretraining baru ~16% selesai (step 4.000 dari 24.604). Dirilis sebagai early checkpoint untuk dokumentasi dan eksplorasi komunitas, bukan untuk produksi.
Nama "Photon" merujuk pada filosofi efisiensi komputasi arsitekturnya β seperti foton, model ini dirancang untuk membawa informasi sebanyak mungkin dengan energi (VRAM) seminimal mungkin.
"90M" merujuk pada total parameter. Parameter aktif per forward pass hanya ~38β42M karena Mixture of Experts.
Evolusi Arsitektur
Photon-90M adalah iterasi ketiga dalam seri Photon, merupakan konvergensi pembelajaran dari dua model sebelumnya.
| Model | Total Params | Aktif | Hidden | Vocab | Status |
|---|---|---|---|---|---|
| Photon-3M | 10.47M | ~3M | 128 | 8K BPE | β Selesai, dipublish |
| Nano-Z Aquila | 88M | 88M (dense) | 768 | β | β Dibatalkan (EST 100+ hari) |
| Photon-90M | 90.23M | ~38β42M | 384 | 16K Unigram | π Dalam training |
Photon-90M mengadopsi arsitektur Dual Sparse dari Photon-3M yang terbukti efisien, dan target skala parameter dari Nano-Z Aquila, dengan pipeline training yang didesain ulang agar bisa selesai di Colab Free.
Arsitektur Dual Sparse
Konsep utama adalah Dual Sparse β dua level sparsity yang bekerja bersamaan untuk memaksimalkan kapasitas representasi dengan footprint komputasi minimal.
MoE β Mixture of Experts
Setiap layer memiliki satu shared expert yang selalu aktif, ditambah empat specialist expert yang dipilih router per token. Hanya 1 dari 4 specialist yang aktif per token.
Efeknya: kapasitas FFN setara 5x dari yang dieksekusi per token, tanpa menambah biaya komputasi secara proporsional. Tiap specialist dapat terspesialisasi pada domain berbeda (sains, berita, sastra, dll).
Referensi: Mixtral of Experts (Mistral AI)
Adaptive Layer Skipping
Router kecil (1 linear layer) di tiap layer memutuskan apakah layer perlu diproses atau dilewati berdasarkan konten input. Skip probability: 0.3.
Efek nyata yang terukur: VRAM hanya ~1.4GB selama training meski total parameter 90M. Jika semua layer aktif seharusnya ~2.5β3GB β selisih ini membuktikan layer skipping bekerja aktif.
Mekanisme backprop menggunakan straight-through estimator sehingga gradien tetap mengalir meski layer di-skip. Bias router diinisialisasi ke 2.0 agar model awalnya jarang skip, lalu belajar skip secara adaptif.
Referensi: Confident Adaptive Language Modeling (CALM)
Komponen Pendukung
| Komponen | Detail | Referensi |
|---|---|---|
| GQA | 8 Query / 2 KV Heads | GQA Paper |
| RoPE | Rotary Position Embedding | RoFormer |
| SwiGLU | Aktivasi FFN | GLU Variants |
| RMSNorm | Normalisasi per layer | RMSNorm Paper |
| Weight Tying | Embedding = LM Head (pretraining) | Press & Wolf, 2017 |
Perbandingan dengan Arsitektur Lain
| Komponen | Mirip Dengan | Catatan |
|---|---|---|
| MoE + Shared Expert | DeepSeek-V2/V3 | DeepSeek juga pakai shared+specialist pattern |
| GQA | LLaMA 3, Mistral | Konsep identik, ratio berbeda |
| RoPE | Hampir semua LLM modern | Standard de facto |
| SwiGLU | LLaMA, PaLM, Gemma | Standard di arsitektur modern |
| RMSNorm | LLaMA, Mistral | Lebih efisien dari LayerNorm |
| Adaptive Layer Skip | Early Exit (Microsoft/Google) | Implementasi custom, terintegrasi langsung ke layer |
Konfigurasi
VOCAB_SIZE = 16.000 (Unigram SentencePiece)
HIDDEN = 384
LAYERS = 12
HEADS = 8Q / 2KV (GQA)
FF_MULT = 3
NUM_EXPERTS = 4 specialist + 1 shared
MAX_SEQ = 512 (diperpanjang dari 256 saat finetune via RoPE extrapolation)
SKIP_PROB = 0.3
Total params : 90.226.572
Aktif/token : ~38β42M (~42% dari total)
Tokenizer
Unigram SentencePiece yang dilatih dari scratch dari dataset yang sama, bukan hasil adopt dari model lain.
Tipe : Unigram SentencePiece
Vocab : 16.000
Special : [UNK] [BOS] [EOS] [PAD]
Training
Fase 1 β Pretraining
Dataset: Lyon28/Corpus-Indonesia + indonesian-nlp/wikipedia-id (~2GB+, ~2 epoch)
Hardware : Tesla T4 15.6GB (Google Colab Free)
Batch size : 32
Grad accumulation : 8 (effective batch 256)
Optimizer : AdamW (lr=3e-4, betas=0.9/0.95, wd=0.01)
Scheduler : Cosine Annealing + Linear Warmup 1.000 step
Mixed Precision : bfloat16
MAX_SEQ : 256
Total steps target: 24.604 (2 epoch)
Checkpoint diambil: Step 4.000 (~16% selesai)
Kurva Loss Pretraining:
| Step | Loss | PPL | LR |
|---|---|---|---|
| 650 | 6.077 | 436 | 1.9e-4 |
| 700 | 5.952 | 385 | 2.1e-4 |
| 800 | 5.758 | 317 | 2.4e-4 |
| 900 | 5.560 | 260 | 2.7e-4 |
| 1000 | 5.354 | 212 | 3.0e-4 |
| 1100 | 5.183 | 178 | 3.0e-4 |
| 1200 | 5.035 | 154 | 3.0e-4 |
| 1300 | 4.950 | 141 | 3.0e-4 |
| 1400 | 4.864 | 130 | 3.0e-4 |
| 4000 | ~4.18 | ~65 | <3.0e-4 |
Target Loss Pretraining:
| Target | Status |
|---|---|
| < 6.0 β model mulai mengenali pola bahasa | β Tercapai step 650 |
| < 5.0 β kalimat mulai memiliki struktur | β Tercapai step 1200 |
| < 4.5 β kalimat koheren | β Tercapai ~step 3000+ |
| < 3.5 β grammar oke, topik nyambung | π― Target ~step 6.000 |
| < 3.0 β minimum layak finetune | π― Target akhir epoch 1 |
| < 2.5 β bagus untuk 90M param | π― Target akhir epoch 2 |
Fase 2 β Instruction Finetuning
Dataset: Ichsan2895/alpaca-gpt4-indonesian (License: CC BY-SA 4.0) β 49.101 sampel valid (difilter dari 49.969, token β€480)
Format prompt:
### Instruksi:
{instruction}
### Respons:
{output}
Base checkpoint : Pretraining step 4.000
MAX_SEQ : 512 (diperpanjang dari 256 via RoPE extrapolation)
Batch size : 16
Grad accumulation : 4 (effective batch 64)
Optimizer : AdamW (lr=5e-5, betas=0.9/0.95, wd=0.01)
Scheduler : Cosine Annealing + Linear Warmup 100 step
Frozen layers : embed + layer 0β5
Trainable layers : layer 6β11 + norm + head
Dihentikan di : ft-step 1.200
Kurva Loss Finetuning:
| ft-step | Loss | PPL |
|---|---|---|
| 100 | 3.410 | 30.3 |
| 300 | 3.158 | 23.5 |
| 500 | 3.052 | 21.2 |
| 767 | 3.000 | 20.1 |
| 1000 | 2.869 | 17.6 |
| 1200 | 2.852 | 17.3 |
Bug yang Ditemukan dan Diperbaiki
Bug 1: find_latest_checkpoint tidak cek Drive.
Fungsi hanya mencari di /content/ yang hilang setiap sesi Colab baru. Fix: scan Drive terlebih dahulu, lalu lokal. Checkpoint valid harus punya model.pt dan training_state.pt.
Bug 2: Skip batch tetap load semua batch ke memori.
if bi < skip_batches: continue tetap men-load tiap batch ke memori sebelum dibuang. Saat resume di tengah epoch, ini menyebabkan proses skip 4.800+ batch memakan waktu sangat lama. Fix: ganti dengan itertools.islice untuk langsung lompat ke posisi batch yang benar.
Bug 3: Script selalu download dataset ulang.
Setiap sesi Colab baru, dataset didownload ulang dari HuggingFace meski tokens_cache.npy dan tokenizer sudah ada di Drive β membuang ~10β15 menit per resume. Fix: cek keberadaan cache dan tokenizer di Drive di awal, skip download jika keduanya sudah ada.
Cara Load
Model menggunakan arsitektur custom. Salin modeling_photon.py dari repo ini, lalu:
import torch
import torch.nn.functional as F
import sentencepiece as spm
from modeling_photon import PhotonModel
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load tokenizer
sp = spm.SentencePieceProcessor()
sp.load("tokenizer.model")
# Load model
cfg = torch.load("config.pt", map_location=device)
model = PhotonModel(**cfg).to(device)
model.load_state_dict(torch.load("model.pt", map_location=device))
model.eval()
Generate dengan instruction format:
def generate(instruksi, max_new=150, temp=0.3, top_p=0.9, rep_penalty=1.3):
prompt = f"### Instruksi:\n{instruksi}\n\n### Respons:\n"
ids = torch.tensor([sp.encode(prompt)], dtype=torch.long).to(device)
with torch.no_grad():
for _ in range(max_new):
if ids.shape[1] >= 512:
ids = ids[:, -511:]
logits = model(ids)
next_logits = logits[:, -1] / temp
for tok_id in ids[0].tolist():
next_logits[0, tok_id] /= rep_penalty
probs = F.softmax(next_logits, dim=-1)
sorted_probs, sidx = torch.sort(probs, descending=True)
cumprobs = torch.cumsum(sorted_probs, dim=-1)
sorted_probs[cumprobs - sorted_probs > top_p] = 0
sorted_probs /= sorted_probs.sum()
next_tok = sidx[0][torch.multinomial(sorted_probs[0], 1)]
if next_tok.item() == sp.eos_id():
break
ids = torch.cat([ids, next_tok.view(1, 1)], dim=-1)
return sp.decode(ids[0].tolist()).split("### Respons:")[-1].strip()
print(generate("Jelaskan apa itu fotosintesis"))
print(generate("Bagaimana cara membuat nasi goreng?"))
Contoh Output
β οΈ Output masih mengandung kesalahan faktual β ini expected karena pretraining baru ~16% selesai. Format instruksi sudah diikuti konsisten.
>>> Jelaskan apa itu fotosintesis
Fotosintesis adalah proses yang melibatkan berbagai bentuk, termasuk
fotosintetis dan artefak...
[struktur kalimat benar, fakta salah]
>>> Apa perbedaan siang dan malam?
Pagi, sore, atau malam.
[singkat tapi faktanya benar β]
>>> Bagaimana cara membuat nasi goreng?
Salah satu cara untuk membuat nasi goreng adalah dengan menggunakan
bahan-bahan berikut... bawang putih dan garam selama sekitar 5 menit
hingga telur matang...
[asosiasi bahan mulai relevan β]
Sudah bisa:
- Format
### Instruksi / ### Responsdiikuti konsisten - Kalimat panjang dengan struktur grammatikal yang lumayan
- Beberapa asosiasi faktual mulai benar
Masih kurang:
- Pengetahuan faktual belum akurat β akan membaik seiring pretraining berlanjut
- Kadang ngelantur ke topik lain di tengah kalimat
Perbandingan Photon-3M vs Photon-90M
| Aspek | Photon-3M (step 2000) | Photon-90M (step 1400) |
|---|---|---|
| Loss | ~5.89 | 4.86 |
| Token Aneh | Ada ('Jropoce', 'dipakat') | Tidak ada |
| Struktur Kalimat | Belum terbentuk | Sudah ada subjek-predikat |
| Vocab | 8.000 (BPE) | 16.000 (Unigram) |
| Konteks Prompt | Sering diabaikan | Masih diikuti |
| Asosiasi Fakta | Random | Ada cluster yang relevan |
Isi Repo
Veenn/Photon-90M-early-instruct
βββ model.pt <- state dict model (finetuned ft-step 1200)
βββ config.pt <- konfigurasi arsitektur
βββ modeling_photon.py <- definisi arsitektur (wajib disertakan)
βββ tokenizer.model <- SentencePiece model
βββ mascot.png <- maskot Photon
βββ loss_curve.jpg <- kurva loss pretraining
βββ README.md
Rencana Selanjutnya
Pretraining masih berjalan. Setelah selesai:
- Selesaikan pretraining β target loss <2.5 di step 24.604
- Sequence extension β 256 β 512 β 1024 secara bertahap via RoPE
- Instruction finetuning ulang β dari base yang lebih matang
- Multimodal β arsitektur modular plug-in, backbone Photon-90M tidak berubah, modul vision/audio bisa dipasang-lepas secara independen
Dilatih di Google Colab Free T4 | From Scratch
Model tree for Veenn/Photon-90M-early-instruct
Base model
Veenn/photon-3m