RoFormer: Verbeterde transformator met roterende posisie-inbedding

RoFormer: Verbeterde transformator met roterende posisie-inbedding

Transformator-gebaseerde modelle is bekend vir hul vermoë om komplekse teks te ontleed en te interpreteer. Hulle maak staat op die begrip van die volgorde en konteks van woorde - take waarby tradisionele posisionele enkoderingsmetodes hul grense getoon het. Deur hierdie gaping aan te spreek, herdefinieer die ROFORMER-model, aangedryf deur die Rotary Position Embedding (RoPE), ons benadering tot posisionele enkodering.

Tradisionele Posisionele Enkodering

Transformators behandel teks as 'n reeks tekens, en laat parallelle verwerking van rye toe vir groter doeltreffendheid. Hierdie krag het egter sy uitdaging gebring: die model se inherente agnostisisme tot tekenorde. Posisionele enkodering was die antwoord, wat elke teken 'n unieke handtekening verskaf wat sy volgordeposisie aandui.

Absolute Posisie-inbeddings

Aanvanklik het modelle soos BERT absolute posisie-inbeddings gebruik, wat 'n vaste vektor aan elke posisie in 'n volgorde toegewys het. Hierdie metode, alhoewel eenvoudig, het inherent nie die vermoë om aan te pas by variasies in volgordelengte nie, of om die relatiewe afstande tussen tekens ** te beklemtoon, van kritieke belang vir die verstaan ​​van baie linguistiese konstrukte.

Relatiewe posisie-inbeddings

Om die dinamiese aard van taal vas te vang, is relatiewe posisie-inbeddings ingestel, met die fokus op die afstand tussen tekens eerder as hul absolute posisies. Ten spyte van hul konseptuele voordeel, het hierdie inbeddings rekenkundige kompleksiteit ingebring, en het nie daarin geslaag om naatloos in die self-aandagmeganisme van Transformers te integreer nie, wat hul doeltreffendheid beperk het.

ROFORMER en Rotary Position Inbedding

Met erkenning van die beperkings van bestaande posisionele enkoderingstrategieë, stel ROFORMER Rotary Position Embedding (RoPE), 'n benadering wat die voordele van absolute en relatiewe posisie-inligting kombineer sonder hul onderskeie nadele.

Roterende posisie-inbedding

RoPE kodeer posisionele inligting deur rotasiematrikse te gebruik, wat die model in staat stel om nie net te verstaan ​​waar 'n teken is nie, maar hoe dit met elke ander teken in 'n volgorde verband hou.

Reformer.pngCredit: ArXiv

Dit werk deur 'n geometriese lens, en behandel tekenposisies as punte in 'n multi-dimensionele ruimte wat geroteer word om hul opeenvolgende verwantskappe te merk. Hierdie rotasie laat die model toe om beide absolute en relatiewe posisionele leidrade binne sy self-aandagmeganisme te bewaar en te ontgin.

Implementering van RoPE

Implementering van RoPE behels die enkodering van elke teken se posisie in 'n rotasiematriks, en die toepassing van hierdie matriks binne die self-aandagmeganisme van die Transformator. Hierdie proses maak voorsiening vir 'n buigsame, dinamiese interpretasie van posisionele inligting, wat wisselende volgordelengtes akkommodeer en die essensie van token-interverwantskappe vaslê sonder noemenswaardige berekeningsbokoste.

Eerstens het jy 'n funksie nodig om die roterende inbeddings te genereer, en dan sal jy hierdie inbeddings in jou model integreer. Die voorbeeld hieronder neem aan dat jy vertroud is met die skep van pasgemaakte lae in Keras.

Stap 1: Definieer die Rotary Embedding-funksie

Hierdie funksie genereer die roterende inbeddings gegewe die maksimum volgorde lengte, en die dimensionaliteit van die inbeddings.

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

Hierdie lyn bereken die inverse van eksponensieel geskaalde frekwensies gebaseer op die posisie-indekse. Hierdie frekwensies word gebruik om sinusvormige patrone vir roterende inbeddings te genereer, wat help om die relatiewe posisionele inligting in rye te enkodeer. Hierdie meganisme is veral nuttig in take waar begrip van die volgorde en relatiewe posisionering van elemente van kardinale belang is, soos in natuurlike taalverwerking of tydreeksanalise.

In besonderhede:

  • tf.range(0, dim, 2, dtype=tf.float32) skep 'n reeks waardes vanaf 0 tot en met dim (eksklusief), met 2 stapsgewys. Die dtype=tf.float32-argument spesifiseer dat die elemente van hierdie tensor 32-bis swaaipuntgetalle is. As dim byvoorbeeld 8 is, sal dit [0, 2, 4, 6] produseer.

  • Die tensor wat deur tf.range geproduseer word, word dan gedeel deur die dimensionaliteit (dim) van die inbeddings. Hierdie bewerking skaal hierdie indekse af na 'n reeks tussen 0 en 1 (eksklusief as dim ewe is, effens inklusief as dim vreemd is, want die reeksstap slaan elke ander waarde oor). Deur die voorbeeld voort te sit met dim = 8, deling deur 8 lewer [0.0, 0.25, 0.5, 0.75].

  • Die 10000 ** (...) bewerking verhoog 10 000 tot die krag van elke element in die voorheen geskaalde tensor. Die basis van 10 000 is ietwat arbitrêr, maar word gekies om te verseker dat die frekwensies oor 'n wye reeks verskil, wat die model help om meer effektief tussen verskillende posisies te onderskei. Vir [0.0, 0.25, 0.5, 0.75] sal dit die kragbewerking op elkeen toepas, wat lei tot waardes wat baie groter is vir hoër elemente.

  • Laastens word die omgekeerde frekwensie verkry deur die resiproke (1/x) van die waardes van die vorige stap te neem. Die inverse frekwensies is kleiner vir hoër indekse, wat beteken dat elemente verder in die volgorde kleiner frekwensies sal hê, wat beïnvloed hoe hul posisies in die model geënkodeer word. Dit laat die inbeddings toe om te skaal op 'n wyse waar relatiewe posisies deur die model se aandagmeganismes afgelei kan word.

