5 soros GPT-stílusú szöveggenerálás Pythonban TensorFlow/Keras segítségével

A Transformerek, noha 2017-ben jelentek meg, csak az elmúlt néhány évben kezdtek el jelentősebb teret hódítani. A technológia elterjedésével olyan platformokon keresztül, mint a HuggingFace, az NLP és Nagy nyelvi modellek (LLM) hozzáférhetőbbé váltak, mint valaha.

Mégis – még a körülöttük és velük együtt járó hype mellett is sok elmélet-orientált útmutatók, nincs sok egyedi megvalósítás az interneten, és az erőforrások sem állnak olyan könnyen elérhetők, mint néhány más hálózattípus esetében, amelyek már régóta léteznek. Bár leegyszerűsítheti munkaciklusát a HuggingFace előre elkészített Transformer használatával (egy másik útmutató témája) érez hogyan működik, ha saját maga épít egyet, mielőtt egy könyvtáron keresztül kivonja belőle. Itt inkább az építkezésre fogunk összpontosítani, mint az elméletre és az optimalizálásra.

Ebben az útmutatóban egy Autoregresszív nyelvi modell nak nek szöveget generálni. Az adatok betöltésének, felosztásának, vektorizálásának, modellkészítésnek, egyedi visszahívás írásának és betanításának/következtetésének gyakorlati és minimalista/tömör szempontjaira összpontosítunk. Ezen feladatok mindegyike részletesebb útmutatókká bontható ki, így a megvalósítást általánosnak tartjuk, teret engedve a testreszabásra és az optimalizálásra a saját adatkészletétől függően.

Az LLM-ek és a GPT-Fyodor típusai

Míg a kategorizálás sokkal bonyolultabbá válhat, megteheti nagyjából A Transformer-alapú nyelvi modelleket három kategóriába sorolhatja:

  • Kódoló alapú modellek – ALBERT, BERT, DistilBERT, RoBERTa
  • Dekóder alapú – GPT, GPT-2, GPT-3, TransformerXL
  • Seq2Seq modellek – BART, mBART, T5

Kódoló alapú A modellek architektúrájában csak Transformer kódolót használnak (általában halmozottan), és kiválóan alkalmasak a mondatok megértésére (osztályozás, elnevezett entitás felismerés, kérdések megválaszolása).

Dekóder alapú A modellek architektúrájában csak Transformer dekódert használnak (szintén általában halmozottan), és kiválóan alkalmasak a jövő előrejelzésére, ami alkalmassá teszi őket szöveggenerálásra.

Seq2Seq A modellek kódolókat és dekódolókat egyaránt kombinálnak, és nagyszerűek a szöveggenerálásban, az összegzésben és ami a legfontosabb – a fordításban.

Az elmúlt néhány évben nagy népszerűségnek örvendő GPT modellcsalád dekóder alapú transzformátormodellek, amelyek nagyszerűen képesek emberszerű szöveget készíteni, nagy adathalmazokra oktatva, és újdonságként kaptak felszólítást. kiindulási mag a nemzedék számára. Például:

generate_text('the truth ultimately is')

Ez a motorháztető alatt ezt a promptot egy GPT-szerű modellbe táplálja, és előállítja:

'the truth ultimately is really a joy in history, this state of life through which is almost invisible, superfluous  teleological...'

Ez valójában egy kis spoiler az útmutató végéről! Egy másik kis spoiler a szöveget létrehozó architektúra:

inputs = layers.Input(shape=(maxlen,))
embedding_layer = keras_nlp.layers.TokenAndPositionEmbedding(vocab_size, maxlen, embed_dim)(inputs)
transformer_block = keras_nlp.layers.TransformerDecoder(embed_dim, num_heads)(embedding_layer)
outputs = layers.Dense(vocab_size, activation='softmax')(transformer_block)
    
model = keras.Model(inputs=inputs, outputs=outputs)

