{ "cells": [ { "cell_type": "markdown", "id": "6c8f222f", "metadata": {}, "source": [ "## [Description](#Description_)\n", "## [Todo](#Todo_)\n", "## [Research](#Research_)\n", "## [Setup](#Setup_)\n", "### - [Requirements](#Requirements_)\n", "### - [Imports](#Imports_)\n", "### - [Globals](#Globals_)\n", "### - [Utils](#Utils_)\n", "## [Data](#Data_)\n", "### - [Annotation structure](#Annotation_structure_)\n", "### - [Data exploration](#Data_exploration_)\n", "### - [Data splits](#Data_splits_)\n", "### - [Expected model output format](#Expected_model_output_format_)\n", "### - [Metrics](#Metrics_)\n", "### - [Dataset](#Dataset_)\n", "## [Model](#Model_)\n", "### - [Add task specific tokens](#Add_task_specific_tokens_)\n", "### - [Add dataset specific tokens](#Add_dataset_specific_tokens_)\n", "### - [Predicting](#Predicting_)\n", "### - [Dataloader](#Dataloader_)\n", "### - [Lightning module](#Lightning_module_)\n", "### - [Callbacks](#Callbacks_)\n", "## [Training](#Training_)\n", "## [Results](#Results_)\n", "### - [Gradio interface](#Gradio_interface_)" ] }, { "cell_type": "markdown", "id": "3b03d3cc", "metadata": {}, "source": [ "## Description " ] }, { "cell_type": "markdown", "id": "64776daa", "metadata": {}, "source": [ "Trying my hand at this kaggle challenge:\n", "\n", "https://www.kaggle.com/competitions/benetech-making-graphs-accessible" ] }, { "cell_type": "markdown", "id": "82bdf04d", "metadata": {}, "source": [ "## Todo " ] }, { "cell_type": "markdown", "id": "965d48df", "metadata": {}, "source": [ "- Add wandb logs: metrics, images, text\n", "- Create separate training script\n", "- Train\n", "- Get familiar with transformers library: main classes, how to work with config\n", "- Do more research, check out notebooks in kaggle\n", "- Check out dataset https://chartinfo.github.io/toolsanddata.html\n", "- Try segmentation -> classification -> parsing pipeline\n", "- Make predicting faster, check out https://pytorch.org/serve/" ] }, { "cell_type": "markdown", "id": "49fece33", "metadata": {}, "source": [ "## Research " ] }, { "cell_type": "markdown", "id": "0940fdc8", "metadata": {}, "source": [ "[Donut](https://arxiv.org/pdf/2111.15664.pdf) - document understanding transformer without the intermediate optical character recognition step.\n", "[Example notebook one](https://github.com/NielsRogge/Transformers-Tutorials/blob/master/Donut/CORD/Fine_tune_Donut_on_a_custom_dataset_(CORD)_with_PyTorch_Lightning.ipynb),\n", "[example notebook two](https://www.kaggle.com/code/nbroad/donut-train-benetech)." ] }, { "cell_type": "markdown", "id": "d9064993", "metadata": {}, "source": [ "## Setup " ] }, { "cell_type": "markdown", "id": "47af4f6b", "metadata": {}, "source": [ "### Imports " ] }, { "cell_type": "code", "execution_count": 2, "id": "8ccdc3b0", "metadata": { "ExecuteTime": { "end_time": "2023-04-27T13:03:49.524541Z", "start_time": "2023-04-27T13:03:29.372899Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 2;\n", " var nbb_unformatted_code = \"%load_ext nb_black\\n%matplotlib inline\\n\\n\\nimport collections\\nimport dataclasses\\nimport datasets\\nimport einops\\nimport enum\\nimport gradio\\nimport glob\\nimport IPython\\nimport imageio\\nimport json\\nimport functools\\nimport matplotlib.animation\\nimport matplotlib.pyplot as plt\\nimport numpy as np\\nimport os\\nimport PIL\\nimport pandas as pd\\nimport pickle\\nimport pprint\\nimport pytorch_lightning as pl\\nimport rapidfuzz\\nimport re\\nimport reprlib\\nimport sklearn.metrics\\nimport torch\\nimport torchvision\\nimport tqdm.autonotebook\\nimport transformers\\nimport types\\nfrom typing import Callable, Literal\\nimport wandb\";\n", " var nbb_formatted_code = \"%load_ext nb_black\\n%matplotlib inline\\n\\n\\nimport collections\\nimport dataclasses\\nimport datasets\\nimport einops\\nimport enum\\nimport gradio\\nimport glob\\nimport IPython\\nimport imageio\\nimport json\\nimport functools\\nimport matplotlib.animation\\nimport matplotlib.pyplot as plt\\nimport numpy as np\\nimport os\\nimport PIL\\nimport pandas as pd\\nimport pickle\\nimport pprint\\nimport pytorch_lightning as pl\\nimport rapidfuzz\\nimport re\\nimport reprlib\\nimport sklearn.metrics\\nimport torch\\nimport torchvision\\nimport tqdm.autonotebook\\nimport transformers\\nimport types\\nfrom typing import Callable, Literal\\nimport wandb\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%load_ext nb_black\n", "%matplotlib inline\n", "\n", "\n", "import collections\n", "import dataclasses\n", "import datasets\n", "import einops\n", "import enum\n", "import gradio\n", "import glob\n", "import IPython\n", "import imageio\n", "import json\n", "import functools\n", "import matplotlib.animation\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import os\n", "import PIL\n", "import pandas as pd\n", "import pickle\n", "import pprint\n", "import pytorch_lightning as pl\n", "import rapidfuzz\n", "import re\n", "import reprlib\n", "import sklearn.metrics\n", "import torch\n", "import torchvision\n", "import tqdm.autonotebook\n", "import transformers\n", "import types\n", "from typing import Callable, Literal\n", "import wandb" ] }, { "cell_type": "markdown", "id": "2b711a53", "metadata": {}, "source": [ "### Requirements" ] }, { "cell_type": "code", "execution_count": null, "id": "ad8e0f9f", "metadata": {}, "outputs": [], "source": [ "def pip_freeze_requirements():\n", " !pip freeze > requirements.txt\n", " \n", "#pip_freeze_requirements()" ] }, { "cell_type": "markdown", "id": "77b39d61", "metadata": {}, "source": [ "### Globals " ] }, { "cell_type": "code", "execution_count": 2, "id": "db1722f2", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.754713Z", "start_time": "2023-04-18T15:47:30.740063Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 2;\n", " var nbb_unformatted_code = \"COMPETITION = \\\"benetech-making-graphs-accessible\\\"\\nDEBUG: bool = False\\nDATA = types.SimpleNamespace()\\nTOKEN = types.SimpleNamespace()\\nCONFIG = types.SimpleNamespace()\\nMODEL = types.SimpleNamespace()\\nTRAINING = types.SimpleNamespace()\";\n", " var nbb_formatted_code = \"COMPETITION = \\\"benetech-making-graphs-accessible\\\"\\nDEBUG: bool = False\\nDATA = types.SimpleNamespace()\\nTOKEN = types.SimpleNamespace()\\nCONFIG = types.SimpleNamespace()\\nMODEL = types.SimpleNamespace()\\nTRAINING = types.SimpleNamespace()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "COMPETITION = \"benetech-making-graphs-accessible\"\n", "DEBUG: bool = False\n", "DATA = types.SimpleNamespace()\n", "TOKEN = types.SimpleNamespace()\n", "CONFIG = types.SimpleNamespace()\n", "MODEL = types.SimpleNamespace()\n", "TRAINING = types.SimpleNamespace()" ] }, { "cell_type": "markdown", "id": "52ea33de", "metadata": {}, "source": [ "### Markdown" ] }, { "cell_type": "code", "execution_count": 3, "id": "c2aefef2", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.801463Z", "start_time": "2023-04-18T15:47:30.758086Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 3;\n", " var nbb_unformatted_code = \"def make_new_markdown_section_with_link(section, header=\\\"##\\\", do_print=True):\\n section_id = section.replace(\\\" \\\", \\\"_\\\") + \\\"_\\\"\\n section_link = f\\\"{header} [{section}](#{section_id})\\\"\\n section_header = f\\\"{header} {section} \\\"\\n if do_print:\\n print(section_link + \\\"\\\\n\\\" + section_header)\\n return section_link, section_header\\n\\n\\ndef make_several_sections(\\n section_names=(\\n \\\"Description\\\",\\n \\\"Imports\\\",\\n \\\"Globals\\\",\\n \\\"Setup\\\",\\n \\\"Data\\\",\\n \\\"Data exploration\\\",\\n \\\"Model\\\",\\n \\\"Training\\\",\\n \\\"Results\\\",\\n )\\n):\\n links, headers = zip(\\n *[\\n make_new_markdown_section_with_link(sn, do_print=False)\\n for sn in section_names\\n ]\\n )\\n print(\\\"\\\\n\\\".join(links + (\\\"\\\",) + headers))\\n\\n\\ndef print_python_libraries_requirements():\\n requirements = !pip freeze\\n requirements = \\\"\\\\n\\\".join(requirements)\\n requirements = (\\n f\\\"
\\\\n\\\"\\n f\\\"\\\\t Python requirements \\\\n\\\\n\\\"\\n f\\\"```\\\\n\\\"\\n f\\\"{requirements}\\\\n\\\"\\n f\\\"```\\\\n\\\"\\n f\\\"
\\\"\\n )\\n print(requirements)\";\n", " var nbb_formatted_code = \"def make_new_markdown_section_with_link(section, header=\\\"##\\\", do_print=True):\\n section_id = section.replace(\\\" \\\", \\\"_\\\") + \\\"_\\\"\\n section_link = f\\\"{header} [{section}](#{section_id})\\\"\\n section_header = f\\\"{header} {section} \\\"\\n if do_print:\\n print(section_link + \\\"\\\\n\\\" + section_header)\\n return section_link, section_header\\n\\n\\ndef make_several_sections(\\n section_names=(\\n \\\"Description\\\",\\n \\\"Imports\\\",\\n \\\"Globals\\\",\\n \\\"Setup\\\",\\n \\\"Data\\\",\\n \\\"Data exploration\\\",\\n \\\"Model\\\",\\n \\\"Training\\\",\\n \\\"Results\\\",\\n )\\n):\\n links, headers = zip(\\n *[\\n make_new_markdown_section_with_link(sn, do_print=False)\\n for sn in section_names\\n ]\\n )\\n print(\\\"\\\\n\\\".join(links + (\\\"\\\",) + headers))\\n\\n\\ndef print_python_libraries_requirements():\\n requirements = !pip freeze\\n requirements = \\\"\\\\n\\\".join(requirements)\\n requirements = (\\n f\\\"
\\\\n\\\"\\n f\\\"\\\\t Python requirements \\\\n\\\\n\\\"\\n f\\\"```\\\\n\\\"\\n f\\\"{requirements}\\\\n\\\"\\n f\\\"```\\\\n\\\"\\n f\\\"
\\\"\\n )\\n print(requirements)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def make_new_markdown_section_with_link(section, header=\"##\", do_print=True):\n", " section_id = section.replace(\" \", \"_\") + \"_\"\n", " section_link = f\"{header} [{section}](#{section_id})\"\n", " section_header = f\"{header} {section} \"\n", " if do_print:\n", " print(section_link + \"\\n\" + section_header)\n", " return section_link, section_header\n", "\n", "\n", "def make_several_sections(\n", " section_names=(\n", " \"Description\",\n", " \"Imports\",\n", " \"Globals\",\n", " \"Setup\",\n", " \"Data\",\n", " \"Data exploration\",\n", " \"Model\",\n", " \"Training\",\n", " \"Results\",\n", " )\n", "):\n", " links, headers = zip(\n", " *[\n", " make_new_markdown_section_with_link(sn, do_print=False)\n", " for sn in section_names\n", " ]\n", " )\n", " print(\"\\n\".join(links + (\"\",) + headers))\n" ] }, { "cell_type": "markdown", "id": "bf4ed747", "metadata": {}, "source": [ "### Terminal" ] }, { "cell_type": "code", "execution_count": 4, "id": "1e7c72a6", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.847062Z", "start_time": "2023-04-18T15:47:30.804015Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 4;\n", " var nbb_unformatted_code = \"def mkdir(path, error_if_exists=False):\\n !mkdir {\\\"-p\\\" if not error_if_exists else \\\"\\\"} {path}\\n\\n\\ndef unzip(zip_path, save_path=None, delete_zip=False):\\n !unzip {zip_path} {\\\"-d \\\"+ save_path if save_path else \\\"\\\"}\\n if delete_zip:\\n for path in glob.glob(zip_path):\\n if path.endswith(\\\".zip\\\"):\\n !trash {path}\\n\\n\\ndef unzip_to_data_and_delete():\\n unzip(\\\"data/*\\\", \\\"data\\\", delete_zip=True)\";\n", " var nbb_formatted_code = \"def mkdir(path, error_if_exists=False):\\n !mkdir {\\\"-p\\\" if not error_if_exists else \\\"\\\"} {path}\\n\\n\\ndef unzip(zip_path, save_path=None, delete_zip=False):\\n !unzip {zip_path} {\\\"-d \\\"+ save_path if save_path else \\\"\\\"}\\n if delete_zip:\\n for path in glob.glob(zip_path):\\n if path.endswith(\\\".zip\\\"):\\n !trash {path}\\n\\n\\ndef unzip_to_data_and_delete():\\n unzip(\\\"data/*\\\", \\\"data\\\", delete_zip=True)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def mkdir(path, error_if_exists=False):\n", " !mkdir {\"-p\" if not error_if_exists else \"\"} {path}\n", "\n", "\n", "def unzip(zip_path, save_path=None, delete_zip=False):\n", " !unzip {zip_path} {\"-d \"+ save_path if save_path else \"\"}\n", " if delete_zip:\n", " for path in glob.glob(zip_path):\n", " if path.endswith(\".zip\"):\n", " !trash {path}\n", "\n", "\n", "def unzip_to_data_and_delete():\n", " unzip(\"data/*\", \"data\", delete_zip=True)" ] }, { "cell_type": "markdown", "id": "0fb17c9d", "metadata": {}, "source": [ "### Kaggle" ] }, { "cell_type": "code", "execution_count": 5, "id": "aae473b0", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.868185Z", "start_time": "2023-04-18T15:47:30.851313Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 5;\n", " var nbb_unformatted_code = \"def kaggle_competitions_search(search_term):\\n !kaggle competitions list -s {search_term}\\n\\n\\ndef kaggle_competitions_files(competition):\\n !kaggle competitions files {competition}\\n\\n\\ndef kaggle_competitions_download(competition, save_path=\\\"data\\\", filename=None):\\n mkdir(save_path)\\n !kaggle competitions download -p {save_path} {\\\"-f \\\" + filename if filename else \\\"\\\"} {competition}\\n\\n\\ndef kaggle_competitions_submit(competition, filename, message=\\\"submit\\\"):\\n !kaggle competitions submit -f {filename} -m {message} {competition}\\n\\n\\ndef kaggle_competitions_submissions(competition):\\n !kaggle competitions submissions {competition}\";\n", " var nbb_formatted_code = \"def kaggle_competitions_search(search_term):\\n !kaggle competitions list -s {search_term}\\n\\n\\ndef kaggle_competitions_files(competition):\\n !kaggle competitions files {competition}\\n\\n\\ndef kaggle_competitions_download(competition, save_path=\\\"data\\\", filename=None):\\n mkdir(save_path)\\n !kaggle competitions download -p {save_path} {\\\"-f \\\" + filename if filename else \\\"\\\"} {competition}\\n\\n\\ndef kaggle_competitions_submit(competition, filename, message=\\\"submit\\\"):\\n !kaggle competitions submit -f {filename} -m {message} {competition}\\n\\n\\ndef kaggle_competitions_submissions(competition):\\n !kaggle competitions submissions {competition}\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def kaggle_competitions_search(search_term):\n", " !kaggle competitions list -s {search_term}\n", "\n", "\n", "def kaggle_competitions_files(competition):\n", " !kaggle competitions files {competition}\n", "\n", "\n", "def kaggle_competitions_download(competition, save_path=\"data\", filename=None):\n", " mkdir(save_path)\n", " !kaggle competitions download -p {save_path} {\"-f \" + filename if filename else \"\"} {competition}\n", "\n", "\n", "def kaggle_competitions_submit(competition, filename, message=\"submit\"):\n", " !kaggle competitions submit -f {filename} -m {message} {competition}\n", "\n", "\n", "def kaggle_competitions_submissions(competition):\n", " !kaggle competitions submissions {competition}" ] }, { "cell_type": "markdown", "id": "0fdfe95e", "metadata": {}, "source": [ "### Gpu server" ] }, { "cell_type": "code", "execution_count": 7, "id": "f5ba27be", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.967413Z", "start_time": "2023-04-18T15:47:30.909020Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 7;\n", " var nbb_unformatted_code = \"def get_shad_server_username_and_telegram_id_pairs(\\n copy_pasted_table: str or None = None,\\n) -> list[str, str]:\\n table_url = \\\"https://docs.google.com/spreadsheets/u/1/d/e/2PACX-1vRNGT6OeI7zKVFzYPoqmTPh1jCfeVjRLSvFziVgRleyFTOHi1GU39ERo_UixTGcgydG7QcurnSmHgSW/pubhtml?gid=1404550339&single=true\\\"\\n\\n if copy_pasted_table is not None:\\n table = copy_pasted_table\\n else:\\n home = os.environ[\\\"HOME\\\"]\\n table = open(f\\\"{home}/shad_server_username_to_telegram.txt\\\").read()\\n\\n shad_server_username_and_telegram_id_pairs = []\\n for row in table.splitlines():\\n if row.count(\\\"\\\\t\\\") == 0:\\n continue\\n cols = row.split(\\\"\\\\t\\\")\\n shad_server_username = cols[-2]\\n telegram_id = cols[-1]\\n shad_server_username_and_telegram_id_pairs.append(\\n (shad_server_username, telegram_id)\\n )\\n\\n return shad_server_username_and_telegram_id_pairs\\n\\n\\ndef get_nvidia_smi_pid_column():\\n nvidia_smi_pid_column = !nvidia-smi | awk '{print $5}'\\n return nvidia_smi_pid_column\\n\\n\\ndef get_pid_username(pid: int) -> str:\\n username = !ps -o uname= -p {pid}\\n return username[0]\\n\\n\\ndef get_usernames_using_gpu() -> list[str]:\\n nvidia_smi_pid_column = get_nvidia_smi_pid_column()\\n pids_using_gpu = []\\n for row in nvidia_smi_pid_column[::-1]:\\n if row == \\\"PID\\\":\\n break\\n try:\\n pid = int(row)\\n except ValueError:\\n continue\\n pids_using_gpu.append(int(pid))\\n\\n usernames_using_gpu = [get_pid_username(pid) for pid in pids_using_gpu]\\n usernames_using_gpu = list(set(usernames_using_gpu))\\n return usernames_using_gpu\\n\\n\\ndef print_telegram_usernames_using_gpu(table: str or None = None):\\n server_to_telegram = dict(get_shad_server_username_and_telegram_id_pairs(table))\\n usernames_using_gpu = get_usernames_using_gpu()\\n\\n telegram_usernames_using_gpu = []\\n server_usernames_with_unknown_telegram_id = []\\n for username in usernames_using_gpu:\\n if username in server_to_telegram:\\n telegram_usernames_using_gpu.append(server_to_telegram[username])\\n else:\\n server_usernames_with_unknown_telegram_id.append(username)\\n\\n print(\\\"Telegram id of users using gpu:\\\")\\n print(\\\"\\\\n\\\".join(telegram_usernames_using_gpu))\\n\\n if server_usernames_with_unknown_telegram_id:\\n print(\\\"Telegram id is unknown for users:\\\")\\n print(\\\"\\\\n\\\".join(server_usernames_with_unknown_telegram_id))\";\n", " var nbb_formatted_code = \"def get_shad_server_username_and_telegram_id_pairs(\\n copy_pasted_table: str or None = None,\\n) -> list[str, str]:\\n table_url = \\\"https://docs.google.com/spreadsheets/u/1/d/e/2PACX-1vRNGT6OeI7zKVFzYPoqmTPh1jCfeVjRLSvFziVgRleyFTOHi1GU39ERo_UixTGcgydG7QcurnSmHgSW/pubhtml?gid=1404550339&single=true\\\"\\n\\n if copy_pasted_table is not None:\\n table = copy_pasted_table\\n else:\\n home = os.environ[\\\"HOME\\\"]\\n table = open(f\\\"{home}/shad_server_username_to_telegram.txt\\\").read()\\n\\n shad_server_username_and_telegram_id_pairs = []\\n for row in table.splitlines():\\n if row.count(\\\"\\\\t\\\") == 0:\\n continue\\n cols = row.split(\\\"\\\\t\\\")\\n shad_server_username = cols[-2]\\n telegram_id = cols[-1]\\n shad_server_username_and_telegram_id_pairs.append(\\n (shad_server_username, telegram_id)\\n )\\n\\n return shad_server_username_and_telegram_id_pairs\\n\\n\\ndef get_nvidia_smi_pid_column():\\n nvidia_smi_pid_column = !nvidia-smi | awk '{print $5}'\\n return nvidia_smi_pid_column\\n\\n\\ndef get_pid_username(pid: int) -> str:\\n username = !ps -o uname= -p {pid}\\n return username[0]\\n\\n\\ndef get_usernames_using_gpu() -> list[str]:\\n nvidia_smi_pid_column = get_nvidia_smi_pid_column()\\n pids_using_gpu = []\\n for row in nvidia_smi_pid_column[::-1]:\\n if row == \\\"PID\\\":\\n break\\n try:\\n pid = int(row)\\n except ValueError:\\n continue\\n pids_using_gpu.append(int(pid))\\n\\n usernames_using_gpu = [get_pid_username(pid) for pid in pids_using_gpu]\\n usernames_using_gpu = list(set(usernames_using_gpu))\\n return usernames_using_gpu\\n\\n\\ndef print_telegram_usernames_using_gpu(table: str or None = None):\\n server_to_telegram = dict(get_shad_server_username_and_telegram_id_pairs(table))\\n usernames_using_gpu = get_usernames_using_gpu()\\n\\n telegram_usernames_using_gpu = []\\n server_usernames_with_unknown_telegram_id = []\\n for username in usernames_using_gpu:\\n if username in server_to_telegram:\\n telegram_usernames_using_gpu.append(server_to_telegram[username])\\n else:\\n server_usernames_with_unknown_telegram_id.append(username)\\n\\n print(\\\"Telegram id of users using gpu:\\\")\\n print(\\\"\\\\n\\\".join(telegram_usernames_using_gpu))\\n\\n if server_usernames_with_unknown_telegram_id:\\n print(\\\"Telegram id is unknown for users:\\\")\\n print(\\\"\\\\n\\\".join(server_usernames_with_unknown_telegram_id))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def get_shad_server_username_and_telegram_id_pairs(\n", " copy_pasted_table: str or None = None,\n", ") -> list[str, str]:\n", " table_url = \"https://docs.google.com/spreadsheets/u/1/d/e/2PACX-1vRNGT6OeI7zKVFzYPoqmTPh1jCfeVjRLSvFziVgRleyFTOHi1GU39ERo_UixTGcgydG7QcurnSmHgSW/pubhtml?gid=1404550339&single=true\"\n", "\n", " if copy_pasted_table is not None:\n", " table = copy_pasted_table\n", " else:\n", " home = os.environ[\"HOME\"]\n", " table = open(f\"{home}/shad_server_username_to_telegram.txt\").read()\n", "\n", " shad_server_username_and_telegram_id_pairs = []\n", " for row in table.splitlines():\n", " if row.count(\"\\t\") == 0:\n", " continue\n", " cols = row.split(\"\\t\")\n", " shad_server_username = cols[-2]\n", " telegram_id = cols[-1]\n", " shad_server_username_and_telegram_id_pairs.append(\n", " (shad_server_username, telegram_id)\n", " )\n", "\n", " return shad_server_username_and_telegram_id_pairs\n", "\n", "\n", "def get_nvidia_smi_pid_column():\n", " nvidia_smi_pid_column = !nvidia-smi | awk '{print $5}'\n", " return nvidia_smi_pid_column\n", "\n", "\n", "def get_pid_username(pid: int) -> str:\n", " username = !ps -o uname= -p {pid}\n", " return username[0]\n", "\n", "\n", "def get_usernames_using_gpu() -> list[str]:\n", " nvidia_smi_pid_column = get_nvidia_smi_pid_column()\n", " pids_using_gpu = []\n", " for row in nvidia_smi_pid_column[::-1]:\n", " if row == \"PID\":\n", " break\n", " try:\n", " pid = int(row)\n", " except ValueError:\n", " continue\n", " pids_using_gpu.append(int(pid))\n", "\n", " usernames_using_gpu = [get_pid_username(pid) for pid in pids_using_gpu]\n", " usernames_using_gpu = list(set(usernames_using_gpu))\n", " return usernames_using_gpu\n", "\n", "\n", "def print_telegram_usernames_using_gpu(table: str or None = None):\n", " server_to_telegram = dict(get_shad_server_username_and_telegram_id_pairs(table))\n", " usernames_using_gpu = get_usernames_using_gpu()\n", "\n", " telegram_usernames_using_gpu = []\n", " server_usernames_with_unknown_telegram_id = []\n", " for username in usernames_using_gpu:\n", " if username in server_to_telegram:\n", " telegram_usernames_using_gpu.append(server_to_telegram[username])\n", " else:\n", " server_usernames_with_unknown_telegram_id.append(username)\n", "\n", " print(\"Telegram id of users using gpu:\")\n", " print(\"\\n\".join(telegram_usernames_using_gpu))\n", "\n", " if server_usernames_with_unknown_telegram_id:\n", " print(\"Telegram id is unknown for users:\")\n", " print(\"\\n\".join(server_usernames_with_unknown_telegram_id))" ] }, { "cell_type": "markdown", "id": "a5626f18", "metadata": {}, "source": [ "### Environment variables " ] }, { "cell_type": "code", "execution_count": 6, "id": "e496647d", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.899947Z", "start_time": "2023-04-18T15:47:30.872176Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 6;\n", " var nbb_unformatted_code = \"def set_tokenizers_parallelism(enable: bool):\\n os.environ[\\\"TOKENIZERS_PARALLELISM\\\"] = \\\"true\\\" if enable else \\\"false\\\"\\n\\n\\ndef set_torch_device_order_pci_bus():\\n os.environ[\\\"CUDA_DEVICE_ORDER\\\"] = \\\"PCI_BUS_ID\\\"\\n\\n\\nset_tokenizers_parallelism(False)\\nset_torch_device_order_pci_bus()\";\n", " var nbb_formatted_code = \"def set_tokenizers_parallelism(enable: bool):\\n os.environ[\\\"TOKENIZERS_PARALLELISM\\\"] = \\\"true\\\" if enable else \\\"false\\\"\\n\\n\\ndef set_torch_device_order_pci_bus():\\n os.environ[\\\"CUDA_DEVICE_ORDER\\\"] = \\\"PCI_BUS_ID\\\"\\n\\n\\nset_tokenizers_parallelism(False)\\nset_torch_device_order_pci_bus()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def set_tokenizers_parallelism(enable: bool):\n", " os.environ[\"TOKENIZERS_PARALLELISM\"] = \"true\" if enable else \"false\"\n", "\n", "\n", "def set_torch_device_order_pci_bus():\n", " os.environ[\"CUDA_DEVICE_ORDER\"] = \"PCI_BUS_ID\"\n", "\n", "\n", "set_tokenizers_parallelism(False)\n", "set_torch_device_order_pci_bus()" ] }, { "cell_type": "markdown", "id": "202c992a", "metadata": {}, "source": [ "### Utils " ] }, { "cell_type": "code", "execution_count": 17, "id": "7a52ce27", "metadata": { "ExecuteTime": { "end_time": "2023-04-25T19:29:59.305379Z", "start_time": "2023-04-25T19:29:59.169804Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 17;\n", " var nbb_unformatted_code = \"def path_to_dict(path, print_only_last_dirname=False):\\n dirpath, dirnames, filenames = next(os.walk(path))\\n path_contents = filenames\\n\\n for dirname in dirnames:\\n full_dirname = os.path.join(path, dirname)\\n path_contents.append(path_to_dict(full_dirname, print_only_last_dirname=True))\\n\\n if print_only_last_dirname:\\n path = os.path.split(path)[-1]\\n\\n return {path: path_contents}\\n\\n\\ndef pprint_path_contents(path):\\n path_dict = path_to_dict(path)\\n short_path_repr = reprlib.repr(path_dict)\\n short_path_dict = eval(short_path_repr)\\n string = pprint.pformat(short_path_dict).replace(\\\"Ellipsis\\\", \\\"...\\\")\\n print(string)\\n \\n \\ndef load_pickle_or_build_object_and_save(pickle_path:str, build_object: Callable[[], \\\"T\\\"]) -> \\\"T\\\":\\n if not os.path.exists(pickle_path):\\n pickle.dump(build_object(), open(pickle_path, \\\"wb\\\"))\\n else:\\n print(f\\\"Reusing object {pickle_path}.\\\")\\n return pickle.load(open(pickle_path, \\\"rb\\\"))\";\n", " var nbb_formatted_code = \"def path_to_dict(path, print_only_last_dirname=False):\\n dirpath, dirnames, filenames = next(os.walk(path))\\n path_contents = filenames\\n\\n for dirname in dirnames:\\n full_dirname = os.path.join(path, dirname)\\n path_contents.append(path_to_dict(full_dirname, print_only_last_dirname=True))\\n\\n if print_only_last_dirname:\\n path = os.path.split(path)[-1]\\n\\n return {path: path_contents}\\n\\n\\ndef pprint_path_contents(path):\\n path_dict = path_to_dict(path)\\n short_path_repr = reprlib.repr(path_dict)\\n short_path_dict = eval(short_path_repr)\\n string = pprint.pformat(short_path_dict).replace(\\\"Ellipsis\\\", \\\"...\\\")\\n print(string)\\n\\n\\ndef load_pickle_or_build_object_and_save(\\n pickle_path: str, build_object: Callable[[], \\\"T\\\"]\\n) -> \\\"T\\\":\\n if not os.path.exists(pickle_path):\\n pickle.dump(build_object(), open(pickle_path, \\\"wb\\\"))\\n else:\\n print(f\\\"Reusing object {pickle_path}.\\\")\\n return pickle.load(open(pickle_path, \\\"rb\\\"))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def path_to_dict(path, print_only_last_dirname=False):\n", " dirpath, dirnames, filenames = next(os.walk(path))\n", " path_contents = filenames\n", "\n", " for dirname in dirnames:\n", " full_dirname = os.path.join(path, dirname)\n", " path_contents.append(path_to_dict(full_dirname, print_only_last_dirname=True))\n", "\n", " if print_only_last_dirname:\n", " path = os.path.split(path)[-1]\n", "\n", " return {path: path_contents}\n", "\n", "\n", "def pprint_path_contents(path):\n", " path_dict = path_to_dict(path)\n", " short_path_repr = reprlib.repr(path_dict)\n", " short_path_dict = eval(short_path_repr)\n", " string = pprint.pformat(short_path_dict).replace(\"Ellipsis\", \"...\")\n", " print(string)\n", "\n", "\n", "def load_pickle_or_build_object_and_save(\n", " pickle_path: str, build_object: Callable[[], \"T\"]\n", ") -> \"T\":\n", " if not os.path.exists(pickle_path):\n", " pickle.dump(build_object(), open(pickle_path, \"wb\"))\n", " else:\n", " print(f\"Reusing object {pickle_path}.\")\n", " return pickle.load(open(pickle_path, \"rb\"))" ] }, { "cell_type": "markdown", "id": "cdf2b470", "metadata": {}, "source": [ "## Data " ] }, { "cell_type": "code", "execution_count": 8, "id": "098e77ae", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:30.981098Z", "start_time": "2023-04-18T15:47:30.971522Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 8;\n", " var nbb_unformatted_code = \"if not os.path.exists(\\\"data\\\"):\\n kaggle_competitions_download(COMPETITION)\\n unzip_to_data_and_delete()\";\n", " var nbb_formatted_code = \"if not os.path.exists(\\\"data\\\"):\\n kaggle_competitions_download(COMPETITION)\\n unzip_to_data_and_delete()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if not os.path.exists(\"data\"):\n", " kaggle_competitions_download(COMPETITION)\n", " unzip_to_data_and_delete()" ] }, { "cell_type": "code", "execution_count": 10, "id": "1c7232a4", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:31.219671Z", "start_time": "2023-04-18T15:47:31.028004Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'data': ['sample_submission.csv',\n", " {'train': [{'images': ['52ecbd029a07.jpg',\n", " 'fd7e3f0e4d43.jpg',\n", " 'f0122da6cbe1.jpg',\n", " '2a186a0fa1ae.jpg',\n", " '6559c7a7d153.jpg',\n", " '5fd880333d07.jpg',\n", " ...]},\n", " {'annotations': ['0f4f52fc3f4b.json',\n", " '35f0ec146509.json',\n", " '2e374a37e404.json',\n", " '96578b79c571.json',\n", " 'dfbd6e21c301.json',\n", " '0893be463049.json',\n", " ...]}]},\n", " {'test': [{'images': ['000b92c3b098.jpg',\n", " '01b45b831589.jpg',\n", " '00dcf883a459.jpg',\n", " '007a18eb4e09.jpg',\n", " '00f5404753cf.jpg']}]}]}\n" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 10;\n", " var nbb_unformatted_code = \"pprint_path_contents(\\\"data\\\")\";\n", " var nbb_formatted_code = \"pprint_path_contents(\\\"data\\\")\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pprint_path_contents(\"data\")" ] }, { "cell_type": "code", "execution_count": 8, "id": "c0a85e8a", "metadata": { "ExecuteTime": { "end_time": "2023-04-27T13:04:21.517594Z", "start_time": "2023-04-27T13:04:21.491793Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 8;\n", " var nbb_unformatted_code = \"@functools.cache\\ndef load_train_image_ids() -> list[str]:\\n train_image_ids = [i.replace(\\\".jpg\\\", \\\"\\\") for i in os.listdir(\\\"data/train/images\\\")]\\n return train_image_ids[: 1000 if DEBUG else None]\\n\\n\\n@functools.cache\\ndef load_test_image_ids() -> list[str]:\\n return [i.replace(\\\".jpg\\\", \\\"\\\") for i in os.listdir(\\\"data/test/images\\\")]\\n\\n\\n@functools.cache\\ndef load_image_annotation(image_id: str) -> dict:\\n return json.load(open(f\\\"data/train/annotations/{image_id}.json\\\"))\\n\\n\\ndef load_image(image_id: str) -> np.ndarray:\\n return imageio.v3.imread(open(f\\\"data/train/images/{image_id}.jpg\\\", \\\"rb\\\"))\";\n", " var nbb_formatted_code = \"@functools.cache\\ndef load_train_image_ids() -> list[str]:\\n train_image_ids = [i.replace(\\\".jpg\\\", \\\"\\\") for i in os.listdir(\\\"data/train/images\\\")]\\n return train_image_ids[: 1000 if DEBUG else None]\\n\\n\\n@functools.cache\\ndef load_test_image_ids() -> list[str]:\\n return [i.replace(\\\".jpg\\\", \\\"\\\") for i in os.listdir(\\\"data/test/images\\\")]\\n\\n\\n@functools.cache\\ndef load_image_annotation(image_id: str) -> dict:\\n return json.load(open(f\\\"data/train/annotations/{image_id}.json\\\"))\\n\\n\\ndef load_image(image_id: str) -> np.ndarray:\\n return imageio.v3.imread(open(f\\\"data/train/images/{image_id}.jpg\\\", \\\"rb\\\"))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@functools.cache\n", "def load_train_image_ids() -> list[str]:\n", " train_image_ids = [i.replace(\".jpg\", \"\") for i in os.listdir(\"data/train/images\")]\n", " return train_image_ids[: 1000 if DEBUG else None]\n", "\n", "\n", "@functools.cache\n", "def load_test_image_ids() -> list[str]:\n", " return [i.replace(\".jpg\", \"\") for i in os.listdir(\"data/test/images\")]\n", "\n", "\n", "@functools.cache\n", "def load_image_annotation(image_id: str) -> dict:\n", " return json.load(open(f\"data/train/annotations/{image_id}.json\"))\n", "\n", "\n", "def load_image(image_id: str) -> np.ndarray:\n", " return imageio.v3.imread(open(f\"data/train/images/{image_id}.jpg\", \"rb\"))" ] }, { "cell_type": "markdown", "id": "e6e7d333", "metadata": {}, "source": [ "### Annotation structure " ] }, { "cell_type": "code", "execution_count": 12, "id": "1e98517b", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:31.349287Z", "start_time": "2023-04-18T15:47:31.250789Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 12;\n", " var nbb_unformatted_code = \"class Source(enum.Enum):\\n generated = \\\"generated\\\"\\n extracted = \\\"extracted\\\"\\n\\n\\nclass ChartType(enum.Enum):\\n dot = \\\"dot\\\"\\n horizontal_bar = \\\"horizontal_bar\\\"\\n vertical_bar = \\\"vertical_bar\\\"\\n line = \\\"line\\\"\\n scatter = \\\"scatter\\\"\\n\\n\\n@dataclasses.dataclass\\nclass PlotBoundingBox:\\n height: int\\n width: int\\n x0: int\\n y0: int\\n\\n def get_bounds(self):\\n xs = [self.x0, self.x0 + self.width, self.x0 + self.width, self.x0, self.x0]\\n ys = [self.y0, self.y0, self.y0 + self.height, self.y0 + self.height, self.y0]\\n return xs, ys\\n\\n\\n@dataclasses.dataclass\\nclass DataPoint:\\n x: float or str\\n y: float or str\\n\\n\\nclass TextRole(enum.Enum):\\n axis_title = \\\"axis_title\\\"\\n chart_title = \\\"chart_title\\\"\\n legend_label = \\\"legend_label\\\"\\n tick_grouping = \\\"tick_grouping\\\"\\n tick_label = \\\"tick_label\\\"\\n other = \\\"other\\\"\\n\\n\\n@dataclasses.dataclass\\nclass Polygon:\\n x0: int\\n x1: int\\n x2: int\\n x3: int\\n y0: int\\n y1: int\\n y2: int\\n y3: int\\n\\n def get_bounds(self):\\n xs = [\\n self.x0,\\n self.x1,\\n self.x2,\\n self.x3,\\n self.x0,\\n ]\\n ys = [\\n self.y0,\\n self.y1,\\n self.y2,\\n self.y3,\\n self.y0,\\n ]\\n return xs, ys\\n\\n\\n@dataclasses.dataclass\\nclass Text:\\n id: int\\n polygon: Polygon\\n role: TextRole\\n text: str\\n\\n def __post_init__(self):\\n self.polygon = Polygon(**self.polygon)\\n self.role = TextRole(self.role)\\n\\n\\nclass ValuesType(enum.Enum):\\n categorical = \\\"categorical\\\"\\n numerical = \\\"numerical\\\"\\n\\n\\n@dataclasses.dataclass\\nclass Tick:\\n id: int\\n x: int\\n y: int\\n\\n\\nclass TickType(enum.Enum):\\n markers = \\\"markers\\\"\\n separators = \\\"separators\\\"\\n\\n\\n@dataclasses.dataclass\\nclass Axis:\\n values_type: ValuesType\\n tick_type: TickType\\n ticks: list[Tick]\\n\\n def __post_init__(self):\\n self.values_type = ValuesType(self.values_type)\\n self.tick_type = TickType(self.tick_type)\\n self.ticks = [\\n Tick(id=kw[\\\"id\\\"], x=kw[\\\"tick_pt\\\"][\\\"x\\\"], y=kw[\\\"tick_pt\\\"][\\\"y\\\"])\\n for kw in self.ticks\\n ]\\n\\n def get_bounds(self):\\n min_x = min(tick.x for tick in self.ticks)\\n max_x = max(tick.x for tick in self.ticks)\\n min_y = min(tick.y for tick in self.ticks)\\n max_y = max(tick.y for tick in self.ticks)\\n xs = [min_x, max_x, max_x, min_x, min_x]\\n ys = [min_y, min_y, max_y, max_y, min_y]\\n return xs, ys\\n\\n\\ndef convert_dashes_to_underscores_in_key_names(dictionary):\\n return {k.replace(\\\"-\\\", \\\"_\\\"): v for k, v in dictionary.items()}\\n\\n\\n@dataclasses.dataclass\\nclass Axes:\\n x_axis: Axis\\n y_axis: Axis\\n\\n def __post_init__(self):\\n self.x_axis = Axis(**convert_dashes_to_underscores_in_key_names(self.x_axis))\\n self.y_axis = Axis(**convert_dashes_to_underscores_in_key_names(self.y_axis))\\n\\n\\ndef preprocess_numerical_value(value):\\n value = float(value)\\n value = 0 if np.isnan(value) else value\\n return value\\n\\n\\ndef preprocess_value(value, value_type: ValuesType):\\n if value_type == ValuesType.numerical:\\n return preprocess_numerical_value(value)\\n else:\\n return str(value)\\n\\n\\n@dataclasses.dataclass\\nclass Annotation:\\n source: Source\\n chart_type: ChartType\\n plot_bb: PlotBoundingBox\\n text: list[Text]\\n axes: Axes\\n data_series: list[DataPoint]\\n\\n def __post_init__(self):\\n self.source = Source(self.source)\\n self.chart_type = ChartType(self.chart_type)\\n self.plot_bb = PlotBoundingBox(**self.plot_bb)\\n self.text = [Text(**kw) for kw in self.text]\\n self.axes = Axes(**convert_dashes_to_underscores_in_key_names(self.axes))\\n self.data_series = [DataPoint(**kw) for kw in self.data_series]\\n\\n for i in range(len(self.data_series)):\\n self.data_series[i].x = preprocess_value(\\n self.data_series[i].x, self.axes.x_axis.values_type\\n )\\n self.data_series[i].y = preprocess_value(\\n self.data_series[i].y, self.axes.y_axis.values_type\\n )\\n\\n @staticmethod\\n def from_dict_with_dashes(kwargs):\\n return Annotation(**convert_dashes_to_underscores_in_key_names(kwargs))\\n\\n @staticmethod\\n def from_image_index(image_index: int):\\n image_id = load_train_image_ids()[image_index]\\n return Annotation.from_dict_with_dashes(load_image_annotation(image_id))\\n\\n def get_text_by_role(self, text_role: TextRole) -> list[Text]:\\n return [t for t in self.text if t.role == text_role]\\n\\n\\n@dataclasses.dataclass\\nclass AnnotatedImage:\\n id: str\\n image: np.ndarray\\n annotation: Annotation\\n\\n @staticmethod\\n def from_image_id(image_id: str):\\n return AnnotatedImage(\\n id=image_id,\\n image=load_image(image_id),\\n annotation=Annotation.from_dict_with_dashes(\\n load_image_annotation(image_id)\\n ),\\n )\\n\\n @staticmethod\\n def from_image_index(image_index: int):\\n return AnnotatedImage.from_image_id(load_train_image_ids()[image_index])\\n\\n\\ndef generate_annotated_images():\\n for image_id in tqdm.autonotebook.tqdm(\\n load_train_image_ids(), \\\"Iterating over annotated images\\\"\\n ):\\n yield AnnotatedImage.from_image_id(image_id)\";\n", " var nbb_formatted_code = \"class Source(enum.Enum):\\n generated = \\\"generated\\\"\\n extracted = \\\"extracted\\\"\\n\\n\\nclass ChartType(enum.Enum):\\n dot = \\\"dot\\\"\\n horizontal_bar = \\\"horizontal_bar\\\"\\n vertical_bar = \\\"vertical_bar\\\"\\n line = \\\"line\\\"\\n scatter = \\\"scatter\\\"\\n\\n\\n@dataclasses.dataclass\\nclass PlotBoundingBox:\\n height: int\\n width: int\\n x0: int\\n y0: int\\n\\n def get_bounds(self):\\n xs = [self.x0, self.x0 + self.width, self.x0 + self.width, self.x0, self.x0]\\n ys = [self.y0, self.y0, self.y0 + self.height, self.y0 + self.height, self.y0]\\n return xs, ys\\n\\n\\n@dataclasses.dataclass\\nclass DataPoint:\\n x: float or str\\n y: float or str\\n\\n\\nclass TextRole(enum.Enum):\\n axis_title = \\\"axis_title\\\"\\n chart_title = \\\"chart_title\\\"\\n legend_label = \\\"legend_label\\\"\\n tick_grouping = \\\"tick_grouping\\\"\\n tick_label = \\\"tick_label\\\"\\n other = \\\"other\\\"\\n\\n\\n@dataclasses.dataclass\\nclass Polygon:\\n x0: int\\n x1: int\\n x2: int\\n x3: int\\n y0: int\\n y1: int\\n y2: int\\n y3: int\\n\\n def get_bounds(self):\\n xs = [\\n self.x0,\\n self.x1,\\n self.x2,\\n self.x3,\\n self.x0,\\n ]\\n ys = [\\n self.y0,\\n self.y1,\\n self.y2,\\n self.y3,\\n self.y0,\\n ]\\n return xs, ys\\n\\n\\n@dataclasses.dataclass\\nclass Text:\\n id: int\\n polygon: Polygon\\n role: TextRole\\n text: str\\n\\n def __post_init__(self):\\n self.polygon = Polygon(**self.polygon)\\n self.role = TextRole(self.role)\\n\\n\\nclass ValuesType(enum.Enum):\\n categorical = \\\"categorical\\\"\\n numerical = \\\"numerical\\\"\\n\\n\\n@dataclasses.dataclass\\nclass Tick:\\n id: int\\n x: int\\n y: int\\n\\n\\nclass TickType(enum.Enum):\\n markers = \\\"markers\\\"\\n separators = \\\"separators\\\"\\n\\n\\n@dataclasses.dataclass\\nclass Axis:\\n values_type: ValuesType\\n tick_type: TickType\\n ticks: list[Tick]\\n\\n def __post_init__(self):\\n self.values_type = ValuesType(self.values_type)\\n self.tick_type = TickType(self.tick_type)\\n self.ticks = [\\n Tick(id=kw[\\\"id\\\"], x=kw[\\\"tick_pt\\\"][\\\"x\\\"], y=kw[\\\"tick_pt\\\"][\\\"y\\\"])\\n for kw in self.ticks\\n ]\\n\\n def get_bounds(self):\\n min_x = min(tick.x for tick in self.ticks)\\n max_x = max(tick.x for tick in self.ticks)\\n min_y = min(tick.y for tick in self.ticks)\\n max_y = max(tick.y for tick in self.ticks)\\n xs = [min_x, max_x, max_x, min_x, min_x]\\n ys = [min_y, min_y, max_y, max_y, min_y]\\n return xs, ys\\n\\n\\ndef convert_dashes_to_underscores_in_key_names(dictionary):\\n return {k.replace(\\\"-\\\", \\\"_\\\"): v for k, v in dictionary.items()}\\n\\n\\n@dataclasses.dataclass\\nclass Axes:\\n x_axis: Axis\\n y_axis: Axis\\n\\n def __post_init__(self):\\n self.x_axis = Axis(**convert_dashes_to_underscores_in_key_names(self.x_axis))\\n self.y_axis = Axis(**convert_dashes_to_underscores_in_key_names(self.y_axis))\\n\\n\\ndef preprocess_numerical_value(value):\\n value = float(value)\\n value = 0 if np.isnan(value) else value\\n return value\\n\\n\\ndef preprocess_value(value, value_type: ValuesType):\\n if value_type == ValuesType.numerical:\\n return preprocess_numerical_value(value)\\n else:\\n return str(value)\\n\\n\\n@dataclasses.dataclass\\nclass Annotation:\\n source: Source\\n chart_type: ChartType\\n plot_bb: PlotBoundingBox\\n text: list[Text]\\n axes: Axes\\n data_series: list[DataPoint]\\n\\n def __post_init__(self):\\n self.source = Source(self.source)\\n self.chart_type = ChartType(self.chart_type)\\n self.plot_bb = PlotBoundingBox(**self.plot_bb)\\n self.text = [Text(**kw) for kw in self.text]\\n self.axes = Axes(**convert_dashes_to_underscores_in_key_names(self.axes))\\n self.data_series = [DataPoint(**kw) for kw in self.data_series]\\n\\n for i in range(len(self.data_series)):\\n self.data_series[i].x = preprocess_value(\\n self.data_series[i].x, self.axes.x_axis.values_type\\n )\\n self.data_series[i].y = preprocess_value(\\n self.data_series[i].y, self.axes.y_axis.values_type\\n )\\n\\n @staticmethod\\n def from_dict_with_dashes(kwargs):\\n return Annotation(**convert_dashes_to_underscores_in_key_names(kwargs))\\n\\n @staticmethod\\n def from_image_index(image_index: int):\\n image_id = load_train_image_ids()[image_index]\\n return Annotation.from_dict_with_dashes(load_image_annotation(image_id))\\n\\n def get_text_by_role(self, text_role: TextRole) -> list[Text]:\\n return [t for t in self.text if t.role == text_role]\\n\\n\\n@dataclasses.dataclass\\nclass AnnotatedImage:\\n id: str\\n image: np.ndarray\\n annotation: Annotation\\n\\n @staticmethod\\n def from_image_id(image_id: str):\\n return AnnotatedImage(\\n id=image_id,\\n image=load_image(image_id),\\n annotation=Annotation.from_dict_with_dashes(\\n load_image_annotation(image_id)\\n ),\\n )\\n\\n @staticmethod\\n def from_image_index(image_index: int):\\n return AnnotatedImage.from_image_id(load_train_image_ids()[image_index])\\n\\n\\ndef generate_annotated_images():\\n for image_id in tqdm.autonotebook.tqdm(\\n load_train_image_ids(), \\\"Iterating over annotated images\\\"\\n ):\\n yield AnnotatedImage.from_image_id(image_id)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "class Source(enum.Enum):\n", " generated = \"generated\"\n", " extracted = \"extracted\"\n", "\n", "\n", "class ChartType(enum.Enum):\n", " dot = \"dot\"\n", " horizontal_bar = \"horizontal_bar\"\n", " vertical_bar = \"vertical_bar\"\n", " line = \"line\"\n", " scatter = \"scatter\"\n", "\n", "\n", "@dataclasses.dataclass\n", "class PlotBoundingBox:\n", " height: int\n", " width: int\n", " x0: int\n", " y0: int\n", "\n", " def get_bounds(self):\n", " xs = [self.x0, self.x0 + self.width, self.x0 + self.width, self.x0, self.x0]\n", " ys = [self.y0, self.y0, self.y0 + self.height, self.y0 + self.height, self.y0]\n", " return xs, ys\n", "\n", "\n", "@dataclasses.dataclass\n", "class DataPoint:\n", " x: float or str\n", " y: float or str\n", "\n", "\n", "class TextRole(enum.Enum):\n", " axis_title = \"axis_title\"\n", " chart_title = \"chart_title\"\n", " legend_label = \"legend_label\"\n", " tick_grouping = \"tick_grouping\"\n", " tick_label = \"tick_label\"\n", " other = \"other\"\n", "\n", "\n", "@dataclasses.dataclass\n", "class Polygon:\n", " x0: int\n", " x1: int\n", " x2: int\n", " x3: int\n", " y0: int\n", " y1: int\n", " y2: int\n", " y3: int\n", "\n", " def get_bounds(self):\n", " xs = [\n", " self.x0,\n", " self.x1,\n", " self.x2,\n", " self.x3,\n", " self.x0,\n", " ]\n", " ys = [\n", " self.y0,\n", " self.y1,\n", " self.y2,\n", " self.y3,\n", " self.y0,\n", " ]\n", " return xs, ys\n", "\n", "\n", "@dataclasses.dataclass\n", "class Text:\n", " id: int\n", " polygon: Polygon\n", " role: TextRole\n", " text: str\n", "\n", " def __post_init__(self):\n", " self.polygon = Polygon(**self.polygon)\n", " self.role = TextRole(self.role)\n", "\n", "\n", "class ValuesType(enum.Enum):\n", " categorical = \"categorical\"\n", " numerical = \"numerical\"\n", "\n", "\n", "@dataclasses.dataclass\n", "class Tick:\n", " id: int\n", " x: int\n", " y: int\n", "\n", "\n", "class TickType(enum.Enum):\n", " markers = \"markers\"\n", " separators = \"separators\"\n", "\n", "\n", "@dataclasses.dataclass\n", "class Axis:\n", " values_type: ValuesType\n", " tick_type: TickType\n", " ticks: list[Tick]\n", "\n", " def __post_init__(self):\n", " self.values_type = ValuesType(self.values_type)\n", " self.tick_type = TickType(self.tick_type)\n", " self.ticks = [\n", " Tick(id=kw[\"id\"], x=kw[\"tick_pt\"][\"x\"], y=kw[\"tick_pt\"][\"y\"])\n", " for kw in self.ticks\n", " ]\n", "\n", " def get_bounds(self):\n", " min_x = min(tick.x for tick in self.ticks)\n", " max_x = max(tick.x for tick in self.ticks)\n", " min_y = min(tick.y for tick in self.ticks)\n", " max_y = max(tick.y for tick in self.ticks)\n", " xs = [min_x, max_x, max_x, min_x, min_x]\n", " ys = [min_y, min_y, max_y, max_y, min_y]\n", " return xs, ys\n", "\n", "\n", "def convert_dashes_to_underscores_in_key_names(dictionary):\n", " return {k.replace(\"-\", \"_\"): v for k, v in dictionary.items()}\n", "\n", "\n", "@dataclasses.dataclass\n", "class Axes:\n", " x_axis: Axis\n", " y_axis: Axis\n", "\n", " def __post_init__(self):\n", " self.x_axis = Axis(**convert_dashes_to_underscores_in_key_names(self.x_axis))\n", " self.y_axis = Axis(**convert_dashes_to_underscores_in_key_names(self.y_axis))\n", "\n", "\n", "def preprocess_numerical_value(value):\n", " value = float(value)\n", " value = 0 if np.isnan(value) else value\n", " return value\n", "\n", "\n", "def preprocess_value(value, value_type: ValuesType):\n", " if value_type == ValuesType.numerical:\n", " return preprocess_numerical_value(value)\n", " else:\n", " return str(value)\n", "\n", "\n", "@dataclasses.dataclass\n", "class Annotation:\n", " source: Source\n", " chart_type: ChartType\n", " plot_bb: PlotBoundingBox\n", " text: list[Text]\n", " axes: Axes\n", " data_series: list[DataPoint]\n", "\n", " def __post_init__(self):\n", " self.source = Source(self.source)\n", " self.chart_type = ChartType(self.chart_type)\n", " self.plot_bb = PlotBoundingBox(**self.plot_bb)\n", " self.text = [Text(**kw) for kw in self.text]\n", " self.axes = Axes(**convert_dashes_to_underscores_in_key_names(self.axes))\n", " self.data_series = [DataPoint(**kw) for kw in self.data_series]\n", "\n", " for i in range(len(self.data_series)):\n", " self.data_series[i].x = preprocess_value(\n", " self.data_series[i].x, self.axes.x_axis.values_type\n", " )\n", " self.data_series[i].y = preprocess_value(\n", " self.data_series[i].y, self.axes.y_axis.values_type\n", " )\n", "\n", " @staticmethod\n", " def from_dict_with_dashes(kwargs):\n", " return Annotation(**convert_dashes_to_underscores_in_key_names(kwargs))\n", "\n", " @staticmethod\n", " def from_image_index(image_index: int):\n", " image_id = load_train_image_ids()[image_index]\n", " return Annotation.from_dict_with_dashes(load_image_annotation(image_id))\n", "\n", " def get_text_by_role(self, text_role: TextRole) -> list[Text]:\n", " return [t for t in self.text if t.role == text_role]\n", "\n", "\n", "@dataclasses.dataclass\n", "class AnnotatedImage:\n", " id: str\n", " image: np.ndarray\n", " annotation: Annotation\n", "\n", " @staticmethod\n", " def from_image_id(image_id: str):\n", " return AnnotatedImage(\n", " id=image_id,\n", " image=load_image(image_id),\n", " annotation=Annotation.from_dict_with_dashes(\n", " load_image_annotation(image_id)\n", " ),\n", " )\n", "\n", " @staticmethod\n", " def from_image_index(image_index: int):\n", " return AnnotatedImage.from_image_id(load_train_image_ids()[image_index])\n", "\n", "\n", "def generate_annotated_images():\n", " for image_id in tqdm.autonotebook.tqdm(\n", " load_train_image_ids(), \"Iterating over annotated images\"\n", " ):\n", " yield AnnotatedImage.from_image_id(image_id)" ] }, { "cell_type": "markdown", "id": "dad819b2", "metadata": {}, "source": [ "### Data exploration " ] }, { "cell_type": "code", "execution_count": 13, "id": "f165119d", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:31.364012Z", "start_time": "2023-04-18T15:47:31.352168Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 13;\n", " var nbb_unformatted_code = \"def are_there_nan_values_in_axis_data():\\n for annotated_image in generate_annotated_images():\\n for datapoint in annotated_image.annotation.data_series:\\n for value in [datapoint.x, datapoint.y]:\\n if not isinstance(value, str) and np.isnan(value):\\n return True\\n return False\";\n", " var nbb_formatted_code = \"def are_there_nan_values_in_axis_data():\\n for annotated_image in generate_annotated_images():\\n for datapoint in annotated_image.annotation.data_series:\\n for value in [datapoint.x, datapoint.y]:\\n if not isinstance(value, str) and np.isnan(value):\\n return True\\n return False\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def are_there_nan_values_in_axis_data():\n", " for annotated_image in generate_annotated_images():\n", " for datapoint in annotated_image.annotation.data_series:\n", " for value in [datapoint.x, datapoint.y]:\n", " if not isinstance(value, str) and np.isnan(value):\n", " return True\n", " return False" ] }, { "cell_type": "code", "execution_count": 14, "id": "3ff0494b", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:31.396949Z", "start_time": "2023-04-18T15:47:31.376901Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 14;\n", " var nbb_unformatted_code = \"if DEBUG:\\n print(are_there_nan_values_in_axis_data())\";\n", " var nbb_formatted_code = \"if DEBUG:\\n print(are_there_nan_values_in_axis_data())\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " print(are_there_nan_values_in_axis_data())" ] }, { "cell_type": "code", "execution_count": 15, "id": "21b4baa0", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:31.426840Z", "start_time": "2023-04-18T15:47:31.399796Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 15;\n", " var nbb_unformatted_code = \"def get_image(image_index: int) -> np.ndarray:\\n return load_image(load_train_image_ids()[image_index])\\n\\n\\ndef build_random_image_animation(n_images=100, fps=1, figsize=(6, 4)):\\n image_indices = np.random.permutation(len(load_train_image_ids()))[:n_images]\\n first_image = get_image(image_indices[0])\\n\\n fig, ax = plt.subplots(figsize=figsize)\\n frame = plt.imshow(first_image)\\n plt.axis(\\\"off\\\")\\n plt.close()\\n\\n def animate(frame_index):\\n image_index = image_indices[frame_index]\\n image = get_image(image_index)\\n frame.set_data(image)\\n\\n return matplotlib.animation.FuncAnimation(\\n fig=fig,\\n func=animate,\\n frames=len(image_indices),\\n interval=int(1000 / fps),\\n )\";\n", " var nbb_formatted_code = \"def get_image(image_index: int) -> np.ndarray:\\n return load_image(load_train_image_ids()[image_index])\\n\\n\\ndef build_random_image_animation(n_images=100, fps=1, figsize=(6, 4)):\\n image_indices = np.random.permutation(len(load_train_image_ids()))[:n_images]\\n first_image = get_image(image_indices[0])\\n\\n fig, ax = plt.subplots(figsize=figsize)\\n frame = plt.imshow(first_image)\\n plt.axis(\\\"off\\\")\\n plt.close()\\n\\n def animate(frame_index):\\n image_index = image_indices[frame_index]\\n image = get_image(image_index)\\n frame.set_data(image)\\n\\n return matplotlib.animation.FuncAnimation(\\n fig=fig,\\n func=animate,\\n frames=len(image_indices),\\n interval=int(1000 / fps),\\n )\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def get_image(image_index: int) -> np.ndarray:\n", " return load_image(load_train_image_ids()[image_index])\n", "\n", "\n", "def build_random_image_animation(n_images=100, fps=1, figsize=(6, 4)):\n", " image_indices = np.random.permutation(len(load_train_image_ids()))[:n_images]\n", " first_image = get_image(image_indices[0])\n", "\n", " fig, ax = plt.subplots(figsize=figsize)\n", " frame = plt.imshow(first_image)\n", " plt.axis(\"off\")\n", " plt.close()\n", "\n", " def animate(frame_index):\n", " image_index = image_indices[frame_index]\n", " image = get_image(image_index)\n", " frame.set_data(image)\n", "\n", " return matplotlib.animation.FuncAnimation(\n", " fig=fig,\n", " func=animate,\n", " frames=len(image_indices),\n", " interval=int(1000 / fps),\n", " )" ] }, { "cell_type": "code", "execution_count": 16, "id": "0d592d35", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:38.818101Z", "start_time": "2023-04-18T15:47:31.431284Z" } }, "outputs": [ { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 16;\n", " var nbb_unformatted_code = \"IPython.display.HTML(build_random_image_animation().to_html5_video())\";\n", " var nbb_formatted_code = \"IPython.display.HTML(build_random_image_animation().to_html5_video())\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "IPython.display.HTML(build_random_image_animation().to_html5_video())" ] }, { "cell_type": "code", "execution_count": 17, "id": "edf90004", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:38.868611Z", "start_time": "2023-04-18T15:47:38.832024Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 17;\n", " var nbb_unformatted_code = \"def visualize_image_stats(figsize=(12, 8)):\\n image_shapes = [ai.image.shape for ai in generate_annotated_images()]\\n\\n fig, axes = plt.subplots(nrows=2, ncols=2, figsize=figsize)\\n\\n height, width, channel = zip(*image_shapes)\\n\\n IPython.display.display(\\n pd.DataFrame(dict(width=width, height=height, channel=channel)).describe()\\n )\\n\\n plt.sca(axes[0][0])\\n plt.title(\\\"Image shapes\\\")\\n plt.xlabel(\\\"Width\\\")\\n plt.ylabel(\\\"Height\\\")\\n plt.scatter(\\n width,\\n height,\\n marker=\\\".\\\",\\n alpha=0.3,\\n )\\n plt.grid()\\n\\n plt.sca(axes[0][1])\\n plt.title(\\\"Width\\\")\\n plt.hist(width, bins=50)\\n plt.grid()\\n\\n plt.sca(axes[1][0])\\n plt.title(\\\"Height\\\")\\n plt.hist(height, bins=50)\\n plt.grid()\\n\\n plt.sca(axes[1][1])\\n plt.axis(\\\"off\\\")\\n\\n plt.tight_layout()\";\n", " var nbb_formatted_code = \"def visualize_image_stats(figsize=(12, 8)):\\n image_shapes = [ai.image.shape for ai in generate_annotated_images()]\\n\\n fig, axes = plt.subplots(nrows=2, ncols=2, figsize=figsize)\\n\\n height, width, channel = zip(*image_shapes)\\n\\n IPython.display.display(\\n pd.DataFrame(dict(width=width, height=height, channel=channel)).describe()\\n )\\n\\n plt.sca(axes[0][0])\\n plt.title(\\\"Image shapes\\\")\\n plt.xlabel(\\\"Width\\\")\\n plt.ylabel(\\\"Height\\\")\\n plt.scatter(\\n width,\\n height,\\n marker=\\\".\\\",\\n alpha=0.3,\\n )\\n plt.grid()\\n\\n plt.sca(axes[0][1])\\n plt.title(\\\"Width\\\")\\n plt.hist(width, bins=50)\\n plt.grid()\\n\\n plt.sca(axes[1][0])\\n plt.title(\\\"Height\\\")\\n plt.hist(height, bins=50)\\n plt.grid()\\n\\n plt.sca(axes[1][1])\\n plt.axis(\\\"off\\\")\\n\\n plt.tight_layout()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def visualize_image_stats(figsize=(12, 8)):\n", " image_shapes = [ai.image.shape for ai in generate_annotated_images()]\n", "\n", " fig, axes = plt.subplots(nrows=2, ncols=2, figsize=figsize)\n", "\n", " height, width, channel = zip(*image_shapes)\n", "\n", " IPython.display.display(\n", " pd.DataFrame(dict(width=width, height=height, channel=channel)).describe()\n", " )\n", "\n", " plt.sca(axes[0][0])\n", " plt.title(\"Image shapes\")\n", " plt.xlabel(\"Width\")\n", " plt.ylabel(\"Height\")\n", " plt.scatter(\n", " width,\n", " height,\n", " marker=\".\",\n", " alpha=0.3,\n", " )\n", " plt.grid()\n", "\n", " plt.sca(axes[0][1])\n", " plt.title(\"Width\")\n", " plt.hist(width, bins=50)\n", " plt.grid()\n", "\n", " plt.sca(axes[1][0])\n", " plt.title(\"Height\")\n", " plt.hist(height, bins=50)\n", " plt.grid()\n", "\n", " plt.sca(axes[1][1])\n", " plt.axis(\"off\")\n", "\n", " plt.tight_layout()" ] }, { "cell_type": "code", "execution_count": 18, "id": "f385dc34", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:38.879630Z", "start_time": "2023-04-18T15:47:38.875047Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 18;\n", " var nbb_unformatted_code = \"if DEBUG:\\n visualize_image_stats()\";\n", " var nbb_formatted_code = \"if DEBUG:\\n visualize_image_stats()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " visualize_image_stats()" ] }, { "cell_type": "code", "execution_count": 19, "id": "c068b2ac", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:38.900221Z", "start_time": "2023-04-18T15:47:38.881375Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 19;\n", " var nbb_unformatted_code = \"CONFIG.image_width = 720\\nCONFIG.image_height = 512\";\n", " var nbb_formatted_code = \"CONFIG.image_width = 720\\nCONFIG.image_height = 512\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.image_width = 720\n", "CONFIG.image_height = 512" ] }, { "cell_type": "code", "execution_count": 20, "id": "24f7f000", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:38.943528Z", "start_time": "2023-04-18T15:47:38.902282Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 20;\n", " var nbb_unformatted_code = \"def plot_image_with_annotations(image_id: str, show_categorical_data=True):\\n annotated_image = AnnotatedImage.from_image_id(image_id)\\n annotation = annotated_image.annotation\\n image = annotated_image.image\\n plt.subplots(figsize=(8, 6))\\n plt.imshow(image)\\n\\n if show_categorical_data:\\n IPython.display.display(\\n pd.Series(\\n dict(\\n source=annotation.source.value,\\n chart_type=annotation.chart_type.value,\\n x_values_type=annotation.axes.x_axis.values_type.value,\\n y_values_type=annotation.axes.y_axis.values_type.value,\\n x_tick_type=annotation.axes.x_axis.tick_type.value,\\n y_tick_type=annotation.axes.y_axis.tick_type.value,\\n )\\n )\\n )\\n\\n plt.plot(*annotation.plot_bb.get_bounds(), c=\\\"red\\\", label=\\\"bounding_box\\\")\\n\\n plt.scatter(\\n *list(zip(*[[tick.x, tick.y] for tick in annotation.axes.x_axis.ticks])),\\n label=\\\"x_ticks\\\"\\n )\\n plt.scatter(\\n *list(zip(*[[tick.x, tick.y] for tick in annotation.axes.y_axis.ticks])),\\n label=\\\"y_ticks\\\"\\n )\\n\\n text_role_colors = dict(zip(TextRole, plt.cm.Accent.colors))\\n seen_roles = set()\\n for i, text in enumerate(annotation.text):\\n xs = [\\n text.polygon.x0,\\n text.polygon.x1,\\n text.polygon.x2,\\n text.polygon.x3,\\n text.polygon.x0,\\n ]\\n ys = [\\n text.polygon.y0,\\n text.polygon.y1,\\n text.polygon.y2,\\n text.polygon.y3,\\n text.polygon.y0,\\n ]\\n plt.plot(\\n xs,\\n ys,\\n c=text_role_colors[text.role],\\n label=text.role.value if text.role not in seen_roles else None,\\n )\\n seen_roles.add(text.role)\\n\\n plt.legend(bbox_to_anchor=(1.04, 1), loc=\\\"upper left\\\")\";\n", " var nbb_formatted_code = \"def plot_image_with_annotations(image_id: str, show_categorical_data=True):\\n annotated_image = AnnotatedImage.from_image_id(image_id)\\n annotation = annotated_image.annotation\\n image = annotated_image.image\\n plt.subplots(figsize=(8, 6))\\n plt.imshow(image)\\n\\n if show_categorical_data:\\n IPython.display.display(\\n pd.Series(\\n dict(\\n source=annotation.source.value,\\n chart_type=annotation.chart_type.value,\\n x_values_type=annotation.axes.x_axis.values_type.value,\\n y_values_type=annotation.axes.y_axis.values_type.value,\\n x_tick_type=annotation.axes.x_axis.tick_type.value,\\n y_tick_type=annotation.axes.y_axis.tick_type.value,\\n )\\n )\\n )\\n\\n plt.plot(*annotation.plot_bb.get_bounds(), c=\\\"red\\\", label=\\\"bounding_box\\\")\\n\\n plt.scatter(\\n *list(zip(*[[tick.x, tick.y] for tick in annotation.axes.x_axis.ticks])),\\n label=\\\"x_ticks\\\"\\n )\\n plt.scatter(\\n *list(zip(*[[tick.x, tick.y] for tick in annotation.axes.y_axis.ticks])),\\n label=\\\"y_ticks\\\"\\n )\\n\\n text_role_colors = dict(zip(TextRole, plt.cm.Accent.colors))\\n seen_roles = set()\\n for i, text in enumerate(annotation.text):\\n xs = [\\n text.polygon.x0,\\n text.polygon.x1,\\n text.polygon.x2,\\n text.polygon.x3,\\n text.polygon.x0,\\n ]\\n ys = [\\n text.polygon.y0,\\n text.polygon.y1,\\n text.polygon.y2,\\n text.polygon.y3,\\n text.polygon.y0,\\n ]\\n plt.plot(\\n xs,\\n ys,\\n c=text_role_colors[text.role],\\n label=text.role.value if text.role not in seen_roles else None,\\n )\\n seen_roles.add(text.role)\\n\\n plt.legend(bbox_to_anchor=(1.04, 1), loc=\\\"upper left\\\")\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def plot_image_with_annotations(image_id: str, show_categorical_data=True):\n", " annotated_image = AnnotatedImage.from_image_id(image_id)\n", " annotation = annotated_image.annotation\n", " image = annotated_image.image\n", " plt.subplots(figsize=(8, 6))\n", " plt.imshow(image)\n", "\n", " if show_categorical_data:\n", " IPython.display.display(\n", " pd.Series(\n", " dict(\n", " source=annotation.source.value,\n", " chart_type=annotation.chart_type.value,\n", " x_values_type=annotation.axes.x_axis.values_type.value,\n", " y_values_type=annotation.axes.y_axis.values_type.value,\n", " x_tick_type=annotation.axes.x_axis.tick_type.value,\n", " y_tick_type=annotation.axes.y_axis.tick_type.value,\n", " )\n", " )\n", " )\n", "\n", " plt.plot(*annotation.plot_bb.get_bounds(), c=\"red\", label=\"bounding_box\")\n", "\n", " plt.scatter(\n", " *list(zip(*[[tick.x, tick.y] for tick in annotation.axes.x_axis.ticks])),\n", " label=\"x_ticks\"\n", " )\n", " plt.scatter(\n", " *list(zip(*[[tick.x, tick.y] for tick in annotation.axes.y_axis.ticks])),\n", " label=\"y_ticks\"\n", " )\n", "\n", " text_role_colors = dict(zip(TextRole, plt.cm.Accent.colors))\n", " seen_roles = set()\n", " for i, text in enumerate(annotation.text):\n", " xs = [\n", " text.polygon.x0,\n", " text.polygon.x1,\n", " text.polygon.x2,\n", " text.polygon.x3,\n", " text.polygon.x0,\n", " ]\n", " ys = [\n", " text.polygon.y0,\n", " text.polygon.y1,\n", " text.polygon.y2,\n", " text.polygon.y3,\n", " text.polygon.y0,\n", " ]\n", " plt.plot(\n", " xs,\n", " ys,\n", " c=text_role_colors[text.role],\n", " label=text.role.value if text.role not in seen_roles else None,\n", " )\n", " seen_roles.add(text.role)\n", "\n", " plt.legend(bbox_to_anchor=(1.04, 1), loc=\"upper left\")" ] }, { "cell_type": "code", "execution_count": 21, "id": "a54cc20e", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.579100Z", "start_time": "2023-04-18T15:47:38.949939Z" } }, "outputs": [ { "data": { "text/plain": [ "source generated\n", "chart_type line\n", "x_values_type categorical\n", "y_values_type numerical\n", "x_tick_type markers\n", "y_tick_type markers\n", "dtype: object" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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pQU8nsM65Omnn+aaa65h6dKlfPbZZ/zwhz+kuLiY6667jquvvpqNGzcyc+ZM0tLSuPPOOznnnHNYs2bNAXNUdsRHH31Et27d+Oijj9i0aROXXHIJQ4YM4brrrgOSCtiuXbv46KOPsNls3HTTTVRXH9qV/e677+bhhx+mZ8+e3H333Vx66aVs2rQJVVVZuHAh119/PQ8++CDnnXcec+bM4Ze//OVh9c2mTZt45ZVXeOutt2hqauKaa67hJz/5Cc8//zwAf/rTn/j973/PE088wdChQ/nXv/7Feeedx1dffUXPnj15+umnGThwII8++ig333wz119/PQUFBfzqV786rHp0hIgWKDjq+Lw+/H4/dXV1PPjgg/zqV7/ijTfeYPfu3aiqSjwep7q6mjfeeIN77rmHhx9+mGAwSFpa2n5JPkOhEO+99x733HMPjzzyiJWQ04xQBcnIW08//TQvvPACmzZtIjMzE4fDYVlsnE4nK1as4IEHHqCxsdFa9aioqCAtLQ2v14vL5bJWYXVd59lnn+Wpp55i1apVxGIx/vnPf/Lcc8/x+eefoygKGRkZrFu3jn/+85+8++67lsWrsLCQhoYG3n33XR566CFLQLHZbMRiMSoqKvjLX/5CRUUFXq+XnJwcK8nuX//6V55++mnWrVtH3759KS8v56mnnuL+++/nlVdeQZZlXC4XTz/9NO+++y47duwgMzOTQCDA8uXL+fe//82///1vSyAbOnQo8Xic2bNnc/vtt/Pggw/S0NBAPB5n06ZN/PWvf+XNN9+krKwMWZbZvHkz27Zts5I0m6vpdrudmpoann76aV566SWWLVtGIpHgoYce4uc//zlz5syxNuqb1idVVampqeHf//439913H0uXLqW+vt7KCZZIJHj55Zf58MMP2blzJ+vWreOvf/0r69evp6amhoqKCl566SXLErd06VL+8Y9/UFlZSXZ2Ns3NzezevZva2lrcbnebwACRSIQdO3bwy1/+EpfLxahRo+jXrx9Op9OKKhiPx2loaOCll17igQceYPHixTQ2NlpR3yBpkWlsbGTdunX84Q9/YNWqVfj9fvLy8mhoaOB///d/ee6559ixY4e18r948WL+9a9/sXHjRpxOJ926daOqqsqyHrWPzJeKYRh8/PHHPPbYY9Z4L1++nN/85je88847LFq0iOeeew673c7ixYt54YUXmDVrFolEgtmzZ/P+++9bCRAhuSK6ZMkS/vCHP3D//fezYsUKwuEwhmFY99DOnTt57LHHmD59Oi+88ALr168nEAjQ1NTE66+/zrvvvsvGjRsJBAL4/X4+/PBD/vnPf/Kf//yHvLw8xo0bR05ODp9//jkPP/wwt99+O/Pnz6elpcWK7pdIJFi0aBF/+MMfeO6551i1apXVv2Y9duzYwX333ce2bduora3lww8/5P777+c3v/kNiUSCvLw8S6G///77qaqqYuDAgYwYMYL09HTefvtt7r77bp544gk+++wzq43vvPMO//73v1m2bFmrNTSp/GzdupXq6mqysrIYOHAg27Zt46WXXuK1115j48aNVgCJpUuX8sorr/Dqq6/Sr18/YrEYmzZtYu/evWRlZVFXV8eTTz7Je++9R319PQMHDqRXr140Nzfz2GOPccMNN3D//fej67q1wNTY2Mjf/vY3a/U2NccTJPN6VVdX8+GHH/LYY4+xZcsWZFnG6/XiaFVU//73v/Pzn/+cxx57jE8++QRILnosXLiQ999/n88//7yNJTl1zum6zkMPPcTvf/975s1LKryvv/46t912G2+88QbNzc1WNMlIJMKKFStYsGCBFW3xL3/5C7/5zW949tlnreAgplW6srKSf/7zn9xwww28+OKLbN261XquqqpKJBJh1apVzJs3zzqfubr9r3/9q00UT4Hgv4GioiL++Mc/0rt3by677DJ++tOf8sc//tFSqv7xj39wyimnMHjwYJ5//nl27tzJG2+8cVjXCAQC/PnPf6ZPnz5MmTKFc889l7lz5wKwYcMG3n33XZ588klOPvlkhg8fzj//+U/C4fAhz3vHHXdw7rnn0qtXL+699162bdvGpk2bAHjssceYPHkyd9xxB7169eInP/kJkydPPqx6RyIRnnnmGYYMGcKpp57KY489xksvvcTu3bsBePjhh7nzzjv53ve+R+/evXnwwQfbBAgpKCjgiSee4Be/+AV33XUXs2bN4rnnnmsTxOrrIixXgqOOrut4vV569uzJwIED2bBhA0uXLqVHjx5cccUVyLLMxx9/zMqVK2lpacHr9dKnTx/LjclckQmFQixbtox169ZRV1fHkiVL+PLLL+nevTs+n89yAystLcXlcpGWlka/fv3aJMy12WxkZ2czZMgQPvroI8rLyzn99NO54IIL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q6Opqcmy3rW0tDBnzhxmzJhBcXExP//5z2loSOaKqqqqsqyPkUiEl19+mQULFpCZmcmzzz5r7S2srq5uzdFm58ILL7TCyZsWH/O+NlMyxGIxqqqqLEWroaGBzz//nEWLFrF06VJOPvlkcnNzOf/886mtreXXv/41sVjMciU0iUaj1gLI8uXLrYiOkHTLVlWVDRs20K9fP8ujoKSkhLPPPptXXnmF1157jZKSEi677DLeeust/H4/V155pRWK3bTcmvn1FEWhqqrKssgD1vlefvllXn31VcrKyvj+97/PO++8g81m4wc/+EEyDPzxtWVDIPjWmDdvnvX3448/vt/3gUCAZ5555qDnuP766/dTFv7nf/7H+nvGjBn7HWNG0zPJy8vbL9DEFVdc0eZ96qJraWnpfhZx01U6leuuu84K926+79Gjx4Ebk8L06dOZPn06AD/+8Y87LCPLMvfccw/33HPPft+ZLpOp2Gw2Pvvss05d/1AI5Upw1Nm5cyc7duxg+PDh1n6WzMxMJk6cyN69ezn33HPx+/189dVX7N27l7PPPpt4PG5FvQqFQnzyySd0796djRs3UlhYaK229unTx0qyunnzZoqKili8eDFlZWXous6GDRt49dVXWbVqFSUlJWRlZbF792727t3LSSedZG3yb2xsJDs7m/LycmtjvbmCPHLkSE455RS2b9/OwoUL2bVrF+eddx4jRoyge/fuloWosLCQK6+8kq+++orm5mZeffVVy3Wnd+/e9O/f33JfamlpYfv27Xz11VcMGTKErVu3sm7dOkt4vfDCC3G5XGzbto01a9ZQV1dHbm4uNpvNChSgaRqffPKJFWq+pqaGVatWkZOTw5YtW/B4PGRkZFBRUcHixYuJRCKWwHrOOedYfsuVlZVUVVVRWlqK0+nknXfeYffu3QSDQStCnLmvxrRuLFu2jJ49e1ruV6qqcscdd7BkyRI2bdrE559/zrhx41i5cqXl/22ueHfr1o2srCxKSkoIBoNs2LCBYcOG0a1bN8v9qrq6mvLycurr69mzZw+lpaWkpaVRU1PDunXrsNvtDBgwgA0bNjBz5ky++uorvF4vQ4cOBZLuSqn7fcwoiYsXL8blclFWVkZaWhorV65EVVVUVaW6utoKo+52uykoKEBRFD766CNKSkrIz89n4MCB/OhHP+LZZ59l1apV1NXVWfvu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xAg8Hg8PPPDAQY9xuVx4vV5UVT2oG+ALL7zA3r17WbZsGRkZGQD06NFjv3KLFi1iypQp3H333dx+++3W55WVlUybNo2BAwcCUF5e/nWaeMIi3AIFAoFAIBAIBIIUqpsPrFh9nXJfh4cffphEIsG///1vnn/+eRwOxxE574oVKxg6dKilWHVEZWUlZ511Fr/61a/aKFYAN910E/fddx9jx47lnnvu4csvvzwi9TpREMqVQCAQCAQCgUCQQo7PeUTLfR02b97Mrl270HWdrVu3HrHzulyuQ5bJzs5m1KhRvPjiizQ1NbX57tprr2XLli1cccUVrFq1ihEjRvDYY48dsfp1dYRyJRAIBAKBQCAQpDCqLINuficH2k0lkYwaOKrswNafb0IsFuPyyy/nkksu4Te/+Q3XXnst1dXVhzzObrejadpBywwaNIgVK1ZQV1d3wDIul4u3334bp9PJxIkTaW5ubvN9UVER119/Pa+//jq33347Tz75ZOca9l+AUK4EAoFAIBAIBIIUFFninqn9APZTsMz390zt963lu7r77rtpbGzk0Ucf5c4776RXr1784Ac/OORxpaWlVFRUsGLFCmpqaohGo/uVufTSS8nLy+OCCy5g4cKFbNmyhddee41PP/20TTmPx8M777yDqqpMnjyZlpYWAG655Rbee+89Kioq+OKLL/joo4/o27fvkWn4CYBQrgQCgUAgEAgEgnZMGtCNxy8fRp6/retfnt/J45cP+9byXM2bN49HHnmEZ599lrS0NGRZ5tlnn2XBggU8/vjjBz122rRpTJo0idNPP53s7GxefPHF/crY7Xbef/99cnJyOOeccxg4cCC//e1vURRlv7Jer5d3330XwzA499xzCQaDaJrGDTfcQN++fZk0aRK9evXir3/96xFrf1dHMgyjoyiTxzVNTU34/X4aGxtJS0s71tURCAQCgUAgELTjWMtrkUiEiooKysrKcDq//t4oTTdYWlFHdXOEHF/SFfDbslgJjk8OZy6JUOwCgUAgEAgEAsEBUGTpWwm3LjgxEW6BAoFAIBAIBAJBF6B///54vd4OX88///yxrp4AYbkSCAQCgUAgEAi6BLNmzSIej3f4XW5u7lGujaAjhHIlEAgEAoFAIBB0AUpKSo51FQSHQLgFCgQCgUAgEAgEAsERQChXAoFAIBAIBAKBQHAEEMqVQCAQ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WUE3jK6xIdoMh2cY6MFgUshwu5G83n0/vBzfClaqgijJMoamYbQG5iCRwAiHk24UHg90RrnSTeVKB1knObrmXquks1/yExnJkNocbJDcm9E+CMYRR1UxotHkNd1uDDOgQOo+nuN4zCC5388wjOQeA/O9JGHoOno8nhyvLtAOjGSAG3O/Dq37dwxdT+7x07TkfGjde2W43fvanLIgJRlG19hzBcn2JRLoLheGzZYcq1blytprdrwLuCl7rJCSSx+GYYCmJdvldoPHg3SAzd5dDl1Hd7mSY2WOV/u9Vl1h7pmYSknqeLndSDZbl2vHfvvddB0UBSMex3A4kveY4JjhdDq58847+fnPf47dbmfs2LHs3buXr7766qCugiY9e/bk1VdfZdGiRQQCAf7whz+wZ8+eTilXpaWlzJ07l7Fjx+JwOKxcVQcrX1FRwYoVKygsLMTn8+23qJyTk4PL5WL27NlWTIL2gS98Ph933HEHt956K7quM27cOBobG1m4cCFpaWnW3rOuwHH+S3RwUlfAUv83icViRCIR0tLSLPPp8OHDufHGG/n+979Pjx49qKurO6yoRZIktXE/dDocnHvuuRQWFiLLMm63m6uvvpohQ4bgdrvJz89n/PjxZGdn09LSwimnnMIFF1zAyJEjD31dWYFJDwLJsNxt2m5aJCY9gKzaukykvc7UsSu049tDom28ddN+tW+HgmFFB9SSL8ks03qGb0HLah/lrP0YHc+KcEccKAR5V5l7lnLU+n/79rQfj9Rynfn8eKV9G81XV6k/dL0+/6akjlNH37WPbHk80r5++y3qpnx2PLfDpH1bBMcnv/zlL7n99tv51a9+Rd++fbnkkkuorq7u1LH/+7//y7Bhw5g4cSKnnXYaeXl5nU4K/Pvf/54PPviAoqKiTu11mjZtGpMmTeL0008nOzt7v5DvkIys/eijj/LEE0+Qn5/P+eef3+G5fvOb3/DLX/6SBx54gL59+zJp0iTeeecdK5R7V6HLW64OhiRJBINB3G43gUAATdMoKyvD5/Phcrks14vUkL6HIhqNkkgxOMUSBuNOPZ1gKIQsy7haV1JjCYNINILT42PYiJPo038QNlXFZrNZriHxzlhd+50H332auqeuJYvmfZ+n5RM7416UXueitj7cD6cdx5r2wmH7EL3Hu7DeXqD75oK63Loqqre68rULmY0C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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 21;\n", " var nbb_unformatted_code = \"plot_image_with_annotations(np.random.choice(load_train_image_ids()))\";\n", " var nbb_formatted_code = \"plot_image_with_annotations(np.random.choice(load_train_image_ids()))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_image_with_annotations(np.random.choice(load_train_image_ids()))" ] }, { "cell_type": "markdown", "id": "88ae66a0", "metadata": {}, "source": [ "### Data splits " ] }, { "cell_type": "code", "execution_count": 22, "id": "7b2e2e49", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.606668Z", "start_time": "2023-04-18T15:47:39.581401Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 22;\n", " var nbb_unformatted_code = \"def split_train_indices_by_source():\\n extracted_image_indices = []\\n generated_image_indices = []\\n for i, annotated_image in enumerate(generate_annotated_images()):\\n if annotated_image.annotation.source == Source.extracted:\\n extracted_image_indices.append(i)\\n else:\\n generated_image_indices.append(i)\\n return extracted_image_indices, generated_image_indices\\n\\n\\ndef get_train_val_split_indices(val_fraction=0.1, seed=42):\\n np.random.seed(42)\\n val_size = int(len(load_train_image_ids()) * val_fraction)\\n\\n extracted_image_indices, generated_image_indices = split_train_indices_by_source()\\n extracted_image_indices = np.random.permutation(extracted_image_indices)\\n generated_image_indices = np.random.permutation(generated_image_indices)\\n\\n val_indices = extracted_image_indices[:val_size]\\n n_generated_images_in_val = val_size - len(val_indices)\\n val_indices = np.concatenate(\\n [val_indices, generated_image_indices[:n_generated_images_in_val]]\\n )\\n\\n train_indices = generated_image_indices[n_generated_images_in_val:]\\n\\n assert len(set(train_indices) | set(val_indices)) == len(load_train_image_ids())\\n assert len(val_indices) == val_size\\n assert len(set(train_indices) & set(val_indices)) == 0\\n\\n return train_indices, val_indices\";\n", " var nbb_formatted_code = \"def split_train_indices_by_source():\\n extracted_image_indices = []\\n generated_image_indices = []\\n for i, annotated_image in enumerate(generate_annotated_images()):\\n if annotated_image.annotation.source == Source.extracted:\\n extracted_image_indices.append(i)\\n else:\\n generated_image_indices.append(i)\\n return extracted_image_indices, generated_image_indices\\n\\n\\ndef get_train_val_split_indices(val_fraction=0.1, seed=42):\\n np.random.seed(42)\\n val_size = int(len(load_train_image_ids()) * val_fraction)\\n\\n extracted_image_indices, generated_image_indices = split_train_indices_by_source()\\n extracted_image_indices = np.random.permutation(extracted_image_indices)\\n generated_image_indices = np.random.permutation(generated_image_indices)\\n\\n val_indices = extracted_image_indices[:val_size]\\n n_generated_images_in_val = val_size - len(val_indices)\\n val_indices = np.concatenate(\\n [val_indices, generated_image_indices[:n_generated_images_in_val]]\\n )\\n\\n train_indices = generated_image_indices[n_generated_images_in_val:]\\n\\n assert len(set(train_indices) | set(val_indices)) == len(load_train_image_ids())\\n assert len(val_indices) == val_size\\n assert len(set(train_indices) & set(val_indices)) == 0\\n\\n return train_indices, val_indices\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def split_train_indices_by_source():\n", " extracted_image_indices = []\n", " generated_image_indices = []\n", " for i, annotated_image in enumerate(generate_annotated_images()):\n", " if annotated_image.annotation.source == Source.extracted:\n", " extracted_image_indices.append(i)\n", " else:\n", " generated_image_indices.append(i)\n", " return extracted_image_indices, generated_image_indices\n", "\n", "\n", "def get_train_val_split_indices(val_fraction=0.1, seed=42):\n", " np.random.seed(42)\n", " val_size = int(len(load_train_image_ids()) * val_fraction)\n", "\n", " extracted_image_indices, generated_image_indices = split_train_indices_by_source()\n", " extracted_image_indices = np.random.permutation(extracted_image_indices)\n", " generated_image_indices = np.random.permutation(generated_image_indices)\n", "\n", " val_indices = extracted_image_indices[:val_size]\n", " n_generated_images_in_val = val_size - len(val_indices)\n", " val_indices = np.concatenate(\n", " [val_indices, generated_image_indices[:n_generated_images_in_val]]\n", " )\n", "\n", " train_indices = generated_image_indices[n_generated_images_in_val:]\n", "\n", " assert len(set(train_indices) | set(val_indices)) == len(load_train_image_ids())\n", " assert len(val_indices) == val_size\n", " assert len(set(train_indices) & set(val_indices)) == 0\n", "\n", " return train_indices, val_indices" ] }, { "cell_type": "code", "execution_count": 23, "id": "5ae948ff", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.648756Z", "start_time": "2023-04-18T15:47:39.608585Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Reusing split indices.\n" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 23;\n", " var nbb_unformatted_code = \"CONFIG.val_fraction = 0.1\\nCONFIG.seed = 42\\nCONFIG.train_indices_path = \\\"train_indices.pickle\\\"\\nCONFIG.val_indices_path = \\\"val_indices.pickle\\\"\\n\\nif os.path.exists(CONFIG.train_indices_path) and os.path.exists(\\n CONFIG.val_indices_path\\n):\\n DATA.train_indices = pickle.load(open(CONFIG.train_indices_path, \\\"rb\\\"))\\n DATA.val_indices = pickle.load(open(CONFIG.val_indices_path, \\\"rb\\\"))\\n print(\\\"Reusing split indices.\\\")\\nelse:\\n DATA.train_indices = (\\n DATA.train_indices,\\n DATA.val_indices,\\n ) = get_train_val_split_indices(CONFIG.val_fraction, CONFIG.seed)\\n pickle.dump(DATA.train_indices, open(CONFIG.train_indices_path, \\\"wb\\\"))\\n pickle.dump(DATA.val_indices, open(CONFIG.val_indices_path, \\\"wb\\\"))\";\n", " var nbb_formatted_code = \"CONFIG.val_fraction = 0.1\\nCONFIG.seed = 42\\nCONFIG.train_indices_path = \\\"train_indices.pickle\\\"\\nCONFIG.val_indices_path = \\\"val_indices.pickle\\\"\\n\\nif os.path.exists(CONFIG.train_indices_path) and os.path.exists(\\n CONFIG.val_indices_path\\n):\\n DATA.train_indices = pickle.load(open(CONFIG.train_indices_path, \\\"rb\\\"))\\n DATA.val_indices = pickle.load(open(CONFIG.val_indices_path, \\\"rb\\\"))\\n print(\\\"Reusing split indices.\\\")\\nelse:\\n DATA.train_indices = (\\n DATA.train_indices,\\n DATA.val_indices,\\n ) = get_train_val_split_indices(CONFIG.val_fraction, CONFIG.seed)\\n pickle.dump(DATA.train_indices, open(CONFIG.train_indices_path, \\\"wb\\\"))\\n pickle.dump(DATA.val_indices, open(CONFIG.val_indices_path, \\\"wb\\\"))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.val_fraction = 0.1\n", "CONFIG.seed = 42\n", "CONFIG.train_val_indices_path = \"data/train_val_indices.pickle\"\n", "\n", "DATA.train_indices, DATA.val_indices = load_pickle_or_build_object_and_save(\n", " CONFIG.train_val_indices_path,\n", " lambda : get_train_val_split_indices(CONFIG.val_fraction, CONFIG.seed)\n", ")" ] }, { "cell_type": "markdown", "id": "2a8711a2", "metadata": {}, "source": [ "### Expected model output format " ] }, { "cell_type": "code", "execution_count": 24, "id": "52e5fc7e", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.678486Z", "start_time": "2023-04-18T15:47:39.650465Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
iddata_serieschart_type
0000b92c3b098_xabc;defvertical_bar
1000b92c3b098_y0.0;1.0vertical_bar
2007a18eb4e09_xabc;defvertical_bar
3007a18eb4e09_y0.0;1.0vertical_bar
\n", "
" ], "text/plain": [ " id data_series chart_type\n", "0 000b92c3b098_x abc;def vertical_bar\n", "1 000b92c3b098_y 0.0;1.0 vertical_bar\n", "2 007a18eb4e09_x abc;def vertical_bar\n", "3 007a18eb4e09_y 0.0;1.0 vertical_bar" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 24;\n", " var nbb_unformatted_code = \"pd.read_csv(\\\"data/sample_submission.csv\\\").head(4)\";\n", " var nbb_formatted_code = \"pd.read_csv(\\\"data/sample_submission.csv\\\").head(4)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "pd.read_csv(\"data/sample_submission.csv\").head(4)" ] }, { "cell_type": "markdown", "id": "4be2fa0d", "metadata": {}, "source": [ "In the Benetech competition I need to predict chart type and axis values, so I will create appropriate tokens and later add them to the transformer." ] }, { "cell_type": "code", "execution_count": 25, "id": "6d209989", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.708025Z", "start_time": "2023-04-18T15:47:39.680130Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 25;\n", " var nbb_unformatted_code = \"def to_token_str(value: str or enum.Enum):\\n string = value.name if isinstance(value, enum.Enum) else value\\n if re.fullmatch(\\\"<.*>\\\", string):\\n return string\\n else:\\n return f\\\"<{string}>\\\"\\n\\n\\nTOKEN.benetech_prompt = to_token_str(\\\"benetech_prompt\\\")\\nTOKEN.benetech_prompt_end = to_token_str(\\\"/benetech_prompt\\\")\\n\\nfor chart_type in ChartType:\\n setattr(TOKEN, chart_type.name, to_token_str(chart_type))\\n\\nfor values_type in ValuesType:\\n setattr(TOKEN, values_type.name, to_token_str(values_type))\\n\\nTOKEN.x_start = to_token_str(\\\"x_start\\\")\\nTOKEN.y_start = to_token_str(\\\"y_start\\\")\\nTOKEN.value_separator = to_token_str(\\\";\\\")\";\n", " var nbb_formatted_code = \"def to_token_str(value: str or enum.Enum):\\n string = value.name if isinstance(value, enum.Enum) else value\\n if re.fullmatch(\\\"<.*>\\\", string):\\n return string\\n else:\\n return f\\\"<{string}>\\\"\\n\\n\\nTOKEN.benetech_prompt = to_token_str(\\\"benetech_prompt\\\")\\nTOKEN.benetech_prompt_end = to_token_str(\\\"/benetech_prompt\\\")\\n\\nfor chart_type in ChartType:\\n setattr(TOKEN, chart_type.name, to_token_str(chart_type))\\n\\nfor values_type in ValuesType:\\n setattr(TOKEN, values_type.name, to_token_str(values_type))\\n\\nTOKEN.x_start = to_token_str(\\\"x_start\\\")\\nTOKEN.y_start = to_token_str(\\\"y_start\\\")\\nTOKEN.value_separator = to_token_str(\\\";\\\")\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def to_token_str(value: str or enum.Enum):\n", " string = value.name if isinstance(value, enum.Enum) else value\n", " if re.fullmatch(\"<.*>\", string):\n", " return string\n", " else:\n", " return f\"<{string}>\"\n", "\n", "\n", "TOKEN.benetech_prompt = to_token_str(\"benetech_prompt\")\n", "TOKEN.benetech_prompt_end = to_token_str(\"/benetech_prompt\")\n", "\n", "for chart_type in ChartType:\n", " setattr(TOKEN, chart_type.name, to_token_str(chart_type))\n", "\n", "for values_type in ValuesType:\n", " setattr(TOKEN, values_type.name, to_token_str(values_type))\n", "\n", "TOKEN.x_start = to_token_str(\"x_start\")\n", "TOKEN.y_start = to_token_str(\"y_start\")\n", "TOKEN.value_separator = to_token_str(\";\")" ] }, { "cell_type": "code", "execution_count": 26, "id": "6a100c8e", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.743966Z", "start_time": "2023-04-18T15:47:39.722826Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 26;\n", " var nbb_unformatted_code = \"CONFIG.float_scientific_notation_string_precision = 5\\n\\n\\ndef convert_number_to_scientific_string(value: int or float) -> str:\\n return f\\\"{value:.{CONFIG.float_scientific_notation_string_precision}e}\\\"\\n\\n\\ndef convert_axis_data_to_string(\\n axis_data: list[str or float], values_type: ValuesType\\n) -> str:\\n formatted_axis_data = []\\n for value in axis_data:\\n if values_type == ValuesType.numerical:\\n value = convert_number_to_scientific_string(value)\\n formatted_axis_data.append(value)\\n return TOKEN.value_separator.join(formatted_axis_data)\\n\\n\\ndef convert_string_to_axis_data(string, values_type: ValuesType):\\n data = string.split(TOKEN.value_separator)\\n if values_type == ValuesType.numerical:\\n data = [float(i) for i in data]\\n return data\\n\\n\\ndef compute_numeric_data_loss_due_to_string_conversion():\\n squared_error = 0\\n n_numeric_values = 0\\n for annotated_image in generate_annotated_images():\\n annotation = annotated_image.annotation\\n for axis, data in zip(\\n [annotation.axes.x_axis, annotation.axes.y_axis],\\n [\\n [dp.x for dp in annotation.data_series],\\n [dp.y for dp in annotation.data_series],\\n ],\\n ):\\n if axis.values_type == ValuesType.numerical:\\n string = convert_axis_data_to_string(data, ValuesType.numerical)\\n reconverted_data = convert_string_to_axis_data(\\n string, ValuesType.numerical\\n )\\n squared_error += (\\n (np.array(data) - np.array(reconverted_data)) ** 2\\n ).sum()\\n n_numeric_values += len(data)\\n\\n mse = squared_error**0.5 / n_numeric_values\\n return mse\";\n", " var nbb_formatted_code = \"CONFIG.float_scientific_notation_string_precision = 5\\n\\n\\ndef convert_number_to_scientific_string(value: int or float) -> str:\\n return f\\\"{value:.{CONFIG.float_scientific_notation_string_precision}e}\\\"\\n\\n\\ndef convert_axis_data_to_string(\\n axis_data: list[str or float], values_type: ValuesType\\n) -> str:\\n formatted_axis_data = []\\n for value in axis_data:\\n if values_type == ValuesType.numerical:\\n value = convert_number_to_scientific_string(value)\\n formatted_axis_data.append(value)\\n return TOKEN.value_separator.join(formatted_axis_data)\\n\\n\\ndef convert_string_to_axis_data(string, values_type: ValuesType):\\n data = string.split(TOKEN.value_separator)\\n if values_type == ValuesType.numerical:\\n data = [float(i) for i in data]\\n return data\\n\\n\\ndef compute_numeric_data_loss_due_to_string_conversion():\\n squared_error = 0\\n n_numeric_values = 0\\n for annotated_image in generate_annotated_images():\\n annotation = annotated_image.annotation\\n for axis, data in zip(\\n [annotation.axes.x_axis, annotation.axes.y_axis],\\n [\\n [dp.x for dp in annotation.data_series],\\n [dp.y for dp in annotation.data_series],\\n ],\\n ):\\n if axis.values_type == ValuesType.numerical:\\n string = convert_axis_data_to_string(data, ValuesType.numerical)\\n reconverted_data = convert_string_to_axis_data(\\n string, ValuesType.numerical\\n )\\n squared_error += (\\n (np.array(data) - np.array(reconverted_data)) ** 2\\n ).sum()\\n n_numeric_values += len(data)\\n\\n mse = squared_error**0.5 / n_numeric_values\\n return mse\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.float_scientific_notation_string_precision = 5\n", "\n", "\n", "def convert_number_to_scientific_string(value: int or float) -> str:\n", " return f\"{value:.{CONFIG.float_scientific_notation_string_precision}e}\"\n", "\n", "\n", "def convert_axis_data_to_string(\n", " axis_data: list[str or float], values_type: ValuesType\n", ") -> str:\n", " formatted_axis_data = []\n", " for value in axis_data:\n", " if values_type == ValuesType.numerical:\n", " value = convert_number_to_scientific_string(value)\n", " formatted_axis_data.append(value)\n", " return TOKEN.value_separator.join(formatted_axis_data)\n", "\n", "\n", "def convert_string_to_axis_data(string, values_type: ValuesType):\n", " data = string.split(TOKEN.value_separator)\n", " if values_type == ValuesType.numerical:\n", " data = [float(i) for i in data]\n", " return data\n", "\n", "\n", "def compute_numeric_data_loss_due_to_string_conversion():\n", " squared_error = 0\n", " n_numeric_values = 0\n", " for annotated_image in generate_annotated_images():\n", " annotation = annotated_image.annotation\n", " for axis, data in zip(\n", " [annotation.axes.x_axis, annotation.axes.y_axis],\n", " [\n", " [dp.x for dp in annotation.data_series],\n", " [dp.y for dp in annotation.data_series],\n", " ],\n", " ):\n", " if axis.values_type == ValuesType.numerical:\n", " string = convert_axis_data_to_string(data, ValuesType.numerical)\n", " reconverted_data = convert_string_to_axis_data(\n", " string, ValuesType.numerical\n", " )\n", " squared_error += (\n", " (np.array(data) - np.array(reconverted_data)) ** 2\n", " ).sum()\n", " n_numeric_values += len(data)\n", "\n", " mse = squared_error**0.5 / n_numeric_values\n", " return mse" ] }, { "cell_type": "code", "execution_count": 27, "id": "e5ae33b0", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.782581Z", "start_time": "2023-04-18T15:47:39.750579Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 27;\n", " var nbb_unformatted_code = \"if DEBUG:\\n print(compute_numeric_data_loss_due_to_string_conversion())\";\n", " var nbb_formatted_code = \"if DEBUG:\\n print(compute_numeric_data_loss_due_to_string_conversion())\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " print(compute_numeric_data_loss_due_to_string_conversion())" ] }, { "cell_type": "code", "execution_count": 28, "id": "46dff28d", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.858163Z", "start_time": "2023-04-18T15:47:39.785386Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 28;\n", " var nbb_unformatted_code = \"@dataclasses.dataclass\\nclass BenetechOutput:\\n chart_type: ChartType\\n x_values_type: ValuesType\\n y_values_type: ValuesType\\n x_data: list[str or float]\\n y_data: list[str or float]\\n\\n def __post_init__(self):\\n self.chart_type = ChartType(self.chart_type)\\n self.x_values_type = ValuesType(self.x_values_type)\\n self.y_values_type = ValuesType(self.y_values_type)\\n assert isinstance(self.x_data, list)\\n assert isinstance(self.y_data, list)\\n\\n def get_main_characteristics(self):\\n return (\\n self.chart_type,\\n self.x_values_type,\\n self.y_values_type,\\n len(self.x_data),\\n len(self.y_data),\\n )\\n\\n @staticmethod\\n def from_annotation(annotation: Annotation):\\n return BenetechOutput(\\n chart_type=annotation.chart_type,\\n x_values_type=annotation.axes.x_axis.values_type,\\n y_values_type=annotation.axes.y_axis.values_type,\\n x_data=[dp.x for dp in annotation.data_series],\\n y_data=[dp.y for dp in annotation.data_series],\\n )\\n\\n def to_string(self):\\n return self.format_strings(\\n chart_type=self.chart_type,\\n x_values_type=self.x_values_type,\\n y_values_type=self.y_values_type,\\n x_data=convert_axis_data_to_string(self.x_data, self.x_values_type),\\n y_data=convert_axis_data_to_string(self.y_data, self.y_values_type),\\n )\\n\\n @staticmethod\\n def format_strings(*, chart_type, x_values_type, y_values_type, x_data, y_data):\\n chart_type = to_token_str(chart_type)\\n x_values_type = to_token_str(x_values_type)\\n y_values_type = to_token_str(y_values_type)\\n return (\\n f\\\"{TOKEN.benetech_prompt}{chart_type}\\\"\\n f\\\"{TOKEN.x_start}{x_values_type}{x_data}\\\"\\n f\\\"{TOKEN.y_start}{y_values_type}{y_data}\\\"\\n f\\\"{TOKEN.benetech_prompt_end}\\\"\\n )\\n\\n @staticmethod\\n def get_string_pattern():\\n field_names = [field.name for field in dataclasses.fields(BenetechOutput)]\\n pattern = BenetechOutput.format_strings(\\n **{field_name: f\\\"(?P<{field_name}>.*?)\\\" for field_name in field_names}\\n )\\n return pattern\\n\\n @staticmethod\\n def does_string_match_expected_pattern(string):\\n return bool(re.fullmatch(BenetechOutput.get_string_pattern(), string))\\n\\n @staticmethod\\n def from_string(string):\\n fullmatch = re.fullmatch(BenetechOutput.get_string_pattern(), string)\\n benetech_kwargs = fullmatch.groupdict()\\n benetech_kwargs[\\\"chart_type\\\"] = ChartType(benetech_kwargs[\\\"chart_type\\\"])\\n benetech_kwargs[\\\"x_values_type\\\"] = ValuesType(benetech_kwargs[\\\"x_values_type\\\"])\\n benetech_kwargs[\\\"y_values_type\\\"] = ValuesType(benetech_kwargs[\\\"y_values_type\\\"])\\n benetech_kwargs[\\\"x_data\\\"] = convert_string_to_axis_data(\\n benetech_kwargs[\\\"x_data\\\"], benetech_kwargs[\\\"x_values_type\\\"]\\n )\\n benetech_kwargs[\\\"y_data\\\"] = convert_string_to_axis_data(\\n benetech_kwargs[\\\"y_data\\\"], benetech_kwargs[\\\"y_values_type\\\"]\\n )\\n return BenetechOutput(**benetech_kwargs)\\n\\n\\ndef get_annotation_ground_truth_str(annotation: Annotation):\\n benetech_output = BenetechOutput(\\n chart_type=annotation.chart_type,\\n x_values_type=annotation.axes.x_axis.values_type,\\n x_data=[dp.x for dp in annotation.data_series],\\n y_values_type=annotation.axes.y_axis.values_type,\\n y_data=[dp.y for dp in annotation.data_series],\\n )\\n return benetech_output.to_string()\\n\\n\\ndef get_annotation_ground_truth_str_from_image_index(image_index: int) -> str:\\n return get_annotation_ground_truth_str(Annotation.from_image_index(0))\";\n", " var nbb_formatted_code = \"@dataclasses.dataclass\\nclass BenetechOutput:\\n chart_type: ChartType\\n x_values_type: ValuesType\\n y_values_type: ValuesType\\n x_data: list[str or float]\\n y_data: list[str or float]\\n\\n def __post_init__(self):\\n self.chart_type = ChartType(self.chart_type)\\n self.x_values_type = ValuesType(self.x_values_type)\\n self.y_values_type = ValuesType(self.y_values_type)\\n assert isinstance(self.x_data, list)\\n assert isinstance(self.y_data, list)\\n\\n def get_main_characteristics(self):\\n return (\\n self.chart_type,\\n self.x_values_type,\\n self.y_values_type,\\n len(self.x_data),\\n len(self.y_data),\\n )\\n\\n @staticmethod\\n def from_annotation(annotation: Annotation):\\n return BenetechOutput(\\n chart_type=annotation.chart_type,\\n x_values_type=annotation.axes.x_axis.values_type,\\n y_values_type=annotation.axes.y_axis.values_type,\\n x_data=[dp.x for dp in annotation.data_series],\\n y_data=[dp.y for dp in annotation.data_series],\\n )\\n\\n def to_string(self):\\n return self.format_strings(\\n chart_type=self.chart_type,\\n x_values_type=self.x_values_type,\\n y_values_type=self.y_values_type,\\n x_data=convert_axis_data_to_string(self.x_data, self.x_values_type),\\n y_data=convert_axis_data_to_string(self.y_data, self.y_values_type),\\n )\\n\\n @staticmethod\\n def format_strings(*, chart_type, x_values_type, y_values_type, x_data, y_data):\\n chart_type = to_token_str(chart_type)\\n x_values_type = to_token_str(x_values_type)\\n y_values_type = to_token_str(y_values_type)\\n return (\\n f\\\"{TOKEN.benetech_prompt}{chart_type}\\\"\\n f\\\"{TOKEN.x_start}{x_values_type}{x_data}\\\"\\n f\\\"{TOKEN.y_start}{y_values_type}{y_data}\\\"\\n f\\\"{TOKEN.benetech_prompt_end}\\\"\\n )\\n\\n @staticmethod\\n def get_string_pattern():\\n field_names = [field.name for field in dataclasses.fields(BenetechOutput)]\\n pattern = BenetechOutput.format_strings(\\n **{field_name: f\\\"(?P<{field_name}>.*?)\\\" for field_name in field_names}\\n )\\n return pattern\\n\\n @staticmethod\\n def does_string_match_expected_pattern(string):\\n return bool(re.fullmatch(BenetechOutput.get_string_pattern(), string))\\n\\n @staticmethod\\n def from_string(string):\\n fullmatch = re.fullmatch(BenetechOutput.get_string_pattern(), string)\\n benetech_kwargs = fullmatch.groupdict()\\n benetech_kwargs[\\\"chart_type\\\"] = ChartType(benetech_kwargs[\\\"chart_type\\\"])\\n benetech_kwargs[\\\"x_values_type\\\"] = ValuesType(benetech_kwargs[\\\"x_values_type\\\"])\\n benetech_kwargs[\\\"y_values_type\\\"] = ValuesType(benetech_kwargs[\\\"y_values_type\\\"])\\n benetech_kwargs[\\\"x_data\\\"] = convert_string_to_axis_data(\\n benetech_kwargs[\\\"x_data\\\"], benetech_kwargs[\\\"x_values_type\\\"]\\n )\\n benetech_kwargs[\\\"y_data\\\"] = convert_string_to_axis_data(\\n benetech_kwargs[\\\"y_data\\\"], benetech_kwargs[\\\"y_values_type\\\"]\\n )\\n return BenetechOutput(**benetech_kwargs)\\n\\n\\ndef get_annotation_ground_truth_str(annotation: Annotation):\\n benetech_output = BenetechOutput(\\n chart_type=annotation.chart_type,\\n x_values_type=annotation.axes.x_axis.values_type,\\n x_data=[dp.x for dp in annotation.data_series],\\n y_values_type=annotation.axes.y_axis.values_type,\\n y_data=[dp.y for dp in annotation.data_series],\\n )\\n return benetech_output.to_string()\\n\\n\\ndef get_annotation_ground_truth_str_from_image_index(image_index: int) -> str:\\n return get_annotation_ground_truth_str(Annotation.from_image_index(0))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@dataclasses.dataclass\n", "class BenetechOutput:\n", " chart_type: ChartType\n", " x_values_type: ValuesType\n", " y_values_type: ValuesType\n", " x_data: list[str or float]\n", " y_data: list[str or float]\n", "\n", " def __post_init__(self):\n", " self.chart_type = ChartType(self.chart_type)\n", " self.x_values_type = ValuesType(self.x_values_type)\n", " self.y_values_type = ValuesType(self.y_values_type)\n", " assert isinstance(self.x_data, list)\n", " assert isinstance(self.y_data, list)\n", "\n", " def get_main_characteristics(self):\n", " return (\n", " self.chart_type,\n", " self.x_values_type,\n", " self.y_values_type,\n", " len(self.x_data),\n", " len(self.y_data),\n", " )\n", "\n", " @staticmethod\n", " def from_annotation(annotation: Annotation):\n", " return BenetechOutput(\n", " chart_type=annotation.chart_type,\n", " x_values_type=annotation.axes.x_axis.values_type,\n", " y_values_type=annotation.axes.y_axis.values_type,\n", " x_data=[dp.x for dp in annotation.data_series],\n", " y_data=[dp.y for dp in annotation.data_series],\n", " )\n", "\n", " def to_string(self):\n", " return self.format_strings(\n", " chart_type=self.chart_type,\n", " x_values_type=self.x_values_type,\n", " y_values_type=self.y_values_type,\n", " x_data=convert_axis_data_to_string(self.x_data, self.x_values_type),\n", " y_data=convert_axis_data_to_string(self.y_data, self.y_values_type),\n", " )\n", "\n", " @staticmethod\n", " def format_strings(*, chart_type, x_values_type, y_values_type, x_data, y_data):\n", " chart_type = to_token_str(chart_type)\n", " x_values_type = to_token_str(x_values_type)\n", " y_values_type = to_token_str(y_values_type)\n", " return (\n", " f\"{TOKEN.benetech_prompt}{chart_type}\"\n", " f\"{TOKEN.x_start}{x_values_type}{x_data}\"\n", " f\"{TOKEN.y_start}{y_values_type}{y_data}\"\n", " f\"{TOKEN.benetech_prompt_end}\"\n", " )\n", "\n", " @staticmethod\n", " def get_string_pattern():\n", " field_names = [field.name for field in dataclasses.fields(BenetechOutput)]\n", " pattern = BenetechOutput.format_strings(\n", " **{field_name: f\"(?P<{field_name}>.*?)\" for field_name in field_names}\n", " )\n", " return pattern\n", "\n", " @staticmethod\n", " def does_string_match_expected_pattern(string):\n", " return bool(re.fullmatch(BenetechOutput.get_string_pattern(), string))\n", "\n", " @staticmethod\n", " def from_string(string):\n", " fullmatch = re.fullmatch(BenetechOutput.get_string_pattern(), string)\n", " benetech_kwargs = fullmatch.groupdict()\n", " benetech_kwargs[\"chart_type\"] = ChartType(benetech_kwargs[\"chart_type\"])\n", " benetech_kwargs[\"x_values_type\"] = ValuesType(benetech_kwargs[\"x_values_type\"])\n", " benetech_kwargs[\"y_values_type\"] = ValuesType(benetech_kwargs[\"y_values_type\"])\n", " benetech_kwargs[\"x_data\"] = convert_string_to_axis_data(\n", " benetech_kwargs[\"x_data\"], benetech_kwargs[\"x_values_type\"]\n", " )\n", " benetech_kwargs[\"y_data\"] = convert_string_to_axis_data(\n", " benetech_kwargs[\"y_data\"], benetech_kwargs[\"y_values_type\"]\n", " )\n", " return BenetechOutput(**benetech_kwargs)\n", "\n", "\n", "def get_annotation_ground_truth_str(annotation: Annotation):\n", " benetech_output = BenetechOutput(\n", " chart_type=annotation.chart_type,\n", " x_values_type=annotation.axes.x_axis.values_type,\n", " x_data=[dp.x for dp in annotation.data_series],\n", " y_values_type=annotation.axes.y_axis.values_type,\n", " y_data=[dp.y for dp in annotation.data_series],\n", " )\n", " return benetech_output.to_string()\n", "\n", "\n", "def get_annotation_ground_truth_str_from_image_index(image_index: int) -> str:\n", " return get_annotation_ground_truth_str(Annotation.from_image_index(image_index))" ] }, { "cell_type": "code", "execution_count": 29, "id": "8342617b", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.881898Z", "start_time": "2023-04-18T15:47:39.861073Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 29;\n", " var nbb_unformatted_code = \"if DEBUG:\\n print(BenetechOutput.get_string_pattern(), \\\"\\\\n\\\")\\n print(\\n get_annotation_ground_truth_str(AnnotatedImage.from_image_index(0).annotation),\\n \\\"\\\\n\\\",\\n )\\n pprint.pprint(\\n BenetechOutput.from_string(get_annotation_ground_truth_str_from_image_index(0))\\n )\\n pprint.pprint(BenetechOutput.from_annotation(Annotation.from_image_index(0)))\";\n", " var nbb_formatted_code = \"if DEBUG:\\n print(BenetechOutput.get_string_pattern(), \\\"\\\\n\\\")\\n print(\\n get_annotation_ground_truth_str(AnnotatedImage.from_image_index(0).annotation),\\n \\\"\\\\n\\\",\\n )\\n pprint.pprint(\\n BenetechOutput.from_string(get_annotation_ground_truth_str_from_image_index(0))\\n )\\n pprint.pprint(BenetechOutput.from_annotation(Annotation.from_image_index(0)))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " print(BenetechOutput.get_string_pattern(), \"\\n\")\n", " print(\n", " get_annotation_ground_truth_str(AnnotatedImage.from_image_index(0).annotation),\n", " \"\\n\",\n", " )\n", " pprint.pprint(\n", " BenetechOutput.from_string(get_annotation_ground_truth_str_from_image_index(0))\n", " )\n", " pprint.pprint(BenetechOutput.from_annotation(Annotation.from_image_index(0)))" ] }, { "cell_type": "markdown", "id": "3368ace9", "metadata": {}, "source": [ "### Metrics " ] }, { "cell_type": "code", "execution_count": 30, "id": "3901ad2f", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.926904Z", "start_time": "2023-04-18T15:47:39.883983Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 30;\n", " var nbb_unformatted_code = \"def normalized_rmse(expected: list[float], predicted: list[float]) -> float:\\n return (1 - sklearn.metrics.r2_score(expected, predicted)) ** 0.5\\n\\n\\ndef normalized_levenshtein_distance(expected: list[str], predicted: list[str]) -> float:\\n total_distance = 0\\n for e, p in zip(expected, predicted):\\n total_distance += rapidfuzz.distance.Levenshtein.distance(e, p)\\n total_length = np.sum([len(e) for e in expected])\\n return total_distance / total_length\\n\\n\\ndef sigmoid(x):\\n return 1 / (1 + np.exp(-x))\\n\\n\\ndef positive_loss_to_score(x):\\n return 2 * sigmoid(-x)\\n\\n\\ndef score_axis_values(values_type, expected, predicted):\\n if values_type == ValuesType.numerical:\\n loss = normalized_rmse(expected, predicted)\\n else:\\n loss = normalized_levenshtein_distance(expected, predicted)\\n return positive_loss_to_score(loss)\\n\\n\\ndef benetech_score(expected: BenetechOutput, predicted: BenetechOutput) -> float:\\n if expected.get_main_characteristics() != predicted.get_main_characteristics():\\n return 0\\n x_score = score_axis_values(\\n expected.x_values_type, expected.x_data, predicted.x_data\\n )\\n y_score = score_axis_values(\\n expected.y_values_type, expected.y_data, predicted.y_data\\n )\\n return (x_score + y_score) / 2\\n\\n\\ndef benetech_score_string_prediction(expected_data_index: int, predicted_string: str):\\n if not BenetechOutput.does_string_match_expected_pattern(predicted_string):\\n return 0\\n expected_annotation = Annotation.from_image_index(expected_data_index)\\n expected_output = BenetechOutput.from_annotation(expected_annotation)\\n predicted_output = BenetechOutput.from_string(predicted_string)\\n return benetech_score(expected_output, predicted_output)\";\n", " var nbb_formatted_code = \"def normalized_rmse(expected: list[float], predicted: list[float]) -> float:\\n return (1 - sklearn.metrics.r2_score(expected, predicted)) ** 0.5\\n\\n\\ndef normalized_levenshtein_distance(expected: list[str], predicted: list[str]) -> float:\\n total_distance = 0\\n for e, p in zip(expected, predicted):\\n total_distance += rapidfuzz.distance.Levenshtein.distance(e, p)\\n total_length = np.sum([len(e) for e in expected])\\n return total_distance / total_length\\n\\n\\ndef sigmoid(x):\\n return 1 / (1 + np.exp(-x))\\n\\n\\ndef positive_loss_to_score(x):\\n return 2 * sigmoid(-x)\\n\\n\\ndef score_axis_values(values_type, expected, predicted):\\n if values_type == ValuesType.numerical:\\n loss = normalized_rmse(expected, predicted)\\n else:\\n loss = normalized_levenshtein_distance(expected, predicted)\\n return positive_loss_to_score(loss)\\n\\n\\ndef benetech_score(expected: BenetechOutput, predicted: BenetechOutput) -> float:\\n if expected.get_main_characteristics() != predicted.get_main_characteristics():\\n return 0\\n x_score = score_axis_values(\\n expected.x_values_type, expected.x_data, predicted.x_data\\n )\\n y_score = score_axis_values(\\n expected.y_values_type, expected.y_data, predicted.y_data\\n )\\n return (x_score + y_score) / 2\\n\\n\\ndef benetech_score_string_prediction(expected_data_index: int, predicted_string: str):\\n if not BenetechOutput.does_string_match_expected_pattern(predicted_string):\\n return 0\\n expected_annotation = Annotation.from_image_index(expected_data_index)\\n expected_output = BenetechOutput.from_annotation(expected_annotation)\\n predicted_output = BenetechOutput.from_string(predicted_string)\\n return benetech_score(expected_output, predicted_output)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def normalized_rmse(expected: list[float], predicted: list[float]) -> float:\n", " return (1 - sklearn.metrics.r2_score(expected, predicted)) ** 0.5\n", "\n", "\n", "def normalized_levenshtein_distance(expected: list[str], predicted: list[str]) -> float:\n", " total_distance = 0\n", " for e, p in zip(expected, predicted):\n", " total_distance += rapidfuzz.distance.Levenshtein.distance(e, p)\n", " total_length = np.sum([len(e) for e in expected])\n", " return total_distance / total_length\n", "\n", "\n", "def sigmoid(x):\n", " return 1 / (1 + np.exp(-x))\n", "\n", "\n", "def positive_loss_to_score(x):\n", " return 2 * sigmoid(-x)\n", "\n", "\n", "def score_axis_values(values_type, expected, predicted):\n", " if values_type == ValuesType.numerical:\n", " loss = normalized_rmse(expected, predicted)\n", " else:\n", " loss = normalized_levenshtein_distance(expected, predicted)\n", " return positive_loss_to_score(loss)\n", "\n", "\n", "def benetech_score(expected: BenetechOutput, predicted: BenetechOutput) -> float:\n", " if expected.get_main_characteristics() != predicted.get_main_characteristics():\n", " return 0\n", " x_score = score_axis_values(\n", " expected.x_values_type, expected.x_data, predicted.x_data\n", " )\n", " y_score = score_axis_values(\n", " expected.y_values_type, expected.y_data, predicted.y_data\n", " )\n", " return (x_score + y_score) / 2\n", "\n", "\n", "def benetech_score_string_prediction(expected_data_index: int, predicted_string: str):\n", " if not BenetechOutput.does_string_match_expected_pattern(predicted_string):\n", " return 0\n", " expected_annotation = Annotation.from_image_index(expected_data_index)\n", " expected_output = BenetechOutput.from_annotation(expected_annotation)\n", " predicted_output = BenetechOutput.from_string(predicted_string)\n", " return benetech_score(expected_output, predicted_output)" ] }, { "cell_type": "markdown", "id": "83bcf99d", "metadata": {}, "source": [ "### Dataset " ] }, { "cell_type": "code", "execution_count": null, "id": "2f874683", "metadata": { "ExecuteTime": { "start_time": "2023-04-19T11:32:23.159Z" } }, "outputs": [], "source": [ "1" ] }, { "cell_type": "code", "execution_count": 31, "id": "e532ac55", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:39.990566Z", "start_time": "2023-04-18T15:47:39.933447Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 31;\n", " var nbb_unformatted_code = \"@dataclasses.dataclass\\nclass DataItem:\\n image: torch.FloatTensor\\n target_string: str\\n data_index: int\\n\\n def __post_init__(self):\\n shape = einops.parse_shape(self.image, \\\"channel height width\\\")\\n assert shape[\\\"channel\\\"] == 3, \\\"Image is expected to have 3 channels.\\\"\\n\\n\\nclass Dataset(torch.utils.data.Dataset):\\n def __init__(self, split: Literal[\\\"train\\\", \\\"val\\\", \\\"complete\\\"]):\\n super().__init__()\\n match split:\\n case \\\"train\\\":\\n self.indices = DATA.train_indices\\n case \\\"val\\\":\\n self.indices = DATA.val_indices\\n case \\\"complete\\\":\\n self.indices = np.arange(len(load_train_image_ids()))\\n case _:\\n raise ValueError(f\\\"Unknown split {split}.\\\")\\n self.to_tensor = torchvision.transforms.ToTensor()\\n\\n def __len__(self):\\n return len(self.indices)\\n\\n def __getitem__(self, idx: int) -> DataItem:\\n data_index = self.indices[idx]\\n\\n annotated_image = AnnotatedImage.from_image_index(data_index)\\n\\n image = annotated_image.image\\n image = self.to_tensor(image)\\n\\n target_string = get_annotation_ground_truth_str(annotated_image.annotation)\\n\\n return DataItem(image=image, target_string=target_string, data_index=data_index)\";\n", " var nbb_formatted_code = \"@dataclasses.dataclass\\nclass DataItem:\\n image: torch.FloatTensor\\n target_string: str\\n data_index: int\\n\\n def __post_init__(self):\\n shape = einops.parse_shape(self.image, \\\"channel height width\\\")\\n assert shape[\\\"channel\\\"] == 3, \\\"Image is expected to have 3 channels.\\\"\\n\\n\\nclass Dataset(torch.utils.data.Dataset):\\n def __init__(self, split: Literal[\\\"train\\\", \\\"val\\\", \\\"complete\\\"]):\\n super().__init__()\\n match split:\\n case \\\"train\\\":\\n self.indices = DATA.train_indices\\n case \\\"val\\\":\\n self.indices = DATA.val_indices\\n case \\\"complete\\\":\\n self.indices = np.arange(len(load_train_image_ids()))\\n case _:\\n raise ValueError(f\\\"Unknown split {split}.\\\")\\n self.to_tensor = torchvision.transforms.ToTensor()\\n\\n def __len__(self):\\n return len(self.indices)\\n\\n def __getitem__(self, idx: int) -> DataItem:\\n data_index = self.indices[idx]\\n\\n annotated_image = AnnotatedImage.from_image_index(data_index)\\n\\n image = annotated_image.image\\n image = self.to_tensor(image)\\n\\n target_string = get_annotation_ground_truth_str(annotated_image.annotation)\\n\\n return DataItem(image=image, target_string=target_string, data_index=data_index)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@dataclasses.dataclass\n", "class DataItem:\n", " image: torch.FloatTensor\n", " target_string: str\n", " data_index: int\n", "\n", " def __post_init__(self):\n", " shape = einops.parse_shape(self.image, \"channel height width\")\n", " assert shape[\"channel\"] == 3, \"Image is expected to have 3 channels.\"\n", "\n", "\n", "class Dataset(torch.utils.data.Dataset):\n", " def __init__(self, split: Literal[\"train\", \"val\", \"complete\"]):\n", " super().__init__()\n", " match split:\n", " case \"train\":\n", " self.indices = DATA.train_indices\n", " case \"val\":\n", " self.indices = DATA.val_indices\n", " case \"complete\":\n", " self.indices = np.arange(len(load_train_image_ids()))\n", " case _:\n", " raise ValueError(f\"Unknown split {split}.\")\n", " self.to_tensor = torchvision.transforms.ToTensor()\n", "\n", " def __len__(self):\n", " return len(self.indices)\n", "\n", " def __getitem__(self, idx: int) -> DataItem:\n", " data_index = self.indices[idx]\n", "\n", " annotated_image = AnnotatedImage.from_image_index(data_index)\n", "\n", " image = annotated_image.image\n", " image = self.to_tensor(image)\n", "\n", " target_string = get_annotation_ground_truth_str(annotated_image.annotation)\n", "\n", " return DataItem(image=image, target_string=target_string, data_index=data_index)" ] }, { "cell_type": "code", "execution_count": 32, "id": "0ccf561f", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:40.023555Z", "start_time": "2023-04-18T15:47:39.992916Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 32;\n", " var nbb_unformatted_code = \"DATA.train_dataset = Dataset(\\\"train\\\")\\nDATA.val_dataset = Dataset(\\\"val\\\")\\nDATA.complete_dataset = Dataset(\\\"complete\\\")\";\n", " var nbb_formatted_code = \"DATA.train_dataset = Dataset(\\\"train\\\")\\nDATA.val_dataset = Dataset(\\\"val\\\")\\nDATA.complete_dataset = Dataset(\\\"complete\\\")\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "DATA.train_dataset = Dataset(\"train\")\n", "DATA.val_dataset = Dataset(\"val\")\n", "DATA.complete_dataset = Dataset(\"complete\")" ] }, { "cell_type": "code", "execution_count": 33, "id": "773d4fcc", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:40.136084Z", "start_time": "2023-04-18T15:47:40.031292Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "16<;>17<;>18<;>19<;>20<;>21<;>22<;>23<;>24<;>25<;>26<;>27<;>28<;>29<;>303.79953e+02<;>4.12642e+02<;>3.82075e+02<;>3.69340e+02<;>2.86557e+02<;>2.65330e+02<;>2.35613e+02<;>2.56840e+02<;>1.99528e+02<;>1.95283e+02<;>2.12264e+02<;>1.88915e+02<;>1.91038e+02<;>1.94434e+02<;>2.18632e+02\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/home/dkkoshman/YSDA/python3.10/lib/python3.10/site-packages/torchvision/transforms/functional.py:152: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at ../torch/csrc/utils/tensor_numpy.cpp:206.)\n", " img = torch.from_numpy(pic.transpose((2, 0, 1))).contiguous()\n" ] }, { "data": { "image/png": "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bwRBsGXLlpmZGTEapGn6/e9/f2Zmxjl33333bdiw4dy5cwcOHNi/f//evXtFt5KpYseOHePj41EUvfLKK3v27Ll8+fJzzz3X6XR27NjxxBNPAPjFL35x+fLl6enpBx980Hv/93//99bap59++plnnsnzfG5uTuaVp59+ulKpHDp06JVXXtm1a9eXv/xleUhWVlZWV1dlmXz58uVDhw7VarXl5eXFxcX77rtPbkEYhp1Op1qtHj9+fHZ2Ns/z999//8EHH4yiqFqtXr58+S//8i+JaN++ffv37z979uwHH3xw6NChr33ta3Ecj4yMPPvss977b3/729bakydPHjt2rNlsPvLII7t37263288//3yv15ucnPz85z/PzIcPH87zfHFx8atf/Wq9Xn/zzTcfffTRMAzffPPNhx9+GMCBAweeffbZL3zhC3L6R48eff3119euXfu5z30uTdMXX3xxdHR0w4YNYRi++OKLp0+fTtP0mWeeOXfu3LFjxyqVyuOPPy5OlGq1KsI0y7If/vCH69evz/N8/fr1O3bskLlw7dq1W7duTZLkueeeE33wxIkTv/d7v7dr167Lly8fP3587969o6Oj27dv37t377/9t/9WVIRDhw79m3/zb5xzb7/99uLiYpqmcRwfP378tdde27x589LSUq1We+WVV7rdbhAEX/nKV2q12vvvv//SSy9prb/0pS/JUO90OqdOnTp69Giz2fy93/u92dnZM2fOvP3220R09OjRP/zDP2w0Gq+99tr8/Hyz2Xz88ce3bdvWbrcrlcrExMTo6OjRo0dF0H/5y1+enJx8//33jx8/LhLwnnvuOXDgwE9/+tM4jnfv3n3q1Klt27bV6/W/+7u/+/rXvy7X+atf/eq5c+d+/vOfh2H4hS98AcCxY8fm5uYuXrw4Njb2zDPPdLvd119/fXV1VSk1OTn5uc99TuxdtVpNjDY7d+6cnp7OskyW4IXzA8DU1BSAwsizY8eOIAief/75jRs3rlmzRhZG1Wp19+7dRFRY/J577rn9+/dPTU2988471Wp1fHz86NGjrVZreXn5C1/4wrp16+bn5//f//t/nU7n0Ucfveeee86ePXvo0KFms/nUU0/Nzs7+r//1v+ShKExYdxOfeS1ejC0ACn/j2NgYMydJsrq6+vTTT4vy3ul0Nm3a1Ov1Lly4sH79+qmpqXa7ffbs2Z/97GeVSuX3f//3f/rTn4r6cOHChb/+679es2bNmjVrlpeXZe0fhuFbb73VbDYPHTqUZZksTpMk+eCDD7TWIoW99z/5yU82bty4Y8eOWq32wQcfMPPy8rJYMEVfSNP0zJkzxph169bJTDM1NbV27dqNGzdOTEzEcVyr1ZRShw8f3rNnz2OPPTY+Pv7mm2+KOWX//v333HOPWELEQp2maZ7n8sx0Oh0ZuDt27Ni/f/+ZM2dOnz4N4P7779++ffupU6dWVlbGx8e3bdv2zDPP/N7v/Z448URVPHv27KVLl5aWlg4ePPinf/qnDz74YK/Xu3z5sth5RkdHjxw5orVuNpsnT54cGRmpVqvvvvuuKOxi5TfGPPXUU/Pz85cvX/7ggw8qlcq2bdtk8Z4kyXe+852HHnrowIED1trl5eULFy5897vfnZqamp2d/au/+qtKpfLkk08uLi7W63WZ6iYmJi5evNhqtX7yk59ore+9997169cDyPN806ZNs7Oz8/PzrVaLmU+fPi3rlVOnTokR5uWXX/7X//pfb9q0CcC777576NCh73znO6dPn261WpOTk9u2bRNrwLp167Zs2XLvvfc+88wzzWbztddeazQae/fujePYObdmzZrFxcV2u52m6dzc3PHjx0dHR/M8f+utt2SMaa3FJnDhwoWxsbENGzaImWvz5s1Jkjz66KPnz593zk1NTTnnnn/++d27d4+OjspgkM9u2bJFjHUANm/evHfv3kcffbTRaPzoRz+q1+uPPPIIgJ///Odi1mDmp59+WlTvXq9Xq9U2btz4pS996YknnhArx9zcXK1W27NnT6/X27Bhw9mzZ0+ePLl169bp6ekLFy6ISUprvbq6ury8PD09/cgjj8RxfPr06cXFxUOHDo2Pj8/NzZ07d65arW7dunXHjh379u3bsGFDkiTnzp3r9Xqvv/76+fPn5+fnz5w5A+BnP/vZl7/85dnZ2R/96EcLCwuiPt9zzz0yqczPz7/77rtr1qyZnp4+ffq0LExFgz558uTLL7/8wgsv/NVf/dX/+T//B4CM/5MnT/7N3/zNz372M3moz507J1oaEa2urh47dmz//v0AlFLPPffcyMjIAw88IEu0wnl74MCB1dXVN954o1qtViqVd999d8OGDbVa7dVXX83zfGxs7Mknn5yenj569GiapisrK6dOnfrmN785PT39q1/9anFx8cknn5yamhp28N41fOZFfCHflVKycKvVauPj4wcOHGDmxx9/PIqiF154YXR0NI7j5eXlX/7yl2IeXV1d3bBhw9zc3NGjR3/84x+vXbtWDNbW2pWVlc2bN4vZTnxBGzduHBsbO3LkSJZlO3bsmJqaEiODiJj169evX7++Wq1evHhxenr6nnvuWbdunegR3W5XhLIcahiG3W53y5YtDzzwgJjaiWhycnLDhg3ValUe+CRJTp48GcfxzMzMpk2bxONUqVREWRYrikiiwne6sLAwMjIyOTkpOqw8h5OTk+fOnfvBD36wsLDw3nvvidtQvMHLy8tRFMVxvGXLlv37909OTiqlRkZGNm/e/P3vf/+dd94ZGRlZs2ZN4TEWa3gURUqpe++9d+vWreJxLe4CEc3Ozk5OTr766qtHjhzZuXNnlmXLy8ui8j/77LOvvfba8ePH8zyfnp42xvzlX/7lhQsXWq3WF7/4xZWVlYMHD4pR6K233rp48eKZM2def/11MVOsXbt2586ds7Ozcl+2bNkiBtw0TQs7sljJxCu4du3a//k//+fZs2dFPB05cuT73//+pk2bVlZWxOhfq9XEztNoNCYmJrrdbqPR2Lx589zc3PPPPx9F0cjIyPnz52Vqj+NYZp377rtv165d4qwDIJaKN998880337z//vujKBKbkkzbFy9eDIJADu/ChQsnTpx49NFHxfIg5ngikigvCdEZGRmRPQDo9Xpyvhs3bkySpNFoVCqVTZs2iRFG7ppcqJdffvmHP/zh4uJir9e7ePHisWPHVlZWxOKfJMnzzz//3nvvXbp0SXytMl2Njo7WarXJycm1a9fmeb68vNzr9V566aWLFy9qrZlZvJSNRmNyclLMO+fPn5+bm9u1a9e5c+eOHj26Y8cO7/3777//13/916dOnbr//vvjOH755ZcPHTr05ptvikVL/M/79++XhaPMZCKOjTF79+79sz/7sy9/+cvtdvvixYvW2q9//evf/va3H3nkkfn5+aWlpeeee+71118/c+aMBPAcP358YmJi586dSZKcOXPm2LFjZ8+efeedd959912xpIVh+OSTT3Y6nePHjzNzpVKRpdu5c+dWVlYajYYx5sCBA6+99trBgwePHTsWRZG1dmpqSsyhMvsePXr0yJEjcpHvMj7zIl6MazKSRORVq9XZ2VlZ/o+Njc3MzDz77LPbtm0Tn9WWLVu+853v/Mmf/MnDDz+slFpeXn7wwQf/5b/8l3/8x38sBtnZ2dmpqannn3++2+3WarVWqyWxKGvXrv3FL36RZZnYSSToIoqiKIq896J0JEly+fJlcauKEBHREwTBe++9J/pX4bZdXl42xkhM4fAUFYZhvV6XmEgMAhDb7bYsewuLsLgEJiYmmPnYsWNibh4ZGXn00Ue/8Y1vPPnkkyMjI++99966deu++MUvrl27VpYdQRBMT0+Pj48751ZXV0UHb7fb4pp7/PHH//RP/3RhYeHnP/85M0dR1Ov15ufnK5VKp9MpvI7ingIgdobV1VVZNu3cufPgwYMLCwtbtmyJ41gcG2+//fbmzZu/9a1viRlqzZo1jz766De/+c1f/epXQRBs27btj//4j1ut1vPPPy+LgF27dj3wwAPinpVv995fvnzZGLNmzZrC/CphG9VqVV5IUAeAP/qjP/qjP/qj119//ezZs1NTU/fff/+/+lf/6tFHH926dasIRwnKlPCMbrcbRREzP/jgg//oH/2jLMt+8YtftFotmXHF35tlmbW21+vJPZUxBmB1dfXixYujo6NiApLoLJnj33777W3btgVBcP78+b/927/9whe+sHHjRgkBSJJkdHR0fn7+9OnTjUZjdHRUa62UWl1dbTabci/m5+clSLTw7sr8J9+Spunly5fPnDmzd+/eP//zPxeD0o4dO1qt1tmzZ3fs2LG0tBSG4e7du7/97W9/5zvf2bVrlzGmML6LNyXPcwn03LBhw5o1ax555JE//MM//NKXvlSv140xYpcnoscff/zMmTPvvPPOV7/6VVnNPPXUU51OZ3R09Lvf/e4/+Sf/ZPPmzSMjIxMTE/fff/+/+Bf/4k//9E/Hx8dlsHU6HTHHi6Ig11wpJXOb6AfiClZKtVqtLMuSJJmYmHjggQf+8T/+xzJxinSWh1drPTMz893vfnf37t1yDBMTE+LulkX5888/v2XLFpHpDz/88AMPPPDP/tk/e+KJJ1qt1vHjxx955JE//uM/loA0sb5KxM709PQf/dEf1Wq1X/3qV3elOf4zb4sX3UdGjDh2vPcPP/zwX//1Xz/66KMSwTYyMtJoNJRSMzMz991333/7b/+tWq3u379fa/3Nb37z8OHDr7766p49e3bu3LlmzRpjzDe+8Y1f/OIXhw8f3rdv3+zsrChTX/rSl374wx9+4xvfGBsbE48TgIceeuiFF174r//1v+7duzcIgu9973s/+tGPXnzxxS1btnz3u9/13m/fvv3w4cNvv/32mjVrZChLnKK1dvv27UmSaK03bNhw5syZV1555cEHHwTgnHvqqad++tOf/sVf/IVS6vd///clik5sBUWUxerq6qZNm/7H//gfYRiOj4//wR/8ATN/7Wtfe+GFFw4dOnTffffFcbxv374f/vCH//2//3fRRiuVyszMzFtvvRUEwb59+6anp8VIun79+kqlkmXZCy+8cPr06V27dt17773izxQBNDExIY/E+vXrFxcXJyYmtmzZIgFzAEQPbTQaMkHed999IkaNMVNTU7t27XrxxRer1eq6deuyLPvggw/eeOMNsYqKcamwKU9PT1cqlZ/97GdEJDGjX//611944YX/9J/+0+OPP26MWb9+PRFJuNvU1FSv19u3b98LL7ywtLQkcUHOub/5m79ZWFjYtm2bRMKdP3/+P//n/zw1NfXFL34xSZJ77rnn4MGDWZZ98Ytf3LJly2uvvXby5ElZfh0+fDiO461bt0qcZZqmmzdv7vV6Sqn169dLmKys3gDkef7SSy8dPnx4fHz8hz/84fbt2++7777HH3/88OHDL7300vbt27/2ta9lWfbLX/5yeXn5Zz/72dmzZx944IE4jp955pkf/OAHKysrW7duffDBB8XYdebMmV27dol2+cwzzzz33HOvvfba5OSkyNMNGzZIdKN49aMo6na7mzdvfv7559M0FYl2/Pjx7du3r1279uDBg0EQ7N27d/v27d///ver1eo999wzMTEhQ4iZJyYmjh8/fvDgwe3btz/44IPdbveLX/zij3/840ajMTs7++STT9ZqtdHR0R/84AfPPPPM1NTUnj17Wq3W2rVrx8bGxA3OzF/5ylf+7//9v2EYShzXU0899fLLL/+X//JfpqenxRY/MzMjMn12dlbid0Ux2rJlS7PZ/I//8T8GQfDkk0/W63XRxy9dujQ9Pf2Vr3yFmcfGxnq9nqwqTp06NTExsWvXLlkcABATXKfTKUKfu93u6Ojozp07jx079vDDD+d5vn379vfff/8nP/lJHMf79+/ftWvXzMzMT3/6UwDyGMZxLLapmZmZM2fOvPjii81m87HHHiusvncTn/m4+GEkrUN+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ZVleunRpf39/ZWUlhPDTn/60ruuFhQURKcvyl2mB+Q05ZVlOJpMUBGWM+du//dvJZPLEE0+0Wq0vfOELJ0+enE6nP/vZz65fv556bNKbIvL4fsvMZVkOh0PnnPf+0qVLCwsLp06dUtW9vT1mvnv37pUrV77//e+HEB5T1ExNGzOfXYBZzMWrr746mUw+97nPJRdEr9e7evVqt9tdXFxMX0zFEtFjulaScmqE9M7Ozs54PF5fX7fWptspbt++fenSJVX9qH7/JUh5DwG8+eabdV33ej0i+uY3v/nCCy/84Ac/uHnz5ng8TgM8jfHHFJWaPfWcEMJoNNrf3x8MBjHGd999N80ladxtb2/XdZ00z/y7xpjHl//Rlvm4j/p3DWttURQpsw0zj0ajqqqGw2G32xWRtbW1L3/5y9/+9rfrut7d3f0VVEbqOnVd48BOz/M8hHD9+vVkdc4zLvzC1AupgzJzutKk3W632+2VlZV+v3/58uVXXnnlz//8z//Vv/pXzPyf/tN/+rj1nGurdrs9z/PTbrf//t//+9/97nefeuqphYUFY0yWZan+jyon9bw02Ky16aEGg8G///f/Psuy73znO1mWVVV1586dNK2mcZ7GajYLFcJjsmKk6xtTa7z33ntJuxVFkfpxmgjnIzD9xMfCe//aa68x81e/+tWUvrQsy5///OdFUZw4cWI6nU6n0/F4nASaBPFQxuMxDqmMqqq2trb29/d///d/n5nH47Ex5nOf+9xzzz3Xbrd//OMf/wr1BHD37t26rs+fP3/y5MmyLK9evVpVVZrpr1y5Mp1OvfcxxsFg8KhyiqJg5iQm55wxxnt///790Wj01a9+dXl5GUCn0/na17729NNPr6ys3L17NzV1it1Ks9Rj6umcS5doArh58+bOzs7S0lKyotrt9vnz57/yla9cuHChqqp09eajypl3EiKy1iY9FWO8devWcDh85plnTpw4QUTj8Xh7e/utt9564oknUjcQESJSVVV9zBBLnYqZe72eqr7zzjtXr149efLk0tJSCOF73/ve2bNn/8W/+Bd/8id/8vLLL29ubv4C8TxACKHVar311lsbGxvf/e53z5w5E2N88skn/9k/+2fPPfdcr9dbW1sTkWQ6PKaeVVXFGK21zrk0ha+trX3uc5/7xje+8a1vfeuHP/xhWZZziahqnierX1IL4GBe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Y8U3HKax4hs+VWKMrVbr+eef/zf/5t9MJhPn3CuvvHL9+nUcnBkGME+wg0Pp1dL5ID1ILDMcDtOZrDRbzL+enODpfBYO8selTJDpdVVV8zeTvfz1r399fX09qcUXXnjh3r17VVXt7u7+23/7b2/evKmq3vv/8l/+SzqNhQMjOmnYVLf04vjx4y+//HJStekD6X/T0Zt5ysCqqkaj0fb29okTJ1LaHAA3btz467/+6xhjr9e7ceOGiKRknIcDIlM58xN2L7/88iuvvKKqt27dev7551Ma0bQHm35IRObJ1OYNO5lMUsuISPr8JyLmhr8zNFZ8w6dKMjNDCBcuXLh06dIf/MEfdLvd+/fvV1WV8gsePXr0/v377XY7z/PXXnvt+PHj77zzzsrKypNPPvnmm2/2+/2vf/3rd+/eHY1Gw+Hw5z//eafT+frXv15V1c7OztWrV9vt9tNPP720tPSTn/xka2ur1Wo9++yzS0tL6ZjrpUuXNjc38zxfWlp66qmnnn/++Rs3brz++usXLlzodrvW2iNHjuzu7uZ5vrm5ubS0dPXq1S996UtbW1spsd10On311VevXLnyzDPPPPPMM9baq1ev/uQnP1lbW3v22WdXV1e73e6xY8feeuutnZ2d73znOykNZ8rhtbOz471fWlq6ePHiO++8c/ny5fX1dVXt9/ve++vXr1+6dGl5efnixYvj8fj9999PiYyeeeaZbre7vb396quvpkTZX/nKV9KscOzYsatXr+7v79+4cePIkSNEtLOzc/PmTSI6c+bMwsLCZDJ5+eWXAayvrz/zzDO3bt3a2NgAsLa2dvTo0fRE+CVOjTb8VtNY8Q2fNiLS7XaffvrpjY2N27dvp/Ooxpjbt28nc/v69eubm5vW2mvXrm1vb//+7//+22+/fenSpeeeey5lQzt+/Pje3t69e/e++c1vDofDN954w3v/zjvvfPnLXw4hvPHGG/v7+2+++Wa32/3a1762tLSUcldcvnz5vffeO3/+/IULF956663RaHTmzJnTp08vLCwsLS2l46zLy8vXrl2bTCbb29tPP/10yuC2u7t7/PjxPM+vX79urf0n/+SfDIfDW7duvfXWW++8884/+kf/aH19/fnnnwcwnU4vXbp09+7d5Hfqdrv9fv/9999/++23z507d+HChevXr29tbZ09e/bYsWNnz549derU4uLi2tra+vr6+vr6mTNnUqBRnucrKyt37twZDAbj8fjSpUsXL168cOHC7u5uMsyrqjp37tyRI0f+83/+z9ba73znO/fu3Xv33XeXlpa63e5LL73UarX29/e/9a1vfetb3/rpT3+6u7sbQvibv/mbxcXFdrv9EQ/S/8x5goa/4zQqvuFTJYUettvthYWFM2fOXLlyJeXjTcGCc+98VVXp1oWnnnpqaWmp3++fP39+eXk55XWp6/rYsWMpT3en0xkOh5cuXRqPx/v7+1mWbW1tOedSJu6Ui6Yoiv39/StXrpw6derUqVNHjhxptVqDwaDdbrdarWPHjuEgjcGZM2f6/f7+/n5Zlk899dTa2tqdO3fu379/6tQpY8zbb789Go3efffde/fu3bp1K93YcO3atdu3b4vIdDqNMV66dGkymTz77LMArLXD4fD69esLCwvHjx8/ceLEsWPHtre3UwD+PPFROi3V6/XSlUxZlp04cWJ1dbXf76ccudeuXdvc3Ew5RCeTiao651qt1qlTp8bjccoRXZblPBf8/fv3U4zN9vb2zZs3U2PWdX3kyJFz586trq6m+SxlwU05W36TfaLhk6RR8Q2fKikNy9bWFoAvf/nLIvLaa6+lizuS7gYwv9cmub/LslTVxcXFFEbS6/V2d3eTwz0pu/mGZLql4cyZM8nPM51O51nv51nSAHjv0ywSY9zY2Eh+j+l0SkStVmt5eTn5uNM27M9+9rN79+6trKykuccYc/Lkya985SsXL15cXFx0zq2trT3zzDPf/va3p9NpuhGpqqq9vT0chD8mBZp8+ul3U16dZErP1f3hjdxkVrdara2tLVVttVqLi4udTuepp57q9/sp5yKAxcXFLMvS1WPpopI8z8+fP//FL35xa2vr9u3bKVM8DvYhFhYWUqOl382yzFqb/GafZh9o+DRpVHzDp0pSxykJbVEUZ8+eTTnTsyxbWVm5ffv29evXU5rZyWTS6XS2trbSZRc3btwwxqyurm5ubq6srIzH4x//+Mfb29shhMXFxS996Uv9fj8Z/ulCuJT5uSiK5EMviuLJJ5+8fv36tWvX7t+/H0JYX19P92Mk3ZplWZpasix7++23U+Ly48ePb21ttdvt9Mnz58+n5LSpcFXd399PN/wZYxYXF621586dO3v27Isvvri9vd1qtZxzp06d2tnZuXPnzq1bt7a2tk6ePLm8vKyqw+Ewaduk9IfD4euvv54yV9d17b1fXV01xjjnTp482e/3u93u2bNn03VmAFIO6nTPooisrKykzxPR0aNHrbUpUeXZs2dTM6Zmn581O5wBoonA+QzTHH1q+FRJauXFF1+8ePFi2mn8/ve/f/bs2bNnz25ubl67dq3T6Xjv2+322bNn33777fPnz2dZduPGjV6vt7S09P7772dZdvTo0UuXLnW73XfffffEiRNPPfXUdDqdTCZvvPFGv98/duzY+vr622+/vbCwsLi4mPLxhhCKorh06dJoNCqKYmlp6fz583fu3Ll58+aXv/zldMtrMrfTxXJPP/108gv95Cc/OX369KlTpwDs7++/9957b7/99tNPP/3FL36Rme/du/fCCy8sLS2dOnXq/PnzP/vZz86cObO0tPTTn/709OnTx48fT4mLk/cmzUbPPPPM3t7erVu3nnzyyflNZFVVpcovLi5ubGwcO3ZseXl5e3u7qqqlpaXNzc0f//jHa2trx44dm98ulNIIJ/97URSLi4u3b99OVwM+9dRTx48f393dfe2119IlYufOnUsem6effjr9YgpPevwVYA2/7WiThqzhUyYlMEgZ80MI89sekgoeDoftdjsFHaZE6smTcDg/1zxj8Efu9Dgchz4/KJQs2ZSefp7ZP2nz+aUx6YvpMx9JR6yqaTHxkbTsODC98zz/iCP7cDVS+u/5D6WfSHn800MlV3gK7U9W+Tzbe0rvnq6zmBee4oIO508+fAI21XxnZyetEpLnKpU8r8A8Rdqj6tzwWaJR8Q0NDQ2fWZoEBg0NDQ2fZRoV39DQ0PCZpVHxDQ0NDZ9ZGhXf0NDQ8JmlUfENDQ0Nn1kaFd/Q0NDwmaVR8Q0NDQ2fWRoV39DQ0PCZpVHxDQ0NDZ9ZGhXf0NDQ8JmlUfENDQ0Nn1kaFd/Q0NDwmaVR8Q0NDQ2fWRoV39DQ0PCZ5f8P2Pqo0QpbnhkAAAAASUVORK5CYII=", "text/plain": [ "" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 33;\n", " var nbb_unformatted_code = \"print(DATA.train_dataset[0].target_string)\\ntorchvision.transforms.functional.to_pil_image(DATA.train_dataset[0].image)\";\n", " var nbb_formatted_code = \"print(DATA.train_dataset[0].target_string)\\ntorchvision.transforms.functional.to_pil_image(DATA.train_dataset[0].image)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "print(DATA.train_dataset[0].target_string)\n", "torchvision.transforms.functional.to_pil_image(DATA.train_dataset[0].image)" ] }, { "cell_type": "markdown", "id": "ec80e30c", "metadata": {}, "source": [ "## Model " ] }, { "cell_type": "code", "execution_count": 4, "id": "b44db7e4", "metadata": { "ExecuteTime": { "end_time": "2023-04-19T11:35:49.248446Z", "start_time": "2023-04-19T11:35:49.165590Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 4;\n", " var nbb_unformatted_code = \"transformers.processing_utils.ProcessorMixin?\";\n", " var nbb_formatted_code = \"transformers.processing_utils.ProcessorMixin?\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "transformers.processing_utils.ProcessorMixin?" ] }, { "cell_type": "code", "execution_count": null, "id": "954300a4", "metadata": {}, "outputs": [], "source": [ "transformers.VisionEncoderDecoderModel.to" ] }, { "cell_type": "code", "execution_count": 12, "id": "7ce37bda", "metadata": { "ExecuteTime": { "end_time": "2023-04-19T11:39:30.070268Z", "start_time": "2023-04-19T11:39:22.652334Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 12;\n", " var nbb_unformatted_code = \"de = transformers.VisionEncoderDecoderModel.from_pretrained(\\n \\\"naver-clova-ix/donut-base\\\"\\n)\";\n", " var nbb_formatted_code = \"de = transformers.VisionEncoderDecoderModel.from_pretrained(\\\"naver-clova-ix/donut-base\\\")\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "de = transformers.VisionEncoderDecoderModel.from_pretrained(\n", " \"naver-clova-ix/donut-base\"\n", ")" ] }, { "cell_type": "code", "execution_count": 9, "id": "d7dfcf78", "metadata": { "ExecuteTime": { "end_time": "2023-04-19T11:38:51.404917Z", "start_time": "2023-04-19T11:38:50.578616Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Could not find image processor class in the image processor config or the model config. Loading based on pattern matching with the model's feature extractor configuration.\n" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 9;\n", " var nbb_unformatted_code = \"donut_processor = transformers.DonutProcessor.from_pretrained(\\n \\\"naver-clova-ix/donut-base\\\"\\n)\";\n", " var nbb_formatted_code = \"donut_processor = transformers.DonutProcessor.from_pretrained(\\n \\\"naver-clova-ix/donut-base\\\"\\n)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "donut_processor = transformers.DonutProcessor.from_pretrained(\n", " \"naver-clova-ix/donut-base\"\n", ")" ] }, { "cell_type": "code", "execution_count": 34, "id": "5257aba3", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:51.142992Z", "start_time": "2023-04-18T15:47:40.137637Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Could not find image processor class in the image processor config or the model config. Loading based on pattern matching with the model's feature extractor configuration.\n" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 34;\n", " var nbb_unformatted_code = \"CONFIG.pretrained_model_name = \\\"naver-clova-ix/donut-base\\\"\\nCONFIG.encoder_decoder_config = transformers.VisionEncoderDecoderConfig.from_pretrained(\\n CONFIG.pretrained_model_name\\n)\\nCONFIG.encoder_decoder_config.encoder.image_size = (\\n CONFIG.image_width,\\n CONFIG.image_height,\\n)\\n\\nMODEL.donut_processor = transformers.DonutProcessor.from_pretrained(\\n CONFIG.pretrained_model_name\\n)\\nMODEL.donut_processor.image_processor.size = dict(\\n width=CONFIG.image_width, height=CONFIG.image_height\\n)\\nMODEL.donut_processor.image_processor.do_align_long_axis = False\\nMODEL.tokenizer = MODEL.donut_processor.tokenizer\\nMODEL.encoder_decoder = transformers.VisionEncoderDecoderModel.from_pretrained(\\n CONFIG.pretrained_model_name, config=CONFIG.encoder_decoder_config\\n)\\n\\nCONFIG.encoder_decoder_config.pad_token_id = MODEL.tokenizer.pad_token_id\\nCONFIG.encoder_decoder_config.decoder_start_token_id = (\\n MODEL.tokenizer.convert_tokens_to_ids(TOKEN.benetech_prompt)\\n)\\nCONFIG.encoder_decoder_config.bos_token_id = (\\n CONFIG.encoder_decoder_config.decoder_start_token_id\\n)\\nCONFIG.encoder_decoder_config.eos_token_id = MODEL.tokenizer.convert_tokens_to_ids(\\n TOKEN.benetech_prompt_end\\n)\\nMODEL.tokenizer.eos_token_id = CONFIG.encoder_decoder_config.eos_token_id\";\n", " var nbb_formatted_code = \"CONFIG.pretrained_model_name = \\\"naver-clova-ix/donut-base\\\"\\nCONFIG.encoder_decoder_config = transformers.VisionEncoderDecoderConfig.from_pretrained(\\n CONFIG.pretrained_model_name\\n)\\nCONFIG.encoder_decoder_config.encoder.image_size = (\\n CONFIG.image_width,\\n CONFIG.image_height,\\n)\\n\\nMODEL.donut_processor = transformers.DonutProcessor.from_pretrained(\\n CONFIG.pretrained_model_name\\n)\\nMODEL.donut_processor.image_processor.size = dict(\\n width=CONFIG.image_width, height=CONFIG.image_height\\n)\\nMODEL.donut_processor.image_processor.do_align_long_axis = False\\nMODEL.tokenizer = MODEL.donut_processor.tokenizer\\nMODEL.encoder_decoder = transformers.VisionEncoderDecoderModel.from_pretrained(\\n CONFIG.pretrained_model_name, config=CONFIG.encoder_decoder_config\\n)\\n\\nCONFIG.encoder_decoder_config.pad_token_id = MODEL.tokenizer.pad_token_id\\nCONFIG.encoder_decoder_config.decoder_start_token_id = (\\n MODEL.tokenizer.convert_tokens_to_ids(TOKEN.benetech_prompt)\\n)\\nCONFIG.encoder_decoder_config.bos_token_id = (\\n CONFIG.encoder_decoder_config.decoder_start_token_id\\n)\\nCONFIG.encoder_decoder_config.eos_token_id = MODEL.tokenizer.convert_tokens_to_ids(\\n TOKEN.benetech_prompt_end\\n)\\nMODEL.tokenizer.eos_token_id = CONFIG.encoder_decoder_config.eos_token_id\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.pretrained_model_name = \"naver-clova-ix/donut-base\"\n", "CONFIG.encoder_decoder_config = transformers.VisionEncoderDecoderConfig.from_pretrained(\n", " CONFIG.pretrained_model_name\n", ")\n", "CONFIG.encoder_decoder_config.encoder.image_size = (\n", " CONFIG.image_width,\n", " CONFIG.image_height,\n", ")\n", "\n", "MODEL.donut_processor = transformers.DonutProcessor.from_pretrained(\n", " CONFIG.pretrained_model_name\n", ")\n", "MODEL.donut_processor.image_processor.size = dict(\n", " width=CONFIG.image_width, height=CONFIG.image_height\n", ")\n", "MODEL.donut_processor.image_processor.do_align_long_axis = False\n", "MODEL.tokenizer = MODEL.donut_processor.tokenizer\n", "MODEL.encoder_decoder = transformers.VisionEncoderDecoderModel.from_pretrained(\n", " CONFIG.pretrained_model_name, config=CONFIG.encoder_decoder_config\n", ")\n", "\n", "CONFIG.encoder_decoder_config.pad_token_id = MODEL.tokenizer.pad_token_id\n", "CONFIG.encoder_decoder_config.decoder_start_token_id = (\n", " MODEL.tokenizer.convert_tokens_to_ids(TOKEN.benetech_prompt)\n", ")\n", "CONFIG.encoder_decoder_config.bos_token_id = (\n", " CONFIG.encoder_decoder_config.decoder_start_token_id\n", ")\n", "CONFIG.encoder_decoder_config.eos_token_id = MODEL.tokenizer.convert_tokens_to_ids(\n", " TOKEN.benetech_prompt_end\n", ")\n", "MODEL.tokenizer.eos_token_id = CONFIG.encoder_decoder_config.eos_token_id" ] }, { "cell_type": "markdown", "id": "d40f590d", "metadata": {}, "source": [ "### Add task specific tokens " ] }, { "cell_type": "code", "execution_count": 35, "id": "42516577", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:51.159825Z", "start_time": "2023-04-18T15:47:51.144998Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 35;\n", " var nbb_unformatted_code = \"def add_unknown_tokens_to_tokenizer(unknown_tokens: list[str]):\\n assert set(unknown_tokens) == set(unknown_tokens) - set(\\n MODEL.tokenizer.vocab.keys()\\n ), \\\"Tokens are not unknown.\\\"\\n\\n MODEL.tokenizer.add_tokens(unknown_tokens)\\n MODEL.encoder_decoder.decoder.resize_token_embeddings(len(MODEL.tokenizer))\";\n", " var nbb_formatted_code = \"def add_unknown_tokens_to_tokenizer(unknown_tokens: list[str]):\\n assert set(unknown_tokens) == set(unknown_tokens) - set(\\n MODEL.tokenizer.vocab.keys()\\n ), \\\"Tokens are not unknown.\\\"\\n\\n MODEL.tokenizer.add_tokens(unknown_tokens)\\n MODEL.encoder_decoder.decoder.resize_token_embeddings(len(MODEL.tokenizer))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def add_unknown_tokens_to_tokenizer(unknown_tokens: list[str]):\n", " assert set(unknown_tokens) == set(unknown_tokens) - set(\n", " MODEL.tokenizer.vocab.keys()\n", " ), \"Tokens are not unknown.\"\n", "\n", " MODEL.tokenizer.add_tokens(unknown_tokens)\n", " MODEL.encoder_decoder.decoder.resize_token_embeddings(len(MODEL.tokenizer))" ] }, { "cell_type": "code", "execution_count": 36, "id": "81a93859", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.651571Z", "start_time": "2023-04-18T15:47:51.162085Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 36;\n", " var nbb_unformatted_code = \"add_unknown_tokens_to_tokenizer(list(TOKEN.__dict__.values()))\";\n", " var nbb_formatted_code = \"add_unknown_tokens_to_tokenizer(list(TOKEN.__dict__.values()))\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "add_unknown_tokens_to_tokenizer(list(TOKEN.__dict__.values()))" ] }, { "cell_type": "markdown", "id": "8070590a", "metadata": {}, "source": [ "### Add dataset specific tokens " ] }, { "cell_type": "code", "execution_count": 37, "id": "fe319b38", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.681837Z", "start_time": "2023-04-18T15:47:52.654564Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 37;\n", " var nbb_unformatted_code = \"def find_unknown_tokens_for_tokenizer() -> collections.Counter:\\n unknown_tokens_counter = collections.Counter()\\n\\n for annotated_image in generate_annotated_images():\\n ground_truth = get_annotation_ground_truth_str(annotated_image.annotation)\\n\\n input_ids = MODEL.tokenizer(ground_truth).input_ids\\n tokens = MODEL.tokenizer.tokenize(ground_truth, add_special_tokens=True)\\n\\n for token_id, token in zip(input_ids, tokens, strict=True):\\n if token_id == MODEL.tokenizer.unk_token_id:\\n unknown_tokens_counter.update([token])\\n\\n return unknown_tokens_counter\";\n", " var nbb_formatted_code = \"def find_unknown_tokens_for_tokenizer() -> collections.Counter:\\n unknown_tokens_counter = collections.Counter()\\n\\n for annotated_image in generate_annotated_images():\\n ground_truth = get_annotation_ground_truth_str(annotated_image.annotation)\\n\\n input_ids = MODEL.tokenizer(ground_truth).input_ids\\n tokens = MODEL.tokenizer.tokenize(ground_truth, add_special_tokens=True)\\n\\n for token_id, token in zip(input_ids, tokens, strict=True):\\n if token_id == MODEL.tokenizer.unk_token_id:\\n unknown_tokens_counter.update([token])\\n\\n return unknown_tokens_counter\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def find_unknown_tokens_for_tokenizer() -> collections.Counter:\n", " unknown_tokens_counter = collections.Counter()\n", "\n", " for annotated_image in generate_annotated_images():\n", " ground_truth = get_annotation_ground_truth_str(annotated_image.annotation)\n", "\n", " input_ids = MODEL.tokenizer(ground_truth).input_ids\n", " tokens = MODEL.tokenizer.tokenize(ground_truth, add_special_tokens=True)\n", "\n", " for token_id, token in zip(input_ids, tokens, strict=True):\n", " if token_id == MODEL.tokenizer.unk_token_id:\n", " unknown_tokens_counter.update([token])\n", "\n", " return unknown_tokens_counter" ] }, { "cell_type": "code", "execution_count": 38, "id": "91a5cc71", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.708844Z", "start_time": "2023-04-18T15:47:52.687009Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 38;\n", " var nbb_unformatted_code = \"if DEBUG:\\n print(find_unknown_tokens_for_tokenizer())\";\n", " var nbb_formatted_code = \"if DEBUG:\\n print(find_unknown_tokens_for_tokenizer())\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " print(find_unknown_tokens_for_tokenizer())" ] }, { "cell_type": "code", "execution_count": 39, "id": "02efe707", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.806582Z", "start_time": "2023-04-18T15:47:52.714235Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 39;\n", " var nbb_unformatted_code = \"CONFIG.unknown_tokens_for_tokenizer_path = \\\"unknown_tokens_for_tokenizer.pickle\\\"\\n\\nif not os.path.exists(CONFIG.unknown_tokens_for_tokenizer_path):\\n pickle.dump(\\n list(find_unknown_tokens_for_tokenizer().keys()),\\n open(CONFIG.unknown_tokens_for_tokenizer_path, \\\"wb\\\"),\\n )\\n\\nadd_unknown_tokens_to_tokenizer(\\n pickle.load(open(CONFIG.unknown_tokens_for_tokenizer_path, \\\"rb\\\"))\\n)\";\n", " var nbb_formatted_code = \"CONFIG.unknown_tokens_for_tokenizer_path = \\\"unknown_tokens_for_tokenizer.pickle\\\"\\n\\nif not os.path.exists(CONFIG.unknown_tokens_for_tokenizer_path):\\n pickle.dump(\\n list(find_unknown_tokens_for_tokenizer().keys()),\\n open(CONFIG.unknown_tokens_for_tokenizer_path, \\\"wb\\\"),\\n )\\n\\nadd_unknown_tokens_to_tokenizer(\\n pickle.load(open(CONFIG.unknown_tokens_for_tokenizer_path, \\\"rb\\\"))\\n)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.unknown_tokens_for_tokenizer_path = \"data/unknown_tokens_for_tokenizer.pickle\"\n", "\n", "add_unknown_tokens_to_tokenizer(\n", " load_pickle_or_build_object_and_save(\n", " CONFIG.unknown_tokens_for_tokenizer_path,\n", " lambda :list(find_unknown_tokens_for_tokenizer().keys())\n", " )\n", ")" ] }, { "cell_type": "code", "execution_count": 40, "id": "2fa909a1", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.827973Z", "start_time": "2023-04-18T15:47:52.817963Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 40;\n", " var nbb_unformatted_code = \"def compute_target_tokens_length_distribution():\\n token_lenghts = []\\n for data_item in tqdm.autonotebook.tqdm(\\n DATA.complete_dataset, desc=\\\"Encoding target strings\\\"\\n ):\\n encoding = MODEL.tokenizer(data_item.target_string)\\n token_lenghts.append(len(encoding.input_ids))\\n return token_lenghts\\n\\n\\ndef visualize_target_tokens_length_distribution():\\n token_lenghts = compute_target_tokens_length_distribution()\\n plt.hist(token_lenghts, bins=50)\\n plt.title(\\\"Token length\\\")\\n series = pd.Series(token_lenghts, name=\\\"Token length\\\").to_frame().describe()\\n IPython.display.display(series)\";\n", " var nbb_formatted_code = \"def compute_target_tokens_length_distribution():\\n token_lenghts = []\\n for data_item in tqdm.autonotebook.tqdm(\\n DATA.complete_dataset, desc=\\\"Encoding target strings\\\"\\n ):\\n encoding = MODEL.tokenizer(data_item.target_string)\\n token_lenghts.append(len(encoding.input_ids))\\n return token_lenghts\\n\\n\\ndef visualize_target_tokens_length_distribution():\\n token_lenghts = compute_target_tokens_length_distribution()\\n plt.hist(token_lenghts, bins=50)\\n plt.title(\\\"Token length\\\")\\n series = pd.Series(token_lenghts, name=\\\"Token length\\\").to_frame().describe()\\n IPython.display.display(series)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def compute_target_tokens_length_distribution():\n", " token_lenghts = []\n", " for data_item in tqdm.autonotebook.tqdm(\n", " DATA.complete_dataset, desc=\"Encoding target strings\"\n", " ):\n", " encoding = MODEL.tokenizer(data_item.target_string)\n", " token_lenghts.append(len(encoding.input_ids))\n", " return token_lenghts\n", "\n", "\n", "def visualize_target_tokens_length_distribution():\n", " token_lenghts = compute_target_tokens_length_distribution()\n", " plt.hist(token_lenghts, bins=50)\n", " plt.title(\"Token length\")\n", " series = pd.Series(token_lenghts, name=\"Token length\").to_frame().describe()\n", " IPython.display.display(series)" ] }, { "cell_type": "code", "execution_count": 41, "id": "76eb6a64", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.870437Z", "start_time": "2023-04-18T15:47:52.837124Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 41;\n", " var nbb_unformatted_code = \"if DEBUG:\\n visualize_target_tokens_length_distribution()\";\n", " var nbb_formatted_code = \"if DEBUG:\\n visualize_target_tokens_length_distribution()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " visualize_target_tokens_length_distribution()" ] }, { "cell_type": "code", "execution_count": 42, "id": "b8a7f491", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.886816Z", "start_time": "2023-04-18T15:47:52.873931Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 42;\n", " var nbb_unformatted_code = \"CONFIG.encoder_decoder_config.decoder.max_length = 512\";\n", " var nbb_formatted_code = \"CONFIG.encoder_decoder_config.decoder.max_length = 512\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.encoder_decoder_config.decoder.max_length = 512" ] }, { "cell_type": "markdown", "id": "c688a4a9", "metadata": {}, "source": [ "### Predicting " ] }, { "cell_type": "code", "execution_count": 43, "id": "36672135", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.919334Z", "start_time": "2023-04-18T15:47:52.888629Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 43;\n", " var nbb_unformatted_code = \"def generate_token_strings(images: torch.Tensor, skip_special_tokens=True) -> list[str]:\\n decoder_output = MODEL.encoder_decoder.generate(\\n images,\\n max_length=10 if DEBUG else CONFIG.encoder_decoder_config.decoder.max_length,\\n eos_token_id=MODEL.tokenizer.eos_token_id,\\n return_dict_in_generate=True,\\n )\\n return MODEL.tokenizer.batch_decode(\\n decoder_output.sequences, skip_special_tokens=skip_special_tokens\\n )\\n\\n\\ndef predict_string(image) -> str:\\n image = MODEL.donut_processor(\\n image, random_padding=False, return_tensors=\\\"pt\\\"\\n ).pixel_values\\n string = generate_token_strings(image)[0]\\n return string\\n\\n\\ndef predict_benetech_output(image):\\n string = predict_string(image)\\n assert BenetechOutput.does_string_match_expected_pattern(string)\\n return BenetechOutput.from_string(string)\";\n", " var nbb_formatted_code = \"def generate_token_strings(images: torch.Tensor, skip_special_tokens=True) -> list[str]:\\n decoder_output = MODEL.encoder_decoder.generate(\\n images,\\n max_length=10 if DEBUG else CONFIG.encoder_decoder_config.decoder.max_length,\\n eos_token_id=MODEL.tokenizer.eos_token_id,\\n return_dict_in_generate=True,\\n )\\n return MODEL.tokenizer.batch_decode(\\n decoder_output.sequences, skip_special_tokens=skip_special_tokens\\n )\\n\\n\\ndef predict_string(image) -> str:\\n image = MODEL.donut_processor(\\n image, random_padding=False, return_tensors=\\\"pt\\\"\\n ).pixel_values\\n string = generate_token_strings(image)[0]\\n return string\\n\\n\\ndef predict_benetech_output(image):\\n string = predict_string(image)\\n assert BenetechOutput.does_string_match_expected_pattern(string)\\n return BenetechOutput.from_string(string)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def generate_token_strings(images: torch.Tensor, skip_special_tokens=True) -> list[str]:\n", " decoder_output = MODEL.encoder_decoder.generate(\n", " images,\n", " max_length=10 if DEBUG else CONFIG.encoder_decoder_config.decoder.max_length,\n", " eos_token_id=MODEL.tokenizer.eos_token_id,\n", " return_dict_in_generate=True,\n", " )\n", " return MODEL.tokenizer.batch_decode(\n", " decoder_output.sequences, skip_special_tokens=skip_special_tokens\n", " )\n", "\n", "\n", "def predict_string(image) -> str:\n", " image = MODEL.donut_processor(\n", " image, random_padding=False, return_tensors=\"pt\"\n", " ).pixel_values\n", " string = generate_token_strings(image)[0]\n", " return string\n", "\n", "\n", "def predict_benetech_output(image):\n", " string = predict_string(image)\n", " assert BenetechOutput.does_string_match_expected_pattern(string)\n", " return BenetechOutput.from_string(string)" ] }, { "cell_type": "markdown", "id": "2a090da9", "metadata": {}, "source": [ "### Dataloader " ] }, { "cell_type": "code", "execution_count": 44, "id": "8637a86a", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:52.982298Z", "start_time": "2023-04-18T15:47:52.921598Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 44;\n", " var nbb_unformatted_code = \"@dataclasses.dataclass\\nclass Batch:\\n images: torch.FloatTensor\\n labels: torch.IntTensor\\n data_indices: list[int]\\n\\n def __post_init__(self):\\n if DEBUG:\\n images_shape = einops.parse_shape(self.images, \\\"batch channel height width\\\")\\n labels_shape = einops.parse_shape(self.labels, \\\"batch label\\\")\\n assert images_shape[\\\"batch\\\"] == labels_shape[\\\"batch\\\"]\\n assert len(self.data_indices) == images_shape[\\\"batch\\\"]\\n\\n\\ndef replace_pad_token_id_with_negative_hundred_for_hf_transformers_automatic_batch_transformation(\\n token_ids,\\n):\\n token_ids[token_ids == MODEL.tokenizer.pad_token_id] = -100\\n return token_ids\\n\\n\\ndef collate_function(batch: list[DataItem], split: Literal[\\\"train\\\", \\\"val\\\"]) -> Batch:\\n images = [di.image for di in batch]\\n images = MODEL.donut_processor(\\n images, random_padding=split == \\\"train\\\", return_tensors=\\\"pt\\\"\\n ).pixel_values\\n\\n target_token_ids = MODEL.tokenizer(\\n [di.target_string for di in batch],\\n add_special_tokens=False,\\n max_length=CONFIG.encoder_decoder_config.decoder.max_length,\\n padding=\\\"max_length\\\",\\n truncation=True,\\n return_tensors=\\\"pt\\\",\\n ).input_ids\\n labels = replace_pad_token_id_with_negative_hundred_for_hf_transformers_automatic_batch_transformation(\\n target_token_ids\\n )\\n\\n data_indices = [di.data_index for di in batch]\\n\\n return Batch(images=images, labels=labels, data_indices=data_indices)\\n\\n\\nCONFIG.batch_size = 2 if DEBUG else 2\\nCONFIG.num_workers = 4\\n\\n\\ndef build_dataloader(split: Literal[\\\"train\\\", \\\"val\\\"]):\\n return torch.utils.data.DataLoader(\\n DATA.train_dataset if split == \\\"train\\\" else DATA.val_dataset,\\n batch_size=CONFIG.batch_size,\\n shuffle=split == \\\"train\\\",\\n num_workers=CONFIG.num_workers,\\n collate_fn=functools.partial(collate_function, split=split),\\n )\\n\\n\\nDATA.train_dataloader = build_dataloader(\\\"train\\\")\\nDATA.val_dataloader = build_dataloader(\\\"val\\\")\";\n", " var nbb_formatted_code = \"@dataclasses.dataclass\\nclass Batch:\\n images: torch.FloatTensor\\n labels: torch.IntTensor\\n data_indices: list[int]\\n\\n def __post_init__(self):\\n if DEBUG:\\n images_shape = einops.parse_shape(self.images, \\\"batch channel height width\\\")\\n labels_shape = einops.parse_shape(self.labels, \\\"batch label\\\")\\n assert images_shape[\\\"batch\\\"] == labels_shape[\\\"batch\\\"]\\n assert len(self.data_indices) == images_shape[\\\"batch\\\"]\\n\\n\\ndef replace_pad_token_id_with_negative_hundred_for_hf_transformers_automatic_batch_transformation(\\n token_ids,\\n):\\n token_ids[token_ids == MODEL.tokenizer.pad_token_id] = -100\\n return token_ids\\n\\n\\ndef collate_function(batch: list[DataItem], split: Literal[\\\"train\\\", \\\"val\\\"]) -> Batch:\\n images = [di.image for di in batch]\\n images = MODEL.donut_processor(\\n images, random_padding=split == \\\"train\\\", return_tensors=\\\"pt\\\"\\n ).pixel_values\\n\\n target_token_ids = MODEL.tokenizer(\\n [di.target_string for di in batch],\\n add_special_tokens=False,\\n max_length=CONFIG.encoder_decoder_config.decoder.max_length,\\n padding=\\\"max_length\\\",\\n truncation=True,\\n return_tensors=\\\"pt\\\",\\n ).input_ids\\n labels = replace_pad_token_id_with_negative_hundred_for_hf_transformers_automatic_batch_transformation(\\n target_token_ids\\n )\\n\\n data_indices = [di.data_index for di in batch]\\n\\n return Batch(images=images, labels=labels, data_indices=data_indices)\\n\\n\\nCONFIG.batch_size = 2 if DEBUG else 2\\nCONFIG.num_workers = 4\\n\\n\\ndef build_dataloader(split: Literal[\\\"train\\\", \\\"val\\\"]):\\n return torch.utils.data.DataLoader(\\n DATA.train_dataset if split == \\\"train\\\" else DATA.val_dataset,\\n batch_size=CONFIG.batch_size,\\n shuffle=split == \\\"train\\\",\\n num_workers=CONFIG.num_workers,\\n collate_fn=functools.partial(collate_function, split=split),\\n )\\n\\n\\nDATA.train_dataloader = build_dataloader(\\\"train\\\")\\nDATA.val_dataloader = build_dataloader(\\\"val\\\")\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "@dataclasses.dataclass\n", "class Batch:\n", " images: torch.FloatTensor\n", " labels: torch.IntTensor\n", " data_indices: list[int]\n", "\n", " def __post_init__(self):\n", " if DEBUG:\n", " images_shape = einops.parse_shape(self.images, \"batch channel height width\")\n", " labels_shape = einops.parse_shape(self.labels, \"batch label\")\n", " assert images_shape[\"batch\"] == labels_shape[\"batch\"]\n", " assert len(self.data_indices) == images_shape[\"batch\"]\n", "\n", "\n", "def replace_pad_token_id_with_negative_hundred_for_hf_transformers_automatic_batch_transformation(\n", " token_ids,\n", "):\n", " token_ids[token_ids == MODEL.tokenizer.pad_token_id] = -100\n", " return token_ids\n", "\n", "\n", "def collate_function(batch: list[DataItem], split: Literal[\"train\", \"val\"]) -> Batch:\n", " images = [di.image for di in batch]\n", " images = MODEL.donut_processor(\n", " images, random_padding=split == \"train\", return_tensors=\"pt\"\n", " ).pixel_values\n", "\n", " target_token_ids = MODEL.tokenizer(\n", " [di.target_string for di in batch],\n", " add_special_tokens=False,\n", " max_length=CONFIG.encoder_decoder_config.decoder.max_length,\n", " padding=\"max_length\",\n", " truncation=True,\n", " return_tensors=\"pt\",\n", " ).input_ids\n", " labels = replace_pad_token_id_with_negative_hundred_for_hf_transformers_automatic_batch_transformation(\n", " target_token_ids\n", " )\n", "\n", " data_indices = [di.data_index for di in batch]\n", "\n", " return Batch(images=images, labels=labels, data_indices=data_indices)\n", "\n", "\n", "CONFIG.batch_size = 2 if DEBUG else 2\n", "CONFIG.num_workers = 4\n", "\n", "\n", "def build_dataloader(split: Literal[\"train\", \"val\"]):\n", " return torch.utils.data.DataLoader(\n", " DATA.train_dataset if split == \"train\" else DATA.val_dataset,\n", " batch_size=CONFIG.batch_size,\n", " shuffle=split == \"train\",\n", " num_workers=CONFIG.num_workers,\n", " collate_fn=functools.partial(collate_function, split=split),\n", " )\n", "\n", "\n", "DATA.train_dataloader = build_dataloader(\"train\")\n", "DATA.val_dataloader = build_dataloader(\"val\")" ] }, { "cell_type": "code", "execution_count": 45, "id": "bf389ff2", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:53.034897Z", "start_time": "2023-04-18T15:47:52.984707Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 45;\n", " var nbb_unformatted_code = \"def test_dataloaders():\\n for batch in tqdm.autonotebook.tqdm(\\n DATA.val_dataloader, \\\"Iterating over val dataloader\\\"\\n ):\\n pass\\n for batch in tqdm.autonotebook.tqdm(\\n DATA.train_dataloader, \\\"Iterating over train dataloader\\\"\\n ):\\n pass\";\n", " var nbb_formatted_code = \"def test_dataloaders():\\n for batch in tqdm.autonotebook.tqdm(\\n DATA.val_dataloader, \\\"Iterating over val dataloader\\\"\\n ):\\n pass\\n for batch in tqdm.autonotebook.tqdm(\\n DATA.train_dataloader, \\\"Iterating over train dataloader\\\"\\n ):\\n pass\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def test_dataloaders():\n", " for batch in tqdm.autonotebook.tqdm(\n", " DATA.val_dataloader, \"Iterating over val dataloader\"\n", " ):\n", " pass\n", " for batch in tqdm.autonotebook.tqdm(\n", " DATA.train_dataloader, \"Iterating over train dataloader\"\n", " ):\n", " pass" ] }, { "cell_type": "code", "execution_count": 46, "id": "0eb3fed2", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:53.076744Z", "start_time": "2023-04-18T15:47:53.037941Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 46;\n", " var nbb_unformatted_code = \"if DEBUG:\\n test_dataloaders()\";\n", " var nbb_formatted_code = \"if DEBUG:\\n test_dataloaders()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "if DEBUG:\n", " test_dataloaders()" ] }, { "cell_type": "markdown", "id": "08146c41", "metadata": {}, "source": [ "### Lightning module " ] }, { "cell_type": "code", "execution_count": 47, "id": "323bb5da", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:53.121327Z", "start_time": "2023-04-18T15:47:53.078769Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 47;\n", " var nbb_unformatted_code = \"CONFIG.learning_rate = 3e-5\\n\\n\\nclass LightningModule(pl.LightningModule):\\n def __init__(self):\\n super().__init__()\\n self.model = MODEL.encoder_decoder\\n\\n def training_step(self, batch: Batch, batch_idx: int) -> torch.Tensor:\\n outputs = self.model(pixel_values=batch.images, labels=batch.labels)\\n loss = outputs.loss\\n self.log(\\\"train_loss\\\", loss)\\n return loss\\n\\n def validation_step(self, batch: Batch, batch_idx: int, dataset_idx: int = 0):\\n outputs = self.model(pixel_values=batch.images, labels=batch.labels)\\n loss = outputs.loss\\n self.log(\\\"val_loss\\\", loss)\\n\\n def configure_optimizers(self) -> torch.optim.Optimizer:\\n optimizer = torch.optim.Adam(self.parameters(), lr=CONFIG.learning_rate)\\n return optimizer\\n\\n\\nMODEL.lightning_module = LightningModule()\";\n", " var nbb_formatted_code = \"CONFIG.learning_rate = 3e-5\\n\\n\\nclass LightningModule(pl.LightningModule):\\n def __init__(self):\\n super().__init__()\\n self.model = MODEL.encoder_decoder\\n\\n def training_step(self, batch: Batch, batch_idx: int) -> torch.Tensor:\\n outputs = self.model(pixel_values=batch.images, labels=batch.labels)\\n loss = outputs.loss\\n self.log(\\\"train_loss\\\", loss)\\n return loss\\n\\n def validation_step(self, batch: Batch, batch_idx: int, dataset_idx: int = 0):\\n outputs = self.model(pixel_values=batch.images, labels=batch.labels)\\n loss = outputs.loss\\n self.log(\\\"val_loss\\\", loss)\\n\\n def configure_optimizers(self) -> torch.optim.Optimizer:\\n optimizer = torch.optim.Adam(self.parameters(), lr=CONFIG.learning_rate)\\n return optimizer\\n\\n\\nMODEL.lightning_module = LightningModule()\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "CONFIG.learning_rate = 3e-5\n", "\n", "\n", "class LightningModule(pl.LightningModule):\n", " def __init__(self):\n", " super().__init__()\n", " self.model = MODEL.encoder_decoder\n", "\n", " def training_step(self, batch: Batch, batch_idx: int) -> torch.Tensor:\n", " outputs = self.model(pixel_values=batch.images, labels=batch.labels)\n", " loss = outputs.loss\n", " self.log(\"train_loss\", loss)\n", " return loss\n", "\n", " def validation_step(self, batch: Batch, batch_idx: int, dataset_idx: int = 0):\n", " outputs = self.model(pixel_values=batch.images, labels=batch.labels)\n", " loss = outputs.loss\n", " self.log(\"val_loss\", loss)\n", "\n", " def configure_optimizers(self) -> torch.optim.Optimizer:\n", " optimizer = torch.optim.Adam(self.parameters(), lr=CONFIG.learning_rate)\n", " return optimizer\n", "\n", "\n", "MODEL.lightning_module = LightningModule()" ] }, { "cell_type": "markdown", "id": "b375ad12", "metadata": {}, "source": [ "### Callbacks " ] }, { "cell_type": "code", "execution_count": 48, "id": "441e54bb", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:53.157826Z", "start_time": "2023-04-18T15:47:53.125547Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 48;\n", " var nbb_unformatted_code = \"class MetricsCallback(pl.callbacks.Callback):\\n def on_validation_batch_start(\\n self, trainer, pl_module, batch: Batch, batch_idx, dataloader_idx=0\\n ):\\n predicted_strings = generate_token_strings(images=batch.images)\\n\\n for expected_data_index, predicted_string in zip(\\n batch.data_indices, predicted_strings, strict=True\\n ):\\n benetech_score = benetech_score_string_prediction(\\n expected_data_index=expected_data_index,\\n predicted_string=predicted_string,\\n )\\n wandb.log(dict(benetech_score=benetech_score))\\n\\n ground_truth_strings = [\\n get_annotation_ground_truth_str_from_image_index(i)\\n for i in batch.data_indices\\n ]\\n string_ids = [load_train_image_ids()[i] for i in batch.data_indices]\\n strings_dataframe = pd.DataFrame(\\n dict(\\n string_ids=string_ids,\\n ground_truth=ground_truth_strings,\\n predicted=predicted_strings,\\n )\\n )\\n wandb.log(dict(strings=wandb.Table(dataframe=strings_dataframe)))\\n\\n\\nclass TransformersCheckpointIO(pl.plugins.CheckpointIO):\\n def save_checkpoint(self, checkpoint, path, storage_options=None):\\n MODEL.donut_processor.save_pretrained(path)\\n MODEL.encoder_decoder.save_pretrained(path)\\n\\n def load_checkpoint(self, path, storage_options=None):\\n pass\\n\\n def remove_checkpoint(self, path):\\n pass\";\n", " var nbb_formatted_code = \"class MetricsCallback(pl.callbacks.Callback):\\n def on_validation_batch_start(\\n self, trainer, pl_module, batch: Batch, batch_idx, dataloader_idx=0\\n ):\\n predicted_strings = generate_token_strings(images=batch.images)\\n\\n for expected_data_index, predicted_string in zip(\\n batch.data_indices, predicted_strings, strict=True\\n ):\\n benetech_score = benetech_score_string_prediction(\\n expected_data_index=expected_data_index,\\n predicted_string=predicted_string,\\n )\\n wandb.log(dict(benetech_score=benetech_score))\\n\\n ground_truth_strings = [\\n get_annotation_ground_truth_str_from_image_index(i)\\n for i in batch.data_indices\\n ]\\n string_ids = [load_train_image_ids()[i] for i in batch.data_indices]\\n strings_dataframe = pd.DataFrame(\\n dict(\\n string_ids=string_ids,\\n ground_truth=ground_truth_strings,\\n predicted=predicted_strings,\\n )\\n )\\n wandb.log(dict(strings=wandb.Table(dataframe=strings_dataframe)))\\n\\n\\nclass TransformersCheckpointIO(pl.plugins.CheckpointIO):\\n def save_checkpoint(self, checkpoint, path, storage_options=None):\\n MODEL.donut_processor.save_pretrained(path)\\n MODEL.encoder_decoder.save_pretrained(path)\\n\\n def load_checkpoint(self, path, storage_options=None):\\n pass\\n\\n def remove_checkpoint(self, path):\\n pass\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "class MetricsCallback(pl.callbacks.Callback):\n", " def on_validation_batch_start(\n", " self, trainer, pl_module, batch: Batch, batch_idx, dataloader_idx=0\n", " ):\n", " predicted_strings = generate_token_strings(images=batch.images)\n", "\n", " for expected_data_index, predicted_string in zip(\n", " batch.data_indices, predicted_strings, strict=True\n", " ):\n", " benetech_score = benetech_score_string_prediction(\n", " expected_data_index=expected_data_index,\n", " predicted_string=predicted_string,\n", " )\n", " wandb.log(dict(benetech_score=benetech_score))\n", "\n", " ground_truth_strings = [\n", " get_annotation_ground_truth_str_from_image_index(i)\n", " for i in batch.data_indices\n", " ]\n", " string_ids = [load_train_image_ids()[i] for i in batch.data_indices]\n", " strings_dataframe = pd.DataFrame(\n", " dict(\n", " string_ids=string_ids,\n", " ground_truth=ground_truth_strings,\n", " predicted=predicted_strings,\n", " )\n", " )\n", " wandb.log(dict(strings=wandb.Table(dataframe=strings_dataframe)))\n", "\n", "\n", "class TransformersCheckpointIO(pl.plugins.CheckpointIO):\n", " def save_checkpoint(self, checkpoint, path, storage_options=None):\n", " MODEL.donut_processor.save_pretrained(path)\n", " MODEL.encoder_decoder.save_pretrained(path)\n", "\n", " def load_checkpoint(self, path, storage_options=None):\n", " pass\n", "\n", " def remove_checkpoint(self, path):\n", " pass" ] }, { "cell_type": "markdown", "id": "7ef3f395", "metadata": {}, "source": [ "## Training " ] }, { "cell_type": "code", "execution_count": 49, "id": "3d12b673", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T15:47:57.593057Z", "start_time": "2023-04-18T15:47:53.160392Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[34m\u001b[1mwandb\u001b[0m: Currently logged in as: \u001b[33mdkoshman\u001b[0m. Use \u001b[1m`wandb login --relogin`\u001b[0m to force relogin\n" ] }, { "data": { "text/html": [ "Tracking run with wandb version 0.14.2" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Run data is saved locally in training/wandb/run-20230418_154756-56t9l4jj" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Syncing run young-forest-7 to Weights & Biases (docs)
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View project at https://wandb.ai/dkoshman/MakingGraphsAccessible" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ " View run at https://wandb.ai/dkoshman/MakingGraphsAccessible/runs/56t9l4jj" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "GPU available: True (cuda), used: True\n", "TPU available: False, using: 0 TPU cores\n", "IPU available: False, using: 0 IPUs\n", "HPU available: False, using: 0 HPUs\n" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 49;\n", " var nbb_unformatted_code = \"TRAINING.accelerator = \\\"cpu\\\" if DEBUG else \\\"gpu\\\"\\nTRAINING.devices = \\\"auto\\\" if TRAINING.accelerator == \\\"cpu\\\" else [3]\\nTRAINING.directory = \\\"training\\\"\\nTRAINING.save_top_k_checkpoints = 3\\nTRAINING.wandb_project_name = \\\"MakingGraphsAccessible\\\"\\nTRAINING.limit_train_batches = 2 if DEBUG else None\\nTRAINING.limit_val_batches = 2 if DEBUG else 0.1\\n\\nTRAINING.model_checkpoint = pl.callbacks.ModelCheckpoint(\\n dirpath=TRAINING.directory,\\n monitor=\\\"val_loss\\\",\\n save_top_k=TRAINING.save_top_k_checkpoints,\\n)\\n\\nTRAINING.logger = pl.loggers.WandbLogger(\\n project=TRAINING.wandb_project_name, save_dir=TRAINING.directory\\n)\\n\\nTRAINING.trainer = pl.Trainer(\\n accelerator=TRAINING.accelerator,\\n devices=TRAINING.devices,\\n plugins=[TransformersCheckpointIO()],\\n callbacks=[TRAINING.model_checkpoint, MetricsCallback()],\\n logger=TRAINING.logger,\\n limit_train_batches=TRAINING.limit_train_batches,\\n limit_val_batches=TRAINING.limit_val_batches,\\n)\";\n", " var nbb_formatted_code = \"TRAINING.accelerator = \\\"cpu\\\" if DEBUG else \\\"gpu\\\"\\nTRAINING.devices = \\\"auto\\\" if TRAINING.accelerator == \\\"cpu\\\" else [3]\\nTRAINING.directory = \\\"training\\\"\\nTRAINING.save_top_k_checkpoints = 3\\nTRAINING.wandb_project_name = \\\"MakingGraphsAccessible\\\"\\nTRAINING.limit_train_batches = 2 if DEBUG else None\\nTRAINING.limit_val_batches = 2 if DEBUG else 0.1\\n\\nTRAINING.model_checkpoint = pl.callbacks.ModelCheckpoint(\\n dirpath=TRAINING.directory,\\n monitor=\\\"val_loss\\\",\\n save_top_k=TRAINING.save_top_k_checkpoints,\\n)\\n\\nTRAINING.logger = pl.loggers.WandbLogger(\\n project=TRAINING.wandb_project_name, save_dir=TRAINING.directory\\n)\\n\\nTRAINING.trainer = pl.Trainer(\\n accelerator=TRAINING.accelerator,\\n devices=TRAINING.devices,\\n plugins=[TransformersCheckpointIO()],\\n callbacks=[TRAINING.model_checkpoint, MetricsCallback()],\\n logger=TRAINING.logger,\\n limit_train_batches=TRAINING.limit_train_batches,\\n limit_val_batches=TRAINING.limit_val_batches,\\n)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "TRAINING.accelerator = \"cpu\" if DEBUG else \"gpu\"\n", "TRAINING.devices = \"auto\" if TRAINING.accelerator == \"cpu\" else [3]\n", "TRAINING.directory = \"training\"\n", "TRAINING.save_top_k_checkpoints = 3\n", "TRAINING.wandb_project_name = \"MakingGraphsAccessible\"\n", "TRAINING.limit_train_batches = 2 if DEBUG else None\n", "TRAINING.limit_val_batches = 2 if DEBUG else 0.1\n", "\n", "TRAINING.model_checkpoint = pl.callbacks.ModelCheckpoint(\n", " dirpath=TRAINING.directory,\n", " monitor=\"val_loss\",\n", " save_top_k=TRAINING.save_top_k_checkpoints,\n", ")\n", "\n", "TRAINING.logger = pl.loggers.WandbLogger(\n", " project=TRAINING.wandb_project_name, save_dir=TRAINING.directory\n", ")\n", "\n", "TRAINING.trainer = pl.Trainer(\n", " accelerator=TRAINING.accelerator,\n", " devices=TRAINING.devices,\n", " plugins=[TransformersCheckpointIO()],\n", " callbacks=[TRAINING.model_checkpoint, MetricsCallback()],\n", " logger=TRAINING.logger,\n", " limit_train_batches=TRAINING.limit_train_batches,\n", " limit_val_batches=TRAINING.limit_val_batches,\n", ")" ] }, { "cell_type": "code", "execution_count": 50, "id": "5c883d58", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T19:50:57.849222Z", "start_time": "2023-04-18T15:47:57.598224Z" }, "collapsed": true }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/home/dkkoshman/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/utilities.py:70: PossibleUserWarning: `max_epochs` was not set. Setting it to 1000 epochs. To train without an epoch limit, set `max_epochs=-1`.\n", " rank_zero_warn(\n", "You are using a CUDA device ('NVIDIA GeForce RTX 3060') that has Tensor Cores. To properly utilize them, you should set `torch.set_float32_matmul_precision('medium' | 'high')` which will trade-off precision for performance. For more details, read https://pytorch.org/docs/stable/generated/torch.set_float32_matmul_precision.html#torch.set_float32_matmul_precision\n", "/home/dkkoshman/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/callbacks/model_checkpoint.py:612: UserWarning: Checkpoint directory /home/dkkoshman/YSDA/machine_learning/transformers/MakingGraphsAccessible/training exists and is not empty.\n", " rank_zero_warn(f\"Checkpoint directory {dirpath} exists and is not empty.\")\n", "LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0,1,2,3,4,5]\n", "\n", " | Name | Type | Params\n", "----------------------------------------------------\n", "0 | model | VisionEncoderDecoderModel | 201 M \n", "----------------------------------------------------\n", "201 M Trainable params\n", "0 Non-trainable params\n", "201 M Total params\n", "807.457 Total estimated model params size (MB)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Sanity Checking: 0it [00:00, ?it/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "/home/dkkoshman/YSDA/python3.10/lib/python3.10/site-packages/transformers/generation/utils.py:1186: UserWarning: You have modified the pretrained model configuration to control generation. This is a deprecated strategy to control generation and will be removed soon, in a future version. Please use a generation configuration file (see https://huggingface.co/docs/transformers/main_classes/text_generation)\n", " warnings.warn(\n", "/home/dkkoshman/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/utilities/data.py:77: UserWarning: Trying to infer the `batch_size` from an ambiguous collection. The batch size we found is 2. To avoid any miscalculations, use `self.log(..., batch_size=batch_size)`.\n", " warning_cache.warn(\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "12adc4c9f9eb4cd095ac4dce87c500ae", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Training: 0it [00:00, ?it/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "9bf5111de98f4c3893eb5ac0597331e7", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Validation: 0it [00:00, ?it/s]" ] }, "metadata": {}, "output_type": "display_data" }, { "ename": "ValueError", "evalue": "could not convert string to float: ' 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[50], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mTRAINING\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrainer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mMODEL\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlightning_module\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[43m \u001b[49m\u001b[43mtrain_dataloaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mDATA\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrain_dataloader\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[43m \u001b[49m\u001b[43mval_dataloaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mDATA\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mval_dataloader\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 5\u001b[0m \u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/trainer/trainer.py:520\u001b[0m, in \u001b[0;36mTrainer.fit\u001b[0;34m(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)\u001b[0m\n\u001b[1;32m 518\u001b[0m model \u001b[38;5;241m=\u001b[39m _maybe_unwrap_optimized(model)\n\u001b[1;32m 519\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstrategy\u001b[38;5;241m.\u001b[39m_lightning_module \u001b[38;5;241m=\u001b[39m model\n\u001b[0;32m--> 520\u001b[0m \u001b[43mcall\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_and_handle_interrupt\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 521\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_fit_impl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrain_dataloaders\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mval_dataloaders\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdatamodule\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mckpt_path\u001b[49m\n\u001b[1;32m 522\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/trainer/call.py:44\u001b[0m, in \u001b[0;36m_call_and_handle_interrupt\u001b[0;34m(trainer, trainer_fn, *args, **kwargs)\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m trainer\u001b[38;5;241m.\u001b[39mstrategy\u001b[38;5;241m.\u001b[39mlauncher\u001b[38;5;241m.\u001b[39mlaunch(trainer_fn, \u001b[38;5;241m*\u001b[39margs, trainer\u001b[38;5;241m=\u001b[39mtrainer, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m---> 44\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mtrainer_fn\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 46\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m _TunerExitException:\n\u001b[1;32m 47\u001b[0m _call_teardown_hook(trainer)\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/trainer/trainer.py:559\u001b[0m, in \u001b[0;36mTrainer._fit_impl\u001b[0;34m(self, model, train_dataloaders, val_dataloaders, datamodule, ckpt_path)\u001b[0m\n\u001b[1;32m 549\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_data_connector\u001b[38;5;241m.\u001b[39mattach_data(\n\u001b[1;32m 550\u001b[0m model, train_dataloaders\u001b[38;5;241m=\u001b[39mtrain_dataloaders, val_dataloaders\u001b[38;5;241m=\u001b[39mval_dataloaders, datamodule\u001b[38;5;241m=\u001b[39mdatamodule\n\u001b[1;32m 551\u001b[0m )\n\u001b[1;32m 553\u001b[0m ckpt_path \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_checkpoint_connector\u001b[38;5;241m.\u001b[39m_select_ckpt_path(\n\u001b[1;32m 554\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;241m.\u001b[39mfn,\n\u001b[1;32m 555\u001b[0m ckpt_path,\n\u001b[1;32m 556\u001b[0m model_provided\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 557\u001b[0m model_connected\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlightning_module \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 558\u001b[0m )\n\u001b[0;32m--> 559\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mckpt_path\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mckpt_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 561\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;241m.\u001b[39mstopped\n\u001b[1;32m 562\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtraining \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/trainer/trainer.py:935\u001b[0m, in \u001b[0;36mTrainer._run\u001b[0;34m(self, model, ckpt_path)\u001b[0m\n\u001b[1;32m 930\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_signal_connector\u001b[38;5;241m.\u001b[39mregister_signal_handlers()\n\u001b[1;32m 932\u001b[0m \u001b[38;5;66;03m# ----------------------------\u001b[39;00m\n\u001b[1;32m 933\u001b[0m \u001b[38;5;66;03m# RUN THE TRAINER\u001b[39;00m\n\u001b[1;32m 934\u001b[0m \u001b[38;5;66;03m# ----------------------------\u001b[39;00m\n\u001b[0;32m--> 935\u001b[0m results \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run_stage\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 937\u001b[0m \u001b[38;5;66;03m# ----------------------------\u001b[39;00m\n\u001b[1;32m 938\u001b[0m \u001b[38;5;66;03m# POST-Training CLEAN UP\u001b[39;00m\n\u001b[1;32m 939\u001b[0m \u001b[38;5;66;03m# ----------------------------\u001b[39;00m\n\u001b[1;32m 940\u001b[0m log\u001b[38;5;241m.\u001b[39mdebug(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m: trainer tearing down\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/trainer/trainer.py:978\u001b[0m, in \u001b[0;36mTrainer._run_stage\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 976\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_run_sanity_check()\n\u001b[1;32m 977\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m torch\u001b[38;5;241m.\u001b[39mautograd\u001b[38;5;241m.\u001b[39mset_detect_anomaly(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_detect_anomaly):\n\u001b[0;32m--> 978\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfit_loop\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 979\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 980\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mUnexpected state \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstate\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/fit_loop.py:201\u001b[0m, in \u001b[0;36m_FitLoop.run\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 199\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 200\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_advance_start()\n\u001b[0;32m--> 201\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43madvance\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 202\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_advance_end()\n\u001b[1;32m 203\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_restarting \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/fit_loop.py:354\u001b[0m, in \u001b[0;36m_FitLoop.advance\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 352\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_data_fetcher\u001b[38;5;241m.\u001b[39msetup(combined_loader)\n\u001b[1;32m 353\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrainer\u001b[38;5;241m.\u001b[39mprofiler\u001b[38;5;241m.\u001b[39mprofile(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrun_training_epoch\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[0;32m--> 354\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mepoch_loop\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_data_fetcher\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/training_epoch_loop.py:134\u001b[0m, in \u001b[0;36m_TrainingEpochLoop.run\u001b[0;34m(self, data_fetcher)\u001b[0m\n\u001b[1;32m 132\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 133\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madvance(data_fetcher)\n\u001b[0;32m--> 134\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mon_advance_end\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 135\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_restarting \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 136\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m:\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/training_epoch_loop.py:248\u001b[0m, in \u001b[0;36m_TrainingEpochLoop.on_advance_end\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 246\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m should_check_val:\n\u001b[1;32m 247\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrainer\u001b[38;5;241m.\u001b[39mvalidating \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m--> 248\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mval_loop\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 249\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrainer\u001b[38;5;241m.\u001b[39mtraining \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 251\u001b[0m \u001b[38;5;66;03m# update plateau LR scheduler after metrics are logged\u001b[39;00m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/utilities.py:174\u001b[0m, in \u001b[0;36m_no_grad_context.._decorator\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 172\u001b[0m context_manager \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mno_grad\n\u001b[1;32m 173\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m context_manager():\n\u001b[0;32m--> 174\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mloop_run\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/evaluation_loop.py:115\u001b[0m, in \u001b[0;36m_EvaluationLoop.run\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 113\u001b[0m previous_dataloader_idx \u001b[38;5;241m=\u001b[39m dataloader_idx\n\u001b[1;32m 114\u001b[0m \u001b[38;5;66;03m# run step hooks\u001b[39;00m\n\u001b[0;32m--> 115\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_evaluation_step\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbatch\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbatch_idx\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdataloader_idx\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 116\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m:\n\u001b[1;32m 117\u001b[0m \u001b[38;5;66;03m# this needs to wrap the `*_step` call too (not just `next`) for `dataloader_iter` support\u001b[39;00m\n\u001b[1;32m 118\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/loops/evaluation_loop.py:369\u001b[0m, in \u001b[0;36m_EvaluationLoop._evaluation_step\u001b[0;34m(self, batch, batch_idx, dataloader_idx)\u001b[0m\n\u001b[1;32m 366\u001b[0m trainer\u001b[38;5;241m.\u001b[39m_logger_connector\u001b[38;5;241m.\u001b[39mon_batch_start(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mstep_kwargs)\n\u001b[1;32m 368\u001b[0m hook_name \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mon_test_batch_start\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m trainer\u001b[38;5;241m.\u001b[39mtesting \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mon_validation_batch_start\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 369\u001b[0m \u001b[43mcall\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call_callback_hooks\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtrainer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhook_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mstep_kwargs\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalues\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 370\u001b[0m call\u001b[38;5;241m.\u001b[39m_call_lightning_module_hook(trainer, hook_name, \u001b[38;5;241m*\u001b[39mstep_kwargs\u001b[38;5;241m.\u001b[39mvalues())\n\u001b[1;32m 372\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbatch_progress\u001b[38;5;241m.\u001b[39mincrement_started()\n", "File \u001b[0;32m~/YSDA/python3.10/lib/python3.10/site-packages/pytorch_lightning/trainer/call.py:190\u001b[0m, in \u001b[0;36m_call_callback_hooks\u001b[0;34m(trainer, hook_name, monitoring_callbacks, *args, **kwargs)\u001b[0m\n\u001b[1;32m 188\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m callable(fn):\n\u001b[1;32m 189\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m trainer\u001b[38;5;241m.\u001b[39mprofiler\u001b[38;5;241m.\u001b[39mprofile(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m[Callback]\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcallback\u001b[38;5;241m.\u001b[39mstate_key\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mhook_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m):\n\u001b[0;32m--> 190\u001b[0m \u001b[43mfn\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtrainer\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrainer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlightning_module\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 192\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m pl_module:\n\u001b[1;32m 193\u001b[0m \u001b[38;5;66;03m# restore current_fx when nested context\u001b[39;00m\n\u001b[1;32m 194\u001b[0m pl_module\u001b[38;5;241m.\u001b[39m_current_fx_name \u001b[38;5;241m=\u001b[39m prev_fx_name\n", "Cell \u001b[0;32mIn[48], line 10\u001b[0m, in \u001b[0;36mMetricsCallback.on_validation_batch_start\u001b[0;34m(self, trainer, pl_module, batch, batch_idx, dataloader_idx)\u001b[0m\n\u001b[1;32m 5\u001b[0m predicted_strings \u001b[38;5;241m=\u001b[39m generate_token_strings(images\u001b[38;5;241m=\u001b[39mbatch\u001b[38;5;241m.\u001b[39mimages)\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m expected_data_index, predicted_string \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(\n\u001b[1;32m 8\u001b[0m batch\u001b[38;5;241m.\u001b[39mdata_indices, predicted_strings, strict\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 9\u001b[0m ):\n\u001b[0;32m---> 10\u001b[0m benetech_score \u001b[38;5;241m=\u001b[39m \u001b[43mbenetech_score_string_prediction\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 11\u001b[0m \u001b[43m \u001b[49m\u001b[43mexpected_data_index\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mexpected_data_index\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 12\u001b[0m \u001b[43m \u001b[49m\u001b[43mpredicted_string\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpredicted_string\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 13\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 14\u001b[0m wandb\u001b[38;5;241m.\u001b[39mlog(\u001b[38;5;28mdict\u001b[39m(benetech_score\u001b[38;5;241m=\u001b[39mbenetech_score))\n\u001b[1;32m 16\u001b[0m ground_truth_strings \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 17\u001b[0m get_annotation_ground_truth_str_from_image_index(i)\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m batch\u001b[38;5;241m.\u001b[39mdata_indices\n\u001b[1;32m 19\u001b[0m ]\n", "Cell \u001b[0;32mIn[30], line 46\u001b[0m, in \u001b[0;36mbenetech_score_string_prediction\u001b[0;34m(expected_data_index, predicted_string)\u001b[0m\n\u001b[1;32m 44\u001b[0m expected_annotation \u001b[38;5;241m=\u001b[39m Annotation\u001b[38;5;241m.\u001b[39mfrom_image_index(expected_data_index)\n\u001b[1;32m 45\u001b[0m expected_output \u001b[38;5;241m=\u001b[39m BenetechOutput\u001b[38;5;241m.\u001b[39mfrom_annotation(expected_annotation)\n\u001b[0;32m---> 46\u001b[0m predicted_output \u001b[38;5;241m=\u001b[39m \u001b[43mBenetechOutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_string\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpredicted_string\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 47\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m benetech_score(expected_output, predicted_output)\n", "Cell \u001b[0;32mIn[28], line 78\u001b[0m, in \u001b[0;36mBenetechOutput.from_string\u001b[0;34m(string)\u001b[0m\n\u001b[1;32m 74\u001b[0m benetech_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124my_values_type\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m ValuesType(benetech_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124my_values_type\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 75\u001b[0m benetech_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mx_data\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m convert_string_to_axis_data(\n\u001b[1;32m 76\u001b[0m benetech_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mx_data\u001b[39m\u001b[38;5;124m\"\u001b[39m], benetech_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mx_values_type\u001b[39m\u001b[38;5;124m\"\u001b[39m]\n\u001b[1;32m 77\u001b[0m )\n\u001b[0;32m---> 78\u001b[0m benetech_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124my_data\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[43mconvert_string_to_axis_data\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 79\u001b[0m \u001b[43m \u001b[49m\u001b[43mbenetech_kwargs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43my_data\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mbenetech_kwargs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43my_values_type\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\n\u001b[1;32m 80\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 81\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m BenetechOutput(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mbenetech_kwargs)\n", "Cell \u001b[0;32mIn[26], line 22\u001b[0m, in \u001b[0;36mconvert_string_to_axis_data\u001b[0;34m(string, values_type)\u001b[0m\n\u001b[1;32m 20\u001b[0m data \u001b[38;5;241m=\u001b[39m string\u001b[38;5;241m.\u001b[39msplit(TOKEN\u001b[38;5;241m.\u001b[39mvalue_separator)\n\u001b[1;32m 21\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m values_type \u001b[38;5;241m==\u001b[39m ValuesType\u001b[38;5;241m.\u001b[39mnumerical:\n\u001b[0;32m---> 22\u001b[0m data \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28mfloat\u001b[39m(i) \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m data]\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m data\n", "Cell \u001b[0;32mIn[26], line 22\u001b[0m, in \u001b[0;36m\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 20\u001b[0m data \u001b[38;5;241m=\u001b[39m string\u001b[38;5;241m.\u001b[39msplit(TOKEN\u001b[38;5;241m.\u001b[39mvalue_separator)\n\u001b[1;32m 21\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m values_type \u001b[38;5;241m==\u001b[39m ValuesType\u001b[38;5;241m.\u001b[39mnumerical:\n\u001b[0;32m---> 22\u001b[0m data \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28;43mfloat\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mi\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m data]\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m data\n", "\u001b[0;31mValueError\u001b[0m: could not convert string to float: ' 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01 3.44975e-01'" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 50;\n", " var nbb_unformatted_code = \"TRAINING.trainer.fit(\\n model=MODEL.lightning_module,\\n train_dataloaders=DATA.train_dataloader,\\n val_dataloaders=DATA.val_dataloader,\\n)\";\n", " var nbb_formatted_code = \"TRAINING.trainer.fit(\\n model=MODEL.lightning_module,\\n train_dataloaders=DATA.train_dataloader,\\n val_dataloaders=DATA.val_dataloader,\\n)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "TRAINING.trainer.fit(\n", " model=MODEL.lightning_module,\n", " train_dataloaders=DATA.train_dataloader,\n", " val_dataloaders=DATA.val_dataloader,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "32541868", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T19:50:57.857936Z", "start_time": "2023-04-18T19:50:57.857925Z" } }, "outputs": [], "source": [ "TRAINING.trainer.validate(model=MODEL.lightning_module, dataloaders=DATA.val_dataloader)" ] }, { "cell_type": "markdown", "id": "b36b5cf7", "metadata": {}, "source": [ "## Results " ] }, { "cell_type": "markdown", "id": "509c9eae", "metadata": {}, "source": [ "### Gradio interface " ] }, { "cell_type": "code", "execution_count": null, "id": "2b569259", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T19:50:57.859236Z", "start_time": "2023-04-18T19:50:57.859226Z" } }, "outputs": [], "source": [ "checkpoint_path = \"training/epoch=0-step=2-v1.ckpt\"\n", "MODEL.donut_processor = MODEL.donut_processor.from_pretrained(checkpoint_path)\n", "MODEL.encoder_decoder = MODEL.encoder_decoder.from_pretrained(checkpoint_path)" ] }, { "cell_type": "code", "execution_count": null, "id": "6eeea089", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T19:50:57.860310Z", "start_time": "2023-04-18T19:50:57.860301Z" } }, "outputs": [], "source": [ "interface = gradio.Interface(\n", " fn=predict_string,\n", " inputs=gradio.Image(type=\"pil\"),\n", " outputs=gradio.Text(),\n", " examples=\"examples\",\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "39d1e3d8", "metadata": { "ExecuteTime": { "end_time": "2023-04-18T19:50:57.861631Z", "start_time": "2023-04-18T19:50:57.861618Z" } }, "outputs": [], "source": [ "interface.launch(share=True)" ] }, { "cell_type": "code", "execution_count": 4, "id": "80124073", "metadata": { "ExecuteTime": { "end_time": "2023-04-27T13:03:57.218129Z", "start_time": "2023-04-27T13:03:57.048661Z" } }, "outputs": [ { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 4;\n", " var nbb_unformatted_code = \"import functools\\n\\nimport gradio\\n\\nfrom config import CONFIG\\nfrom model import (\\n predict_string,\\n build_model,\\n)\";\n", " var nbb_formatted_code = \"import functools\\n\\nimport gradio\\n\\nfrom config import CONFIG\\nfrom model import (\\n predict_string,\\n build_model,\\n)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import functools\n", "\n", "import gradio\n", "\n", "from config import CONFIG\n", "from model import (\n", " predict_string,\n", " build_model,\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "id": "575edbbe", "metadata": { "ExecuteTime": { "end_time": "2023-04-27T13:04:07.359118Z", "start_time": "2023-04-27T13:03:58.074214Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Reusing object data/unknown_tokens_for_tokenizer.pickle.\n" ] }, { "data": { "application/javascript": [ "\n", " setTimeout(function() {\n", " var nbb_cell_id = 5;\n", " var nbb_unformatted_code = \"config = CONFIG\\nconfig.pretrained_model_name = \\\"training/epoch=2-step=163563.ckpt/\\\"\\nmodel = build_model(config)\";\n", " var nbb_formatted_code = \"config = CONFIG\\nconfig.pretrained_model_name = \\\"training/epoch=2-step=163563.ckpt/\\\"\\nmodel = build_model(config)\";\n", " var nbb_cells = Jupyter.notebook.get_cells();\n", " for (var i = 0; i < nbb_cells.length; ++i) {\n", " if (nbb_cells[i].input_prompt_number == nbb_cell_id) {\n", " if (nbb_cells[i].get_text() == nbb_unformatted_code) {\n", " nbb_cells[i].set_text(nbb_formatted_code);\n", " }\n", " break;\n", " }\n", " }\n", " }, 500);\n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "config = CONFIG\n", "config.pretrained_model_name = \"training/epoch=2-step=163563.ckpt/\"\n", "model = build_model(config)" ] } ], "metadata": { "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.10.7" } }, "nbformat": 4, "nbformat_minor": 5 }