Pembuatan Teks Bergaya GPT 5 Baris dengan Python dengan TensorFlow/Keras

Transformers, meskipun dirilis pada tahun 2017, baru mulai mendapatkan daya tarik yang signifikan dalam beberapa tahun terakhir. Dengan proliferasi teknologi melalui platform seperti HuggingFace, NLP dan Model Bahasa Besar (LLM) telah menjadi lebih mudah diakses dari sebelumnya.

Namun – bahkan dengan semua hype di sekitar mereka dan dengan banyak panduan berorientasi teori, tidak banyak implementasi kustom online, dan sumber daya tidak tersedia seperti beberapa jenis jaringan lain, yang telah ada lebih lama. Meskipun Anda dapat menyederhanakan siklus kerja Anda dengan menggunakan Transformer yang dibuat sebelumnya dari HuggingFace (topik panduan lain) – Anda bisa mendapatkan merasa cara kerjanya dengan membangunnya sendiri, sebelum mengabstraksikannya melalui perpustakaan. Kami akan berfokus pada pembangunan, daripada teori dan pengoptimalan di sini.

Dalam panduan ini, kita akan membangun sebuah Model Bahasa Autoregresif untuk menghasilkan teks. Kami akan berfokus pada aspek praktis dan minimalis/ringkas dari memuat data, membaginya, membuatnya menjadi vektor, membangun model, menulis panggilan balik khusus, dan pelatihan/inferensi. Masing-masing tugas ini dapat dibagi menjadi panduan yang lebih detail, jadi kami akan menjaga implementasinya sebagai yang umum, menyisakan ruang untuk penyesuaian dan pengoptimalan tergantung pada kumpulan data Anda sendiri.

Jenis LLM dan GPT-Fyodor

Sementara kategorisasi bisa menjadi jauh lebih rumit – Anda bisa secara luas mengkategorikan model bahasa berbasis Transformer menjadi tiga kategori:

  • Model Berbasis Encoder – ALBERT, BERT, DistilBERT, Roberta
  • Berbasis Dekoder – GPT, GPT-2, GPT-3, TransformerXL
  • Model Seq2Seq – BART, mBART, T5

Berbasis pembuat enkode model hanya menggunakan encoder Transformer dalam arsitekturnya (biasanya, ditumpuk) dan bagus untuk memahami kalimat (klasifikasi, pengenalan entitas bernama, penjawab pertanyaan).

Berbasis decoder model hanya menggunakan dekoder Transformer dalam arsitekturnya (juga biasanya ditumpuk) dan sangat bagus untuk prediksi masa depan, yang membuatnya cocok untuk pembuatan teks.

Seq2Seq model menggabungkan encoder dan decoder dan hebat dalam pembuatan teks, peringkasan dan yang paling penting – terjemahan.

Keluarga model GPT, yang mendapatkan banyak daya tarik dalam beberapa tahun terakhir, adalah model transformator berbasis dekoder, dan hebat dalam menghasilkan teks seperti manusia, dilatih pada kumpulan data yang besar, dan diberikan prompt sebagai yang baru benih awal untuk generasi. Contohnya:

generate_text('the truth ultimately is')

Yang di bawah tenda memasukkan prompt ini ke dalam model seperti GPT, dan menghasilkan:

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

Ini sebenarnya adalah spoiler kecil dari akhir panduan! Spoiler kecil lainnya adalah arsitektur yang menghasilkan teks itu:

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)

Hanya 5 baris yang diperlukan untuk membuat model transformator khusus dekoder – mensimulasikan GPT kecil. Karena kami akan melatih model pada novel Fyodor Dostoyevsky (yang dapat Anda ganti dengan yang lain, dari Wikipedia hingga komentar Reddit) – kami akan memanggil model untuk sementara GPT-Fyodor.

KerasNLP

Trik untuk GPT-Fyodor 5-baris terletak pada KerasNLP, yang dikembangkan oleh tim Keras resmi, sebagai ekstensi horizontal untuk Keras, yang dalam gaya Keras sejati, bertujuan untuk menghadirkan NLP berkekuatan industri ke ujung jari Anda, dengan lapisan baru (encoder, decoder, token embeddings, position embeddings, metrik, tokenizer, dll).

