RoFormer: Továbbfejlesztett transzformátor forgópozíciós beágyazással

RoFormer: Továbbfejlesztett transzformátor forgópozíciós beágyazással

A Transformer-alapú modellek híresek összetett szövegek elemzésére és értelmezésére való képességükről. A szavak sorrendjének és kontextusának megértésére támaszkodnak – olyan feladatok, amelyeknél a hagyományos pozíciókódolási módszerek megmutatták korlátaikat. Ezt a hiányosságot orvosolva a ROFORMER modell, amelyet a Rotary Position Embedding (RoPE) hajt meg, újradefiniálja a helyzetkódoláshoz való hozzáállásunkat.

Hagyományos pozíciókódolás

A transzformátorok a szöveget tokenek sorozataként kezelik, és lehetővé teszik a sorozatok párhuzamos feldolgozását a nagyobb hatékonyság érdekében. Ez az erő azonban meghozta a maga kihívását: a modellben rejlő agnoszticizmust jelképes sorrendben. A pozíciós kódolás volt a válasz, minden jogkivonat egyedi aláírással látva el a szekvencia pozícióját.

Abszolút pozíció beágyazások

Kezdetben az olyan modellek, mint a BERT, abszolút pozíció beágyazást használtak, és egy fix vektort rendeltek a sorozat minden pozíciójához. Ez a módszer, bár egyszerű, hiányzik a szekvenciahossz-változásokhoz való alkalmazkodás képessége, vagy a tokenek közötti relatív távolságok hangsúlyozása, ami számos nyelvi konstrukció megértéséhez kritikus.

Relatív pozíció beágyazások

A nyelv dinamikus természetének megragadására a relatív pozíció beágyazásokat vezették be, amelyek a tokenek közötti távolságra helyezték a hangsúlyt az abszolút pozíciójuk helyett. Koncepcionális előnyük ellenére ezek a beágyazások számítási bonyolultságot vezettek be, és nem tudtak zökkenőmentesen integrálódni a Transformers önfigyelő mechanizmusába, ami korlátozta hatékonyságukat.

ROFORMER és Rotary Position beágyazás

Felismerve a meglévő pozíciókódolási stratégiák korlátait, a ROFORMER bevezeti a Rotary Position Embedding (RoPE) megoldást, amely egyesíti az abszolút és relatív pozícióinformációk előnyeit a megfelelő hátrányok nélkül.

Rotary Position Beágyazás

A RoPE forgási mátrixok segítségével kódolja a helyzetinformációkat, lehetővé téve a modell számára, hogy ne csak azt tudja, hol van egy token, hanem azt is, hogyan viszonyul a sorozat összes többi tokenjéhez.

Reformer.pngCredit: ArXiv

Geometriai lencsén keresztül működik, és a token pozíciókat pontként kezeli egy többdimenziós térben, amelyeket elforgatva jelöli egymás utáni kapcsolataikat. Ez a forgatás lehetővé teszi, hogy a modell megőrizze és kihasználja mind az abszolút, mind a relatív pozíciójeleket az önfigyelő mechanizmusán belül.

Kötél megvalósítása

A RoPE megvalósítása magában foglalja az egyes token pozíciók forgatási mátrixba való kódolását, és ennek a mátrixnak a transzformátor önfigyelő mechanizmusán belüli alkalmazását. Ez a folyamat lehetővé teszi a pozícióinformációk rugalmas, dinamikus értelmezését, alkalmazkodva a változó sorozathosszokhoz, és jelentős számítási többletköltség nélkül megragadja a token kölcsönhatások lényegét.

Először is szüksége lesz egy függvényre a forgó beágyazások létrehozásához, majd integrálja ezeket a beágyazásokat a modelljébe. Az alábbi példa feltételezi, hogy ismeri az egyéni rétegek létrehozását a Kerasban.

1. lépés: Határozza meg a Rotary beágyazási funkciót

Ez a funkció a maximális sorozathossz és a beágyazások méretei alapján állítja elő a forgó beágyazásokat.

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))

