Introductie
Er zijn tal van handleidingen die uitleggen hoe transformatoren werken en voor het bouwen van een intuïtie op een belangrijk element ervan: token- en positie-inbedding.
Door tokens positioneel in te bedden, konden transformatoren niet-rigide relaties tussen tokens (meestal woorden) vertegenwoordigen, wat veel beter is in het modelleren van onze contextgestuurde spraak in taalmodellering. Hoewel het proces relatief eenvoudig is, is het vrij generiek, en de implementaties worden snel een standaardtekst.
In deze korte handleiding bekijken we hoe we KerasNLP, de officiële Keras-add-on, kunnen gebruiken om
PositionEmbedding
enTokenAndPositionEmbedding
.
KerasNLP
KerasNLP is een horizontale toevoeging voor NLP. Op het moment van schrijven is het nog erg jong, met versie 0.3, en de documentatie is nog vrij summier, maar het pakket is al meer dan alleen bruikbaar.
Het biedt toegang tot Keras-lagen, zoals: TokenAndPositionEmbedding
, TransformerEncoder
en TransformerDecoder
, wat het bouwen van aangepaste transformatoren eenvoudiger dan ooit maakt.
Om KerasNLP in ons project te gebruiken, kun je het installeren via pip
:
$ pip install keras_nlp
Eenmaal geïmporteerd in het project, kunt u elke keras_nlp
laag als een standaard Keras-laag.
tokenization
Computers werken met cijfers. We verwoorden onze gedachten in woorden. Om de computer ze te laten kraken, moeten we woorden in een of andere vorm aan getallen toewijzen.
Een veelgebruikte manier om dit te doen is om woorden eenvoudig toe te wijzen aan getallen waarbij elk geheel getal een woord vertegenwoordigt. Een corpus van woorden creëert een woordenschat en elk woord in de woordenschat krijgt een index. U kunt dus een reeks woorden omzetten in een reeks indices die bekend staat als penningen:
def tokenize(sequence):
return tokenized_sequence
sequence = ['I', 'am', 'Wall-E']
sequence = tokenize(sequence)
print(sequence)
Deze reeks tokens kan vervolgens worden ingebed in een dichte vector die de tokens in de latente ruimte definieert:
[[4], [26], [472]] -> [[0.5, 0.25], [0.73, 0.2], [0.1, -0.75]]
Dit wordt meestal gedaan met de Embedding
laag in Keras. Transformers coderen niet alleen met behulp van een standaard Embedding
laag. Zij treden op Embedding
en PositionEmbedding
, en ze bij elkaar optellen, waarbij de reguliere inbeddingen worden verplaatst door hun positie in de latente ruimte.
Met KerasNLP – optreden TokenAndPositionEmbedding
combineert reguliere token-inbedding (Embedding
) met positionele inbedding (PositionEmbedding
).
PositieInbedding
Laten we eens kijken PositionEmbedding
eerst. Het accepteert tensoren en rafelige tensoren en gaat ervan uit dat de laatste dimensie de kenmerken vertegenwoordigt, terwijl de voorlaatste dimensie de reeks vertegenwoordigt.
# Seq
(5, 10)
# Features
De laag accepteert a sequence_length
argument, dat aangeeft, nou ja, de lengte van de invoer- en uitvoerreeks. Laten we doorgaan en positioneel een willekeurige uniforme tensor insluiten:
seq_length = 5
input_data = tf.random.uniform(shape=[5, 10])
input_tensor = keras.Input(shape=[None, 5, 10])
output = keras_nlp.layers.PositionEmbedding(sequence_length=seq_length)(input_tensor)
model = keras.Model(inputs=input_tensor, outputs=output)
model(input_data)
Dit resulteert in:
<tf.Tensor: shape=(5, 10), dtype=float32, numpy=
array([[ 0.23758471, -0.16798696, -0.15070847, 0.208067 , -0.5123104 ,
-0.36670157, 0.27487397, 0.14939266, 0.23843127, -0.23328197],
[-0.51353353, -0.4293166 , -0.30189738, -0.140344 , -0.15444171,
-0.27691704, 0.14078277, -0.22552207, -0.5952263 , -0.5982155 ],
[-0.265581 , -0.12168896, 0.46075982, 0.61768025, -0.36352775,
-0.14212841, -0.26831496, -0.34448475, 0.4418767 , 0.05758983],
[-0.46500492, -0.19256318, -0.23447984, 0.17891657, -0.01812166,
-0.58293337, -0.36404118, 0.54269964, 0.3727749 , 0.33238482],
[-0.2965023 , -0.3390794 , 0.4949159 , 0.32005525, 0.02882379,
-0.15913549, 0.27996767, 0.4387421 , -0.09119213, 0.1294356 ]],
dtype=float32)>
TokenAndPositieInbedding
Het insluiten van tokens en posities komt neer op het gebruik van Embedding
op de invoerreeks, PositionEmbedding
op de ingesloten tokens, en vervolgens deze twee resultaten bij elkaar op te tellen, waardoor de token-inbeddingen in de ruimte effectief worden verplaatst om hun relatieve betekenisvolle relaties te coderen.
Dit kan technisch worden gedaan als:
seq_length = 10
vocab_size = 25
embed_dim = 10
input_data = tf.random.uniform(shape=[5, 10])
input_tensor = keras.Input(shape=[None, 5, 10])
embedding = keras.layers.Embedding(vocab_size, embed_dim)(input_tensor)
position = keras_nlp.layers.PositionEmbedding(seq_length)(embedding)
output = keras.layers.add([embedding, position])
model = keras.Model(inputs=input_tensor, outputs=output)
model(input_data).shape
De ingangen worden ingebed en vervolgens positioneel ingebed, waarna ze bij elkaar worden opgeteld, waardoor een nieuwe positioneel ingebedde vorm ontstaat. Als alternatief kunt u gebruikmaken van de TokenAndPositionEmbedding
laag, die dit onder de motorkap doet:
Bekijk onze praktische, praktische gids voor het leren van Git, met best-practices, door de industrie geaccepteerde normen en bijgevoegd spiekbriefje. Stop met Googlen op Git-commando's en eigenlijk leren het!
...
def call(self, inputs):
embedded_tokens = self.token_embedding(inputs)
embedded_positions = self.position_embedding(embedded_tokens)
outputs = embedded_tokens + embedded_positions
return outputs
Dit maakt het veel schoner om te presteren TokenAndPositionEmbedding
:
seq_length = 10
vocab_size = 25
embed_dim = 10
input_data = tf.random.uniform(shape=[5, 10])
input_tensor = keras.Input(shape=[None, 5, 10])
output = keras_nlp.layers.TokenAndPositionEmbedding(vocabulary_size=vocab_size,
sequence_length=seq_length,
embedding_dim=embed_dim)(input_tensor)
model = keras.Model(inputs=input_tensor, outputs=output)
model(input_data).shape
De gegevens die we aan de laag hebben doorgegeven, zijn nu positioneel ingebed in een latente ruimte van 10 dimensies:
model(input_data)
<tf.Tensor: shape=(5, 10, 10), dtype=float32, numpy=
array([[[-0.01695484, 0.7656435 , -0.84340465, 0.50211895,
-0.3162892 , 0.16375223, -0.3774369 , -0.10028353,
-0.00136751, -0.14690581],
[-0.05646318, 0.00225556, -0.7745967 , 0.5233861 ,
-0.22601983, 0.07024342, 0.0905793 , -0.46133494,
-0.30130145, 0.451248 ],
...
Verder gaan – Handmatig end-to-end project
Je leergierige karakter maakt dat je verder wilt gaan? We raden aan om onze Begeleid project: "Beeldbijschriften met CNN's en Transformers met Keras".
In dit begeleide project leer je hoe je een beeldondertitelingsmodel bouwt, dat een afbeelding als invoer accepteert en een tekstonderschrift als uitvoer produceert.
U leert hoe u:
- Tekst voorbewerken
- Eenvoudig tekstinvoer vectoriseren
- Werk met de
tf.data
API en bouw performante datasets - Bouw Transformers helemaal opnieuw met TensorFlow/Keras en KerasNLP – de officiële horizontale toevoeging aan Keras voor het bouwen van state-of-the-art NLP-modellen
- Bouw hybride architecturen waarbij de output van het ene netwerk wordt gecodeerd voor een ander
Hoe kadreren we beeldonderschriften? De meesten beschouwen het als een voorbeeld van generatief diep leren, omdat we een netwerk leren om beschrijvingen te genereren. Ik beschouw het echter graag als een voorbeeld van neurale machinevertaling - we vertalen de visuele kenmerken van een afbeelding in woorden. Door vertaling genereren we een nieuwe representatie van dat beeld, in plaats van alleen een nieuwe betekenis te genereren. Als je het als vertaling bekijkt, en alleen door het genereren van extensies, krijgt de taak een ander licht en wordt het een beetje intuïtiever.
Door het probleem in te lijsten als een van de vertalingen, wordt het gemakkelijker om erachter te komen welke architectuur we willen gebruiken. Encoder-only Transformers zijn geweldig in het begrijpen van tekst (sentimentanalyse, classificatie, enz.) omdat Encoders betekenisvolle representaties coderen. Modellen met alleen decoders zijn geweldig voor generatie (zoals GPT-3), omdat decoders zinvolle representaties kunnen afleiden in een andere reeks met dezelfde betekenis. Vertaling wordt meestal gedaan door een encoder-decoder-architectuur, waar encoders coderen voor een betekenisvolle representatie van een zin (of afbeelding, in ons geval) en decoders leren om deze reeks om te zetten in een andere betekenisvolle representatie die voor ons beter te interpreteren is (zoals een zin).
Conclusies
Transformers hebben sinds 2017 een grote golf gemaakt en veel geweldige handleidingen bieden inzicht in hoe ze werken, maar toch waren ze voor velen nog steeds ongrijpbaar vanwege de overhead van aangepaste implementaties. KerasNLP pakt dit probleem aan en biedt bouwstenen waarmee je flexibele, krachtige NLP-systemen kunt bouwen, in plaats van voorverpakte oplossingen te bieden.
In deze handleiding hebben we token- en positie-inbedding bekeken met Keras en KerasNLP.