KerasNLP bukan kebun binatang model. Ini adalah bagian dari Keras (sebagai paket terpisah), yang menurunkan hambatan masuk untuk pengembangan model NLP, seperti halnya menurunkan hambatan masuk untuk pengembangan pembelajaran mendalam umum dengan paket utama.

Catatan: Pada penulisan KerasNLP masih diproduksi, dan dalam tahap awal. Perbedaan halus mungkin ada di versi mendatang. Penulisan ini menggunakan versi 0.3.0.

Untuk dapat menggunakan KerasNLP, Anda harus menginstalnya melalui pip:

$ pip install keras_nlp

Dan Anda dapat memverifikasi versi dengan:

keras_nlp.__version__

Menerapkan Model Gaya GPT dengan Keras

Mari kita mulai dengan mengimpor library yang akan kita gunakan – TensorFlow, Keras, KerasNLP, dan NumPy:

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

Memuat data

Mari kita memuat beberapa novel Dostoyevsky – salah satunya akan terlalu pendek untuk model, tanpa sedikit overfitting dari tahap awal dan seterusnya. Kami akan dengan anggun menggunakan file teks mentah dari proyek Gutenberg, karena kesederhanaan bekerja dengan data tersebut:

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:]

Kami hanya mengunduh semua file, menelusurinya, dan menggabungkannya satu di atas yang lain. Ini termasuk beberapa keragaman dalam bahasa yang digunakan, sambil tetap mempertahankannya dengan jelas Fyodor! Untuk setiap file, kami telah melewatkan 10k karakter pertama, yaitu sekitar panjang rata-rata kata pengantar dan intro Gutenberg, jadi kami memiliki sebagian besar isi buku yang utuh untuk setiap iterasi. Mari kita lihat beberapa 500 karakter acak di texts string sekarang:


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'

Mari kita pisahkan string menjadi kalimat sebelum melakukan pemrosesan lainnya:

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

Kami punya 69k kalimat. Saat Anda mengganti n karakter dengan spasi putih dan hitung kata:

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

Catatan: Anda biasanya ingin memiliki setidaknya satu juta kata dalam kumpulan data, dan idealnya, lebih dari itu. Kami bekerja dengan beberapa megabyte data (~5MB) sementara model bahasa lebih umum dilatih pada puluhan gigabyte teks. Ini akan, tentu saja, membuatnya sangat mudah untuk menyesuaikan input teks dan sulit untuk digeneralisasi (kebingungan tinggi tanpa overfitting, atau kebingungan rendah dengan banyak overfitting). Ambil hasilnya dengan sebutir garam.

Namun demikian, mari kita pisahkan ini menjadi latihan, uji dan pengesahan mengatur. Pertama, mari kita hapus string kosong dan acak kalimatnya:


text_list = list(filter(None, text_list))

import random
random.shuffle(text_list)

Kemudian, kita akan melakukan pembagian 70/15/15:

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

Ini adalah cara sederhana, namun efektif untuk melakukan pemisahan validasi uji-latihan. Yuk intip 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', ...

Saatnya standardisasi dan vektorisasi!

Vektorisasi Teks

Jaringan tidak mengerti kata-kata – mereka mengerti angka. Kami ingin menandai kata-kata:

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

Juga, karena panjang kalimat berbeda – padding biasanya ditambahkan ke kiri atau kanan untuk memastikan bentuk yang sama di seluruh kalimat yang dimasukkan. Katakanlah kalimat terpanjang kita adalah 5 kata (token). Dalam hal ini, kalimat Wall-E akan diisi oleh dua nol sehingga kami memastikan bentuk input yang sama:

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

Secara tradisional, ini dilakukan menggunakan TensorFlow Tokenizer dan Keras' pad_sequences() metode – namun, lapisan yang jauh lebih praktis, TextVectorization, dapat digunakan, yang tokenizes dan mengisi masukan Anda, memungkinkan Anda untuk mengekstrak kosakata dan ukurannya, tanpa mengetahui kosakata di muka!

Lihat panduan praktis dan praktis kami untuk mempelajari Git, dengan praktik terbaik, standar yang diterima industri, dan termasuk lembar contekan. Hentikan perintah Googling Git dan sebenarnya belajar itu!

