RoFormer: Transformator yang Ditingkatkan Dengan Penyematan Posisi Putar

RoFormer: Transformator yang Ditingkatkan Dengan Penyematan Posisi Putar

Model berbasis transformator terkenal karena kemampuannya mengurai dan menafsirkan teks yang kompleks. Mereka mengandalkan pemahaman urutan dan konteks kata - tugas di mana metode pengkodean posisi tradisional telah menunjukkan batasnya. Untuk mengatasi kesenjangan ini, model ROFORMER, yang didukung oleh Rotary Position Embedding (RoPE), mendefinisikan ulang pendekatan kami terhadap pengkodean posisi.

Pengkodean Posisi Tradisional

Transformer memperlakukan teks sebagai rangkaian token, dan memungkinkan pemrosesan rangkaian secara paralel untuk efisiensi yang lebih besar. Namun, kekuatan ini membawa tantangan tersendiri: agnostisisme yang melekat pada model terhadap tatanan token. Pengkodean posisi adalah jawabannya, memberikan setiap token tanda tangan unik yang menunjukkan posisi urutannya.

Penyematan Posisi Absolut

Awalnya, model seperti BERT menggunakan penyematan posisi absolut, menetapkan vektor tetap ke setiap posisi secara berurutan. Metode ini, meskipun sederhana, pada dasarnya tidak memiliki kemampuan untuk beradaptasi dengan variasi panjang urutan, atau untuk menekankan jarak relatif antar token, yang penting untuk memahami banyak konstruksi linguistik.

Penyematan Posisi Relatif

Untuk menangkap sifat dinamis bahasa, penyematan posisi relatif diperkenalkan, dengan fokus pada jarak antar token, bukan pada posisi absolutnya. Terlepas dari keunggulan konseptualnya, penyematan ini menimbulkan kompleksitas komputasi, dan gagal diintegrasikan secara mulus ke dalam mekanisme perhatian mandiri Transformers, sehingga membatasi kemanjurannya.

ROFORMER dan Penyematan Posisi Putar

Menyadari keterbatasan strategi pengkodean posisi yang ada, ROFORMER memperkenalkan Rotary Position Embedding (RoPE), sebuah pendekatan yang menggabungkan keunggulan informasi posisi absolut dan relatif tanpa kekurangannya masing-masing.

Penyematan Posisi Putar

RoPE mengkodekan informasi posisi menggunakan matriks rotasi, memungkinkan model untuk memahami tidak hanya di mana sebuah token berada, tetapi juga bagaimana kaitannya dengan setiap token lain secara berurutan.

Reformer.pngCredit: ArXiv

Ini beroperasi melalui lensa geometris, memperlakukan posisi token sebagai titik dalam ruang multidimensi yang diputar untuk menandai hubungan berurutannya. Rotasi ini memungkinkan model untuk mempertahankan dan mengeksploitasi isyarat posisi absolut dan relatif dalam mekanisme perhatian dirinya.

Menerapkan Tali

Penerapan RoPE melibatkan pengkodean posisi setiap token ke dalam matriks rotasi, dan penerapan matriks ini dalam mekanisme perhatian mandiri Transformer. Proses ini memungkinkan interpretasi informasi posisi yang fleksibel dan dinamis, mengakomodasi panjang urutan yang bervariasi dan menangkap esensi keterkaitan token tanpa overhead komputasi yang signifikan.

Pertama, Anda memerlukan fungsi untuk menghasilkan penyematan putar, lalu Anda akan mengintegrasikan penyematan ini ke dalam model Anda. Contoh di bawah ini mengasumsikan Anda sudah terbiasa membuat lapisan khusus di Keras.

Langkah 1: Tentukan Fungsi Penyematan Putar

Fungsi ini menghasilkan penyematan putar berdasarkan panjang urutan maksimum, dan dimensi penyematan.

from tensorflow.keras.layers import Layer
import numpy as np

def get_rotary_embedding(dim, max_seq_len):
    inv_freq = 1.0 / (10000 ** (tf.range(0, dim, 2, dtype=tf.float32) / dim))
    t = tf.range(max_seq_len, dtype=tf.float32)
    freqs = tf.einsum('i,j->ij', t, inv_freq)
    emb = tf.concat((tf.cos(freqs), tf.sin(freqs)), axis=-1)
    return emb

inv_freq = 1.0 / (10000 ** (tf.range(0, dim, 2, dtype=tf.float32) / dim))

