Pytorch
TensorFlow

#
Model

Dalam bagian ini, kita akan melihat lebih dekat cara membuat dan menggunakan model. Kita akan menggunakan kelas `AutoModel`, yang sangat berguna saat Anda ingin menginisialisasi model apa pun dari sebuah checkpoint.

##
Membuat Model Transformer

Mari kita mulai dengan melihat apa yang terjadi saat kita menginisialisasi `AutoModel`:

    from transformers import AutoModel

    model = AutoModel.from_pretrained("bert-base-cased")

Mirip dengan tokenizer, metode `from_pretrained()` akan mengunduh dan menyimpan data model dari Hugging Face Hub. Seperti yang telah disebutkan sebelumnya, nama checkpoint merujuk pada arsitektur dan bobot model tertentu — dalam hal ini, model BERT dengan arsitektur dasar (12 layer, ukuran tersembunyi 768, 12 kepala atensi) dan input cased (membedakan huruf besar/kecil). Banyak checkpoint lain tersedia di Hub — Anda bisa menjelajahinya di sini.

Kelas `AutoModel` dan turunannya sebenarnya hanyalah pembungkus (wrapper) sederhana yang dirancang untuk mengambil arsitektur model yang sesuai dari checkpoint tertentu. Kelas ini adalah kelas “auto” karena akan menebak arsitektur model yang sesuai dan menginisialisasi kelas model yang benar. Namun, jika Anda sudah tahu jenis model yang ingin digunakan, Anda bisa langsung menggunakan kelas arsitektur tersebut:

    from transformers import BertModel

    model = BertModel.from_pretrained("bert-base-cased")

##
Memuat dan Menyimpan

Menyimpan model semudah menyimpan tokenizer. Model memiliki metode `save_pretrained()` yang sama, yang akan menyimpan bobot dan konfigurasi arsitektur model:

    model.save_pretrained("direktori_di_lokal_komputer")

Ini akan menyimpan dua file ke dalam disk Anda:

    ls direktori_di_lokal_komputer

    config.json model.safetensors

Jika Anda membuka file config.json, Anda akan melihat semua atribut yang diperlukan untuk membangun arsitektur model. File ini juga memuat metadata, seperti asal checkpoint dan versi 🤗 Transformers yang digunakan saat terakhir kali menyimpan model.

File pytorch_model.safetensors adalah yang dikenal sebagai state dictionary, berisi bobot model. Kedua file ini saling melengkapi: konfigurasi memberitahu struktur model, sedangkan bobot adalah parameternya.

Untuk menggunakan kembali model yang telah disimpan, gunakan kembali metode `from_pretrained()`:

    from transformers import AutoModel

    model = AutoModel.from_pretrained("direktori_di_lokal_komputer")

Fitur hebat dari 🤗 Transformers adalah kemudahan untuk membagikan model dan tokenizer ke komunitas. Untuk melakukannya, pastikan Anda memiliki akun di Hugging Face. Jika Anda menggunakan notebook, login bisa dilakukan dengan:

    from huggingface_hub import notebook_login

    notebook_login()

Jika tidak, di terminal jalankan:

    huggingface-cli login

Lalu Anda bisa mengunggah model ke Hub dengan metode `push_to_hub()`:

    model.push_to_hub("my-awesome-model")

Ini akan mengunggah file model ke Hub dalam repositori di bawah namespace Anda bernama my-awesome-model. Kemudian siapa pun bisa memuat model Anda dengan metode `from_pretrained()`!

    from transformers import AutoModel

    model = AutoModel.from_pretrained("username-anda/my-awesome-model")

Anda bisa melakukan lebih banyak hal dengan API Hub:

- Mendorong model dari repositori lokal
- Memperbarui file tertentu tanpa mengunggah semuanya
- Menambahkan kartu model untuk mendokumentasikan kemampuan, keterbatasan, bias, dll.

Lihat dokumentasi untuk tutorial lengkap, atau pelajari lebih lanjut di Bab 4.

##
Mengenkode Teks