Mari beradaptasi dan fit a TextVectorization lapisan:

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

Grafik custom_standardization() metode bisa mendapatkan lebih lama dari ini. Kami hanya menurunkan semua input dan menggantinya n dengan " ". Di sinilah Anda benar-benar dapat memasukkan sebagian besar prapemrosesan teks Anda – dan memasoknya ke lapisan vektorisasi melalui opsi opsional standardize argumen. Sekali kamu adapt() lapisan ke teks (array NumPy atau daftar teks) – Anda bisa mendapatkan kosakata, serta ukurannya dari sana:

vocab_size = len(vocab)
vocab_size 

Terakhir, untuk mende-tokenisasi kata, kita akan membuat index_lookup kamus:

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

Ini memetakan semua token ([1, 2, 3, 4, ...]) menjadi kata-kata dalam kosa kata (['a', 'the', 'i', ...]). Dengan memasukkan kunci (indeks token), kita dapat dengan mudah mendapatkan kembali kata tersebut. Anda sekarang dapat menjalankan vectorize_layer() pada input apa pun dan amati kalimat vektor:

vectorize_layer(['hello world!'])

Yang mengakibatkan:

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

Halo memiliki indeks 1 sementara dunia memiliki indeks 7509! Sisanya adalah bantalan untuk maxlen kami telah menghitung.

Kami memiliki sarana untuk membuat vektor teks – sekarang, mari kita buat kumpulan data dari text_train, text_test dan text_valid, menggunakan lapisan vektorisasi kami sebagai media konversi antara kata dan vektor yang dapat dimasukkan ke dalam GPT-Fyodor.

Pembuatan Kumpulan Data

Kami akan membuat tf.data.Dataset untuk setiap set kami, menggunakan from_tensor_slices() dan memberikan daftar, yah, irisan tensor (kalimat):

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)

Setelah dibuat dan diacak (sekali lagi, untuk ukuran yang baik) – kita dapat menerapkan fungsi preprocessing (vektorisasi dan pemisahan urutan):

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)

Grafik preprocess_text() fungsi hanya diperluas dengan dimensi terakhir, membuat vektor teks menggunakan . kami vectorize_layer dan membuat input dan target, diimbangi dengan satu token. Model akan menggunakan [0..n] untuk menyimpulkan n+1, menghasilkan prediksi untuk setiap kata, memperhitungkan semua kata sebelumnya. Mari kita lihat satu entri di salah satu kumpulan data:

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

Menyelidiki input dan target yang dikembalikan, dalam batch 64 (dengan panjang masing-masing 30), kita dapat dengan jelas melihat bagaimana mereka diimbangi oleh satu:

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

Akhirnya – saatnya membangun model!

Definisi Model

Kami akan menggunakan lapisan KerasNLP di sini. Setelah Input, kami akan mengkodekan input melalui a TokenAndPositionEmbedding lapisan, melewati kami vocab_size, maxlen dan embed_dim. Sama embed_dim bahwa lapisan ini mengeluarkan dan memasukkan ke dalam TransformerDecoder akan disimpan di Decoder. Pada saat penulisan, Decoder secara otomatis mempertahankan dimensi input, dan tidak memungkinkan Anda untuk memproyeksikannya ke output yang berbeda, tetapi memungkinkan Anda menentukan dimensi laten melalui intermediate_dim argumen.

Kami akan mengalikan dimensi penyematan dengan dua untuk representasi laten, tetapi Anda dapat mempertahankannya tetap sama atau menggunakan angka yang terlepas dari peredupan penyematan:

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

Di atas decoder, kami memiliki Dense lapisan untuk memilih kata berikutnya dalam urutan, dengan a softmax aktivasi (yang menghasilkan distribusi probabilitas untuk setiap token berikutnya). Mari kita lihat ringkasan modelnya:

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
_________________________________________________________________

GPT-2 menumpuk banyak dekoder – GPT-2 Small memiliki 12 dekoder bertumpuk (117M params), sedangkan GPT-2 Extra Large memiliki 48 dekoder bertumpuk (1.5B param). Model dekoder tunggal kami dengan parameter 13M sederhana harus bekerja cukup baik untuk tujuan pendidikan. Dengan LLM – penskalaan telah terbukti menjadi strategi yang sangat baik, dan Transformers memungkinkan penskalaan yang baik, sehingga memungkinkan untuk melatih model yang sangat besar.