Garis ini menghitung kebalikan dari frekuensi berskala eksponensial berdasarkan indeks posisi. Frekuensi ini digunakan dalam menghasilkan pola sinusoidal untuk penyematan putar, yang membantu dalam mengkodekan informasi posisi relatif secara berurutan. Mekanisme ini sangat berguna dalam tugas-tugas yang memerlukan pemahaman urutan dan posisi relatif elemen, seperti dalam pemrosesan bahasa alami atau analisis deret waktu.

Secara detail:

  • tf.range(0, dim, 2, dtype=tf.float32) membuat rentang nilai mulai dari 0 hingga dim (eksklusif), dilangkahi 2. Argumen dtype=tf.float32 menentukan bahwa elemen tensor ini adalah bilangan floating-point 32-bit. Jika dim adalah 8, misalnya, ini akan menghasilkan [0, 2, 4, 6].

  • Tensor yang dihasilkan oleh tf.range kemudian dibagi dengan dimensi (dim) dari embeddings. Operasi ini menurunkan skala indeks ke rentang antara 0 dan 1 (eksklusif jika dim genap, sedikit inklusif jika dim ganjil, karena langkah rentang melewati setiap nilai lainnya). Melanjutkan contoh dengan dim = 8, membaginya dengan 8 akan menghasilkan [0.0, 0.25, 0.5, 0.75].

  • Operasi 10000 ** (...) menaikkan 10.000 pangkat setiap elemen dalam tensor yang diskalakan sebelumnya. Basis 10.000 agak sewenang-wenang, namun dipilih untuk memastikan bahwa frekuensinya bervariasi dalam rentang yang luas, yang membantu model membedakan berbagai posisi dengan lebih efektif. Untuk [0.0, 0.25, 0.5, 0.75], operasi daya akan diterapkan pada masing-masing elemen, sehingga menghasilkan nilai yang jauh lebih besar untuk elemen yang lebih tinggi.

  • Terakhir, frekuensi invers diperoleh dengan mengambil nilai kebalikan (1/x) dari langkah sebelumnya. Frekuensi inversnya lebih kecil untuk indeks yang lebih tinggi, yang berarti elemen yang berada lebih jauh dalam urutan akan memiliki frekuensi yang lebih kecil, sehingga memengaruhi cara posisinya dikodekan ke dalam model. Hal ini memungkinkan penyematan untuk diskalakan sedemikian rupa sehingga posisi relatif dapat disimpulkan melalui mekanisme perhatian model.

Garis:

freqs = tf.einsum('i,j->ij', t, inv_freq)

menggunakan fungsi tf.einsum TensorFlow, alat yang memungkinkan ekspresi operasi tensor yang ringkas dan efisien menggunakan notasi penjumlahan Einstein.

Operasi ini secara efektif menghitung hasil kali luar dari vektor t dan inv_freq, menghasilkan matriks dengan setiap elemen (i, j) adalah hasil kali elemen ke-i dari t dan elemen ke-j dari inv_freq. Matriks ini (freqs) mewakili frekuensi yang digunakan untuk menghasilkan pola sinusoidal untuk penyematan putar.

Langkah 2: Lapisan Keras Kustom untuk Penyematan Putar

Sekarang, mari buat lapisan Keras khusus yang menerapkan penyematan putar ke tensor masukan. Lapisan ini mengasumsikan bahwa tensor masukan berbentuk (batch_size, sequence_length, embedding_dim).

