وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

تولید متن 5 خطی به سبک GPT در پایتون با TensorFlow/Keras

0 4
زمان لازم برای مطالعه: 12 دقیقه


ترانسفورمرز، حتی با وجود اینکه در سال 2017 منتشر شد، تنها در چند سال اخیر شروع به جذب قابل توجهی کرده است. با گسترش فناوری از طریق پلتفرم هایی مانند HuggingFace، NLP و مدل‌های زبان بزرگ (LLM) در دسترس تر از همیشه شده اند.

با این حال – حتی با همه تبلیغات اطراف آنها و با زیاد راهنماهای تئوری گرا، پیاده سازی های سفارشی زیادی به صورت آنلاین وجود ندارد، و منابع به آسانی مانند برخی از انواع شبکه های دیگر که مدت طولانی تری وجود داشته اند، در دسترس نیستند. در حالی که می توانید چرخه کاری خود را با استفاده از یک ترانسفورماتور از پیش ساخته شده از HuggingFace (موضوع راهنمای دیگری) ساده کنید – می توانید به احساس کنید چگونه کار می کند با ساختن یکی از خودتان، قبل از انتزاع آن از طریق یک کتابخانه. ما تمرکز خواهیم کرد روی ساختمان، به جای تئوری و بهینه سازی در اینجا.

در این راهنما، ما در حال ساختن یک مدل زبان خودرگرسیون به تولید متن. ما تمرکز خواهیم کرد روی جنبه های عملی و حداقلی / مختصر بارگذاری داده ها، تقسیم آن، بردار کردن آن، ساخت یک مدل، نوشتن یک تماس سفارشی و آموزش/استنتاج. هر یک از این وظایف را می توان به راهنماهای دقیق تری تقسیم کرد، بنابراین پیاده سازی را به صورت عمومی نگه می داریم و بسته به آن، فضایی را برای سفارشی سازی و بهینه سازی باقی می گذاریم. روی مجموعه داده خودتان

انواع LLM و GPT-Fyodor

در حالی که طبقه بندی می تواند بسیار پیچیده تر شود – شما می توانید به طور گسترده مدل های زبان مبتنی بر Transformer را به سه دسته دسته بندی کنید:

  • مدل های مبتنی بر رمزگذار – آلبرت، برت، دیستیلبرت، روبرتا
  • مبتنی بر رمزگشا – GPT، GPT-2، GPT-3، TransformerXL
  • مدل های Seq2Seq – BART، mBART، T5

مبتنی بر رمزگذار مدل‌ها فقط از رمزگذار ترانسفورماتور در معماری خود استفاده می‌کنند (معمولاً پشته‌ای) و برای درک جملات (طبقه‌بندی، شناسایی موجودیت نام‌گذاری شده، پاسخ به سؤال) عالی هستند.

مبتنی بر رمزگشا مدل‌ها فقط از رمزگشای ترانسفورماتور در معماری خود استفاده می‌کنند (همچنین معمولاً انباشته شده) و برای پیش‌بینی آینده عالی هستند، که آنها را برای تولید متن مناسب می‌کند.

Seq2Seq مدل‌ها هم رمزگذار و هم رمزگشا را ترکیب می‌کنند و در تولید متن، خلاصه‌سازی و مهم‌تر از همه – ترجمه عالی هستند.

خانواده مدل‌های GPT که در چند سال گذشته محبوبیت زیادی به دست آورده‌اند، مدل‌های ترانسفورماتور مبتنی بر رمزگشا هستند و در تولید متن‌های آموزش‌دیده شبیه انسان عالی هستند. روی مجموعه های بزرگی از داده ها، و به عنوان یک بذر شروع جدید برای تولید، درخواست داده می شود. برای مثال:

generate_text('the truth ultimately is')

که در زیر هود این دستور را به یک مدل GPT مانند می‌رساند و تولید می‌کند:

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

