Pytorch
TensorFlow

#
Fine-tuning Model dengan Trainer API

🤗 Transformers menyediakan kelas `Trainer` untuk membantu Anda melakukan fine-tuning model pralatih apa pun pada dataset Anda menggunakan praktik terbaik modern. Setelah semua praproses data selesai di bagian sebelumnya, hanya ada beberapa langkah lagi untuk mendefinisikan `Trainer`. Bagian yang paling menantang kemungkinan besar adalah menyiapkan lingkungan untuk menjalankan `Trainer.train()`, karena akan berjalan sangat lambat di CPU. Jika Anda tidak memiliki GPU, Anda bisa menggunakan GPU atau TPU gratis di Google Colab.

📚 Sumber Latihan: Sebelum mulai melatih, kenali terlebih dahulu panduan pelatihan 🤗 Transformers dan contoh praktiknya di cookbook fine-tuning.

Contoh kode di bawah mengasumsikan bahwa Anda telah menjalankan contoh di bagian sebelumnya. Berikut ringkasan singkat apa yang Anda perlukan:

    from datasets import load_dataset
    from transformers import AutoTokenizer, DataCollatorWithPadding

    raw_datasets = load_dataset("glue", "mrpc")
    checkpoint = "bert-base-uncased"
    tokenizer = AutoTokenizer.from_pretrained(checkpoint)

    def tokenize_function(example):
        return tokenizer(example["sentence1"], example["sentence2"], truncation=True)

    tokenized_datasets = raw_datasets.map(tokenize_function, batched=True)
    data_collator = DataCollatorWithPadding(tokenizer=tokenizer)

###
Pelatihan

Langkah pertama sebelum kita dapat mendefinisikan `Trainer` adalah membuat kelas `TrainingArguments` yang akan menyimpan semua hyperparameter yang digunakan `Trainer` untuk pelatihan dan evaluasi. Satu-satunya argumen wajib adalah direktori tempat model hasil pelatihan akan disimpan, termasuk checkpoint-checkpoint selama pelatihan. Sisanya bisa dibiarkan default, yang sudah cukup baik untuk fine-tuning dasar.

    from transformers import TrainingArguments

    training_args = TrainingArguments("test-trainer")

Jika Anda ingin model Anda secara otomatis diunggah ke Hub selama pelatihan, tambahkan `push_to_hub=True` dalam `TrainingArguments`. Kita akan mempelajari lebih lanjut tentang ini di Bab 4

🚀 Konfigurasi Lanjutan: Untuk detail lengkap semua argumen pelatihan dan strategi optimasi, lihat dokumentasi TrainingArguments dan cookbook konfigurasi pelatihan.

Langkah kedua adalah mendefinisikan model. Seperti di bab sebelumnya, kita akan menggunakan `AutoModelForSequenceClassification` dengan dua label:

    from transformers import AutoModelForSequenceClassification

    model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

Anda akan melihat bahwa, tidak seperti di Bab 2, Anda akan mendapatkan peringatan setelah menginstansiasi model pretrained ini. Hal ini terjadi karena BERT tidak dilatih sebelumnya untuk mengklasifikasikan pasangan kalimat, sehingga kepala (head) dari model pretrained telah dibuang dan diganti dengan kepala baru yang sesuai untuk tugas klasifikasi sekuens. Peringatan tersebut menunjukkan bahwa beberapa bobot tidak digunakan (yaitu yang terkait dengan kepala pretraining yang dihapus), dan beberapa lainnya diinisialisasi secara acak (yaitu yang digunakan untuk kepala baru). Peringatan ini diakhiri dengan anjuran untuk melatih model tersebut — dan itulah yang akan kita lakukan sekarang.