GPT-3 memiliki "kurus" 175B parameter. Tim Google Brain melatih model parameter 1.6T untuk melakukan penelitian sparsity sambil menjaga komputasi pada tingkat yang sama dengan model yang jauh lebih kecil.

Faktanya, jika kita menambah jumlah decoder dari 1 menjadi 3:

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)

Jumlah parameter kami akan meningkat 400k:

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

Sebagian besar parameter di jaringan kami berasal dari TokenAndPositionEmbedding dan Dense lapisan!

Cobalah berbagai kedalaman dekoder – mulai dari 1 hingga semua cara yang dapat ditangani mesin Anda dan catat hasilnya. Bagaimanapun – kami hampir siap untuk melatih modelnya! Mari kita buat callback khusus yang akan menghasilkan contoh teks pada setiap epoch, sehingga kita dapat melihat bagaimana model belajar membentuk kalimat melalui pelatihan.

Panggilan Balik Khusus

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

Melatih Model

Akhirnya, waktu untuk berlatih! Mari kita cek di train_dataset dan validation_dataset dengan panggilan balik di tempat:

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

Sampler memilih kalimat yang tidak menguntungkan yang dimulai dengan kutipan akhir dan kutipan awal, tetapi masih menghasilkan hasil yang menarik saat pelatihan:

# 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

Ini dimulai dengan:

"Apa yang kamu tidak pernah aku pernah sama" ...

Yang sangat tidak masuk akal. Pada akhir sepuluh zaman pendek, ia menghasilkan sesuatu di sepanjang baris:

“Apa maksudmu pria paling biasa dari seorang pria tentunya”…

Sementara kalimat kedua masih tidak terlalu masuk akal – ini jauh lebih masuk akal daripada yang pertama. Pelatihan yang lebih lama pada lebih banyak data (dengan langkah-langkah prapemrosesan yang lebih rumit) akan menghasilkan hasil yang lebih baik. Kami hanya melatihnya di 10 epoch dengan dropout tinggi untuk melawan ukuran dataset yang kecil. Jika dibiarkan pelatihan lebih lama, itu akan menghasilkan teks yang sangat mirip Fyodor, karena akan menghafal sebagian besar teks itu.

Catatan: Karena outputnya cukup bertele-tele, Anda dapat mengubah verbose argumen sambil menyesuaikan model untuk mengurangi jumlah teks di layar.

Model Inferensi

Untuk melakukan inferensi, kami ingin mereplikasi antarmuka dari TextSampler – metode yang menerima benih dan a response_length (max_tokens). Kami akan menggunakan metode yang sama seperti dalam sampler:

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

Sekarang, Anda dapat menjalankan metode pada sampel baru:

generate_text('the truth ultimately is')


generate_text('the truth ultimately is')

Meningkatkan Hasil?

Jadi, bagaimana Anda dapat meningkatkan hasil? Ada beberapa hal yang cukup dapat ditindaklanjuti yang dapat Anda lakukan:

  • Pembersihan data (bersihkan data input lebih teliti, kami hanya memangkas perkiraan angka dari awal dan menghapus karakter baris baru)
  • Dapatkan lebih banyak data (kami hanya bekerja dengan beberapa megabyte data teks)
  • Skala model di samping data (susun decoder tidak sulit!)

Kesimpulan

Meskipun pipeline prapemrosesan minimalis dan dapat ditingkatkan – pipeline yang diuraikan dalam panduan ini menghasilkan model bergaya GPT yang layak, dengan hanya 5 baris kode yang diperlukan untuk membuat trafo khusus dekoder, menggunakan Keras!

Transformer populer dan dapat diterapkan secara luas untuk pemodelan urutan generik (dan banyak hal dapat dinyatakan sebagai urutan). Sejauh ini, hambatan utama untuk masuk adalah implementasi yang rumit, tetapi dengan KerasNLP – praktisi pembelajaran mendalam dapat memanfaatkan implementasi untuk membangun model dengan cepat dan mudah.

Stempel Waktu:

Lebih dari penyalahgunaan