Model Transformer memproses teks dengan mengubah input menjadi angka. Di sini kita akan lihat secara spesifik bagaimana teks diproses oleh tokenizer. Di Bab 1 kita telah melihat bahwa tokenizer memecah teks menjadi token, lalu mengubah token tersebut menjadi angka. Kita bisa melihat proses ini menggunakan tokenizer sederhana:

    from transformers import AutoTokenizer

    tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

    encoded_input = tokenizer("Hello, I'm a single sentence!")
    print(encoded_input)

    {'input_ids': [101, 8667, 117, 1000, 1045, 1005, 1049, 2235, 17662, 12172, 1012, 102],
     'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
     'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

Kita mendapatkan dictionary dengan:

- `input_ids`: representasi angka dari token
- `token_type_ids`: menunjukkan bagian mana dari input adalah kalimat A atau B (akan dibahas di bagian berikutnya)
- `attention_mask`: menunjukkan token mana yang harus diperhatikan oleh model

Kita bisa mendekode `input_ids` kembali ke bentuk teks:

    tokenizer.decode(encoded_input["input_ids"])

    "[CLS] Hello, I'm a single sentence! [SEP]"

Anda akan melihat bahwa tokenizer telah menambahkan token khusus — `[CLS]` dan `[SEP]` — yang dibutuhkan oleh model. Tidak semua model memerlukan token khusus; token ini digunakan ketika sebuah model telah dilatih sebelumnya (pretrained) dengan token tersebut, dalam hal ini tokenizer perlu menambahkannya karena model tersebut mengharapkannya.

Anda dapat mengenkodekan beberapa kalimat sekaligus, baik dengan menggabungkannya dalam bentuk batch (kita akan membahas ini segera) atau dengan memberikan sebuah daftar:

    encoded_input = tokenizer("How are you?", "I'm fine, thank you!")
    print(encoded_input)

    {'input_ids': [[101, 1731, 1132, 1128, 136, 102], [101, 1045, 1005, 1049, 2503, 117, 5763, 1128, 136, 102]],
     'token_type_ids': [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]],
     'attention_mask': [[1, 1, 1, 1, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]}

Perlu dicatat bahwa saat memberikan beberapa kalimat, tokenizer akan mengembalikan daftar untuk setiap kalimat pada setiap nilai dalam kamus. Kita juga dapat meminta tokenizer untuk langsung mengembalikan tensor dari PyTorch:

    encoded_input = tokenizer("How are you?", "I'm fine, thank you!", return_tensors="pt")
    print(encoded_input)

    {'input_ids': tensor([[  101,  1731,  1132,  1128,   136,   102],
             [  101,  1045,  1005,  1049,  2503,   117,  5763,  1128,   136,   102]]),
     'token_type_ids': tensor([[0, 0, 0, 0, 0, 0],
             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]),
     'attention_mask': tensor([[1, 1, 1, 1, 1, 1],
             [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

Tapi ada masalah: kedua daftar tersebut tidak memiliki panjang yang sama! Array dan tensor harus berbentuk persegi panjang (rectangular), jadi kita tidak bisa langsung mengonversi daftar-daftar ini menjadi tensor PyTorch (atau array NumPy). Tokenizer menyediakan opsi untuk itu: padding.

###
Padding input

Jika kita meminta tokenizer untuk melakukan padding pada input, maka tokenizer akan menyamakan panjang semua kalimat dengan menambahkan token padding khusus ke kalimat-kalimat yang lebih pendek dari yang paling panjang:

    encoded_input = tokenizer(
        ["How are you?", "I'm fine, thank you!"], padding=True, return_tensors="pt"
    )
    print(encoded_input)

    {'input_ids': tensor([[  101,  1731,  1132,  1128,   136,   102,     0,     0,     0,     0],
             [  101,  1045,  1005,  1049,  2503,   117,  5763,  1128,   136,   102]]),
     'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
             [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]),
     'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 0, 0, 0, 0],
             [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

Sekarang kita memiliki tensor berbentuk persegi panjang! Perhatikan bahwa token padding telah dikodekan ke dalam input ID dengan ID 0, dan juga memiliki nilai attention mask sebesar 0. Hal ini karena token padding tersebut tidak seharusnya dianalisis oleh model: mereka bukan bagian dari kalimat yang sebenarnya.

###
Memotong Input

Tensor-tensor tersebut bisa menjadi terlalu besar untuk diproses oleh model. Sebagai contoh, BERT hanya dilatih sebelumnya dengan sekuens hingga 512 token, sehingga tidak dapat memproses sekuens yang lebih panjang. Jika Anda memiliki sekuens yang lebih panjang daripada yang bisa ditangani oleh model, Anda perlu memotongnya (truncate) dengan parameter `truncation`:

    encoded_input = tokenizer(
        "This is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long sentence.",
        truncation=True,
    )
    print(encoded_input["input_ids"])

    [101, 1188, 1110, 170, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1505, 1179, 5650, 119, 102]

Dengan menggabungkan argumen `padding` dan `truncation`, Anda dapat memastikan bahwa tensor Anda memiliki ukuran yang tepat sesuai kebutuhan:

    encoded_input = tokenizer(
        ["How are you?", "I'm fine, thank you!"],
        padding=True,
        truncation=True,
        max_length=5,
        return_tensors="pt",
    )
    print(encoded_input)

    {'input_ids': tensor([[  101,  1731,  1132,  1128,   102],
             [  101,  1045,  1005,  1049,   102]]),
     'token_type_ids': tensor([[0, 0, 0, 0, 0],
             [0, 0, 0, 0, 0]]),
     'attention_mask': tensor([[1, 1, 1, 1, 1],
             [1, 1, 1, 1, 1]])}

###
Menambahkan token khusus

Token khusus (atau setidaknya konsepnya) sangat penting bagi BERT dan model-model turunannya. Token-token ini ditambahkan untuk merepresentasikan batas kalimat dengan lebih baik, seperti awal kalimat (`[CLS]`) atau pemisah antar kalimat (`[SEP]`). Mari kita lihat contoh sederhana:

    encoded_input = tokenizer("How are you?")
    print(encoded_input["input_ids"])
    tokenizer.decode(encoded_input["input_ids"])

    [101, 1731, 1132, 1128, 136, 102]
    '[CLS] How are you? [SEP]'

Token khusus ini secara otomatis ditambahkan oleh tokenizer. Tidak semua model memerlukan token khusus; token ini terutama digunakan ketika sebuah model telah dilatih sebelumnya dengan token-token tersebut, dalam hal ini tokenizer akan menambahkannya karena model mengharapkannya.

###
Kenapa Semua Ini Penting?

Berikut adalah contoh konkret. Perhatikan sekuens-sekuens yang telah dienkode berikut ini:

    sequences = [
        "I've been waiting for a HuggingFace course my whole life.",
        "I hate this so much!",
    ]

Setelah ditokenisasi:

    encoded_sequences = [
        [
            101,
            1045,
            1005,
            2310,
            2042,
            3403,
            2005,
            1037,
            17662,
            12172,
            2607,
            2026,
            2878,
            2166,
            1012,
            102,
        ],
        [101, 1045, 5223, 2023, 2061, 2172, 999, 102],
    ]

Ini adalah daftar sekuens yang telah dienkode: sebuah daftar dari daftar. Tensor hanya menerima bentuk yang persegi panjang (bayangkan seperti matriks). “Array” ini sudah memiliki bentuk persegi panjang, jadi mengonversinya menjadi tensor sangatlah mudah:

    import torch

    model_inputs = torch.tensor(encoded_sequences)

###
Menggunakan Tensor Sebagai Input ke Model

Menggunakan tensor sangat mudah — cukup panggil model dengan input:

    output = model(model_inputs)

Model bisa menerima banyak argumen, tapi hanya `input_ids` yang wajib. Penjelasan lebih lanjut tentang argumen lainnya akan dibahas setelah kita menyelami lebih dalam tokenizer dan bagaimana input dibangun untuk dipahami oleh model Transformer.

< > Update on GitHub