Setelah kita memiliki model, kita bisa mendefinisikan `Trainer` dengan memberikan semua objek yang sudah kita buat sejauh ini — `model`, `training_args`, dataset pelatihan dan validasi, `data_collator`, serta `processing_class`. Parameter `processing_class` adalah fitur baru yang memberi tahu Trainer tokenizer mana yang digunakan:

    from transformers import Trainer

    trainer = Trainer(
        model,
        training_args,
        train_dataset=tokenized_datasets["train"],
        eval_dataset=tokenized_datasets["validation"],
        data_collator=data_collator,
        processing_class=tokenizer,
    )

Jika Anda memberikan tokenizer sebagai `processing_class`, `Trainer` akan secara otomatis menggunakan `DataCollatorWithPadding`. Baris `data_collator=...` bisa diabaikan, tapi kami sertakan di sini untuk menunjukkan bagian penting dari pipeline ini.

📖 Pelajari Lebih Lanjut: Untuk detail lengkap tentang kelas Trainer dan parameternya, kunjungi dokumentasi Trainer API dan contoh lanjutan di cookbook pelatihan.

Untuk melakukan fine-tuning, kita cukup memanggil metode `train()`:

    trainer.train()

Ini akan memulai pelatihan dan melaporkan loss setiap 500 langkah. Namun, ini tidak akan menunjukkan seberapa baik model Anda karena:

1. Kita belum memberi tahu `Trainer` untuk melakukan evaluasi selama pelatihan dengan mengatur `eval_strategy` di `TrainingArguments` ke salah satu dari `"steps"` (melakukan evaluasi setiap `eval_steps`) atau `"epoch"` (melakukan evaluasi di akhir setiap epoch).
2. Kita juga belum memberikan fungsi `compute_metrics()` ke `Trainer` untuk menghitung metrik selama evaluasi tersebut (jika tidak, evaluasi hanya akan mencetak nilai loss, yang bukan angka yang mudah diinterpretasikan).

###
Evaluasi

Mari kita lihat bagaimana cara membangun fungsi `compute_metrics()` yang berguna dan menggunakannya saat kita melatih model berikutnya. Fungsi ini harus menerima objek `EvalPrediction` (yang merupakan tuple bernama dengan field `predictions` dan `label_ids`) dan mengembalikan dictionary yang memetakan string ke angka desimal (string adalah nama metrik yang dikembalikan, dan angka desimal adalah nilai metrik tersebut). Untuk mendapatkan prediksi dari model kita, kita dapat menggunakan perintah `Trainer.predict()`:

    predictions = trainer.predict(tokenized_datasets["validation"])
    print(predictions.predictions.shape, predictions.label_ids.shape)

    (408, 2) (408,)

Output dari metode `predict()` adalah tuple bernama lain yang memiliki tiga field: `predictions`, `label_ids`, dan `metrics`. Field `metrics` hanya akan berisi loss pada dataset yang diberikan, serta metrik waktu (berapa lama waktu yang dibutuhkan untuk melakukan prediksi, secara total dan rata-rata). Setelah kita melengkapi fungsi `compute_metrics()` dan memberikannya ke `Trainer`, field tersebut juga akan berisi metrik yang dikembalikan oleh `compute_metrics()`.

Seperti yang bisa kamu lihat, `predictions` adalah array dua dimensi dengan bentuk 408 x 2 (408 adalah jumlah elemen dalam dataset yang kita gunakan). Ini adalah nilai logit untuk setiap elemen dari dataset yang kita berikan ke `predict()` (seperti yang telah kamu lihat di bab sebelumnya, semua model Transformer mengembalikan logit). Untuk mengubahnya menjadi prediksi yang dapat kita bandingkan dengan label kita, kita perlu mengambil indeks dengan nilai maksimum pada sumbu kedua:

    import numpy as np

    preds = np.argmax(predictions.predictions, axis=-1)