Ez a sor az exponenciálisan skálázott frekvenciák inverzét számítja ki a pozícióindexek alapján. Ezeket a frekvenciákat a forgó beágyazások szinuszos mintázatainak generálására használják, ami segít a relatív helyzetinformáció szekvenciákba való kódolásában. Ez a mechanizmus különösen hasznos olyan feladatokban, ahol az elemek sorrendjének és egymáshoz viszonyított elhelyezkedésének megértése döntő fontosságú, mint például a természetes nyelvi feldolgozás vagy az idősorelemzés.

Részletesen:

  • A tf.range(0, dim, 2, dtype=tf.float32) 0-tól dim'-ig (kizárólag) értéktartományt hoz létre, 2-vel lépve. A dtype=tf.float32` argumentum határozza meg hogy ennek a tenzornak az elemei 32 bites lebegőpontos számok. Ha például a „dim” értéke 8, akkor ez „[0, 2, 4, 6]” értéket eredményez.

  • A "tf.range" által létrehozott tenzort ezután elosztják a beágyazások dimenziójával ("dim"). Ez a művelet leskálázza ezeket az indexeket egy 0 és 1 közötti tartományra (kivéve, ha a "dim" páros, kissé beleértve, ha a "dim" páratlan, mert a tartomány lépése minden más értéket kihagy). Ha a példát a „dim” = 8-cal folytatjuk, 8-cal osztva a következőt kapjuk: „[0,0, 0,25, 0,5, 0,75]”.

  • Az 10000 ** (...) művelet 10 000-et emel az előzőleg skálázott tenzor minden elemének hatványára. A 10 000-es alap némileg önkényes, de azért választották, hogy a frekvenciák széles tartományban változzanak, ami segít a modellnek a különböző pozíciók hatékonyabb megkülönböztetésében. A "[0,0, 0,25, 0,5, 0,75]" esetén mindegyikre alkalmazza a teljesítményműveletet, ami sokkal nagyobb értékeket eredményez a magasabb elemeknél.

  • Végül az inverz frekvenciát úgy kapjuk meg, hogy az előző lépésből származó értékek reciprokát (1/x) vesszük. Az inverz frekvenciák kisebbek magasabb indexeknél, ami azt jelenti, hogy a szekvenciában távolabbi elemek kisebb frekvenciájúak lesznek, ami befolyásolja, hogy pozíciójuk hogyan kerül kódolásra a modellbe. Ez lehetővé teszi a beágyazások méretezését oly módon, hogy a relatív pozíciókra a modell figyelmi mechanizmusain keresztül lehet következtetni.

A vonal:

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

a TensorFlow "tf.einsum" függvényét használja, amely lehetővé teszi a tenzorműveletek tömör és hatékony kifejezését az Einstein-összegzési jelölés használatával.

Ez a művelet hatékonyan kiszámítja a "t" és az "inv_freq" vektorok külső szorzatát, ami egy mátrixot eredményez, ahol minden egyes "(i, j)" elem a "t" "i"-edik elemének és a ' j-edik eleme az inv_freq`-nek. Ez a mátrix ("frekvenciák") azokat a frekvenciákat jelenti, amelyek a forgó beágyazások szinuszos mintáinak generálására szolgálnak.

2. lépés: Egyéni Keras réteg forgó beágyazásokhoz

Most hozzunk létre egy egyéni Keras-réteget, amely forgó beágyazásokat alkalmaz a bemeneti tenzorra. Ez a réteg feltételezi, hogy a bemeneti tenzor (batch_size, series_length, embedding_dim) alakú.

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

Az embeddings = self.rotary_embeddings[:seq_len] sor kiválasztja az előre kiszámított forgó beágyazások megfelelő részhalmazát az aktuális bemeneti sorozathossz alapján. Mivel a sorozatok hossza kötegenként változhat, ez a szeletelési művelet biztosítja, hogy csak a tényleges sorozathossznak megfelelő beágyazások kerüljenek felhasználásra.

