AI-For-Beginners/translations/ar/lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb

497 lines
32 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# الشبكات التوليدية\n",
"\n",
"توفر الشبكات العصبية المتكررة (RNNs) ونسخها ذات الخلايا البوابية مثل خلايا الذاكرة طويلة المدى (LSTMs) ووحدات التكرار البوابية (GRUs) آلية لنمذجة اللغة، أي أنها تستطيع تعلم ترتيب الكلمات وتقديم توقعات للكلمة التالية في التسلسل. هذا يسمح لنا باستخدام الشبكات العصبية المتكررة في **المهام التوليدية**، مثل توليد النصوص العادية، الترجمة الآلية، وحتى وصف الصور.\n",
"\n",
"في بنية الشبكات العصبية المتكررة التي ناقشناها في الوحدة السابقة، كل وحدة متكررة تنتج الحالة المخفية التالية كمخرج. ومع ذلك، يمكننا أيضًا إضافة مخرج آخر لكل وحدة متكررة، مما يسمح لنا بإنتاج **تسلسل** (يكون طوله مساويًا لطول التسلسل الأصلي). علاوة على ذلك، يمكننا استخدام وحدات متكررة لا تقبل مدخلًا في كل خطوة، بل تأخذ فقط متجه حالة أولية، ثم تنتج تسلسلًا من المخرجات.\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",
"الطريقة التي سنقوم بها بتدريب الشبكة العصبية المتكررة لتوليد عناوين الأخبار هي كالتالي. في كل خطوة، سنأخذ عنوانًا واحدًا، يتم إدخاله في الشبكة العصبية المتكررة، وبالنسبة لكل حرف مُدخل، سنطلب من الشبكة توليد الحرف التالي:\n",
"\n",
"![صورة توضح مثالًا لتوليد كلمة \"HELLO\" باستخدام شبكة عصبية متكررة.](../../../../../translated_images/ar/rnn-generate.56c54afb52f9781d.webp)\n",
"\n",
"بالنسبة للحرف الأخير في تسلسلنا، سنطلب من الشبكة توليد رمز `<eos>`.\n",
"\n",
"الفرق الرئيسي بين الشبكة العصبية المتكررة التوليدية التي نستخدمها هنا هو أننا سنأخذ الناتج من كل خطوة من الشبكة العصبية المتكررة، وليس فقط من الخلية النهائية. يمكن تحقيق ذلك عن طريق تحديد معامل `return_sequences` في خلية الشبكة العصبية المتكررة.\n",
"\n",
"لذلك، أثناء التدريب، سيكون الإدخال إلى الشبكة عبارة عن تسلسل من الأحرف المشفرة بطول معين، والناتج سيكون تسلسلًا بنفس الطول، ولكن مُزاحًا بعنصر واحد وينتهي برمز `<eos>`. ستتكون الدفعة الصغيرة (Minibatch) من عدة تسلسلات مثل هذه، وسنحتاج إلى استخدام **التعبئة** لتنسيق جميع التسلسلات.\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",
"ومع ذلك، هذه الوظيفة **Pythonic**، أي أنها لا يمكن ترجمتها تلقائياً إلى الرسم البياني الحسابي الخاص بـ Tensorflow. سنواجه أخطاء إذا حاولنا استخدام هذه الوظيفة مباشرة في وظيفة `Dataset.map`. نحتاج إلى تضمين هذا الاستدعاء Pythonic باستخدام غلاف `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": [
"> **ملاحظة**: قد يبدو التمييز بين وظائف التحويل في Python و Tensorflow معقدًا بعض الشيء، وربما تتساءل لماذا لا نقوم بتحويل مجموعة البيانات باستخدام وظائف Python القياسية قبل تمريرها إلى `fit`. بينما يمكن بالتأكيد القيام بذلك، فإن استخدام `Dataset.map` له ميزة كبيرة، حيث يتم تنفيذ خط أنابيب تحويل البيانات باستخدام الرسم البياني الحسابي لـ Tensorflow، مما يستفيد من حسابات GPU ويقلل الحاجة إلى تمرير البيانات بين CPU و GPU.\n",
"\n",
"الآن يمكننا بناء شبكة المولد الخاصة بنا والبدء في التدريب. يمكن أن تعتمد على أي خلية متكررة ناقشناها في الوحدة السابقة (بسيطة، LSTM أو GRU). في مثالنا سنستخدم LSTM.\n",
"\n",
"نظرًا لأن الشبكة تأخذ الأحرف كمدخلات وحجم المفردات صغير جدًا، فلا نحتاج إلى طبقة تضمين، حيث يمكن إدخال المدخلات المشفرة بطريقة \"one-hot\" مباشرةً إلى خلية LSTM. ستكون طبقة الإخراج عبارة عن مصنف `Dense` يحول مخرجات LSTM إلى أرقام الرموز المشفرة بطريقة \"one-hot\".\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",
"نظرًا لعدم وجود أي مقاييس مفيدة مثل *الدقة*، فإن الطريقة الوحيدة التي يمكننا من خلالها معرفة أن النموذج يتحسن هي من خلال **أخذ عينات** من النصوص المُولدة أثناء التدريب. للقيام بذلك، سنستخدم **الوظائف التلقائية**، أي الوظائف التي يمكننا تمريرها إلى دالة `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",
"* **إضافة المزيد من النصوص**. لقد استخدمنا فقط العناوين لمهمتنا، ولكن قد ترغب في تجربة النصوص الكاملة. تذكر أن الشبكات العصبية التكرارية (RNNs) ليست جيدة جدًا في التعامل مع التسلسلات الطويلة، لذا من المنطقي إما تقسيمها إلى جمل أقصر، أو دائمًا التدريب على طول تسلسل ثابت بقيمة محددة مسبقًا `num_chars` (على سبيل المثال، 256). يمكنك محاولة تعديل المثال أعلاه إلى مثل هذه البنية باستخدام [البرنامج التعليمي الرسمي لـ Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/) كمصدر إلهام.\n",
"\n",
"* **استخدام LSTM متعدد الطبقات**. من المنطقي تجربة 2 أو 3 طبقات من خلايا 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 &lt;b&gt;...&lt;/b&gt;\n",
"Little red riding hood ficed to the spam countered in European &lt;b&gt;...&lt;/b&gt;\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 &lt;b&gt;...&lt;/b&gt;\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": [
"لقد قدمنا ​​معلمة إضافية تسمى **درجة الحرارة**، والتي تُستخدم للإشارة إلى مدى التزامنا بأعلى احتمال. إذا كانت درجة الحرارة 1.0، نقوم بأخذ عينات متعددة بشكل عادل، وعندما تقترب درجة الحرارة من اللانهاية - تصبح جميع الاحتمالات متساوية، ونختار الحرف التالي عشوائيًا. في المثال أدناه يمكننا ملاحظة أن النص يصبح بلا معنى عندما نزيد درجة الحرارة كثيرًا، ويشبه النص \"المتكرر\" الذي يتم إنشاؤه بصعوبة عندما تقترب من 0.\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-28T04:06:21+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "ar"
}
},
"nbformat": 4,
"nbformat_minor": 4
}