Sekarang kita bisa membandingkan `preds` tersebut dengan label yang sebenarnya. Untuk membangun fungsi `compute_metrics()`, kita akan menggunakan metrik dari pustaka 🤗 Evaluate. Kita bisa memuat metrik yang digunakan untuk dataset MRPC semudah kita memuat dataset-nya, kali ini dengan fungsi `evaluate.load()`. Objek yang dikembalikan memiliki metode `compute()` yang bisa kita gunakan untuk menghitung metrik evaluasi:

    import evaluate

    metric = evaluate.load("glue", "mrpc")
    metric.compute(predictions=preds, references=predictions.label_ids)

    {'accuracy': 0.8578431372549019, 'f1': 0.8996539792387542}

Pelajari metrik evaluasi lebih lanjut di dokumentasi 🤗 Evaluate.

Hasil yang Anda peroleh bisa berbeda-beda, karena inisialisasi acak pada kepala model dapat memengaruhi metrik yang dicapai. Di sini, kita dapat melihat bahwa model kita memiliki akurasi sebesar 85,78% pada set validasi dan skor F1 sebesar 89,97. Kedua metrik tersebut digunakan untuk mengevaluasi hasil pada dataset MRPC dalam benchmark GLUE. Tabel pada makalah BERT melaporkan skor F1 sebesar 88,9 untuk model dasar. Model tersebut adalah model `uncased`, sementara kita saat ini menggunakan model `cased`, yang menjelaskan hasil yang lebih baik.

Menggabungkan semuanya, kita mendapatkan fungsi `compute_metrics()` kita:

    def compute_metrics(eval_preds):
        metric = evaluate.load("glue", "mrpc")
        logits, labels = eval_preds
        predictions = np.argmax(logits, axis=-1)
        return metric.compute(predictions=predictions, references=labels)

Dan untuk melihatnya digunakan secara langsung dalam melaporkan metrik di akhir setiap epoch, berikut adalah cara kita mendefinisikan `Trainer` baru dengan fungsi `compute_metrics()` ini:

    training_args = TrainingArguments("test-trainer", eval_strategy="epoch")
    model = AutoModelForSequenceClassification.from_pretrained(checkpoint, num_labels=2)

    trainer = Trainer(
        model,
        training_args,
        train_dataset=tokenized_datasets["train"],
        eval_dataset=tokenized_datasets["validation"],
        data_collator=data_collator,
        processing_class=tokenizer,
        compute_metrics=compute_metrics,
    )

Perlu dicatat bahwa kita membuat objek `TrainingArguments` baru dengan `eval_strategy` diatur ke `"epoch"` dan juga model baru — jika tidak, kita hanya akan melanjutkan pelatihan dari model yang sudah kita latih sebelumnya. Untuk memulai proses pelatihan baru, kita jalankan:

    trainer.train()

Kali ini, proses pelatihan akan melaporkan validation loss dan metrik evaluasi di akhir setiap epoch, selain training loss. Sekali lagi, akurasi atau skor F1 yang Anda dapatkan mungkin sedikit berbeda karena inisialisasi acak pada kepala model, namun tetap akan berada di kisaran yang serupa.

###
Fitur Pelatihan Lanjutan

`Trainer` memiliki banyak fitur bawaan yang membuat praktik terbaik deep learning modern lebih mudah diakses:

Pelatihan dengan Presisi Campuran (Mixed Precision): Gunakan `fp16=True` dalam training arguments untuk pelatihan yang lebih cepat dan penggunaan memori yang lebih rendah:

    training_args = TrainingArguments(
        "test-trainer",
        eval_strategy="epoch",
        fp16=True,  # Aktifkan pelatihan dengan presisi campuran
    )

Akumulasi Gradien (Gradient Accumulation): Berguna untuk mendapatkan ukuran batch efektif yang lebih besar saat memori GPU terbatas:

    training_args = TrainingArguments(
        "test-trainer",
        eval_strategy="epoch",
        per_device_train_batch_size=4,
        gradient_accumulation_steps=4,  # Ukuran batch efektif = 4 * 4 = 16
    )

Pengaturan Learning Rate: `Trainer` secara default menggunakan peluruhan linear (linear decay), tetapi Anda bisa menyesuaikannya:

    training_args = TrainingArguments(
        "test-trainer",
        eval_strategy="epoch",
        learning_rate=2e-5,
        lr_scheduler_type="cosine",  # Coba scheduler lain
    )