Az 'embeddings' változó most egy '(seq_len, embedding_dim)' alakú tenzorral rendelkezik, ahol a 'seq_len' a sorozatok hossza az aktuális kötegben, az 'embedding_dim' pedig a beágyazások dimenziója. Ez a tenzor tartalmazza a forgó pozíciós beágyazásokat a szekvencia minden pozíciójához a seq_len-ig.

Az emb = tf.concat((tf.cos(frekvenciák), tf.sin(frekvenciák)), axis=-1) egyetlen tenzorba egyesíti a helyzeti frekvenciák szinuszos és koszinuszos transzformációit:

  • "tf.cos(freqs)" és "tf.sin(freqs)" a koszinusz-, illetve szinusztranszformációt alkalmazza a 'freqs' tenzorra. A "frekvenciák" tenzor frekvenciaértékeket tartalmaz a bemeneti szekvencia minden pozíciójához és a beágyazási tér minden dimenziójához, amelyeket a sorozatpozíciók és a beágyazási dimenziók inverz frekvenciái alapján számítanak ki. A szinusz- és koszinuszfüggvények elemenként kerülnek alkalmazásra, ami két, a `frekvenciával megegyező alakú tenzort eredményez. Ezek a transzformációk segítenek a pozíció kódolásában oly módon, hogy megragadja a pozícióviszonyok ciklikus jellegét, megkönnyítve a modell azon képességét, hogy megértse a relatív pozíciókat.

-tf.concat((tf.cos(frekvenciák), tf.sin(frekvenciák)), axis=-1) összefűzi a koszinusz- és szinusztranszformált tenzorokat az utolsó tengely mentén (az axis=-1 jelöléssel). Ezeknek a tenzoroknak egymás mellé fűzése hatékonyan megduplázza a "frekvencia" tenzor dimenzióját, az első fele koszinusz-transzformált értékeket, a második fele pedig szinusz-transzformált értékeket jelent minden pozícióhoz. Az összefűzés biztosítja, hogy minden pozíciókódolás szinuszos és koszinuszos információt is tartalmazzon, ami lehetővé teszi a helyzetjelek amplitúdójával és fázisával kapcsolatos információk megőrzését.

  • Az összefűzött tenzor emb most a teljes forgó beágyazást tartalmazza a bemeneti pozíciókhoz. Az 'emb' alakja megegyezik a 'freqs' alakjával az első két dimenziójában (amely a szekvencia pozícióinak és a beágyazási dimenzióknak felel meg), de az utolsó dimenzió kétszer akkora lesz, és figyelembe veszi a szinusz- és koszinuszértékeket is. Ezek a beágyazások a bemeneti beágyazások modulálására szolgálnak helyzetinformációk hozzáadásával, rotációs ekvivariáns módon.

-cos_emb = beágyazások[:, Nincs, :self.dim // 2]:

  1. Az első kettőspont ":" azt jelenti, hogy "az összes elemet ki kell választani ebben a dimenzióban", ami ebben az esetben a sorozat összes pozíciójára vonatkozik.

  2. A "Nincs" egy további dimenzió hozzáadására szolgál, így a tenzor háromdimenziós. Ezt gyakran azért teszik, hogy biztosítsák a kompatibilitást bizonyos műveletekkel, amelyek meghatározott számú dimenzió bemenetét várják. Például, amikor elemenkénti szorzást hajt végre egy másik, háromdimenziós tenzorral, az alakzatoknak a sugárzási szabályok szerint kell igazodniuk.

  3. :self.dim // 2, az utolsó tengely méreteinek első felét választja ki. Mivel az "embedding_dimension" megduplázódik, hogy szinuszos és koszinuszos értékeket is tartalmazzon, a 2-vel való elosztás gyakorlatilag csak a beágyazások koszinuszkomponenseit választja ki.

3. lépés: Integráció Keras modellel

A "RotaryEmbeddingLayer" meghatározása után integrálhatja a Keras modelljébe. Ezt a réteget fel kell vinni a beágyazásokra, mielőtt betáplálná őket a figyelemfelkeltő rétegekbe vagy bármely további modellrétegbe.

Íme egy egyszerűsített példa a forgó beágyazások modellbe való integrálására:

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 Minden jog fenntartva.