Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

1816 строки
143 KiB
Plaintext

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "srXC6pLGLwS6"
},
"source": [
"# Загрузка библиотек"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "yG_n40gFzf9s"
},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"from sklearn.model_selection import train_test_split\n",
"import numpy as np\n",
"import pandas as pd\n",
"import os\n",
"import time\n"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "LshgkZ0cIOor",
"outputId": "903898c0-4205-47d7-a6e3-ca22e79ffba9"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Found GPU at: \n"
]
}
],
"source": [
"device_name = tf.test.gpu_device_name()\n",
"print('Found GPU at: {}'.format(device_name))"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"id": "vWkRnHV0DK0L"
},
"outputs": [],
"source": [
"RANDOM_STATE = 42"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EW8HRqz8Oz_b"
},
"source": [
"# Данные"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UHjdCjDuSvX_"
},
"source": [
"## Загрузка данных\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"id": "pP1Ou4nq_W1o"
},
"outputs": [],
"source": [
"# Выбираем поэта\n",
"poet = 'pushkin' #@param ['mayakovskiy', 'pushkin']\n",
"\n",
"path_to_file = f'{poet}.txt'\n",
"path_to_file = tf.keras.utils.get_file(path_to_file, f'http://uit.mpei.ru/git/main/TDA/raw/branch/master/assets/poems/{path_to_file}')"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "aavnuByVymwK",
"outputId": "1c4c379c-ab1e-4b84-939c-66a7471c0210"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Length of text: 586731 characters\n"
]
}
],
"source": [
"# Загружаем текст из файла.\n",
"# Стихотворения в файле разделены токеном '</s>' - сохраняем в переменную\n",
"with open(path_to_file,encoding = \"utf-8\") as f:\n",
" text = f.read()\n",
"\n",
"print(f'Length of text: {len(text)} characters')\n",
"\n",
"EOS_TOKEN = '</s>'"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Duhg9NrUymwO",
"outputId": "8f485753-1712-47a4-c328-a4a714ec0ea4"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Так и мне узнать случилось,\n",
"Что за птица Купидон;\n",
"Сердце страстное пленилось;\n",
"Признаюсь – и я влюблен!\n",
"Пролетело счастья время,\n",
"Как, любви не зная бремя,\n",
"Я живал да попевал,\n",
"Как в театре и на балах,\n",
"На гуляньях иль в воксалах\n",
"Легким зефиром летал;\n",
"Как, смеясь во зло Амуру,\n",
"Я писал карикатуру\n",
"На любезный женской пол;\n",
"Но напрасно я смеялся,\n",
"Наконец и сам попался,\n",
"Сам, увы! с ума сошел.\n",
"Смехи, вольность – всё под лавку\n",
"Из Катонов я в отставку,\n",
"И теперь я – Селадон!\n",
"Миловидной жрицы Тальи\n",
"Видел прел\n"
]
}
],
"source": [
"# Посмотрим на текст\n",
"print(text[:500])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "dLZNbAnzj2lR"
},
"source": [
"## Подсчет статистик\n",
"\n",
"describe_poems - функция, разбивающая файл на отдельные стихотворения (poem), и расчитывающая их характиеристики:\n",
"* длину (len), \n",
"* количество строк (lines)\n",
"* среднюю длину строки (mean_line_len)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"id": "C7G_weaWnMSg"
},
"outputs": [],
"source": [
"def mean_line_len(poem):\n",
" lines = [len(line.strip()) for line in poem.split('\\n') if len(line.strip())>0]\n",
" return sum(lines)/len(lines)\n",
"\n",
"\n",
"def describe_poems(text,return_df = False):\n",
" poems_list = [poem.strip() for poem in text.split(EOS_TOKEN) if len(poem.strip())>0]\n",
" df = pd.DataFrame(data=poems_list,columns=['poem'])\n",
" df['len'] = df.poem.map(len)\n",
" df['lines'] = df.poem.str.count('\\n')\n",
" df['mean_line_len'] = df.poem.map(mean_line_len)\n",
" if return_df:\n",
" return df\n",
" return df.describe()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 424
},
"id": "8t4QIKLgj8_y",
"outputId": "4ffe0325-70be-4a3f-9fd6-910be40e5dd3"
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>poem</th>\n",
" <th>len</th>\n",
" <th>lines</th>\n",
" <th>mean_line_len</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>Так и мне узнать случилось,\\nЧто за птица Купи...</td>\n",
" <td>2536</td>\n",
" <td>109</td>\n",
" <td>23.114286</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>Хочу воспеть, как дух нечистый Ада\\nОседлан бы...</td>\n",
" <td>5543</td>\n",
" <td>170</td>\n",
" <td>33.372671</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>Покаместь ночь еще не удалилась,\\nПокаместь св...</td>\n",
" <td>4279</td>\n",
" <td>131</td>\n",
" <td>33.451613</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>Ах, отчего мне дивная природа\\nКорреджио искус...</td>\n",
" <td>4435</td>\n",
" <td>131</td>\n",
" <td>33.364341</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>Арист! и ты в толпе служителей Парнасса!\\nТы х...</td>\n",
" <td>3893</td>\n",
" <td>106</td>\n",
" <td>38.642857</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>714</th>\n",
" <td>Чудный сон мне бог послал —\\n\\nС длинной белой...</td>\n",
" <td>860</td>\n",
" <td>38</td>\n",
" <td>22.833333</td>\n",
" </tr>\n",
" <tr>\n",
" <th>715</th>\n",
" <td>О нет, мне жизнь не надоела,\\nЯ жить люблю, я ...</td>\n",
" <td>196</td>\n",
" <td>7</td>\n",
" <td>23.625000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>716</th>\n",
" <td>\"Твой и мой, – говорит Лафонтен —\\nРасторгло у...</td>\n",
" <td>187</td>\n",
" <td>5</td>\n",
" <td>30.333333</td>\n",
" </tr>\n",
" <tr>\n",
" <th>717</th>\n",
" <td>Когда луны сияет лик двурогой\\nИ луч ее во мра...</td>\n",
" <td>269</td>\n",
" <td>7</td>\n",
" <td>32.750000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>718</th>\n",
" <td>Там, устарелый вождь! как ратник молодой,\\nИск...</td>\n",
" <td>256</td>\n",
" <td>5</td>\n",
" <td>41.833333</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>719 rows × 4 columns</p>\n",
"</div>"
],
"text/plain": [
" poem len lines \\\n",
"0 Так и мне узнать случилось,\\nЧто за птица Купи... 2536 109 \n",
"1 Хочу воспеть, как дух нечистый Ада\\nОседлан бы... 5543 170 \n",
"2 Покаместь ночь еще не удалилась,\\nПокаместь св... 4279 131 \n",
"3 Ах, отчего мне дивная природа\\nКорреджио искус... 4435 131 \n",
"4 Арист! и ты в толпе служителей Парнасса!\\nТы х... 3893 106 \n",
".. ... ... ... \n",
"714 Чудный сон мне бог послал —\\n\\nС длинной белой... 860 38 \n",
"715 О нет, мне жизнь не надоела,\\nЯ жить люблю, я ... 196 7 \n",
"716 \"Твой и мой, – говорит Лафонтен —\\nРасторгло у... 187 5 \n",
"717 Когда луны сияет лик двурогой\\nИ луч ее во мра... 269 7 \n",
"718 Там, устарелый вождь! как ратник молодой,\\nИск... 256 5 \n",
"\n",
" mean_line_len \n",
"0 23.114286 \n",
"1 33.372671 \n",
"2 33.451613 \n",
"3 33.364341 \n",
"4 38.642857 \n",
".. ... \n",
"714 22.833333 \n",
"715 23.625000 \n",
"716 30.333333 \n",
"717 32.750000 \n",
"718 41.833333 \n",
"\n",
"[719 rows x 4 columns]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"poem_df = describe_poems(text,return_df = True)\n",
"poem_df"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 300
},
"id": "TmCI6rv1f49T",
"outputId": "444fe362-1a5f-45b0-dc21-146c08e094cb"
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>len</th>\n",
" <th>lines</th>\n",
" <th>mean_line_len</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>count</th>\n",
" <td>719.000000</td>\n",
" <td>719.000000</td>\n",
" <td>719.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>mean</th>\n",
" <td>808.037552</td>\n",
" <td>29.464534</td>\n",
" <td>27.445404</td>\n",
" </tr>\n",
" <tr>\n",
" <th>std</th>\n",
" <td>1046.786862</td>\n",
" <td>39.244020</td>\n",
" <td>5.854564</td>\n",
" </tr>\n",
" <tr>\n",
" <th>min</th>\n",
" <td>74.000000</td>\n",
" <td>5.000000</td>\n",
" <td>8.250000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25%</th>\n",
" <td>280.500000</td>\n",
" <td>9.000000</td>\n",
" <td>24.125000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50%</th>\n",
" <td>453.000000</td>\n",
" <td>16.000000</td>\n",
" <td>25.758065</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75%</th>\n",
" <td>852.000000</td>\n",
" <td>33.000000</td>\n",
" <td>31.522727</td>\n",
" </tr>\n",
" <tr>\n",
" <th>max</th>\n",
" <td>8946.000000</td>\n",
" <td>437.000000</td>\n",
" <td>48.923077</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" len lines mean_line_len\n",
"count 719.000000 719.000000 719.000000\n",
"mean 808.037552 29.464534 27.445404\n",
"std 1046.786862 39.244020 5.854564\n",
"min 74.000000 5.000000 8.250000\n",
"25% 280.500000 9.000000 24.125000\n",
"50% 453.000000 16.000000 25.758065\n",
"75% 852.000000 33.000000 31.522727\n",
"max 8946.000000 437.000000 48.923077"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"poem_df.describe()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rNnrKn_lL-IJ"
},
"source": [
"## Подготовка датасетов"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3mOXOtj1FB1v"
},
"source": [
"Разбиваем данные на тренировочные, валидационные и тестовые"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"id": "MM5Rk7B8D1n-"
},
"outputs": [],
"source": [
"train_poems, test_poems = train_test_split(poem_df.poem.to_list(),test_size = 0.1,random_state = RANDOM_STATE)\n",
"train_poems, val_poems = train_test_split(train_poems,test_size = 0.1,random_state = RANDOM_STATE)\n",
"\n",
"train_poems = f'\\n\\n{EOS_TOKEN}\\n\\n'.join(train_poems)\n",
"val_poems = f'\\n\\n{EOS_TOKEN}\\n\\n'.join(val_poems)\n",
"test_poems = f'\\n\\n{EOS_TOKEN}\\n\\n'.join(test_poems)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6QfP2RCpqdCS"
},
"source": [
"Создаем словарь уникальных символов из текста. Не забываем добавить токен конца стиха."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "IlCgQBRVymwR",
"outputId": "a9769da4-3417-44e4-e491-cd1a09a51869"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"143 unique characters\n",
"['\\n', ' ', '!', '\"', \"'\", '(', ')', '*', ',', '-', '.', '/', ':', ';', '<', '>', '?', 'A', 'B', 'C', 'D', 'E', 'F', 'H', 'I', 'J', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'Z', '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'x', 'y', 'z', '\\xa0', '«', '»', 'à', 'â', 'ç', 'è', 'é', 'ê', 'ô', 'û', 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Э', 'Ю', 'Я', 'а', 'б', 'в', 'г', 'д', 'е', 'ж', 'з', 'и', 'й', 'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я', 'ё', '–', '—', '„', '…', '</s>']\n"
]
}
],
"source": [
"vocab = sorted(set(text))+[EOS_TOKEN]\n",
"print(f'{len(vocab)} unique characters')\n",
"print (vocab)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1s4f1q3iqY8f"
},
"source": [
"Для подачи на вход нейронной сети необходимо закодировать текст в виде числовой последовательности.\n",
"\n",
"Воспользуемся для этого слоем StringLookup \n",
"https://www.tensorflow.org/api_docs/python/tf/keras/layers/StringLookup"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"id": "6GMlCe3qzaL9"
},
"outputs": [],
"source": [
"ids_from_chars = tf.keras.layers.StringLookup(\n",
" vocabulary=list(vocab), mask_token=None)\n",
"chars_from_ids = tf.keras.layers.StringLookup(\n",
" vocabulary=ids_from_chars.get_vocabulary(), invert=True, mask_token=None)\n",
"\n",
"def text_from_ids(ids):\n",
" return tf.strings.reduce_join(chars_from_ids(ids), axis=-1).numpy().decode('utf-8')\n",
" \n",
"def ids_from_text(text):\n",
" return ids_from_chars(tf.strings.unicode_split(text, input_encoding='UTF-8'))\n"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Wd2m3mqkDjRj",
"outputId": "88ebef4b-6488-465e-d2f7-612e27efc0d2"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Корабль испанский тр\n",
"tf.Tensor(\n",
"[ 87 120 122 106 107 117 134 2 114 123 121 106 119 123 116 114 115 2\n",
" 124 122], shape=(20,), dtype=int64)\n",
"Корабль испанский тр\n"
]
}
],
"source": [
"# пример кодирования\n",
"ids = ids_from_text(train_poems[:20])\n",
"res_text = text_from_ids(ids)\n",
"print(train_poems[:20],ids,res_text,sep = '\\n')"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uzC2u022WHsa"
},
"source": [
"Кодируем данные и преобразуем их в Датасеты"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"id": "UopbsKi88tm5"
},
"outputs": [],
"source": [
"train_ids = ids_from_text(train_poems)\n",
"val_ids = ids_from_text(val_poems)\n",
"test_ids = ids_from_text(test_poems)\n",
"\n",
"train_ids_dataset = tf.data.Dataset.from_tensor_slices(train_ids)\n",
"val_ids_dataset = tf.data.Dataset.from_tensor_slices(val_ids)\n",
"test_ids_dataset = tf.data.Dataset.from_tensor_slices(test_ids)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-ZSYAcQV8OGP"
},
"source": [
"Весь текст разбивается на последовательности длины `seq_length`. По этим последовательностям будет предсказываться следующий символ.\n",
"\n",
"**Попробовать разные длины - среднюю длину строки, среднюю длину стиха**"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"id": "C-G2oaTxy6km"
},
"outputs": [],
"source": [
"seq_length = 100\n",
"examples_per_epoch = len(train_ids_dataset)//(seq_length+1)"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "BpdjRO2CzOfZ",
"outputId": "515651a7-765d-4bbf-9e90-8eb9a9380759"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Корабль испанский трехмачтовый,\n",
"Пристать в Голландию готовый:\n",
"На нем мерзавцев сотни три,\n",
"Две обезьян\n"
]
}
],
"source": [
"train_sequences = train_ids_dataset.batch(seq_length+1, drop_remainder=True)\n",
"val_sequences = val_ids_dataset.batch(seq_length+1, drop_remainder=True)\n",
"test_sequences = test_ids_dataset.batch(seq_length+1, drop_remainder=True)\n",
"\n",
"for seq in train_sequences.take(1):\n",
" print(text_from_ids(seq))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UbLcIPBj_mWZ"
},
"source": [
"Создаем датасет с input и target строками\n",
"\n",
"target сдвинута относительно input на один символ.\n"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"id": "9NGu-FkO_kYU"
},
"outputs": [],
"source": [
"def split_input_target(sequence):\n",
" input_text = sequence[:-1]\n",
" target_text = sequence[1:]\n",
" return input_text, target_text"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "WxbDTJTw5u_P",
"outputId": "f44e70c6-b600-4fb3-8073-ba8d774d8832"
},
"outputs": [
{
"data": {
"text/plain": [
"(['П', 'у', 'ш', 'к', 'и'], ['у', 'ш', 'к', 'и', 'н'])"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# пример\n",
"split_input_target(list(\"Пушкин\"))"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"id": "B9iKPXkw5xwa"
},
"outputs": [],
"source": [
"train_dataset = train_sequences.map(split_input_target)\n",
"val_dataset = val_sequences.map(split_input_target)\n",
"test_dataset = test_sequences.map(split_input_target)\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "GNbw-iR0ymwj",
"outputId": "888b397b-5370-4ae4-d2ba-98d54595ee72"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Input : Прими сей череп, Дельвиг, он\n",
"Принадлежит тебе по праву.\n",
"Тебе поведаю, барон,\n",
"Его готическую славу.\n",
"\n",
"\n",
"Target: рими сей череп, Дельвиг, он\n",
"Принадлежит тебе по праву.\n",
"Тебе поведаю, барон,\n",
"Его готическую славу.\n",
"\n",
"П\n"
]
}
],
"source": [
"for input_example, target_example in val_dataset.take(1):\n",
" print(\"Input :\", text_from_ids(input_example))\n",
" print(\"Target:\", text_from_ids(target_example))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MJdfPmdqzf-R"
},
"source": [
"Перемешиваем датасеты и разбиваем их на батчи для оптимизации обучения"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "p2pGotuNzf-S",
"outputId": "d9ae90cb-d904-4528-d0ed-eb11caeb43d3"
},
"outputs": [
{
"data": {
"text/plain": [
"<PrefetchDataset element_spec=(TensorSpec(shape=(64, 100), dtype=tf.int64, name=None), TensorSpec(shape=(64, 100), dtype=tf.int64, name=None))>"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Batch size\n",
"BATCH_SIZE = 64\n",
"\n",
"BUFFER_SIZE = 10000\n",
"\n",
"def prepare_dataset(dataset):\n",
" dataset = (\n",
" dataset\n",
" .shuffle(BUFFER_SIZE)\n",
" .batch(BATCH_SIZE, drop_remainder=True)\n",
" .prefetch(tf.data.experimental.AUTOTUNE))\n",
" return dataset \n",
"\n",
"train_dataset = prepare_dataset(train_dataset)\n",
"val_dataset = prepare_dataset(val_dataset)\n",
"test_dataset = prepare_dataset(test_dataset)\n",
"\n",
"train_dataset"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "r6oUuElIMgVx"
},
"source": [
"# Нейросеть"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "22uVCbSyPBjD"
},
"source": [
"## Построение модели"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "m8gPwEjRzf-Z"
},
"source": [
"Модель состоит из трех слоев\n",
"\n",
"* `tf.keras.layers.Embedding`: Входной слой. Кодирует каждый идентификатор символа в вектор размерностью `embedding_dim`; \n",
"* `tf.keras.layers.GRU`: Рекуррентный слой на ячейках GRU. Выходной вектор размерностью `units=rnn_units` **(Здесь нужно указать тип ячеек в соответствии с вариантом)**\n",
"* `tf.keras.layers.Dense`: Выходной полносвязный слой размерностью `vocab_size`, в который выводится вероятность каждого символа в словаре. \n"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"id": "zHT8cLh7EAsg"
},
"outputs": [],
"source": [
"# Длина словаря символов\n",
"vocab_size = len(vocab)\n",
"\n",
"# размерность Embedding'а\n",
"embedding_dim = 20 #@param{type:\"number\"}\n",
"\n",
"# Параметры RNN-слоя\n",
"rnn_units = 300 #@param {type:\"number\"}\n",
"dropout_p = 0.5"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"id": "wj8HQ2w8z4iO"
},
"outputs": [],
"source": [
"class MyModel(tf.keras.Model):\n",
" def __init__(self, vocab_size, embedding_dim, rnn_units):\n",
" super().__init__(self)\n",
" self.embedding = tf.keras.layers.Embedding(vocab_size, embedding_dim)\n",
" self.gru = tf.keras.layers.GRU(rnn_units,\n",
" dropout = dropout_p,\n",
" return_sequences=True,\n",
" return_state=True)\n",
" self.dense = tf.keras.layers.Dense(vocab_size)\n",
"\n",
" def call(self, inputs, states=None, return_state=False, training=False):\n",
" x = inputs\n",
" x = self.embedding(x, training=training)\n",
" \n",
" if states is None:\n",
" states = self.gru.get_initial_state(x)\n",
"\n",
" x, states = self.gru(x, initial_state=states, training=training)\n",
" x = self.dense(x, training=training)\n",
"\n",
" if return_state:\n",
" return x, states\n",
" else:\n",
" return x"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"id": "IX58Xj9z47Aw"
},
"outputs": [],
"source": [
"model = MyModel(\n",
" vocab_size=len(ids_from_chars.get_vocabulary()),\n",
" embedding_dim=embedding_dim,\n",
" rnn_units=rnn_units)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "RkA5upJIJ7W7"
},
"source": [
"Иллюстрация работы сети\n",
"\n",
"![A drawing of the data passing through the model](https://github.com/tensorflow/text/blob/master/docs/tutorials/images/text_generation_training.png?raw=1)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LdgaUC3tPHAy"
},
"source": [
"## Проверка необученой модели"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "C-_70kKAPrPU",
"outputId": "02de9cf7-29d5-4345-8e02-b8c940ca5c1a"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(64, 100, 144) # (batch_size, sequence_length, vocab_size)\n"
]
}
],
"source": [
"# посмотрим на один батч из датасета\n",
"for input_example_batch, target_example_batch in train_dataset.take(1):\n",
" example_batch_predictions = model(input_example_batch)\n",
" print(example_batch_predictions.shape, \"# (batch_size, sequence_length, vocab_size)\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "uwv0gEkURfx1"
},
"source": [
"prediction() предсказывает логиты вероятности каждого символа на следующей позиции. При этом, если мы будем выбирать символ с максимальной вероятностью, то из раза в раз модель нам будет выдавать один и тот же текст. \n",
"Чтобы этого избежать, нужно выбирать очередной индекс из распределения\n",
"`tf.random.categorical` - чем выше значение на выходном слое полносвязной сети, тем вероятнее, что данный символ будет выбран в качестве очередного. Однако, это не обязательно будет символ с максимальной вероятностью.\n"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "W6_G5P7W1TrE",
"outputId": "5fdc06a0-9be3-42b4-8054-454e997586ee"
},
"outputs": [
{
"data": {
"text/plain": [
"<tf.Tensor: shape=(144,), dtype=float32, numpy=\n",
"array([ 7.04948464e-03, -1.98002765e-03, 3.02454224e-03, -1.94069953e-03,\n",
" 9.08686779e-05, -1.26269402e-03, -3.95816471e-03, 5.32332528e-03,\n",
" -1.58743770e-03, 3.80896078e-03, 4.99830581e-03, -3.53646278e-03,\n",
" -3.50173237e-03, 1.03672473e-02, 4.72654402e-03, 4.48969286e-03,\n",
" -7.25119235e-03, 4.08414472e-03, -6.61874050e-03, -4.53183288e-03,\n",
" 1.36306381e-03, -8.01230408e-03, 4.31668153e-03, 4.37820982e-03,\n",
" -4.18623677e-03, -3.56584322e-03, 2.71524256e-03, -1.40747754e-04,\n",
" -2.54452089e-03, -6.52383547e-03, 9.91060492e-03, -5.61330421e-03,\n",
" -8.06922559e-04, -1.45252305e-03, -1.25302584e-04, 2.54331576e-03,\n",
" -6.65406231e-03, -3.14406748e-03, -1.42855803e-03, 4.38266993e-03,\n",
" 4.06480394e-05, 3.58506199e-03, -1.31492107e-03, -3.76690924e-03,\n",
" -4.61246073e-03, 2.09019426e-03, -6.05216657e-04, 4.94315475e-03,\n",
" -7.38915848e-03, -2.97222170e-04, 1.23252645e-02, -3.27007566e-03,\n",
" 7.75653915e-03, -2.52670376e-03, -7.69718783e-04, -2.05170992e-03,\n",
" 1.18606293e-03, 6.22191140e-03, -4.58527543e-03, 4.21849283e-04,\n",
" 7.42580276e-03, 8.36860761e-03, 4.63361526e-03, 2.71662371e-03,\n",
" 2.59269890e-03, -2.30735121e-03, 6.44756807e-03, -2.63488246e-03,\n",
" -1.40141640e-02, 1.11143891e-04, -5.53287193e-03, -6.43183826e-04,\n",
" -1.15646292e-02, -1.41452125e-04, 1.50612544e-03, 2.67576054e-03,\n",
" -3.87344277e-03, -2.01095594e-03, 3.92267248e-03, 2.47437716e-03,\n",
" 7.02369632e-03, 1.57978013e-03, -6.72074873e-03, 5.20235533e-03,\n",
" -7.60141760e-03, -4.12424142e-03, -1.24696689e-03, -5.03823441e-03,\n",
" 2.94092577e-03, 2.38715275e-03, -1.54204969e-03, -2.16306839e-03,\n",
" -2.10713898e-03, -3.79565591e-03, -5.14758425e-03, -3.90997529e-03,\n",
" -4.30819113e-03, -7.28532323e-04, -2.43837340e-03, 2.76774517e-03,\n",
" -1.66824413e-03, -2.95873499e-03, 5.87470829e-04, -7.67468195e-03,\n",
" -2.17538618e-04, -8.66387784e-03, -4.71618492e-03, -1.63393712e-03,\n",
" -4.77423018e-04, -1.49550312e-03, -3.46688367e-03, 1.21447584e-03,\n",
" 1.32047385e-03, 1.50095311e-03, 1.62522192e-03, -3.79677466e-03,\n",
" 1.57164666e-03, -4.10819892e-03, -3.00779007e-03, 2.36973306e-03,\n",
" -3.77465365e-03, -5.34315477e-05, 1.84188155e-03, 3.53988446e-03,\n",
" 6.51812530e-04, -7.78108952e-05, 4.54718899e-03, 1.03609345e-03,\n",
" -2.62774178e-03, -9.84960934e-05, -6.15748437e-03, 1.74808409e-03,\n",
" -6.90540811e-03, 4.51742392e-03, 2.42682174e-03, -9.07061435e-03,\n",
" -4.85235034e-03, 7.50885578e-04, 6.84963632e-03, -3.08787916e-04,\n",
" 2.59267096e-03, 4.30960301e-03, 3.37237539e-03, 3.88880167e-03],\n",
" dtype=float32)>"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"example_batch_predictions[0][0]\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "0yJ5Je4J1XRb"
},
"source": [
"![image.png](data:image/png;base64,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)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UuAT_ymD15U7"
},
"source": [
"На картинке отмечены наиболее вероятные символы."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"id": "4V4MfFg0RQJg"
},
"outputs": [],
"source": [
"sampled_indices = tf.random.categorical(example_batch_predictions[0], num_samples=1)\n",
"sampled_indices = tf.squeeze(sampled_indices, axis=-1).numpy()"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "YqFMUQc_UFgM",
"outputId": "1842194b-d7d7-4702-bca5-6b03f04b9432"
},
"outputs": [
{
"data": {
"text/plain": [
"array([103, 2, 125, 127, 46, 128, 85, 84, 14, 37, 55, 7, 129,\n",
" 123, 72, 38, 138, 88, 116, 125, 142, 109, 110, 131, 21, 29,\n",
" 15, 99, 118, 48, 15, 143, 106, 139, 28, 115, 119, 8, 41,\n",
" 55, 138, 68, 130, 133, 135, 4, 114, 10, 62, 130, 120, 47,\n",
" 119, 16, 87, 71, 32, 111, 121, 85, 13, 87, 87, 75, 25,\n",
" 91, 41, 83, 51, 106, 100, 133, 3, 9, 37, 36, 103, 61,\n",
" 2, 79, 136, 56, 99, 101, 20, 143, 70, 117, 60, 43, 6,\n",
" 49, 51, 15, 85, 115, 113, 138, 23, 89], dtype=int64)"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sampled_indices"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "xWcFwPwLSo05",
"outputId": "bed36421-88f9-429f-a9cd-099717127029"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Input:\n",
" же прошли. Их мненья, толки, страсти\n",
"Забыты для других. Смотри: вокруг тебя\n",
"Всё новое кипит, былое и\n",
"\n",
"Next Char Predictions:\n",
" Э ухfцИЗ;Vo)чсèWёЛку…гдщDN<Цмh<</s>а–Mйн*aoё»шыэ\"и-vшоgн>КçQепИ:ККôIОaЖkаЧы!,VUЭu ВюpЦШC</s>âлtc(ik<ИйзёFМ\n"
]
}
],
"source": [
"print(\"Input:\\n\", text_from_ids(input_example_batch[0]))\n",
"print()\n",
"print(\"Next Char Predictions:\\n\", text_from_ids(sampled_indices))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LJL0Q0YPY6Ee"
},
"source": [
"## Обучение модели"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "YCbHQHiaa4Ic"
},
"source": [
"\n",
"Можно представить задачу как задачу классификации - по предыдущему состоянию RNN и входу в данный момент времени предсказать класс (очередной символ). "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "trpqTWyvk0nr"
},
"source": [
"### Настройка оптимизатора и функции потерь"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "UAjbjY03eiQ4"
},
"source": [
"В этом случае работает стандартная функция потерь `tf.keras.losses.sparse_categorical_crossentropy`- кроссэнтропия, которая равна минус логарифму предсказанной вероятности для верного класса.\n",
"\n",
"Поскольку модель возвращает логиты, вам необходимо установить флаг `from_logits`."
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"id": "ZOeWdgxNFDXq"
},
"outputs": [],
"source": [
"loss = tf.losses.SparseCategoricalCrossentropy(from_logits=True)"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "4HrXTACTdzY-",
"outputId": "f0dbf6f2-738e-48f8-df7c-0bbf60fc17e4"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Prediction shape: (64, 100, 144) # (batch_size, sequence_length, vocab_size)\n",
"Mean loss: tf.Tensor(4.970122, shape=(), dtype=float32)\n"
]
}
],
"source": [
"example_batch_mean_loss = loss(target_example_batch, example_batch_predictions)\n",
"print(\"Prediction shape: \", example_batch_predictions.shape, \" # (batch_size, sequence_length, vocab_size)\")\n",
"print(\"Mean loss: \", example_batch_mean_loss)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vkvUIneTFiow"
},
"source": [
"Необученная модель не может делать адекватные предсказания. Ее перплексия («коэффициент неопределённости») приблизительно равна размеру словаря. Это говорит о полной неопределенности модели при генерации текста.\n",
"\n",
"Перплексия = exp(кроссэнтропия)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "MAJfS5YoFiHf",
"outputId": "0588a9b2-8598-458f-db1d-6923e6a50502"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"perplexity: 144.04443\n"
]
}
],
"source": [
"print('perplexity: ',np.exp(example_batch_mean_loss))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "jeOXriLcymww"
},
"source": [
"Настраиваем обучение, используя метод `tf.keras.Model.compile`. Используйте `tf.keras.optimizers.Adam` с аргументами по умолчанию и функцией потерь."
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"id": "DDl1_Een6rL0"
},
"outputs": [],
"source": [
"model.compile(optimizer='adam', loss=loss)"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "vPGmAAXmVLGC",
"outputId": "1399a58c-85ff-430d-f67f-942942dec071"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model: \"my_model\"\n",
"_________________________________________________________________\n",
" Layer (type) Output Shape Param # \n",
"=================================================================\n",
" embedding (Embedding) multiple 2880 \n",
" \n",
" gru (GRU) multiple 289800 \n",
" \n",
" dense (Dense) multiple 43344 \n",
" \n",
"=================================================================\n",
"Total params: 336,024\n",
"Trainable params: 336,024\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
]
}
],
"source": [
"model.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "C6XBUUavgF56"
},
"source": [
"Используем `tf.keras.callbacks.ModelCheckpoint`, чтобы убедиться, что контрольные точки сохраняются во время обучения:"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"id": "W6fWTriUZP-n"
},
"outputs": [],
"source": [
"# Directory where the checkpoints will be saved\n",
"checkpoint_dir = './training_checkpoints'\n",
"# Name of the checkpoint files\n",
"checkpoint_prefix = os.path.join(checkpoint_dir, \"ckpt_{epoch}\")\n",
"\n",
"checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(\n",
" filepath=checkpoint_prefix,\n",
" monitor=\"val_loss\",\n",
" save_weights_only=True,\n",
" save_best_only=True)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3Ky3F_BhgkTW"
},
"source": [
"### Обучение!"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"id": "7yGBE2zxMMHs"
},
"outputs": [],
"source": [
"EPOCHS = 5"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "UK-hmKjYVoll",
"outputId": "4403459e-c93d-4361-b6b4-d4f4a29797e5"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"72/72 [==============================] - 24s 301ms/step - loss: 3.7387 - val_loss: 3.4320\n",
"Epoch 2/5\n",
"72/72 [==============================] - 22s 294ms/step - loss: 3.2194 - val_loss: 2.8863\n",
"Epoch 3/5\n",
"72/72 [==============================] - 22s 292ms/step - loss: 2.8698 - val_loss: 2.7059\n",
"Epoch 4/5\n",
"72/72 [==============================] - 23s 309ms/step - loss: 2.7643 - val_loss: 2.6365\n",
"Epoch 5/5\n",
"72/72 [==============================] - 24s 320ms/step - loss: 2.6941 - val_loss: 2.5800\n"
]
}
],
"source": [
"history = model.fit(train_dataset, validation_data = val_dataset, epochs=EPOCHS, callbacks=[checkpoint_callback])"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "UejMtXPmH-U0",
"outputId": "ec06daed-25a1-4ae3-9f9a-cd130e04c216"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9/9 [==============================] - 1s 101ms/step - loss: 2.5769\n",
"eval loss: 2.576871871948242\n",
"perplexity 13.155920322524834\n"
]
}
],
"source": [
"eval_loss = model.evaluate(test_dataset)\n",
"print('eval loss:',eval_loss)\n",
"print('perplexity',np.exp(eval_loss))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kKkD5M6eoSiN"
},
"source": [
"## Генерация текста"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oIdQ8c8NvMzV"
},
"source": [
"Самый простой способ сгенерировать текст с помощью этой модели — запустить ее в цикле и отслеживать внутреннее состояние модели по мере ее выполнения.\n",
"\n",
"![To generate text the model's output is fed back to the input](https://github.com/tensorflow/text/blob/master/docs/tutorials/images/text_generation_sampling.png?raw=1)\n",
"\n",
"Каждый раз, когда вы вызываете модель, вы передаете некоторый текст и внутреннее состояние. Модель возвращает прогноз для следующего символа и его нового состояния. Передайте предсказание и состояние обратно, чтобы продолжить создание текста.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "DjGz1tDkzf-u"
},
"source": [
"Создаем модель реализующую один шаг предсказания:"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"id": "iSBU1tHmlUSs"
},
"outputs": [],
"source": [
"class OneStep(tf.keras.Model):\n",
" def __init__(self, model, chars_from_ids, ids_from_chars, temperature=1.0):\n",
" super().__init__()\n",
" self.temperature = temperature\n",
" self.model = model\n",
" self.chars_from_ids = chars_from_ids\n",
" self.ids_from_chars = ids_from_chars\n",
"\n",
" # Create a mask to prevent \"[UNK]\" from being generated.\n",
" skip_ids = self.ids_from_chars(['[UNK]'])[:, None]\n",
" sparse_mask = tf.SparseTensor(\n",
" # Put a -inf at each bad index.\n",
" values=[-float('inf')]*len(skip_ids),\n",
" indices=skip_ids,\n",
" # Match the shape to the vocabulary\n",
" dense_shape=[len(ids_from_chars.get_vocabulary())])\n",
" self.prediction_mask = tf.sparse.to_dense(sparse_mask)\n",
"\n",
" \n",
" # Этот фрагмент целиком написан с использованием Tensorflow, поэтому его можно выполнять \n",
" # не с помощью интерпретатора языка Python, а через граф операций. Это будет значительно быстрее. \n",
" # Для этого воспользуемся декоратором @tf.function \n",
" @tf.function \n",
" def generate_one_step(self, inputs, states=None,temperature=1.0):\n",
" # Convert strings to token IDs.\n",
" input_chars = tf.strings.unicode_split(inputs, 'UTF-8')\n",
" input_ids = self.ids_from_chars(input_chars).to_tensor()\n",
"\n",
" # Run the model.\n",
" # predicted_logits.shape is [batch, char, next_char_logits]\n",
" predicted_logits, states = self.model(inputs=input_ids, states=states,\n",
" return_state=True)\n",
" # Only use the last prediction.\n",
" predicted_logits = predicted_logits[:, -1, :]\n",
" predicted_logits = predicted_logits/temperature\n",
" # Apply the prediction mask: prevent \"[UNK]\" from being generated.\n",
" predicted_logits = predicted_logits + self.prediction_mask\n",
"\n",
" # Sample the output logits to generate token IDs.\n",
" predicted_ids = tf.random.categorical(predicted_logits, num_samples=1)\n",
" predicted_ids = tf.squeeze(predicted_ids, axis=-1)\n",
"\n",
" # Convert from token ids to characters\n",
" predicted_chars = self.chars_from_ids(predicted_ids)\n",
"\n",
"\n",
" # Return the characters and model state.\n",
" return predicted_chars, states"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"id": "fqMOuDutnOxK"
},
"outputs": [],
"source": [
"one_step_model = OneStep(model, chars_from_ids, ids_from_chars)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "p9yDoa0G3IgQ"
},
"source": [
"Изменяя температуру можно регулировать вариативность текста"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "ST7PSyk9t1mT",
"outputId": "ed0dfecc-3d31-4bfe-efeb-d2315044ef06"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"uКочаму,\n",
"Лыт\n",
"Нума Гве!\n",
"àvо етекы ва;\n",
"Хо> вы,\n",
"Муметы,.\n",
"Воцу:\n",
"ОтекаЕдраэмь эзоспосанах…Я кы.\n",
") маа Почи защоючеты>\n",
"Алаций поши)\"Пры – /й пий лазой\n",
"Еже?\n",
"И,\n",
"В, à*</s>\n",
"logJ\"nДаогей piКо '<vЯйвы\n",
"Срый\n",
"За Sрыша, Жузогой!\n",
"jу,\n",
"yВлаж:.\n",
"jPsдотети;\n",
"Улум!\n",
"Яро\n",
"Не жь вый…\n",
"На…нуше нухотоло!\n",
"érфосчатей пойхоскох,\n",
"ûzСда –\n",
"âШаналемоны узени потя,\n",
"„Я OaéТый с говощащаранымозужмелы,\n",
"Титой !\n",
"И Жычима пруМепобай>\n",
"Дя цый,;\n",
"Зази:\n",
"Унумыйй поль ь,\n",
"Тост,,,\n",
"Дежы!Шоны\n",
"H-му,\n",
"iБачуй,,;цо,\n",
"Тахрей\n",
"Ты а;\n",
"Памогой елыны…\n",
"Жебы\n",
"Ве яны!\n",
"Экычигруй,\n",
"И вьчам ре кабощалуй, ль наша водух, ё ко,\n",
"Чячу бемий>\n",
"Елетанех гружара, eалодищи:\n",
"И,\n",
"Гро вишемороцемапа\"oОмицы\n",
"upЛицль: Преща, Оды iH бочавоча!, Ценобый ни\n",
"Вныла,\n",
"Чу:.\n",
"Ввуй,\n",
"eРаДобе по!\n",
"Qтый,\n",
"Чки fХралошумо:\n",
"na-Койкаца –\n",
"Ай\n",
"Мо,\n",
"i)цыденатедубодех выйха\n",
"Полынене на бы.\n",
"Заму рыхасла cИмино Одорафута уга гоЮй вожве,\n",
"ГчаCКазко.\n",
"Мотя выйхоруnАчлатоный\n",
"Рабойх удапи,\n",
"Ты уТашь,\n",
"Обымаекоги вайзоты зой кишаметумилетелы\n",
"Я, —\n",
"yJи, солыFлы!éuХуZетце, ё\n",
"oПробемнанетече ей.\n",
"Ри,\n",
"Шоный.\n",
"По!\n",
"Ностыгу!\n",
"Hv\n",
"________________________________________________________________________________\n",
"\n",
"Run time: 1.620434284210205\n"
]
}
],
"source": [
"T = 0.5 #@param {type:\"slider\", min:0, max:2, step:0.1}\n",
"N = 1000\n",
"\n",
"start = time.time()\n",
"states = None\n",
"next_char = tf.constant(['\\n'])\n",
"result = [next_char]\n",
"\n",
"for n in range(N):\n",
" next_char, states = one_step_model.generate_one_step(next_char, states=states,temperature=T)\n",
" result.append(next_char)\n",
"\n",
"result = tf.strings.join(result)\n",
"end = time.time()\n",
"\n",
"result_text = result[0].numpy().decode('utf-8')\n",
"print(result_text)\n",
"print('_'*80)\n",
"print('\\nRun time:', end - start)"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 300
},
"id": "VCwWY9xM6KCB",
"outputId": "e709c661-8bbe-4abf-e329-db9af7e6eb55"
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>len</th>\n",
" <th>lines</th>\n",
" <th>mean_line_len</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>count</th>\n",
" <td>2.000000</td>\n",
" <td>2.000000</td>\n",
" <td>2.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>mean</th>\n",
" <td>499.000000</td>\n",
" <td>35.500000</td>\n",
" <td>12.123718</td>\n",
" </tr>\n",
" <tr>\n",
" <th>std</th>\n",
" <td>482.246825</td>\n",
" <td>33.234019</td>\n",
" <td>1.262820</td>\n",
" </tr>\n",
" <tr>\n",
" <th>min</th>\n",
" <td>158.000000</td>\n",
" <td>12.000000</td>\n",
" <td>11.230769</td>\n",
" </tr>\n",
" <tr>\n",
" <th>25%</th>\n",
" <td>328.500000</td>\n",
" <td>23.750000</td>\n",
" <td>11.677244</td>\n",
" </tr>\n",
" <tr>\n",
" <th>50%</th>\n",
" <td>499.000000</td>\n",
" <td>35.500000</td>\n",
" <td>12.123718</td>\n",
" </tr>\n",
" <tr>\n",
" <th>75%</th>\n",
" <td>669.500000</td>\n",
" <td>47.250000</td>\n",
" <td>12.570192</td>\n",
" </tr>\n",
" <tr>\n",
" <th>max</th>\n",
" <td>840.000000</td>\n",
" <td>59.000000</td>\n",
" <td>13.016667</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" len lines mean_line_len\n",
"count 2.000000 2.000000 2.000000\n",
"mean 499.000000 35.500000 12.123718\n",
"std 482.246825 33.234019 1.262820\n",
"min 158.000000 12.000000 11.230769\n",
"25% 328.500000 23.750000 11.677244\n",
"50% 499.000000 35.500000 12.123718\n",
"75% 669.500000 47.250000 12.570192\n",
"max 840.000000 59.000000 13.016667"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"describe_poems(result_text)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "db7UJQr9ILfW"
},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "22rnSwqqICn2"
},
"source": [
"По мотивам https://colab.research.google.com/github/tensorflow/text/blob/master/docs/tutorials/text_generation.ipynb"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.9.13"
}
},
"nbformat": 4,
"nbformat_minor": 1
}