🎯 Optimasi Performa: Untuk teknik pelatihan lanjutan seperti pelatihan terdistribusi, optimasi memori, dan optimasi spesifik perangkat keras, jelajahi panduan performa 🤗 Transformers.

`Trainer` langsung dapat digunakan di beberapa GPU atau TPU, dan menyediakan banyak opsi untuk pelatihan terdistribusi. Kita akan membahas semua fitur tersebut di Bab 10.

Ini menutup pengenalan tentang fine-tuning menggunakan API `Trainer`. Contoh penerapan fine-tuning pada berbagai tugas NLP umum akan dijelaskan di Bab 7, tetapi untuk sekarang mari kita lihat bagaimana melakukan hal yang sama menggunakan training loop PyTorch murni.

📝 Lebih Banyak Contoh: Lihat koleksi lengkap notebook 🤗 Transformers.

##
Kuis Bagian

Uji pemahaman Anda tentang API `Trainer` dan konsep fine-tuning:

###
1. Apa tujuan dari parameter <code> processing_class </code> dalam Trainer?

Ini menentukan arsitektur model yang digunakan. Ini memberi tahu Trainer tokenizer mana yang digunakan untuk memproses data. Ini menentukan ukuran batch untuk pelatihan. Ini mengontrol frekuensi evaluasi.

###
2. Parameter TrainingArguments mana yang mengontrol seberapa sering evaluasi dilakukan saat pelatihan?

eval_frequency eval_strategy evaluation_steps do_eval

###
3. Apa yang diaktifkan oleh <code> fp16=True </code> dalam TrainingArguments?

Presisi integer 16-bit untuk pelatihan yang lebih cepat. Pelatihan dengan presisi campuran menggunakan angka floating-point 16-bit untuk pelatihan lebih cepat dan penggunaan memori lebih rendah. Pelatihan selama tepat 16 epoch. Menggunakan 16 GPU untuk pelatihan terdistribusi.

###
4. Apa peran fungsi <code> compute_metrics </code> dalam Trainer?

Ia menghitung loss selama pelatihan. Ia mengubah logit menjadi prediksi dan menghitung metrik evaluasi seperti akurasi dan F1. Ia menentukan optimizer mana yang akan digunakan. Ia memproses data pelatihan.

###
5. Apa yang terjadi jika Anda tidak menyediakan <code> eval_dataset </code> ke Trainer?

Pelatihan akan gagal dengan error. Trainer akan secara otomatis membagi data pelatihan untuk evaluasi. Anda tidak akan mendapatkan metrik evaluasi selama pelatihan, tapi pelatihan tetap akan berjalan. Model akan menggunakan data pelatihan untuk evaluasi.

###
6. Apa itu gradient accumulation dan bagaimana cara mengaktifkannya?

Ia menyimpan gradien ke disk, diaktifkan dengan save_gradients=True. Ia mengakumulasi gradien dari beberapa batch sebelum melakukan update, diaktifkan dengan gradient_accumulation_steps. Ia mempercepat perhitungan gradien, diaktifkan otomatis dengan fp16. Ia mencegah overflow gradien, diaktifkan dengan gradient_clipping=True.

💡 Inti Penting:

- API `Trainer` menyediakan antarmuka tingkat tinggi yang menangani sebagian besar kompleksitas pelatihan
- Gunakan `processing_class` untuk menentukan tokenizer yang tepat dalam pemrosesan data
- `TrainingArguments` mengontrol semua aspek pelatihan: learning rate, batch size, strategi evaluasi, dan optimasi
- `compute_metrics` memungkinkan evaluasi dengan metrik khusus, bukan hanya loss pelatihan
- Fitur modern seperti presisi campuran (`fp16=True`) dan gradient accumulation bisa secara signifikan meningkatkan efisiensi pelatihan

< > Update on GitHub