این در واقع یک اسپویلر کوچک از انتهای راهنما است! یک اسپویلر کوچک دیگر معماری است که آن متن را تولید کرده است:

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 خط تمام چیزی است که برای ساخت یک مدل ترانسفورماتور فقط رمزگشا لازم است – شبیه سازی یک GPT کوچک. از آنجایی که ما مدل را آموزش خواهیم داد روی رمان‌های فئودور داستایوفسکی (که می‌توانید آن‌ها را با هر چیز دیگری جایگزین کنید، از ویکی‌پدیا گرفته تا نظرات ردیت) – ما به طور آزمایشی مدل را می‌نامیم. GPT-Fyodor.

KerasNLP

ترفند یک GPT-Fyodor 5 خطی در این است KerasNLP، که توسط تیم رسمی Keras توسعه یافته است، به عنوان یک توسعه افقی برای Keras، که به روش واقعی Keras، با هدف رساندن NLP با قدرت صنعتی به نوک انگشتان شما، با لایه های جدید (رمزگذار، رمزگشا، تعبیه توکن، جاسازی موقعیت، معیارها، توکنایزرها و غیره).

KerasNLP یک باغ وحش نمونه نیست. این بخشی از Keras (به عنوان یک بسته جداگانه) است که مانع ورود برای توسعه مدل NLP را کاهش می دهد، همانطور که مانع ورود برای توسعه یادگیری عمیق عمومی با بسته اصلی را کاهش می دهد.

توجه داشته باشید: تا زمان نگارش KerasNLP هنوز در حال تولید و در مراحل اولیه است. تفاوت های ظریف ممکن است در نسخه های بعدی وجود داشته باشد. نوشتن از نسخه استفاده می کند 0.3.0.

برای اینکه بتوانید از KerasNLP استفاده کنید، باید آن را از طریق نصب کنید pip:

$ pip install keras_nlp

و شما می توانید نسخه را با:

keras_nlp.__version__

پیاده سازی مدل GPT-Style با Keras

بیایید با وارد کردن کتابخانه‌هایی که از آنها استفاده خواهیم کرد – TensorFlow، Keras، KerasNLP و NumPy شروع کنیم:

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

در حال بارگیری داده ها

بیایید تعدادی از رمان‌های داستایوفسکی را بارگذاری کنیم – یکی از آن‌ها برای یک مدل بسیار کوتاه است، بدون آن که از مراحل اولیه به بعد کمی بیش از حد مناسب باشد. ما به راحتی از فایل های متنی خام استفاده خواهیم کرد پروژه گوتنبرگ، به دلیل سادگی کار با چنین داده هایی:

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

ما به سادگی همه فایل ها را دانلود کرده ایم، آنها را مرور کرده و آنها را به هم متصل کرده ایم روی بالای دیگری این شامل برخی از تنوع در زبان مورد استفاده است، در حالی که همچنان آن را کاملاً فئودور حفظ می کند! برای هر فایل، 10 هزار کاراکتر اول را حذف کرده‌ایم، که تقریباً طول متوسط ​​پیشگفتار و مقدمه گوتنبرگ است، بنابراین برای هر تکرار، بدنه‌ای کاملاً سالم از کتاب باقی می‌ماند. بیایید نگاهی به 500 کاراکتر تصادفی در آن بیاندازیم texts رشته اکنون:


texts(25000:25500)
'nd that was why\nI addressed you at once. For in unfolding to you the story of my life, I\ndo 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 man\nof feeling and education. Know then that my wife was educated in a\nhigh-class school for the daughters of noblemen, and روی leaving she\ndanced the shawl dance before the governor and other personages for\nwhich she was presented with a gold medal and a certificate of merit.\n'

قبل از انجام هر پردازش دیگری، رشته را به جملات جدا می کنیم:

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

ما 69 هزار جمله داریم. هنگامی که شما جایگزین \n کاراکترها با فاصله خالی و شمارش کلمات:

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

