497 lines
34 KiB
Plaintext
497 lines
34 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"# شبکههای مولد\n",
|
||
"\n",
|
||
"شبکههای عصبی بازگشتی (RNNs) و انواع سلولهای دروازهدار آنها مانند سلولهای حافظه کوتاهمدت بلند (LSTMs) و واحدهای بازگشتی دروازهدار (GRUs) مکانیزمی برای مدلسازی زبان فراهم کردند، یعنی میتوانند ترتیب کلمات را یاد بگیرند و پیشبینیهایی برای کلمه بعدی در یک دنباله ارائه دهند. این قابلیت به ما اجازه میدهد از RNNها برای **وظایف مولد** استفاده کنیم، مانند تولید متن معمولی، ترجمه ماشینی، و حتی توضیحنویسی تصاویر.\n",
|
||
"\n",
|
||
"در معماری RNN که در واحد قبلی بحث کردیم، هر واحد RNN حالت مخفی بعدی را به عنوان خروجی تولید میکرد. با این حال، میتوانیم یک خروجی دیگر به هر واحد بازگشتی اضافه کنیم که به ما اجازه میدهد یک **دنباله** خروجی تولید کنیم (که طول آن برابر با دنباله اصلی است). علاوه بر این، میتوانیم از واحدهای RNN استفاده کنیم که در هر مرحله ورودی دریافت نمیکنند و فقط یک بردار حالت اولیه میگیرند و سپس یک دنباله خروجی تولید میکنند.\n",
|
||
"\n",
|
||
"در این دفترچه، ما بر مدلهای مولد ساده تمرکز خواهیم کرد که به ما کمک میکنند متن تولید کنیم. برای سادهسازی، بیایید یک **شبکه سطح کاراکتر** بسازیم که متن را حرف به حرف تولید کند. در طول آموزش، باید یک متن مرجع را بگیریم و آن را به دنبالههای حرف تقسیم کنیم.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import tensorflow as tf\n",
|
||
"from tensorflow import keras\n",
|
||
"import tensorflow_datasets as tfds\n",
|
||
"import numpy as np\n",
|
||
"\n",
|
||
"ds_train, ds_test = tfds.load('ag_news_subset').values()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## ساخت واژگان کاراکتری\n",
|
||
"\n",
|
||
"برای ساخت یک شبکه مولد در سطح کاراکتر، باید متن را به کاراکترهای جداگانه تقسیم کنیم، نه کلمات. لایه `TextVectorization` که قبلاً استفاده میکردیم نمیتواند این کار را انجام دهد، بنابراین دو گزینه داریم:\n",
|
||
"\n",
|
||
"* متن را به صورت دستی بارگذاری کرده و توکنسازی را «دستی» انجام دهیم، همانطور که در [این مثال رسمی Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/) آمده است.\n",
|
||
"* از کلاس `Tokenizer` برای توکنسازی در سطح کاراکتر استفاده کنیم.\n",
|
||
"\n",
|
||
"ما گزینه دوم را انتخاب میکنیم. `Tokenizer` همچنین میتواند برای توکنسازی در سطح کلمه استفاده شود، بنابراین میتوان به راحتی از توکنسازی کاراکتری به توکنسازی کلمهای تغییر حالت داد.\n",
|
||
"\n",
|
||
"برای انجام توکنسازی در سطح کاراکتر، باید پارامتر `char_level=True` را ارسال کنیم:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def extract_text(x):\n",
|
||
" return x['title']+' '+x['description']\n",
|
||
"\n",
|
||
"def tupelize(x):\n",
|
||
" return (extract_text(x),x['label'])\n",
|
||
"\n",
|
||
"tokenizer = keras.preprocessing.text.Tokenizer(char_level=True,lower=False)\n",
|
||
"tokenizer.fit_on_texts([x['title'].numpy().decode('utf-8') for x in ds_train])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"ما همچنین میخواهیم از یک نشانه ویژه برای نشان دادن **پایان دنباله** استفاده کنیم، که آن را `<eos>` مینامیم. بیایید آن را به صورت دستی به واژگان اضافه کنیم:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"eos_token = len(tokenizer.word_index)+1\n",
|
||
"tokenizer.word_index['<eos>'] = eos_token\n",
|
||
"\n",
|
||
"vocab_size = eos_token + 1"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"اکنون، برای رمزگذاری متن به دنبالههای اعداد، میتوانیم استفاده کنیم:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"[[48, 2, 10, 10, 5, 44, 1, 25, 5, 8, 10, 13, 78]]"
|
||
]
|
||
},
|
||
"execution_count": 4,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"tokenizer.texts_to_sequences(['Hello, world!'])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## آموزش یک RNN مولد برای تولید عناوین\n",
|
||
"\n",
|
||
"روش آموزش RNN برای تولید عناوین خبری به این صورت است: در هر مرحله، یک عنوان را میگیریم، آن را به RNN میدهیم و از شبکه میخواهیم برای هر کاراکتر ورودی، کاراکتر خروجی بعدی را تولید کند:\n",
|
||
"\n",
|
||
"\n",
|
||
"\n",
|
||
"برای آخرین کاراکتر از دنبالهمان، از شبکه میخواهیم که توکن `<eos>` را تولید کند.\n",
|
||
"\n",
|
||
"تفاوت اصلی RNN مولدی که اینجا استفاده میکنیم این است که خروجی هر مرحله از RNN را میگیریم، نه فقط خروجی سلول نهایی. این کار با مشخص کردن پارامتر `return_sequences` برای سلول RNN امکانپذیر است.\n",
|
||
"\n",
|
||
"بنابراین، در طول آموزش، ورودی شبکه یک دنباله از کاراکترهای کدگذاریشده با طول مشخص خواهد بود و خروجی نیز دنبالهای با همان طول خواهد بود که یک عنصر جابهجا شده و با `<eos>` خاتمه مییابد. مینیبچ شامل چندین دنباله از این نوع خواهد بود و برای همتراز کردن تمام دنبالهها نیاز به استفاده از **پدینگ** داریم.\n",
|
||
"\n",
|
||
"بیایید توابعی ایجاد کنیم که مجموعه داده را برای ما تبدیل کنند. از آنجا که میخواهیم دنبالهها را در سطح مینیبچ پد کنیم، ابتدا مجموعه داده را با فراخوانی `.batch()` به صورت بچ تقسیم میکنیم و سپس با استفاده از `map` آن را برای انجام تبدیل تغییر میدهیم. بنابراین، تابع تبدیل کل مینیبچ را به عنوان یک پارامتر دریافت خواهد کرد:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def title_batch(x):\n",
|
||
" x = [t.numpy().decode('utf-8') for t in x]\n",
|
||
" z = tokenizer.texts_to_sequences(x)\n",
|
||
" z = tf.keras.preprocessing.sequence.pad_sequences(z)\n",
|
||
" return tf.one_hot(z,vocab_size), tf.one_hot(tf.concat([z[:,1:],tf.constant(eos_token,shape=(len(z),1))],axis=1),vocab_size)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"چند نکته مهم که در اینجا انجام میدهیم:\n",
|
||
"* ابتدا متن واقعی را از رشتهی تنسور استخراج میکنیم\n",
|
||
"* `text_to_sequences` لیستی از رشتهها را به لیستی از تنسورهای عددی تبدیل میکند\n",
|
||
"* `pad_sequences` این تنسورها را تا طول حداکثرشان پر میکند\n",
|
||
"* در نهایت تمام کاراکترها را به صورت یکهاتی کدگذاری میکنیم، و همچنین جابجایی و افزودن `<eos>` را انجام میدهیم. به زودی خواهیم دید چرا به کاراکترهای یکهاتی کدگذاریشده نیاز داریم\n",
|
||
"\n",
|
||
"با این حال، این تابع **پایتونمحور** است، یعنی نمیتوان آن را به طور خودکار به گراف محاسباتی Tensorflow ترجمه کرد. اگر بخواهیم این تابع را مستقیماً در تابع `Dataset.map` استفاده کنیم، با خطا مواجه خواهیم شد. باید این فراخوانی پایتونمحور را با استفاده از پوششدهندهی `py_function` محصور کنیم:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def title_batch_fn(x):\n",
|
||
" x = x['title']\n",
|
||
" a,b = tf.py_function(title_batch,inp=[x],Tout=(tf.float32,tf.float32))\n",
|
||
" return a,b"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"> **توجه**: ممکن است تشخیص تفاوت بین توابع تبدیل پایتونی و توابع تبدیل Tensorflow کمی پیچیده به نظر برسد و شاید این سوال برایتان پیش بیاید که چرا دادهها را با استفاده از توابع استاندارد پایتون قبل از ارسال به `fit` تبدیل نمیکنیم. در حالی که این کار قطعاً امکانپذیر است، استفاده از `Dataset.map` یک مزیت بزرگ دارد، زیرا خط لوله تبدیل دادهها با استفاده از گراف محاسباتی Tensorflow اجرا میشود که از محاسبات GPU بهره میبرد و نیاز به انتقال دادهها بین CPU و GPU را به حداقل میرساند.\n",
|
||
"\n",
|
||
"حالا میتوانیم شبکه مولد خود را بسازیم و آموزش را شروع کنیم. این شبکه میتواند بر اساس هر سلول بازگشتی که در واحد قبلی بحث کردیم (ساده، LSTM یا GRU) باشد. در مثال ما از LSTM استفاده خواهیم کرد.\n",
|
||
"\n",
|
||
"از آنجا که شبکه کاراکترها را به عنوان ورودی میگیرد و اندازه واژگان نسبتاً کوچک است، نیازی به لایه تعبیه (embedding) نداریم و ورودیهای کدگذاریشده به صورت یکداغ (one-hot-encoded) میتوانند مستقیماً وارد سلول LSTM شوند. لایه خروجی یک طبقهبند `Dense` خواهد بود که خروجی LSTM را به اعداد کدگذاریشده به صورت یکداغ تبدیل میکند.\n",
|
||
"\n",
|
||
"علاوه بر این، از آنجا که با دنبالههایی با طول متغیر سروکار داریم، میتوانیم از لایه `Masking` استفاده کنیم تا ماسکی ایجاد کنیم که بخش پرشده رشته را نادیده بگیرد. این کار به طور دقیق ضروری نیست، زیرا ما خیلی به آنچه که فراتر از توکن `<eos>` میرود علاقهمند نیستیم، اما برای کسب تجربه با این نوع لایه از آن استفاده خواهیم کرد. `input_shape` برابر با `(None, vocab_size)` خواهد بود، که در آن `None` نشاندهنده دنبالهای با طول متغیر است، و شکل خروجی نیز `(None, vocab_size)` خواهد بود، همانطور که میتوانید از `summary` مشاهده کنید:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Model: \"sequential\"\n",
|
||
"_________________________________________________________________\n",
|
||
"Layer (type) Output Shape Param # \n",
|
||
"=================================================================\n",
|
||
"masking (Masking) (None, None, 84) 0 \n",
|
||
"_________________________________________________________________\n",
|
||
"lstm (LSTM) (None, None, 128) 109056 \n",
|
||
"_________________________________________________________________\n",
|
||
"dense (Dense) (None, None, 84) 10836 \n",
|
||
"=================================================================\n",
|
||
"Total params: 119,892\n",
|
||
"Trainable params: 119,892\n",
|
||
"Non-trainable params: 0\n",
|
||
"_________________________________________________________________\n",
|
||
"15000/15000 [==============================] - 229s 15ms/step - loss: 1.5385\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<tensorflow.python.keras.callbacks.History at 0x7fa40c1245e0>"
|
||
]
|
||
},
|
||
"execution_count": 7,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"model = keras.models.Sequential([\n",
|
||
" keras.layers.Masking(input_shape=(None,vocab_size)),\n",
|
||
" keras.layers.LSTM(128,return_sequences=True),\n",
|
||
" keras.layers.Dense(vocab_size,activation='softmax')\n",
|
||
"])\n",
|
||
"\n",
|
||
"model.summary()\n",
|
||
"model.compile(loss='categorical_crossentropy')\n",
|
||
"\n",
|
||
"model.fit(ds_train.batch(8).map(title_batch_fn))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## تولید خروجی\n",
|
||
"\n",
|
||
"حالا که مدل را آموزش دادهایم، میخواهیم از آن برای تولید خروجی استفاده کنیم. ابتدا، نیاز داریم روشی برای رمزگشایی متنی که به صورت دنبالهای از اعداد توکن نمایش داده شده است، داشته باشیم. برای این کار میتوانیم از تابع `tokenizer.sequences_to_texts` استفاده کنیم؛ اما این تابع با توکنسازی در سطح کاراکتر به خوبی کار نمیکند. بنابراین، یک دیکشنری از توکنها از `tokenizer` (به نام `word_index`) میگیریم، یک نقشه معکوس میسازیم و تابع رمزگشایی خودمان را مینویسیم:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 10,
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"reverse_map = {val:key for key, val in tokenizer.word_index.items()}\n",
|
||
"\n",
|
||
"def decode(x):\n",
|
||
" return ''.join([reverse_map[t] for t in x])"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"حالا، بیایید تولید را شروع کنیم. ابتدا یک رشته `start` داریم که آن را به یک دنباله `inp` رمزگذاری میکنیم، و سپس در هر مرحله شبکه خود را فراخوانی میکنیم تا کاراکتر بعدی را پیشبینی کند.\n",
|
||
"\n",
|
||
"خروجی شبکه `out` یک بردار با `vocab_size` عنصر است که احتمال هر نشانه را نشان میدهد، و میتوانیم با استفاده از `argmax` شماره نشانهای که بیشترین احتمال را دارد پیدا کنیم. سپس این کاراکتر را به لیست نشانههای تولید شده اضافه میکنیم و فرآیند تولید را ادامه میدهیم. این فرآیند تولید یک کاراکتر، `size` بار تکرار میشود تا تعداد کاراکترهای مورد نیاز تولید شود، و در صورتی که `eos_token` زودتر مواجه شود، تولید متوقف میشود.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 12,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"'Today #39;s lead to strike for the strike for the strike for the strike (AFP)'"
|
||
]
|
||
},
|
||
"execution_count": 12,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"def generate(model,size=100,start='Today '):\n",
|
||
" inp = tokenizer.texts_to_sequences([start])[0]\n",
|
||
" chars = inp\n",
|
||
" for i in range(size):\n",
|
||
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
|
||
" nc = tf.argmax(out)\n",
|
||
" if nc==eos_token:\n",
|
||
" break\n",
|
||
" chars.append(nc.numpy())\n",
|
||
" inp = inp+[nc]\n",
|
||
" return decode(chars)\n",
|
||
" \n",
|
||
"generate(model)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## نمونهگیری خروجی در حین آموزش\n",
|
||
"\n",
|
||
"از آنجا که ما هیچ معیار مفیدی مانند *دقت* نداریم، تنها راهی که میتوانیم ببینیم مدل ما بهتر میشود یا نه، **نمونهگیری** از رشتههای تولیدشده در حین آموزش است. برای انجام این کار، از **callbacks** استفاده خواهیم کرد، یعنی توابعی که میتوانیم به تابع `fit` بدهیم و این توابع به صورت دورهای در طول آموزش فراخوانی میشوند.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 13,
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"Epoch 1/3\n",
|
||
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.2703\n",
|
||
"Today #39;s a lead in the company for the strike\n",
|
||
"Epoch 2/3\n",
|
||
"15000/15000 [==============================] - 227s 15ms/step - loss: 1.2057\n",
|
||
"Today #39;s the Market Service on Security Start (AP)\n",
|
||
"Epoch 3/3\n",
|
||
"15000/15000 [==============================] - 226s 15ms/step - loss: 1.1752\n",
|
||
"Today #39;s a line on the strike to start for the start\n"
|
||
]
|
||
},
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"<tensorflow.python.keras.callbacks.History at 0x7fa40c74e3d0>"
|
||
]
|
||
},
|
||
"execution_count": 13,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"sampling_callback = keras.callbacks.LambdaCallback(\n",
|
||
" on_epoch_end = lambda batch, logs: print(generate(model))\n",
|
||
")\n",
|
||
"\n",
|
||
"model.fit(ds_train.batch(8).map(title_batch_fn),callbacks=[sampling_callback],epochs=3)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"این مثال از قبل متن نسبتاً خوبی تولید میکند، اما میتوان آن را به چندین روش بهبود داد:\n",
|
||
"\n",
|
||
"* **متن بیشتر**. ما فقط از عناوین برای وظیفه خود استفاده کردهایم، اما ممکن است بخواهید با متن کامل آزمایش کنید. به یاد داشته باشید که RNNها در مدیریت دنبالههای طولانی چندان خوب نیستند، بنابراین منطقی است که یا آنها را به جملات کوتاهتر تقسیم کنید، یا همیشه روی طول دنبالهای ثابت با مقداری از پیش تعریفشده `num_chars` (مثلاً ۲۵۶) آموزش دهید. میتوانید مثال بالا را به چنین معماریای تغییر دهید و از [آموزش رسمی Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/) الهام بگیرید.\n",
|
||
"\n",
|
||
"* **LSTM چندلایه**. منطقی است که ۲ یا ۳ لایه از سلولهای LSTM را امتحان کنید. همانطور که در واحد قبلی اشاره کردیم، هر لایه از LSTM الگوهای خاصی را از متن استخراج میکند، و در مورد تولیدکننده در سطح کاراکتر، میتوان انتظار داشت که لایههای پایینتر LSTM مسئول استخراج هجاها باشند و لایههای بالاتر - کلمات و ترکیبهای کلمهای. این کار به سادگی با ارسال پارامتر تعداد لایهها به سازنده LSTM قابل پیادهسازی است.\n",
|
||
"\n",
|
||
"* همچنین ممکن است بخواهید با **واحدهای GRU** آزمایش کنید و ببینید کدامیک عملکرد بهتری دارند، و با **اندازههای مختلف لایههای مخفی** نیز کار کنید. لایه مخفی بیش از حد بزرگ ممکن است منجر به بیشبرازش شود (برای مثال، شبکه متن دقیق را یاد میگیرد)، و اندازه کوچکتر ممکن است نتیجه خوبی تولید نکند.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"## تولید متن نرم و دما\n",
|
||
"\n",
|
||
"در تعریف قبلی `generate`، همیشه کاراکتری که بالاترین احتمال را داشت به عنوان کاراکتر بعدی در متن تولید شده انتخاب میشد. این باعث میشد که متن اغلب بین دنبالههای کاراکتری مشابه بارها و بارها \"چرخش\" کند، مانند این مثال:\n",
|
||
"```\n",
|
||
"today of the second the company and a second the company ...\n",
|
||
"```\n",
|
||
"\n",
|
||
"با این حال، اگر به توزیع احتمالات برای کاراکتر بعدی نگاه کنیم، ممکن است تفاوت بین چند احتمال بالاتر خیلی زیاد نباشد، به عنوان مثال یک کاراکتر میتواند احتمال 0.2 داشته باشد و دیگری 0.19 و غیره. برای مثال، وقتی به دنبال کاراکتر بعدی در دنباله '*play*' هستیم، کاراکتر بعدی میتواند به همان اندازه فضای خالی باشد یا **e** (مانند کلمه *player*).\n",
|
||
"\n",
|
||
"این ما را به این نتیجه میرساند که همیشه \"منصفانه\" نیست که کاراکتری با احتمال بالاتر را انتخاب کنیم، زیرا انتخاب کاراکتر دوم با احتمال بالاتر نیز ممکن است به متنی معنادار منجر شود. عاقلانهتر است که کاراکترها را از توزیع احتمالاتی که توسط خروجی شبکه داده شده است **نمونهگیری** کنیم.\n",
|
||
"\n",
|
||
"این نمونهگیری میتواند با استفاده از تابع `np.multinomial` انجام شود که توزیع احتمالی **چندجملهای** را پیادهسازی میکند. تابعی که این تولید متن **نرم** را پیادهسازی میکند در زیر تعریف شده است:\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 33,
|
||
"metadata": {
|
||
"scrolled": true
|
||
},
|
||
"outputs": [
|
||
{
|
||
"name": "stdout",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"\n",
|
||
"--- Temperature = 0.3\n",
|
||
"Today #39;s strike #39; to start at the store return\n",
|
||
"On Sunday PO to Be Data Profit Up (Reuters)\n",
|
||
"Moscow, SP wins straight to the Microsoft #39;s control of the space start\n",
|
||
"President olding of the blast start for the strike to pay <b>...</b>\n",
|
||
"Little red riding hood ficed to the spam countered in European <b>...</b>\n",
|
||
"\n",
|
||
"--- Temperature = 0.8\n",
|
||
"Today countie strikes ryder missile faces food market blut\n",
|
||
"On Sunday collores lose-toppy of sale of Bullment in <b>...</b>\n",
|
||
"Moscow, IBM Diffeiting in Afghan Software Hotels (Reuters)\n",
|
||
"President Ol Luster for Profit Peaced Raised (AP)\n",
|
||
"Little red riding hood dace on depart talks #39; bank up\n",
|
||
"\n",
|
||
"--- Temperature = 1.0\n",
|
||
"Today wits House buiting debate fixes #39; supervice stake again\n",
|
||
"On Sunday arling digital poaching In for level\n",
|
||
"Moscow, DS Up 7, Top Proble Protest Caprey Mamarian Strike\n",
|
||
"President teps help of roubler stepted lessabul-Dhalitics (AFP)\n",
|
||
"Little red riding hood signs on cash in Carter-youb\n",
|
||
"\n",
|
||
"--- Temperature = 1.3\n",
|
||
"Today wits flawer ro, pSIA figat's co DroftwavesIs Talo up\n",
|
||
"On Sunday hround elitwing wint EU Powerburlinetien\n",
|
||
"Moscow, Bazz #39;s sentries olymen winnelds' next for Olympite Huc?\n",
|
||
"President lost securitys from power Elections in Smiltrials\n",
|
||
"Little red riding hood vides profit, exponituity, profitmainalist-at said listers\n",
|
||
"\n",
|
||
"--- Temperature = 1.8\n",
|
||
"Today #39;It: He deat: N.KA Asside\n",
|
||
"On Sunday i arry Par aldeup patient Wo stele1\n"
|
||
]
|
||
},
|
||
{
|
||
"ename": "KeyError",
|
||
"evalue": "0",
|
||
"output_type": "error",
|
||
"traceback": [
|
||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
|
||
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"\\n--- Temperature = {i}\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgenerate_soft\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0msize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m300\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mstart\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwords\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mtemperature\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||
"\u001b[0;32m<ipython-input-33-db32367a0feb>\u001b[0m in \u001b[0;36mgenerate_soft\u001b[0;34m(model, size, start, temperature)\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mchars\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0minp\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minp\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnc\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 13\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mchars\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 14\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 15\u001b[0m \u001b[0mwords\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'Today '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'On Sunday '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Moscow, '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'President '\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'Little red riding hood '\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
||
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36mdecode\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||
"\u001b[0;32m<ipython-input-10-3f5fa6130b1d>\u001b[0m in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mdecode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mreverse_map\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
||
"\u001b[0;31mKeyError\u001b[0m: 0"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"def generate_soft(model,size=100,start='Today ',temperature=1.0):\n",
|
||
" inp = tokenizer.texts_to_sequences([start])[0]\n",
|
||
" chars = inp\n",
|
||
" for i in range(size):\n",
|
||
" out = model(tf.expand_dims(tf.one_hot(inp,vocab_size),0))[0][-1]\n",
|
||
" probs = tf.exp(tf.math.log(out)/temperature).numpy().astype(np.float64)\n",
|
||
" probs = probs/np.sum(probs)\n",
|
||
" nc = np.argmax(np.random.multinomial(1,probs,1))\n",
|
||
" if nc==eos_token:\n",
|
||
" break\n",
|
||
" chars.append(nc)\n",
|
||
" inp = inp+[nc]\n",
|
||
" return decode(chars)\n",
|
||
"\n",
|
||
"words = ['Today ','On Sunday ','Moscow, ','President ','Little red riding hood ']\n",
|
||
" \n",
|
||
"for i in [0.3,0.8,1.0,1.3,1.8]:\n",
|
||
" print(f\"\\n--- Temperature = {i}\")\n",
|
||
" for j in range(5):\n",
|
||
" print(generate_soft(model,size=300,start=words[j],temperature=i))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"ما یک پارامتر دیگر به نام **دما** معرفی کردهایم که برای نشان دادن میزان پایبندی به بالاترین احتمال استفاده میشود. اگر دما ۱.۰ باشد، نمونهگیری چندجملهای منصفانه انجام میدهیم، و زمانی که دما به بینهایت میرسد - همه احتمالات برابر میشوند و ما به صورت تصادفی کاراکتر بعدی را انتخاب میکنیم. در مثال زیر میتوان مشاهده کرد که متن با افزایش بیش از حد دما بیمعنی میشود و زمانی که دما به ۰ نزدیکتر میشود، به متن سخت-تولید شده \"چرخهای\" شباهت پیدا میکند.\n"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"metadata": {},
|
||
"source": [
|
||
"\n---\n\n**سلب مسئولیت**: \nاین سند با استفاده از سرویس ترجمه هوش مصنوعی [Co-op Translator](https://github.com/Azure/co-op-translator) ترجمه شده است. در حالی که ما تلاش میکنیم دقت را حفظ کنیم، لطفاً توجه داشته باشید که ترجمههای خودکار ممکن است شامل خطاها یا نادرستیها باشند. سند اصلی به زبان اصلی آن باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حساس، توصیه میشود از ترجمه حرفهای انسانی استفاده کنید. ما مسئولیتی در قبال سوء تفاهمها یا تفسیرهای نادرست ناشی از استفاده از این ترجمه نداریم.\n"
|
||
]
|
||
}
|
||
],
|
||
"metadata": {
|
||
"interpreter": {
|
||
"hash": "16af2a8bbb083ea23e5e41c7f5787656b2ce26968575d8763f2c4b17f9cd711f"
|
||
},
|
||
"kernelspec": {
|
||
"display_name": "Python 3.8.12 ('py38')",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.8.12"
|
||
},
|
||
"coopTranslator": {
|
||
"original_hash": "9fbb7d5fda708537649f71f5f646fcde",
|
||
"translation_date": "2025-08-31T16:52:32+00:00",
|
||
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
|
||
"language_code": "fa"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 4
|
||
} |