Die lyn:

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

gebruik TensorFlow se tf.einsum-funksie, 'n instrument wat dit moontlik maak vir bondige en doeltreffende uitdrukking van tensor-bewerkings deur die Einstein-opsommingsnotasie te gebruik.

Hierdie bewerking bereken effektief die buitenste produk van die t en inv_freq vektore, wat lei tot 'n matriks waar elke element (i, j) die produk is van die i-de element van t en die j-de element van inv_freq. Hierdie matriks (freqs) verteenwoordig die frekwensies wat gebruik word om die sinusvormige patrone vir die roterende inbeddings te genereer.

Stap 2: Pasgemaakte Keras-laag vir roterende inbeddings

Kom ons skep nou 'n pasgemaakte Keras-laag wat roterende inbeddings op die invoertensor toepas. Hierdie laag neem aan dat die invoertensor van vorm (batch_size, sequence_length, embedding_dim) is.

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

Die reël inbeddings = self.rotary_embeddings[:seq_len] kies die toepaslike subset van voorafberekende roterende inbeddings gebaseer op die huidige invoervolgordelengte. Aangesien die lengte van reekse van een bondel na 'n ander kan wissel, verseker hierdie snybewerking dat slegs die inbeddings wat met die werklike reekslengte ooreenstem, gebruik word.

Die veranderlike "inbeddings" het nou 'n tensor van vorm '(seq_len, embedding_dim)', waar 'seq_len' die lengte van die rye in die huidige bondel is, en 'embedding_dim' is die dimensionaliteit van die inbeddings. Hierdie tensor bevat die roterende posisionele inbeddings vir elke posisie in die volgorde tot en met seq_len.

emb = tf.concat((tf.cos(freqs), tf.sin(freqs)), as=-1) kombineer sinus- en cosinustransformasies van posisionele frekwensies in 'n enkele tensor:

-tf.cos(freqs) en tf.sin(freqs) pas die cosinus- en sinustransformasies onderskeidelik toe op die freqs-tensor. Die freqs tensor bevat frekwensiewaardes vir elke posisie in die invoervolgorde en elke dimensie van die inbeddingspasie, bereken op grond van die volgordeposisies en die omgekeerde frekwensies van die inbeddingdimensies. Die sinus- en cosinusfunksies word elementgewys toegepas, wat lei tot twee tensors van dieselfde vorm as freqs. Hierdie transformasies help om die posisie te enkodeer op 'n manier wat die sikliese aard van posisionele verhoudings vasvang, wat die model se vermoë om relatiewe posisies te verstaan, vergemaklik.

-tf.concat((tf.cos(freqs), tf.sin(freqs)), as=-1) verbind die cosinus- en sinus-getransformeerde tensors langs die laaste as (aangedui deur as=-1). Die samevoeging van hierdie tensors langs mekaar verdubbel effektief die dimensionaliteit van die freqs tensor, met die eerste helfte wat cosinus-getransformeerde waardes verteenwoordig en die tweede helfte wat sinus-getransformeerde waardes vir elke posisie verteenwoordig. Die aaneenskakeling verseker dat elke posisionele enkodering beide sinus- en cosinus-inligting bevat, wat die behoud van inligting oor beide die amplitude en fase van die posisionele seine moontlik maak.

  • Die aaneengeskakelde tensor emb hou nou die volledige roterende inbeddings vir die invoerposisies. Die vorm van emb sal dieselfde wees as freqs in sy eerste twee dimensies (wat ooreenstem met ryposisies en inbeddingsdimensies), maar sy laaste dimensie sal twee keer so groot wees, wat beide sinus- en cosinuswaardes in ag neem. Hierdie inbeddings word gebruik om die insetinbeddings te moduleer deur posisionele inligting op 'n rotasie-ekwivariante wyse by te voeg.

-cos_emb = inbeddings[:, Geen, :self.dim // 2]:

  1. Die eerste dubbelpunt : beteken "kies alle elemente in hierdie dimensie," wat, in hierdie geval, verwys na alle posisies in die ry.

  2. Geen word gebruik om 'n bykomende dimensie by te voeg, wat die tensor 3-dimensioneel maak. Dit word dikwels gedoen om versoenbaarheid te verseker met sekere bewerkings wat insette van 'n spesifieke aantal dimensies verwag. Byvoorbeeld, wanneer elementsgewyse vermenigvuldiging uitgevoer word met 'n ander tensor wat 3-dimensioneel is, moet die vorms in lyn wees volgens uitsaaireëls.

  3. :self.dim // 2, kies die eerste helfte van die afmetings in die laaste as. Aangesien die 'inbedding_dimensie' verdubbel word om beide sinus- en cosinuswaardes in te sluit, kies deling deur 2 effektief net die cosinuskomponente van die inbeddings.

Stap 3: Integrasie met 'n Keras-model

Nadat jy die RotaryEmbeddingLayer gedefinieer het, kan jy dit in jou Keras-model integreer. Hierdie laag moet op jou inbeddings aangebring word voordat dit in aandaglae of enige daaropvolgende modellae ingevoer word.

Hier is 'n vereenvoudigde voorbeeld van hoe om die roterende inbeddings in 'n model te integreer:

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 Alle regte voorbehou.