توجه داشته باشید: شما معمولاً می خواهید حداقل یک میلیون کلمه در یک مجموعه داده داشته باشید، و در حالت ایده آل، خیلی بیشتر از آن. ما با چند مگابایت داده (~ 5 مگابایت) کار می کنیم در حالی که مدل های زبان معمولاً آموزش داده می شوند روی ده ها گیگابایت متن این، به طور طبیعی، تناسب بیش از حد ورودی متن را بسیار آسان و تعمیم آن را دشوار می کند (گیج شدن زیاد بدون برازش بیش از حد، یا گیجی کم با اضافه کردن زیاد). نتایج را با یک دانه نمک بگیرید.

با این وجود، اجازه دهید اینها را به یک تقسیم کنیم آموزش، تست و اعتبار سنجی تنظیم. ابتدا رشته های خالی را حذف می کنیم و جملات را به هم می زنیم:


text_list = list(filter(None, text_list))

import random
random.shuffle(text_list)

سپس، تقسیم 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):)

این یک روش ساده و در عین حال موثر برای انجام تقسیم بندی قطار-آزمون- اعتبار سنجی است. بیایید نگاهی به آن بیندازیم text_train:

(' It was a dull morning, but the snow had ceased',
 '\n\n"Pierre, you who know so much of what goes روی here, can you really have\nknown nothing of this business and have heard nothing about it?"\n\n"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 he\nsaid?"\n\nThere was a general outcry; but then suddenly an incident took place\nwhich no one could have anticipated', ...

زمان استانداردسازی و برداری است!

بردار سازی متن

شبکه ها کلمات را درک نمی کنند – آنها اعداد را درک می کنند. ما می خواهیم کلمات را “توکنیزه” کنیم:

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

همچنین، از آنجایی که جملات از نظر طول متفاوت هستند – padding معمولاً به چپ یا راست اضافه می‌شود تا از شکل یکسانی در جملاتی که وارد می‌شوند اطمینان حاصل شود. بگویید طولانی‌ترین جمله ما 5 کلمه (توکن) است. در آن صورت، جمله Wall-E با دو صفر پر می‌شود، بنابراین از همان شکل ورودی اطمینان می‌دهیم:

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

به طور سنتی، این کار با استفاده از TensorFlow انجام می شد Tokenizer و کراس pad_sequences() روش ها – با این حال، یک لایه بسیار مفیدتر، TextVectorization، می توان استفاده کرد که “توکنیزه می کند” و ورودی خود را اضافه می کند و به شما این امکان را می دهد که واژگان و اندازه آن را بدون دانستن واژگان از قبل استخراج کنید!

بیایید وفق دهیم و مناسب باشیم TextVectorization لایه:

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

را custom_standardization() روش می تواند خیلی طولانی تر از این باشد. ما به سادگی تمام ورودی ها را پایین آورده ایم و جایگزین شده ایم \n با " ". اینجاست که می‌توانید بیشتر پیش‌پردازش خود را برای متن قرار دهید – و آن را از طریق گزینه اختیاری به لایه برداری ارائه کنید. standardize بحث و جدل. یک بار شما adapt() لایه به متن (آرایه NumPy یا لیست متون) – می توانید واژگان و همچنین اندازه آن را از آنجا دریافت کنید:

vocab_size = len(vocab)
vocab_size 

در نهایت، برای «توکن زدایی» کلمات، یک علامت ایجاد می کنیم index_lookup فرهنگ لغت:

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

همه توکن ها را نقشه برداری می کند ((1, 2, 3, 4, ...)) به کلمات موجود در واژگان (('a', 'the', 'i', ...)). با عبور از یک کلید (شاخص نشانه) به راحتی می توانیم کلمه را پس بگیریم. اکنون می توانید اجرا کنید vectorize_layer() روی هر ورودی و مشاهده جملات برداری:

vectorize_layer(('hello world!'))

که منجر به:

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

سلام دارای شاخص از 1 در حالی که جهان دارای شاخص است 7509! بقیه بالشتک به maxlen ما محاسبه کرده ایم

ما ابزاری برای بردار کردن متن داریم – اکنون، بیایید مجموعه های داده را از آن ایجاد کنیم text_train، text_test و text_valid، با استفاده از لایه برداری ما به عنوان یک رسانه تبدیل بین کلمات و بردارهایی که می توانند به GPT-Fyodor وارد شوند.

ایجاد مجموعه داده

ما در حال ایجاد یک tf.data.Dataset برای هر یک از مجموعه های ما ، استفاده from_tensor_slices() و ارائه فهرستی از، خوب، برش های تانسور (جملات):

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)