5 sor elegendő egy csak dekóderrel működő transzformátormodell elkészítéséhez – egy kis GPT-t szimulálva. Mivel a modellt Fjodor Dosztojevszkij regényein fogjuk kiképezni (amit bármi mással helyettesíthetsz, a Wikipédiától a Reddit kommentekig) – próbaképpen a modellt hívjuk. GPT-Fjodor.

KerasNLP

Az 5 soros GPT-Fyodor trükkje ebben rejlik KerasNLP, amelyet a hivatalos Keras csapat fejlesztett ki, a Keras vízszintes kiterjesztéseként, amely igazi Keras módra arra törekszik, hogy új rétegekkel (kódolók, dekóderek, token beágyazások, pozícióbeágyazások, metrikák) kéznél legyen az iparágilag erős NLP. tokenizátorok stb.).

A KerasNLP nem modell állatkert. Ez a Keras része (külön csomagként), amely csökkenti az NLP-modell-fejlesztés belépési korlátait, éppúgy, mint a fő csomaggal az általános mély tanulási fejlesztések belépési korlátait.

Jegyzet: Íráskor a KerasNLP-t még mindig gyártják, és még korai szakaszban. A jövőbeli verziókban apró eltérések lehetnek. Az írás verziót használ 0.3.0.

A KerasNLP használatához telepítenie kell a következőn keresztül pip:

$ pip install keras_nlp

A verziót pedig a következővel ellenőrizheti:

keras_nlp.__version__

GPT-stílusú modell megvalósítása Kerasszal

Kezdjük azzal, hogy importáljuk a használni kívánt könyvtárakat – TensorFlow, Keras, KerasNLP és NumPy:

import tensorflow as tf
from tensorflow import keras
import keras_nlp
import numpy as np

adatok betöltése

Töltsünk be néhány Dosztojevszkij-regényt – az egyik túl rövid lenne ahhoz, hogy egy modell elférjen, anélkül, hogy a korai szakasztól kezdődően túl lenne illesztve. Kedvezően fogjuk használni a nyers szöveges fájlokat Project Gutenberg, az ilyen adatokkal való munka egyszerűsége miatt:

crime_and_punishment_url = 'https://www.gutenberg.org/files/2554/2554-0.txt'
brothers_of_karamazov_url = 'https://www.gutenberg.org/files/28054/28054-0.txt'
the_idiot_url = 'https://www.gutenberg.org/files/2638/2638-0.txt'
the_possessed_url = 'https://www.gutenberg.org/files/8117/8117-0.txt'

paths = [crime_and_punishment_url, brothers_of_karamazov_url, the_idiot_url, the_possessed_url]
names = ['Crime and Punishment', 'Brothers of Karamazov', 'The Idiot', 'The Possessed']
texts = ''
for index, path in enumerate(paths):
    filepath = keras.utils.get_file(f'{names[index]}.txt', origin=path)
    text = ''
    with open(filepath, encoding='utf-8') as f:
        text = f.read()
        
        
        
        texts += text[10000:]

Egyszerűen letöltöttük az összes fájlt, végignéztük őket, és egymásra fűztük őket. Ez magában foglalja a használt nyelv némi változatosságát, miközben továbbra is egyértelműen Fjodor! Minden egyes fájlnál kihagytuk az első 10 500 karaktert, ami az előszó és a Gutenberg-bevezető átlagos hosszának felel meg, így maradt a könyv nagyjából érintetlen törzse minden iterációhoz. Vessünk egy pillantást néhány véletlenszerű XNUMX karakterre a texts string most:


texts[25000:25500]
'nd that was whynI addressed you at once. For in unfolding to you the story of my life, Indo not wish to make myself a laughing-stock before these idle listeners,nwho indeed know all about it already, but I am looking for a mannof feeling and education. Know then that my wife was educated in anhigh-class school for the daughters of noblemen, and on leaving shendanced the shawl dance before the governor and other personages fornwhich she was presented with a gold medal and a certificate of merit.n'

Minden más feldolgozás előtt válasszuk szét a karakterláncot mondatokra:

text_list = texts.split('.')
len(text_list) 