class RotaryEmbeddingLayer(Layer):
    def __init__(self, dim, max_seq_len, **kwargs):
        super().__init__(**kwargs)
        self.dim = dim
        self.max_seq_len = max_seq_len
        self.rotary_embeddings = get_rotary_embedding(dim, max_seq_len)

    def call(self, inputs):
        seq_len = tf.shape(inputs)[1]
        embeddings = self.rotary_embeddings[:seq_len]
        
        cos_emb = embeddings[:, None, :self.dim // 2]
        sin_emb = embeddings[:, None, self.dim // 2:]
        
        # Decompose inputs into sine and cosine components
        inputs_cos = inputs[..., :self.dim // 2]
        inputs_sin = inputs[..., self.dim // 2:]
        
        # Apply rotary embeddings
        rotated_cos = inputs_cos * cos_emb - inputs_sin * sin_emb
        rotated_sin = inputs_sin * cos_emb + inputs_cos * sin_emb
        
        return tf.concat([rotated_cos, rotated_sin], axis=-1)

    def get_config(self):
        config = super().get_config()
        config.update({
            "dim": self.dim,
            "max_seq_len": self.max_seq_len
        })
        return config

Baris embeddings = self.rotary_embeddings[:seq_len] memilih subset yang sesuai dari penyematan putar yang telah dihitung sebelumnya berdasarkan panjang urutan masukan saat ini. Karena panjang urutan dapat bervariasi dari satu kumpulan ke kumpulan lainnya, operasi pemotongan ini memastikan bahwa hanya penyematan yang sesuai dengan panjang urutan sebenarnya yang digunakan.

Variabel embeddings sekarang memiliki tensor bentuk (seq_len, embedding_dim), dengan seq_len adalah panjang urutan dalam kumpulan saat ini, dan embedding_dim adalah dimensi embeddings. Tensor ini berisi penyematan posisi putar untuk setiap posisi dalam urutan hingga seq_len.

emb = tf.concat((tf.cos(freqs), tf.sin(freqs)), axis=-1) menggabungkan transformasi sinus dan kosinus dari frekuensi posisi menjadi tensor tunggal:

-tf.cos(freqs) dan tf.sin(freqs) masing-masing menerapkan transformasi kosinus dan sinus ke tensor freqs. Tensor freqs berisi nilai frekuensi untuk setiap posisi dalam urutan masukan dan setiap dimensi ruang penyematan, dihitung berdasarkan posisi urutan dan frekuensi kebalikan dari dimensi penyematan. Fungsi sinus dan kosinus diterapkan berdasarkan elemen, menghasilkan dua tensor dengan bentuk yang sama seperti freq. Transformasi ini membantu mengkodekan posisi dengan cara yang menangkap sifat siklus hubungan posisi, memfasilitasi kemampuan model untuk memahami posisi relatif.

-tf.concat((tf.cos(freqs), tf.sin(freqs)), axis=-1) menggabungkan tensor transformasi kosinus dan sinus di sepanjang sumbu terakhir (dilambangkan dengan axis=-1). Menggabungkan tensor-tensor ini secara berdampingan secara efektif menggandakan dimensi tensor freqs, dengan paruh pertama mewakili nilai-nilai transformasi kosinus dan paruh kedua mewakili nilai-nilai transformasi sinus untuk setiap posisi. Penggabungan memastikan bahwa setiap pengkodean posisi berisi informasi sinus dan kosinus, yang memungkinkan pelestarian informasi tentang amplitudo dan fase sinyal posisi.

  • emb tensor gabungan kini menampung penyematan putar lengkap untuk posisi masukan. Bentuk emb akan sama dengan freqs dalam dua dimensi pertamanya (sesuai dengan posisi urutan dan dimensi penyematan), namun dimensi terakhirnya akan dua kali lebih besar, memperhitungkan nilai sinus dan kosinus. Penyematan ini digunakan untuk memodulasi penyematan masukan dengan menambahkan informasi posisi secara rotasi ekuivalen.

-cos_emb = penyematan[:, Tidak ada, :self.dim // 2]:

  1. Titik dua pertama : berarti "pilih semua elemen dalam dimensi ini", yang dalam hal ini mengacu pada semua posisi dalam urutan.

  2. None digunakan untuk menambahkan dimensi tambahan, sehingga tensor menjadi 3 dimensi. Hal ini sering dilakukan untuk memastikan kompatibilitas dengan operasi tertentu yang mengharapkan masukan sejumlah dimensi tertentu. Misalnya, saat melakukan perkalian berdasarkan elemen dengan tensor lain yang berbentuk 3 dimensi, bentuknya harus sejajar sesuai dengan aturan penyiaran.

  3. :self.dim // 2, memilih paruh pertama dimensi pada sumbu terakhir. Karena embedding_dimension digandakan untuk menyertakan nilai sinus dan cosinus, membagi dengan 2 secara efektif hanya akan memilih komponen cosinus dari embeddings.

Langkah 3: Integrasi dengan Model Keras

Setelah mendefinisikan RotaryEmbeddingLayer, Anda dapat mengintegrasikannya ke dalam model Keras Anda. Lapisan ini harus diterapkan pada embeddings Anda sebelum memasukkannya ke dalam lapisan perhatian atau lapisan model berikutnya.

Berikut adalah contoh sederhana tentang cara mengintegrasikan penyematan putar ke dalam model:

from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Embedding, Dense

max_seq_len = 512
embedding_dim = 64

inp = Input(shape=(max_seq_len,))
x = Embedding(input_dim=10000, output_dim=embedding_dim)(inp)
x = RotaryEmbeddingLayer(dim=embedding_dim, max_seq_len=max_seq_len)(x)
# Add your model's layers here, e.g., Transformer blocks
x = Dense(1, activation='sigmoid')(x)

model = Model(inputs=inp, outputs=x)
model.summary()

Code Labs Academy © 2025 Semua hak dilindungi undang-undang.