پس از ایجاد و مخلوط کردن (دوباره، برای اندازه گیری خوب) – می توانیم یک تابع پیش پردازش (بردارسازی و تقسیم ترتیب) را اعمال کنیم:

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)

را preprocess_text() تابع به سادگی با آخرین بعد گسترش می یابد، متن را با استفاده از ما “بردار” می کند vectorize_layer و ورودی ها و اهداف را ایجاد می کند که با یک توکن جبران می شود. مدل استفاده خواهد کرد (0..n) استنباط کردن n+1، برای هر کلمه یک پیش بینی به دست می دهد و تمام کلمات قبل از آن را محاسبه می کند. بیایید نگاهی به یک ورودی واحد در هر یک از مجموعه داده ها بیندازیم:

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

با بررسی ورودی‌ها و اهداف برگشتی، در دسته‌های 64 تایی (با طول هر کدام 30 عدد)، به وضوح می‌توانیم ببینیم که چگونه آنها با یک جبران می‌شوند:

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

سرانجام – وقت آن است که مدل را بسازیم!

تعریف مدل

ما در اینجا از لایه های Kerasnlp استفاده خواهیم کرد. بعد از یک Input، ما ورودی را از طریق a رمزگذاری می کنیم TokenAndPositionEmbedding لایه، عبور در ما vocab_size، maxlen و embed_dim. همینطور embed_dim که این لایه وارد شده و وارد می شود TransformerDecoder خواهد بود در رسیور نگهداری می شود. در زمان نوشتن، رسیور به طور خودکار ابعاد ورودی را حفظ می کند، و به شما اجازه نمی دهد آن را در خروجی دیگری قرار دهید، اما به شما اجازه می دهد ابعاد پنهان را از طریق intermediate_dim بحث و جدل.

برای نمایش پنهان، ابعاد جاسازی را در دو ضرب می‌کنیم، اما می‌توانید آن را ثابت نگه دارید یا از عددی جدا شده از کمرنگ‌های تعبیه‌شده استفاده کنید:

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

در بالای رمزگذار ، ما Dense لایه برای انتخاب کلمه بعدی در دنباله، با a softmax فعال سازی (که توزیع احتمال را برای هر توکن بعدی تولید می کند). بیایید نگاهی به خلاصه مدل بیندازیم:

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 رمزگشاهای زیادی را روی هم قرار می دهد – GPT-2 Small دارای 12 رمزگشای پشته ای (117M پارامتر) است، در حالی که GPT-2 Extra Large دارای 48 رمزگشای پشته ای (1.5B پارامتر) است. مدل تک رمزگشای ما با پارامترهای ساده 13M باید برای اهداف آموزشی به اندازه کافی خوب کار کند. با LLM ها – ثابت شده است که افزایش مقیاس یک استراتژی بسیار خوب است، و ترانسفورماتورها اجازه مقیاس بندی خوب را می دهند و آموزش مدل های بسیار بزرگ را امکان پذیر می کند.

GPT-3 دارای یک “ضعیف” پارامترهای 175B. تیم Google Brain یک مدل پارامتر 1.6T را برای انجام تحقیقات پراکنده و در عین حال محاسبات آموزش داد. روی همان سطح مدل های کوچکتر.

در واقع، اگر تعداد رمزگشاها را از 1 به 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)

تعداد پارامتر ما 400K افزایش می یابد:

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

بیشتر پارامترهای شبکه ما از TokenAndPositionEmbedding و Dense لایه های!