69 ezer mondatunk van. Amikor kicseréli a n karaktereket szóközzel, és számolja meg a szavakat:

len(texts.replace('n', ' ').split(' ')) 

Jegyzet: Általában legalább egymillió szót szeretne egy adatkészletben, és ideális esetben ennél sokkal többet. Néhány megabájt adattal (~5 MB) dolgozunk, míg a nyelvi modelleket általában több tíz gigabájtnyi szövegre tanítják. Ez természetesen nagyon könnyűvé teszi a szövegbevitel túlillesztését és nehézkessé teszi az általánosítást (nagy zavartság túlillesztés nélkül, vagy alacsony zavar sok túlillesztéssel). Vigye az eredményeket egy szem sóval.

Ennek ellenére osszuk fel ezeket a edzés, teszt és a érvényesítés készlet. Először is távolítsuk el az üres karakterláncokat, és keverjük össze a mondatokat:


text_list = list(filter(None, text_list))

import random
random.shuffle(text_list)

Ezután 70/15/15 arányban osztunk fel:

length = len(text_list)
text_train = text_list[:int(0.7*length)]
text_test = text_list[int(0.7*length):int(0.85*length)]
text_valid = text_list[int(0.85*length):]

Ez egy egyszerű, de hatékony módja a vonat-teszt-ellenőrzés felosztásának. Vessünk egy pillantást text_train:

