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

497 lines
30 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# רשתות גנרטיביות\n",
"\n",
"רשתות עצביות חוזרות (RNNs) והגרסאות שלהן עם תאים מבוקרים, כמו תאי זיכרון לטווח ארוך (LSTMs) ויחידות חוזרות מבוקרות (GRUs), מספקות מנגנון למידול שפה, כלומר, הן יכולות ללמוד את סדר המילים ולספק תחזיות למילה הבאה ברצף. הדבר מאפשר לנו להשתמש ב-RNNs עבור **משימות גנרטיביות**, כמו יצירת טקסט רגיל, תרגום מכונה ואפילו יצירת כיתוב לתמונות.\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",
"![תמונה המציגה דוגמה ליצירת המילה 'HELLO' באמצעות RNN.](../../../../../translated_images/he/rnn-generate.56c54afb52f9781d.webp)\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",
"* קודם כל אנחנו שולפים את הטקסט עצמו מתוך ה-String Tensor\n",
"* `text_to_sequences` ממיר את רשימת המחרוזות לרשימה של טנסורים של מספרים שלמים\n",
"* `pad_sequences` משלים את הטנסורים לאורך המקסימלי שלהם\n",
"* לבסוף, אנחנו מבצעים קידוד one-hot לכל התווים, וגם מבצעים את ההסטה והוספת `<eos>`. בקרוב נבין למה אנחנו צריכים תווים מקודדים ב-one-hot\n",
"\n",
"עם זאת, הפונקציה הזו היא **Pythonic**, כלומר היא לא יכולה להיות מתורגמת אוטומטית לגרף חישובי של Tensorflow. נקבל שגיאות אם ננסה להשתמש בפונקציה הזו ישירות בתוך הפונקציה `Dataset.map`. עלינו לעטוף את הקריאה ה-Pythonic הזו באמצעות ה-wrapper `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": [
"> **Note**: ההבחנה בין פונקציות טרנספורמציה בסגנון פייתון לבין פונקציות טרנספורמציה של Tensorflow עשויה להיראות מורכבת מדי, ואתם אולי שואלים מדוע לא לבצע את טרנספורמציית הנתונים באמצעות פונקציות פייתון סטנדרטיות לפני שמעבירים אותם ל-`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`; עם זאת, היא לא עובדת טוב עם טוקניזציה ברמת תווים. לכן ניקח מילון של טוקנים מהטוקנייזר (שנקרא `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",
"* **יותר טקסט**. השתמשנו רק בכותרות עבור המשימה שלנו, אך ייתכן שתרצה להתנסות בטקסט מלא. זכור ש-RNNs אינם מצטיינים בהתמודדות עם רצפים ארוכים, ולכן הגיוני או לחלק אותם למשפטים קצרים יותר, או תמיד להתאמן על רצף קבוע באורך מוגדר מראש `num_chars` (לדוגמה, 256). תוכל לנסות לשנות את הדוגמה לעיל לארכיטקטורה כזו, תוך שימוש ב[מדריך הרשמי של Keras](https://keras.io/examples/generative/lstm_character_level_text_generation/) כהשראה.\n",
"\n",
"* **LSTM רב-שכבתי**. הגיוני לנסות 2 או 3 שכבות של תאי 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 &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-28T21:32:48+00:00",
"source_file": "lessons/5-NLP/17-GenerativeNetworks/GenerativeTF.ipynb",
"language_code": "he"
}
},
"nbformat": 4,
"nbformat_minor": 4
}