Uz transformatoriem balstīti modeļi ir slaveni ar savu spēju parsēt un interpretēt sarežģītu tekstu. Viņi paļaujas uz vārdu secības un konteksta izpratni - uzdevumiem, kuros tradicionālās pozicionālās kodēšanas metodes ir parādījušas savas robežas. Lai novērstu šo plaisu, ROFORMER modelis, ko darbina Rotary Position Embedding (RoPE), no jauna definē mūsu pieeju pozicionālajai kodēšanai.
Tradicionālais pozīcijas kodējums
Transformatori uztver tekstu kā marķieru sēriju un ļauj paralēli apstrādāt secības, lai nodrošinātu lielāku efektivitāti. Tomēr šis spēks radīja savu izaicinājumu: modelim raksturīgais agnosticisms simboliskā secībā. Pozicionālais kodējums bija atbilde, nodrošinot katram marķierim unikālu parakstu, kas apzīmē tā secības pozīciju.
Absolūtās pozīcijas iegulšana
Sākotnēji tādi modeļi kā BERT izmantoja absolūtās pozīcijas iegulšanu, katrai secības pozīcijai piešķirot fiksētu vektoru. Lai gan šī metode ir vienkārša, tai pēc būtības pietrūkst spējas pielāgoties secības garuma variācijām vai uzsvērt relatīvos attālumus starp marķieriem, kas ir būtiski daudzu lingvistisko konstrukciju izpratnei.
Relatīvās pozīcijas iegulšana
Lai uztvertu valodas dinamisko raksturu, tika ieviesti relatīvās pozīcijas ieguljumi, koncentrējoties uz attālumu starp marķieriem, nevis uz to absolūtajām pozīcijām. Neskatoties uz to konceptuālajām priekšrocībām, šie ieguljumi radīja skaitļošanas sarežģītību un nespēja nemanāmi integrēties Transformeru uzmanības pievēršanas mehānismā, ierobežojot to efektivitāti.
ROFORMER un Rotary Position iegulšana
Atzīstot esošo pozicionālās kodēšanas stratēģiju ierobežojumus, ROFORMER ievieš Rotary Position Embedding (RoPE) – pieeju, kas apvieno absolūtās un relatīvās pozīcijas informācijas priekšrocības bez to attiecīgiem trūkumiem.
Rotācijas pozīcijas iegulšana
RoPE kodē pozīcijas informāciju, izmantojot rotācijas matricas, ļaujot modelim saprast ne tikai to, kur atrodas marķieris, bet arī to, kā tas ir saistīts ar katru citu marķieri pēc kārtas.
Credit: ArXiv
Tas darbojas caur ģeometrisku lēcu, apstrādājot marķiera pozīcijas kā punktus daudzdimensiju telpā, kas tiek pagriezti, lai atzīmētu to secīgās attiecības. Šī rotācija ļauj modelim saglabāt un izmantot gan absolūtās, gan relatīvās pozicionālās norādes tā pašapziņas mehānismā.
Troses ieviešana
RoPE ieviešana ietver katra marķiera pozīcijas kodēšanu rotācijas matricā un šīs matricas pielietošanu transformatora pašapziņas mehānismā. Šis process ļauj elastīgi, dinamiski interpretēt pozicionālo informāciju, pielāgojot dažādus secību garumus un tverot marķieru savstarpējo attiecību būtību bez ievērojamām skaitļošanas izmaksām.
Pirmkārt, jums būs nepieciešama funkcija, lai ģenerētu rotējošo iegulšanu, un pēc tam šīs iegulšanas integrēsiet savā modelī. Tālāk sniegtajā piemērā tiek pieņemts, ka esat iepazinies ar pielāgotu slāņu izveidi programmā Keras.
1. solis: definējiet rotācijas iegulšanas funkciju
Šī funkcija ģenerē rotējošās iegulšanas, ņemot vērā maksimālo secības garumu un iegulšanas izmēru.
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))
Šī līnija aprēķina eksponenciāli mērogotu frekvenču apgriezto vērtību, pamatojoties uz pozīcijas indeksiem. Šīs frekvences tiek izmantotas, lai ģenerētu sinusoidālus modeļus rotācijas iegulšanai, kas palīdz secībās kodēt relatīvo pozīcijas informāciju. Šis mehānisms ir īpaši noderīgs uzdevumos, kuros elementu secības un relatīvā novietojuma izpratne ir ļoti svarīga, piemēram, dabiskās valodas apstrādē vai laikrindu analīzē.
Sīkāk:
- "tf.range(0, dim, 2, dtype=tf.float32)" izveido vērtību diapazonu, sākot no 0 līdz "dim" (izņemot), soli pa 2. Arguments "dtype=tf.float32" norāda ka šī tenzora elementi ir 32 bitu peldošā komata skaitļi. Piemēram, ja “dim” ir 8, tiek iegūts “[0, 2, 4, 6]”.
- Tf.range radītais tenzors tiek dalīts ar iegulto dimensiju (“dim”). Šī darbība samazina šos indeksus līdz diapazonam no 0 līdz 1 (izņemot, ja "dim" ir pāra, nedaudz iekļaujot, ja "dim" ir nepāra, jo diapazona solis izlaiž katru otro vērtību). Turpinot piemēru ar "dim" = 8, dalot ar 8, iegūst "[0,0, 0,25, 0,5, 0,75]".
-
Darbība `10000** (...) paaugstina 10 000 līdz katra elementa jaudai iepriekš mērogotajā tensorā. Bāze 10 000 ir zināmā mērā patvaļīga, taču tā ir izvēlēta, lai nodrošinātu, ka frekvences mainās plašā diapazonā, kas palīdz modelim efektīvāk atšķirt dažādas pozīcijas. Ja parametrs ir “[0,0, 0,25, 0,5, 0,75]”, katram no tiem tiktu piemērota jaudas darbība, kā rezultātā vērtības būtu daudz lielākas augstākiem elementiem.
-
Visbeidzot, apgrieztā frekvence tiek iegūta, ņemot apgriezto vērtību (1/x) no iepriekšējās darbības vērtībām. Apgrieztās frekvences ir mazākas augstākiem indeksiem, kas nozīmē, ka elementiem, kas atrodas tālāk secībā, būs mazākas frekvences, kas ietekmē to, kā to pozīcijas tiek kodētas modelī. Tas ļauj iegulšanu mērogot tādā veidā, ka relatīvās pozīcijas var secināt, izmantojot modeļa uzmanības mehānismus.
Līnija:
freqs = tf.einsum('i,j->ij', t, inv_freq)
izmanto TensorFlow funkciju `tf.einsum' — rīku, kas ļauj kodolīgi un efektīvi izteikt tenzora darbības, izmantojot Einšteina summēšanas apzīmējumu.
Šī darbība efektīvi aprēķina vektoru "t" un "inv_freq" ārējo reizinājumu, kā rezultātā tiek iegūta matrica, kurā katrs elements "(i, j)" ir "t" un "i" elementa reizinājums. j`-tais “inv_freq” elements. Šī matrica (frekvences) attēlo frekvences, kas tiek izmantotas, lai ģenerētu sinusoidālos modeļus rotācijas iegulšanai.
2. darbība: pielāgots Keras slānis rotācijas iegulšanai
Tagad izveidosim pielāgotu Keras slāni, kas ievades tensoram izmanto rotācijas iegulšanu. Šajā slānī tiek pieņemts, ka ievades tensoram ir forma “(partijas_lielums, secības_garums, iegulšanas_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
Rindā “embeddings = self.rotary_embeddings[:seq_len]” tiek atlasīta atbilstošā iepriekš aprēķināto rotācijas iegulto apakškopa, pamatojoties uz pašreizējo ievades secības garumu. Tā kā secību garums dažādās partijās var atšķirties, šī sadalīšanas darbība nodrošina, ka tiek izmantoti tikai tie ieguljumi, kas atbilst faktiskajam secības garumam.
Mainīgajam “embeddings” tagad ir formas tenzors “(seq_len, embedding_dim)”, kur “seq_len” ir pašreizējās partijas secību garums, bet “embedding_dim” ir iegulto elementu izmēri. Šis tensors satur rotācijas pozicionālo iegulšanu katrai pozīcijai secībā līdz "seq_len".
`emb = tf.concat((tf.cos(freqs), tf.sin(freqs)), axis=-1)' apvieno pozicionālo frekvenču sinusa un kosinusa transformācijas vienā tensorā:
- "tf.cos(freqs)" un "tf.sin(freqs)" piemēro kosinusa un sinusa transformācijas attiecīgi "freqs" tensoram. Tensors Freqs satur frekvenču vērtības katrai pozīcijai ievades secībā un katrai iegulšanas telpas dimensijai, kas aprēķinātas, pamatojoties uz secības pozīcijām un iegulšanas dimensiju apgrieztajām frekvencēm. Sinusa un kosinusa funkcijas tiek pielietotas elementāri, kā rezultātā tiek iegūti divi tenzori ar tādu pašu formu kā
frekvence
. Šīs transformācijas palīdz kodēt pozīciju tādā veidā, kas atspoguļo pozicionālo attiecību ciklisko raksturu, atvieglojot modeļa spēju izprast relatīvās pozīcijas.
-tf.concat((tf.cos(freqs), tf.sin(freqs)), axis=-1)' savieno kosinusa un sinusa pārveidotos tenzorus pa pēdējo asi (apzīmēta ar
axis=-1`). Šo tensoru savienošana blakus efektīvi dubulto 'frekvenču' tensora dimensiju, un pirmā puse attēlo kosinusa pārveidotās vērtības, bet otrā puse - sinusotransformētas vērtības katrai pozīcijai. Savienošana nodrošina, ka katrs pozicionālais kodējums satur gan sinusa, gan kosinusa informāciju, kas ļauj saglabāt informāciju gan par pozicionālo signālu amplitūdu, gan fāzi.
- Savienotajā tensorā “emb” tagad ir visi ievades pozīciju rotējošie ieguljumi. “emb” forma būs tāda pati kā “freqs” pirmajās divās dimensijās (atbilst secības pozīcijām un iegulšanas izmēriem), taču tā pēdējā dimensija būs divreiz lielāka, ņemot vērā gan sinusa, gan kosinusa vērtības. Šīs iegulšanas tiek izmantotas, lai modulētu ievades iegulšanu, pievienojot pozīcijas informāciju rotācijas līdzvērtīgā veidā.
-cos_emb = iegulšanas[:, Nav, :self.dim // 2]
:
1. Pirmais kols :
nozīmē "atlasīt visus elementus šajā dimensijā", kas šajā gadījumā attiecas uz visām pozīcijām secībā.
2. Neviens tiek izmantots, lai pievienotu papildu dimensiju, padarot tensoru trīsdimensiju. Tas bieži tiek darīts, lai nodrošinātu savietojamību ar noteiktām operācijām, kas sagaida ievadi ar noteiktu izmēru skaitu. Piemēram, veicot elementu reizināšanu ar citu tensoru, kas ir trīsdimensiju, formām ir jāsaskaņo saskaņā ar apraides noteikumiem.
:self.dim // 2
, atlasa dimensiju pirmo pusi pēdējā asī. Tā kā parametrs “embedding_dimension” ir dubultots, lai iekļautu gan sinusa, gan kosinusa vērtības, dalot ar 2, tiek atlasīti tikai iegulšanas kosinusa komponenti.
3. darbība. Integrācija ar Keras modeli
Pēc RotaryEmbeddingLayer
definēšanas varat to integrēt savā Keras modelī. Šis slānis ir jāuzklāj jūsu iegulumiem, pirms tos ievadāt uzmanības slāņos vai jebkuros turpmākajos modeļa slāņos.
Tālāk ir sniegts vienkāršots piemērs, kā modelī integrēt rotējošo iegulšanu.
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()