[' It was a dull morning, but the snow had ceased',
 'nn"Pierre, you who know so much of what goes on here, can you really havenknown nothing of this business and have heard nothing about it?"nn"What? What a set! So it's not enough to be a child in your old age,nyou must be a spiteful child too! Varvara Petrovna, did you hear what hensaid?"nnThere was a general outcry; but then suddenly an incident took placenwhich no one could have anticipated', ...

Ideje a szabványosításnak és vektorizálásnak!

Szöveg vektorizálása

A hálózatok nem értik a szavakat – értik a számokat. A szavakat szeretnénk jelképessé tenni:

...
sequence = ['I', 'am', 'Wall-E']
sequence = tokenize(sequence)
print(sequence) # [4, 26, 472]
...

Ezenkívül, mivel a mondatok hossza különbözik, a kitöltés általában balra vagy jobbra kerül, hogy a betáplált mondatok azonos alakját biztosítsák. Tegyük fel, hogy a leghosszabb mondatunk 5 szóból (jelzőkből) áll. Ebben az esetben a Wall-E mondatot két nulla tölti ki, így ugyanazt a bemeneti alakot biztosítjuk:

sequence = pad_sequence(sequence)
print(sequence) # [4, 26, 472, 0, 0]

Hagyományosan ez TensorFlow segítségével történt Tokenizer és Keras pad_sequences() módszerek – azonban sokkal kényelmesebb réteg, TextVectorization, használható, ami tokenizál és a párnázza a bemenetet, lehetővé téve a szókincs és annak méretének kinyerését anélkül, hogy előre ismerné a szószót!

Tekintse meg gyakorlatias, gyakorlati útmutatónkat a Git tanulásához, amely tartalmazza a bevált gyakorlatokat, az iparág által elfogadott szabványokat és a mellékelt csalólapot. Hagyd abba a guglizást a Git parancsokkal, és valójában tanulni meg!

Alkalmazkodjunk és illeszkedjünk a TextVectorization réteg:

from tensorflow.keras.layers import TextVectorization

def custom_standardization(input_string):
    sentence = tf.strings.lower(input_string)
    sentence = tf.strings.regex_replace(sentence, "n", " ")
    return sentence

maxlen = 50



vectorize_layer = TextVectorization(
    standardize = custom_standardization,
    output_mode="int",
    output_sequence_length=maxlen + 1,
)

vectorize_layer.adapt(text_list)
vocab = vectorize_layer.get_vocabulary()

A custom_standardization() a módszer sokkal hosszabb lehet ennél. Egyszerűen kisbetűsre csökkentettük az összes bevitelt és kicseréltük n val vel " ". Itt végezheti el igazán a szöveg előfeldolgozásának nagy részét – és továbbíthatja azt a vektorizációs rétegnek az opcionálisan standardize érv. Ha egyszer adapt() a réteget a szöveghez (NumPy tömb vagy szöveglista) – onnan kaphatja meg a szókincset és annak méretét:

vocab_size = len(vocab)
vocab_size 

Végül a szavak tokenizálásának megszüntetéséhez létrehozunk egy index_lookup szótár:

index_lookup = dict(zip(range(len(vocab)), vocab))    
index_lookup[5] 

Leképezi az összes tokent ([1, 2, 3, 4, ...]) a szókincs szavaihoz (['a', 'the', 'i', ...]). Kulcs (token index) átadásával könnyen visszakaphatjuk a szót. Most már futtathatja a vectorize_layer() bármely bemeneten, és figyelje meg a vektorizált mondatokat:

vectorize_layer(['hello world!'])

Aminek eredménye:

<tf.Tensor: shape=(1, 51), dtype=int64, numpy=
array([[   1, 7509,    0,    0,    0,    0,    0,    0,    0,    0,    0,
           0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
           0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
           0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
           0,    0,    0,    0,    0,    0,    0]], dtype=int64)>

Hello az indexe 1 míg a világnak az indexe van 7509! A többi a párnázás a maxlen kiszámoltuk.

Megvannak az eszközeink a szöveg vektorizálására – most hozzunk létre adatkészleteket text_train, text_test és a text_valid, vektorizációs rétegünket használva konverziós közegként a szavak és a GPT-Fyodorba betáplálható vektorok között.

Adatkészlet létrehozása

Létrehozunk egy tf.data.Dataset minden készletünkhöz, segítségével from_tensor_slices() és a tenzorszeletek (mondatok) listájának megadása:

batch_size = 64

train_dataset = tf.data.Dataset.from_tensor_slices(text_train)
train_dataset = train_dataset.shuffle(buffer_size=256)
train_dataset = train_dataset.batch(batch_size)

test_dataset = tf.data.Dataset.from_tensor_slices(text_test)
test_dataset = test_dataset.shuffle(buffer_size=256)
test_dataset = test_dataset.batch(batch_size)

valid_dataset = tf.data.Dataset.from_tensor_slices(text_valid)
valid_dataset = valid_dataset.shuffle(buffer_size=256)
valid_dataset = valid_dataset.batch(batch_size)

Létrehozva és megkeverve (ismét, jó mértékig) – alkalmazhatunk egy előfeldolgozási (vektorizálás és sorozatfelosztás) függvényt:

def preprocess_text(text):
    text = tf.expand_dims(text, -1)
    tokenized_sentences = vectorize_layer(text)
    x = tokenized_sentences[:, :-1]
    y = tokenized_sentences[:, 1:]
    return x, y


train_dataset = train_dataset.map(preprocess_text)
train_dataset = train_dataset.prefetch(tf.data.AUTOTUNE)

test_dataset = test_dataset.map(preprocess_text)
test_dataset = test_dataset.prefetch(tf.data.AUTOTUNE)

valid_dataset = valid_dataset.map(preprocess_text)
valid_dataset = valid_dataset.prefetch(tf.data.AUTOTUNE)

A preprocess_text() függvény egyszerűen kibővül az utolsó dimenzióval, vektorizálja a szöveget a mi használatával vectorize_layer és létrehozza a bemeneteket és célokat egyetlen tokennel ellensúlyozva. A modell használni fogja [0..n] következtetni n+1, amely minden szóhoz jóslatot ad, figyelembe véve az előtte lévő összes szót. Vessünk egy pillantást egyetlen bejegyzésre bármelyik adatkészletben:

for entry in train_dataset.take(1):
    print(entry)

A visszaadott bemeneteket és célokat 64-es kötegekben (egyenként 30-as hosszúságban) vizsgálva jól látható, hogyan ellensúlyozzák őket egy:

(<tf.Tensor: shape=(64, 50), dtype=int64, numpy=
array([[17018,   851,     2, ...,     0,     0,     0],
       [  330,    74,     4, ...,     0,     0,     0],
       [   68,   752, 30273, ...,     0,     0,     0],
       ...,
       [    7,    73,  2004, ...,     0,     0,     0],
       [   44,    42,    67, ...,     0,     0,     0],
       [  195,   252,   102, ...,     0,     0,     0]], dtype=int64)>, <tf.Tensor: shape=(64, 50), dtype=int64, numpy=
array([[  851,     2,  8289, ...,     0,     0,     0],
       [   74,     4,    34, ...,     0,     0,     0],
       [  752, 30273,  7514, ...,     0,     0,     0],
       ...,
       [   73,  2004,    31, ...,     0,     0,     0],
       [   42,    67,    76, ...,     0,     0,     0],
       [  252,   102,  8596, ...,     0,     0,     0]], dtype=int64)>)

Végre – itt az ideje a modell megépítésének!

Modell meghatározása

Itt a KerasNLP rétegeket fogjuk használni. Miután egy Input, kódoljuk a bemenetet a TokenAndPositionEmbedding réteg, áthaladva a mi vocab_size, maxlen és a embed_dim. Ugyanaz embed_dim hogy ez a réteg kimeneteket és bemeneteket ad a TransformerDecoder lesz a Dekóderben tárolva. Íráskor a Dekóder automatikusan fenntartja a bemeneti dimenziót, és nem teszi lehetővé, hogy más kimenetre vetítse ki, de lehetővé teszi a látens dimenziók meghatározását a intermediate_dim érv.

A látens ábrázoláshoz megszorozzuk a beágyazás méreteit kettővel, de megtarthatja ugyanazt, vagy használhat egy számot, amely elválasztja a beágyazási dimenzióktól:

embed_dim = 128
num_heads = 4

def create_model():
    inputs = keras.layers.Input(shape=(maxlen,), dtype=tf.int32)
    embedding_layer = keras_nlp.layers.TokenAndPositionEmbedding(vocab_size, maxlen, embed_dim)(inputs)
    decoder = keras_nlp.layers.TransformerDecoder(intermediate_dim=embed_dim, 
                                                            num_heads=num_heads, 
                                                            dropout=0.5)(embedding_layer)
    
    outputs = keras.layers.Dense(vocab_size, activation='softmax')(decoder)
    
    model = keras.Model(inputs=inputs, outputs=outputs)
    
    model.compile(
        optimizer="adam", 
        loss='sparse_categorical_crossentropy',
        metrics=[keras_nlp.metrics.Perplexity(), 'accuracy']
    )
    return model

model = create_model()
model.summary()

A dekóder tetején van egy Dense réteget a sorozat következő szavának kiválasztásához a softmax aktiválás (amely minden következő token valószínűségi eloszlását állítja elő). Nézzük a modell összefoglalóját:

Model: "model_5"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_6 (InputLayer)        [(None, 30)]              0         
                                                                 
 token_and_position_embeddin  (None, 30, 128)          6365824   
 g_5 (TokenAndPositionEmbedd                                     
 ing)                                                            
                                                                 
 transformer_decoder_5 (Tran  (None, 30, 128)          132480    
 sformerDecoder)                                                 
                                                                 
 dense_5 (Dense)             (None, 30, 49703)         6411687   
                                                                 
=================================================================
Total params: 13,234,315
Trainable params: 13,234,315
Non-trainable params: 0
_________________________________________________________________

A GPT-2 sok dekódert tartalmaz – a GPT-2 Small 12 egymásra halmozott dekódert (117 millió param), míg a GPT-2 Extra Large 48 egymásra halmozott dekódert (1.5 B param) tartalmaz. A szerény 13M paraméterekkel rendelkező egy-dekóderes modellünk oktatási célokra elég jól működik. Az LLM-ekkel – a méretnövelés rendkívül jó stratégiának bizonyult, a Transformers pedig jó skálázást tesz lehetővé, lehetővé téve a rendkívül nagy modellek betanítását.

A GPT-3 rendelkezik a "csekély" 175B paraméterek. A Google Brain csapata kiképzett egy 1.6T paraméteres modellt a ritkaságkutatás elvégzésére, miközben a számításokat a sokkal kisebb modellekkel azonos szinten tartotta.

Ami azt illeti, ha a dekóderek számát 1-ről 3-ra növeljük:

def create_model():
    inputs = keras.layers.Input(shape=(maxlen,), dtype=tf.int32)
    x = keras_nlp.layers.TokenAndPositionEmbedding(vocab_size, maxlen, embed_dim)(inputs)
    for i in range(4):
        x = keras_nlp.layers.TransformerDecoder(intermediate_dim=embed_dim*2, num_heads=num_heads,                                                             dropout=0.5)(x)
    do = keras.layers.Dropout(0.4)(x)
    outputs = keras.layers.Dense(vocab_size, activation='softmax')(do)
    
    model = keras.Model(inputs=inputs, outputs=outputs)

A paraméterek száma 400 ezerrel növekedne:

Total params: 13,631,755
Trainable params: 13,631,755
Non-trainable params: 0

Hálózatunk legtöbb paramétere a TokenAndPositionEmbedding és a Dense rétegek!

Próbálja ki a dekóder különböző mélységeit – 1-től egészen addig, amíg a készülék képes kezelni, és jegyezze fel az eredményeket. Mindenesetre – már majdnem készen állunk a modell betanítására! Hozzunk létre egy egyéni visszahívást, amely minden korszakban szövegmintát készít, így láthatjuk, hogyan tanul meg a modell a képzés során mondatokat alkotni.

Egyéni visszahívás

class TextSampler(keras.callbacks.Callback):
    def __init__(self, start_prompt, max_tokens):
        self.start_prompt = start_prompt
        self.max_tokens = max_tokens
        
    
    
    def sample_token(self, logits):
        logits, indices = tf.math.top_k(logits, k=5, sorted=True)
        indices = np.asarray(indices).astype("int32")
        preds = keras.activations.softmax(tf.expand_dims(logits, 0))[0]
        preds = np.asarray(preds).astype("float32")
        return np.random.choice(indices, p=preds)

    def on_epoch_end(self, epoch, logs=None):
        decoded_sample = self.start_prompt
        
        for i in range(self.max_tokens-1):
            tokenized_prompt = vectorize_layer([decoded_sample])[:, :-1]
            predictions = self.model.predict([tokenized_prompt], verbose=0)
            
            
            
            
            sample_index = len(decoded_sample.strip().split())-1
            
            sampled_token = self.sample_token(predictions[0][sample_index])
            sampled_token = index_lookup[sampled_token]
            decoded_sample += " " + sampled_token
            
        print(f"nSample text:n{decoded_sample}...n")


random_sentence = ' '.join(random.choice(text_valid).replace('n', ' ').split(' ')[:4])
sampler = TextSampler(random_sentence, 30)
reducelr = keras.callbacks.ReduceLROnPlateau(patience=10, monitor='val_loss')

A modell képzése

Végre itt az edzés ideje! Fogjuk be magunkba train_dataset és a validation_dataset a visszahívásokkal a helyükön:

model = create_model()
history = model.fit(train_dataset, 
                    validation_data=valid_dataset,
                    epochs=10, 
                    callbacks=[sampler, reducelr])

A mintavevő egy szerencsétlen mondatot választott, amely az utolsó idézettel és a kezdő idézettel kezdődik, de így is érdekes eredményeket produkál edzés közben:

# Epoch training
Epoch 1/10
658/658 [==============================] - ETA: 0s - loss: 2.7480 - perplexity: 15.6119 - accuracy: 0.6711
# on_epoch_end() sample generation
Sample text:
”  “What do you had not been i had been the same man was not be the same eyes to been a whole man and he did a whole man to the own...
# Validation
658/658 [==============================] - 158s 236ms/step - loss: 2.7480 - perplexity: 15.6119 - accuracy: 0.6711 - val_loss: 2.2130 - val_perplexity: 9.1434 - val_accuracy: 0.6864 - lr: 0.0010
...
Sample text:
”  “What do you know it is it all this very much as i should not have a great impression  in the room to be  able of it in my heart...

658/658 [==============================] - 149s 227ms/step - loss: 1.7753 - perplexity: 5.9019 - accuracy: 0.7183 - val_loss: 2.0039 - val_perplexity: 7.4178 - val_accuracy: 0.7057 - lr: 0.0010

A következővel kezdődik:

„Mi nem voltál, én is ugyanilyen voltam”…

Aminek igazából nem sok értelme van. A tíz rövid korszak végére a következőképpen produkál valamit:

„Hogy érted azt, hogy természetesen a leghétköznapibb ember”…

Bár a második mondatnak még mindig nincs túl sok értelme – sokkal értelmesebb, mint az első. A több adatra vonatkozó hosszabb képzés (bonyolultabb előfeldolgozási lépésekkel) jobb eredményeket hozna. Csak 10 nagy lemorzsolódású korszakra tanítottuk, hogy leküzdjük a kis adatkészletméretet. Ha sokkal tovább hagynák edzeni, nagyon Fjodor-szerű szöveget produkálna, mert nagy darabokat memorizált volna belőle.

Jegyzet: Mivel a kimenet meglehetősen bőbeszédű, módosíthatja a verbose argumentum, miközben illeszkedik a modellhez a képernyőn megjelenő szöveg mennyiségének csökkentése érdekében.

Modellkövetkeztetés

Következtetés végrehajtásához meg akarjuk replikálni a felületet TextSampler – vetőmagot elfogadó módszer és a response_length (max_tokens). Ugyanazokat a módszereket fogjuk használni, mint a mintavevőben:

def sample_token(logits):
        logits, indices = tf.math.top_k(logits, k=5, sorted=True)
        indices = np.asarray(indices).astype("int32")
        preds = keras.activations.softmax(tf.expand_dims(logits, 0))[0]
        preds = np.asarray(preds).astype("float32")
        return np.random.choice(indices, p=preds)

def generate_text(prompt, response_length=20):
    decoded_sample = prompt
    for i in range(response_length-1):
        tokenized_prompt = vectorize_layer([decoded_sample])[:, :-1]
        predictions = model.predict([tokenized_prompt], verbose=0)
        sample_index = len(decoded_sample.strip().split())-1

        sampled_token = sample_token(predictions[0][sample_index])
        sampled_token = index_lookup[sampled_token]
        decoded_sample += " " + sampled_token
    return decoded_sample

Most már futtathatja a módszert új mintákon:

generate_text('the truth ultimately is')


generate_text('the truth ultimately is')

Eredmények javulása?

Tehát hogyan javíthatja az eredményeket? Van néhány nagyon hasznos dolog, amit megtehetsz:

  • Adatok tisztítása (a bemeneti adatokat alaposabban tisztítsa meg, csak egy hozzávetőleges számot vágtunk az elejétől kezdve, és eltávolítottuk az újsor karaktereket)
  • Szerezzen több adatot (csak néhány megabájt szöveges adattal dolgoztunk)
  • Méretezze a modellt az adatok mellett (a dekóderek halmozása nem nehéz!)

Következtetés

Míg az előfeldolgozási folyamat minimalista és javítható – az ebben az útmutatóban felvázolt folyamat egy tisztességes GPT-stílusú modellt hozott létre, mindössze 5 sornyi kóddal egy egyedi, csak dekóderhez használható transzformátor felépítéséhez Keras használatával!

A transzformátorok népszerűek és széles körben alkalmazhatók az általános sorozatmodellezésben (és sok minden kifejezhető szekvenciaként). Eddig a belépés fő akadálya a nehézkes megvalósítás volt, de a KerasNLP-vel – a mély tanulással foglalkozó szakemberek kihasználhatják az implementációkat a modellek gyors és egyszerű elkészítéséhez.

Időbélyeg:

Még több Stackabus