اعماق مختلف رمزگشا را امتحان کنید – از 1 تا تمام راهی که دستگاه شما می تواند کار کند و نتایج را یادداشت کنید. در هر صورت – ما تقریباً آماده آموزش مدل هستیم! بیایید یک پاسخ تماس سفارشی ایجاد کنیم که نمونه ای از متن را تولید می کند روی در هر دوره، بنابراین ما می توانیم ببینیم که چگونه مدل از طریق آموزش جملات را می آموزد.

پاسخ به تماس سفارشی

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

آموزش مدل

بالاخره وقت تمرین است! بیایید خودمان را کنار بگذاریم train_dataset و validation_dataset با تماس های برگشتی:

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

نمونه‌گر جمله‌ی تاسف‌آوری را انتخاب کرد که با نقل قول پایان و شروع نقل‌قول شروع می‌شود، اما همچنان نتایج جالبی را در حین آموزش ایجاد می‌کند:

# 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

با این شروع می شود:

“چی بودی که نبودی من همون بودم”…

که واقعاً چندان منطقی نیست. در پایان ده دوره کوتاه، چیزی در امتداد خطوط زیر تولید می کند:

“منظورت چیست که البته معمولی ترین مرد یک مرد است”…

در حالی که جمله دوم هنوز خیلی معنا ندارد – بسیار حساس تر از جمله اول است. آموزش طولانی تر روی داده های بیشتر (با مراحل پیش پردازش پیچیده تر) نتایج بهتری به همراه خواهد داشت. ما فقط آن را آموزش داده ایم روی 10 دوره با انصراف زیاد برای مبارزه با اندازه داده کوچک. اگر برای مدت طولانی تری به آموزش رها می شد، متن بسیار فئودور مانند تولید می کرد، زیرا تکه های بزرگی از آن را حفظ می کرد.

توجه داشته باشید: از آنجایی که خروجی نسبتاً پرمخاطب است، می توانید آن را تغییر دهید verbose آرگومان در حالی که برازش مدل برای کاهش مقدار متن روی صفحه نمایش

استنتاج مدل

برای انجام استنتاج، می خواهیم رابط کاربری را تکرار کنیم TextSampler – روشی که بذر و الف می پذیرد response_length (max_tokens). ما از همان روش‌هایی که در نمونه‌گر استفاده می‌کنیم استفاده می‌کنیم:

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

حالا می توانید روش را اجرا کنید روی نمونه های جدید:

generate_text('the truth ultimately is')


generate_text('the truth ultimately is')

بهبود نتایج؟

بنابراین، چگونه می توانید نتایج را بهبود بخشید؟ چند کار بسیار عملی وجود دارد که می توانید انجام دهید:

  • تمیز کردن داده ها (داده های ورودی را با دقت بیشتری تمیز کنید، ما فقط یک عدد تقریبی را از ابتدا کوتاه کردیم و کاراکترهای خط جدید را حذف کردیم)
  • داده های بیشتری دریافت کنید (ما فقط با چند مگابایت داده متنی کار کردیم)
  • مدل را در کنار داده ها مقیاس کنید (انباشته کردن رمزگشاها کار سختی نیست!)

نتیجه

در حالی که خط لوله پیش پردازش حداقلی است و می توان آن را بهبود بخشید – خط لوله مشخص شده در این راهنما یک مدل مناسب به سبک GPT ایجاد کرد، با تنها 5 خط کد مورد نیاز برای ساخت یک ترانسفورماتور فقط رمزگشای سفارشی، با استفاده از Keras!

ترانسفورماتورها برای مدل‌سازی توالی عمومی محبوب و به طور گسترده قابل استفاده هستند (و بسیاری از چیزها را می‌توان به صورت توالی بیان کرد). تا کنون، مانع اصلی ورود، یک پیاده سازی دست و پا گیر بود، اما با KerasNLP – متخصصان یادگیری عمیق می توانند از پیاده سازی ها برای ساخت سریع و آسان مدل ها استفاده کنند.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-06 05:24:03

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید