{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# AMMICO Demonstration Notebook\n", "With ammico, you can analyze text on images and image content at the same time. This is a demonstration notebook to showcase the capabilities of ammico.\n", "You can run this notebook on google colab or locally / on your own HPC resource. The first cell only runs on google colab; on all other machines, you need to create a conda environment first and install ammico from the Python Package Index using \n", "```pip install ammico``` \n", "Alternatively you can install the development version from the GitHub repository \n", "```pip install git+https://github.com/ssciwr/AMMICO.git```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:42:44.420408Z", "iopub.status.busy": "2024-02-19T08:42:44.420216Z", "iopub.status.idle": "2024-02-19T08:42:44.428568Z", "shell.execute_reply": "2024-02-19T08:42:44.428037Z" } }, "outputs": [], "source": [ "# if running on google colab\n", "# flake8-noqa-cell\n", "\n", "if \"google.colab\" in str(get_ipython()):\n", " # update python version\n", " # install setuptools\n", " # %pip install setuptools==61 -qqq\n", " # uninstall some pre-installed packages due to incompatibility\n", " %pip uninstall tensorflow-probability dopamine-rl lida pandas-gbq torchaudio torchdata torchtext orbax-checkpoint flex-y -qqq\n", " # install ammico\n", " %pip install git+https://github.com/ssciwr/ammico.git -qqq\n", " # mount google drive for data and API key\n", " from google.colab import drive\n", "\n", " drive.mount(\"/content/drive\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use a test dataset\n", "You can download a dataset for test purposes. Skip this step if you use your own data." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:42:44.430935Z", "iopub.status.busy": "2024-02-19T08:42:44.430571Z", "iopub.status.idle": "2024-02-19T08:42:51.757352Z", "shell.execute_reply": "2024-02-19T08:42:51.756689Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "Downloading readme: 0%| | 0.00/21.0 [00:00 `Restart session`. And rerun the notebook again. All required packages will already be installed, so the execution will be very fast. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Step 0: Create and set a Google Cloud Vision Key\n", "\n", "Please note that for the [Google Cloud Vision API](https://cloud.google.com/vision/docs/setup) (the TextDetector class) you need to set a key in order to process the images. A key is generated following [these instructions](../set_up_credentials.md). This key is ideally set as an environment variable using for example\n", "```\n", "os.environ[\n", " \"GOOGLE_APPLICATION_CREDENTIALS\"\n", "] = \"/content/drive/MyDrive/misinformation-data/misinformation-campaign-981aa55a3b13.json\"\n", "```\n", "where you place the key on your Google Drive if running on colab, or place it in a local folder on your machine." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:43:01.943248Z", "iopub.status.busy": "2024-02-19T08:43:01.942735Z", "iopub.status.idle": "2024-02-19T08:43:01.945881Z", "shell.execute_reply": "2024-02-19T08:43:01.945338Z" } }, "outputs": [], "source": [ "# os.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"] = \"/content/drive/MyDrive/misinformation-data/misinformation-campaign-981aa55a3b13.json\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Step 1: Read your data into AMMICO\n", "The ammico package reads in one or several input files given in a folder for processing. The user can select to read in all image files in a folder, to include subfolders via the `recursive` option, and can select the file extension that should be considered (for example, only \"jpg\" files, or both \"jpg\" and \"png\" files). For reading in the files, the ammico function `find_files` is used, with optional keywords:\n", "\n", "| input key | input type | possible input values |\n", "| --------- | ---------- | --------------------- |\n", "`path` | `str` | the directory containing the image files (defaults to the location set by environment variable `AMMICO_DATA_HOME`) |\n", "| `pattern` | `str\\|list` | the file extensions to consider (defaults to \"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\", \"avif\", \"tiff\") |\n", "| `recursive` | `bool` | include subdirectories recursively (defaults to `True`) |\n", "| `limit` | `int` | maximum number of files to read (defaults to `20`, for all images set to `None` or `-1`) |\n", "| `random_seed` | `str` | the random seed for shuffling the images; applies when only a few images are read and the selection should be preserved (defaults to `None`) |\n", "\n", "The `find_files` function returns a nested dict that contains the file ids and the paths to the files and is empty otherwise. This dict is filled step by step with more data as each detector class is run on the data (see below).\n", "\n", "If you downloaded the test dataset above, you can directly provide the path you already set for the test directory, `data_path`." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:43:01.948209Z", "iopub.status.busy": "2024-02-19T08:43:01.947847Z", "iopub.status.idle": "2024-02-19T08:43:01.952312Z", "shell.execute_reply": "2024-02-19T08:43:01.951836Z" } }, "outputs": [], "source": [ "image_dict = ammico.find_files(\n", " # path=\"/content/drive/MyDrive/misinformation-data/\",\n", " path=data_path.as_posix(),\n", " limit=15,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2: Inspect the input files using the graphical user interface\n", "A Dash user interface is to select the most suitable options for the analysis, before running a complete analysis on the whole data set. The options for each detector module are explained below in the corresponding sections; for example, different models can be selected that will provide slightly different results. This way, the user can interactively explore which settings provide the most accurate results. In the interface, the nested `image_dict` is passed through the `AnalysisExplorer` class. The interface is run on a specific port which is passed using the `port` keyword; if a port is already in use, it will return an error message, in which case the user should select a different port number. \n", "The interface opens a dash app inside the Jupyter Notebook and allows selection of the input file in the top left dropdown menu, as well as selection of the detector type in the top right, with options for each detector type as explained below. The output of the detector is shown directly on the right next to the image. This way, the user can directly inspect how updating the options for each detector changes the computed results, and find the best settings for a production run." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:43:01.954766Z", "iopub.status.busy": "2024-02-19T08:43:01.954396Z", "iopub.status.idle": "2024-02-19T08:43:01.978861Z", "shell.execute_reply": "2024-02-19T08:43:01.977627Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "analysis_explorer = ammico.AnalysisExplorer(image_dict)\n", "analysis_explorer.run_server(port=8055)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3: Analyze all images\n", "The analysis can be run in production on all images in the data set. Depending on the size of the data set and the computing resources available, this can take some time. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to set the dump file creation `dump_file` in order to save the calculated data every `dump_every` images. " ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:43:01.981825Z", "iopub.status.busy": "2024-02-19T08:43:01.981158Z", "iopub.status.idle": "2024-02-19T08:43:01.984935Z", "shell.execute_reply": "2024-02-19T08:43:01.983983Z" } }, "outputs": [], "source": [ "# dump file name\n", "dump_file = \"dump_file.csv\"\n", "# dump every N images \n", "dump_every = 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The desired detector modules are called sequentially in any order, for example the `EmotionDetector`:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:43:01.988248Z", "iopub.status.busy": "2024-02-19T08:43:01.987632Z", "iopub.status.idle": "2024-02-19T08:44:04.645259Z", "shell.execute_reply": "2024-02-19T08:44:04.644561Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/6 [00:00=3.7.2 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from en-core-web-md==3.7.1) (3.7.4)\n", "Requirement already satisfied: spacy-legacy<3.1.0,>=3.0.11 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (3.0.12)\n", "Requirement already satisfied: spacy-loggers<2.0.0,>=1.0.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (1.0.5)\n", "Requirement already satisfied: murmurhash<1.1.0,>=0.28.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (1.0.10)\n", "Requirement already satisfied: cymem<2.1.0,>=2.0.2 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.0.8)\n", "Requirement already satisfied: preshed<3.1.0,>=3.0.2 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (3.0.9)\n", "Requirement already satisfied: thinc<8.3.0,>=8.2.2 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (8.2.3)\n", "Requirement already satisfied: wasabi<1.2.0,>=0.9.1 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (1.1.2)\n", "Requirement already satisfied: srsly<3.0.0,>=2.4.3 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.4.8)\n", "Requirement already satisfied: catalogue<2.1.0,>=2.0.6 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.0.10)\n", "Requirement already satisfied: weasel<0.4.0,>=0.1.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (0.3.4)\n", "Requirement already satisfied: typer<0.10.0,>=0.3.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (0.9.0)\n", "Requirement already satisfied: smart-open<7.0.0,>=5.2.1 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (6.4.0)\n", "Requirement already satisfied: tqdm<5.0.0,>=4.38.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (4.66.2)\n", "Requirement already satisfied: requests<3.0.0,>=2.13.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.31.0)\n", "Requirement already satisfied: pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (1.10.14)\n", "Requirement already satisfied: jinja2 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (3.1.3)\n", "Requirement already satisfied: setuptools in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (58.1.0)\n", "Requirement already satisfied: packaging>=20.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (23.2)\n", "Requirement already satisfied: langcodes<4.0.0,>=3.2.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (3.3.0)\n", "Requirement already satisfied: numpy>=1.19.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (1.23.4)\n", "Requirement already satisfied: typing-extensions>=4.2.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from pydantic!=1.8,!=1.8.1,<3.0.0,>=1.7.4->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (4.5.0)\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (3.3.2)\n", "Requirement already satisfied: idna<4,>=2.5 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.10)\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.2.1)\n", "Requirement already satisfied: certifi>=2017.4.17 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from requests<3.0.0,>=2.13.0->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2024.2.2)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: blis<0.8.0,>=0.7.8 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from thinc<8.3.0,>=8.2.2->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (0.7.11)\n", "Requirement already satisfied: confection<1.0.0,>=0.0.1 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from thinc<8.3.0,>=8.2.2->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (0.1.4)\n", "Requirement already satisfied: click<9.0.0,>=7.1.1 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from typer<0.10.0,>=0.3.0->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (8.1.7)\n", "Requirement already satisfied: cloudpathlib<0.17.0,>=0.7.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from weasel<0.4.0,>=0.1.0->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (0.16.0)\n", "Requirement already satisfied: MarkupSafe>=2.0 in /opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages (from jinja2->spacy<3.8.0,>=3.7.2->en-core-web-md==3.7.1) (2.1.5)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Installing collected packages: en-core-web-md\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Successfully installed en-core-web-md-3.7.1\n", "\u001b[38;5;2m✔ Download and installation successful\u001b[0m\n", "You can now load the package via spacy.load('en_core_web_md')\n", "\u001b[38;5;3m⚠ Restart to reload dependencies\u001b[0m\n", "If you are in a Jupyter or Colab notebook, you may need to restart Python in\n", "order to load all the package's dependencies. You can do this by selecting the\n", "'Restart kernel' or 'Restart runtime' option.\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\r", "config.json: 0%| | 0.00/1.80k [00:00\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", " \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", " \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", "
filenamefacemultiple_facesno_faceswears_maskagegenderraceemotionemotion (category)...text_languagetext_englishtext_cleantext_summarysentimentsentiment_scoreentityentity_typeconst_image_summary3_non-deterministic_summary
0data-test/img4.pngNoNo0[No][None][None][None][None][None]...enMOODOVIN XIXIMOODOVIN XI XI: Vladimir Putin, Vladimir Vlad...POSITIVE0.66[MOODOVIN XI][ORG]a river running through a city next to tall bu...[buildings near a waterway with small boats pa...
1data-test/img1.pngNoNo0[No][None][None][None][None][None]...enSCATTERING THEORY The Quantum Theory of Nonrel...THEORY The Quantum Theory of Collisions JOHN R...SCATTERING THEORY The Quantum Theory of Nonre...POSITIVE0.91[Non, ##vist, Col, ##N, R, T, ##AYL, Universit...[MISC, MISC, MISC, ORG, PER, PER, ORG, ORG]a close up of a piece of paper with writing on it[a white paper with some black writing on it, ...
2data-test/img2.pngNoNo0[No][None][None][None][None][None]...enTHE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO M...THE PROBLEM DOM NVS TIO MINA Monographs on Num...H. H. W. WILKINSON: The AlgebriNEGATIVE0.97[ALGEBRAIC EIGENVAL, NVS TIO MI, J, H, WILKINSON][MISC, ORG, ORG, ORG, ORG]a yellow book with green lettering on it[an old book with a picture of the slogan of t...
\n", "

3 rows × 21 columns

\n", "" ], "text/plain": [ " filename face multiple_faces no_faces wears_mask age \\\n", "0 data-test/img4.png No No 0 [No] [None] \n", "1 data-test/img1.png No No 0 [No] [None] \n", "2 data-test/img2.png No No 0 [No] [None] \n", "\n", " gender race emotion emotion (category) ... text_language \\\n", "0 [None] [None] [None] [None] ... en \n", "1 [None] [None] [None] [None] ... en \n", "2 [None] [None] [None] [None] ... en \n", "\n", " text_english \\\n", "0 MOODOVIN XI \n", "1 SCATTERING THEORY The Quantum Theory of Nonrel... \n", "2 THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO M... \n", "\n", " text_clean \\\n", "0 XI \n", "1 THEORY The Quantum Theory of Collisions JOHN R... \n", "2 THE PROBLEM DOM NVS TIO MINA Monographs on Num... \n", "\n", " text_summary sentiment \\\n", "0 MOODOVIN XI XI: Vladimir Putin, Vladimir Vlad... POSITIVE \n", "1 SCATTERING THEORY The Quantum Theory of Nonre... POSITIVE \n", "2 H. H. W. WILKINSON: The Algebri NEGATIVE \n", "\n", " sentiment_score entity \\\n", "0 0.66 [MOODOVIN XI] \n", "1 0.91 [Non, ##vist, Col, ##N, R, T, ##AYL, Universit... \n", "2 0.97 [ALGEBRAIC EIGENVAL, NVS TIO MI, J, H, WILKINSON] \n", "\n", " entity_type \\\n", "0 [ORG] \n", "1 [MISC, MISC, MISC, ORG, PER, PER, ORG, ORG] \n", "2 [MISC, ORG, ORG, ORG, ORG] \n", "\n", " const_image_summary \\\n", "0 a river running through a city next to tall bu... \n", "1 a close up of a piece of paper with writing on it \n", "2 a yellow book with green lettering on it \n", "\n", " 3_non-deterministic_summary \n", "0 [buildings near a waterway with small boats pa... \n", "1 [a white paper with some black writing on it, ... \n", "2 [an old book with a picture of the slogan of t... \n", "\n", "[3 rows x 21 columns]" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image_df.head(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or write to a csv file:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:50:22.391547Z", "iopub.status.busy": "2024-02-19T08:50:22.391161Z", "iopub.status.idle": "2024-02-19T08:50:25.022235Z", "shell.execute_reply": "2024-02-19T08:50:25.021403Z" } }, "outputs": [ { "ename": "OSError", "evalue": "Cannot save file into a non-existent directory: '/content/drive/MyDrive/misinformation-data'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mOSError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[15], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mimage_df\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_csv\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/content/drive/MyDrive/misinformation-data/data_out.csv\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/util/_decorators.py:333\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments..decorate..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 327\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m>\u001b[39m num_allow_args:\n\u001b[1;32m 328\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[1;32m 329\u001b[0m msg\u001b[38;5;241m.\u001b[39mformat(arguments\u001b[38;5;241m=\u001b[39m_format_argument_list(allow_args)),\n\u001b[1;32m 330\u001b[0m \u001b[38;5;167;01mFutureWarning\u001b[39;00m,\n\u001b[1;32m 331\u001b[0m stacklevel\u001b[38;5;241m=\u001b[39mfind_stack_level(),\n\u001b[1;32m 332\u001b[0m )\n\u001b[0;32m--> 333\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\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/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/core/generic.py:3961\u001b[0m, in \u001b[0;36mNDFrame.to_csv\u001b[0;34m(self, path_or_buf, sep, na_rep, float_format, columns, header, index, index_label, mode, encoding, compression, quoting, quotechar, lineterminator, chunksize, date_format, doublequote, escapechar, decimal, errors, storage_options)\u001b[0m\n\u001b[1;32m 3950\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m, ABCDataFrame) \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mto_frame()\n\u001b[1;32m 3952\u001b[0m formatter \u001b[38;5;241m=\u001b[39m DataFrameFormatter(\n\u001b[1;32m 3953\u001b[0m frame\u001b[38;5;241m=\u001b[39mdf,\n\u001b[1;32m 3954\u001b[0m header\u001b[38;5;241m=\u001b[39mheader,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 3958\u001b[0m decimal\u001b[38;5;241m=\u001b[39mdecimal,\n\u001b[1;32m 3959\u001b[0m )\n\u001b[0;32m-> 3961\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mDataFrameRenderer\u001b[49m\u001b[43m(\u001b[49m\u001b[43mformatter\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_csv\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 3962\u001b[0m \u001b[43m \u001b[49m\u001b[43mpath_or_buf\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3963\u001b[0m \u001b[43m \u001b[49m\u001b[43mlineterminator\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlineterminator\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3964\u001b[0m \u001b[43m \u001b[49m\u001b[43msep\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msep\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3965\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3966\u001b[0m \u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3967\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompression\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcompression\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3968\u001b[0m \u001b[43m \u001b[49m\u001b[43mquoting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mquoting\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3969\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3970\u001b[0m \u001b[43m \u001b[49m\u001b[43mindex_label\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mindex_label\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3971\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3972\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunksize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunksize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3973\u001b[0m \u001b[43m \u001b[49m\u001b[43mquotechar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mquotechar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3974\u001b[0m \u001b[43m \u001b[49m\u001b[43mdate_format\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdate_format\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3975\u001b[0m \u001b[43m \u001b[49m\u001b[43mdoublequote\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdoublequote\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3976\u001b[0m \u001b[43m \u001b[49m\u001b[43mescapechar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mescapechar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3977\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3978\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/formats/format.py:1014\u001b[0m, in \u001b[0;36mDataFrameRenderer.to_csv\u001b[0;34m(self, path_or_buf, encoding, sep, columns, index_label, mode, compression, quoting, quotechar, lineterminator, chunksize, date_format, doublequote, escapechar, errors, storage_options)\u001b[0m\n\u001b[1;32m 993\u001b[0m created_buffer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 995\u001b[0m csv_formatter \u001b[38;5;241m=\u001b[39m CSVFormatter(\n\u001b[1;32m 996\u001b[0m path_or_buf\u001b[38;5;241m=\u001b[39mpath_or_buf,\n\u001b[1;32m 997\u001b[0m lineterminator\u001b[38;5;241m=\u001b[39mlineterminator,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1012\u001b[0m formatter\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfmt,\n\u001b[1;32m 1013\u001b[0m )\n\u001b[0;32m-> 1014\u001b[0m \u001b[43mcsv_formatter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msave\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1016\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m created_buffer:\n\u001b[1;32m 1017\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(path_or_buf, StringIO)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/formats/csvs.py:251\u001b[0m, in \u001b[0;36mCSVFormatter.save\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;124;03mCreate the writer & save.\u001b[39;00m\n\u001b[1;32m 249\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 250\u001b[0m \u001b[38;5;66;03m# apply compression and byte/text conversion\u001b[39;00m\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 252\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfilepath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 253\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 254\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 255\u001b[0m \u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 256\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompression\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcompression\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 257\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 258\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m handles:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;66;03m# Note: self.encoding is irrelevant here\u001b[39;00m\n\u001b[1;32m 260\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mwriter \u001b[38;5;241m=\u001b[39m csvlib\u001b[38;5;241m.\u001b[39mwriter(\n\u001b[1;32m 261\u001b[0m handles\u001b[38;5;241m.\u001b[39mhandle,\n\u001b[1;32m 262\u001b[0m lineterminator\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlineterminator,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 267\u001b[0m quotechar\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mquotechar,\n\u001b[1;32m 268\u001b[0m )\n\u001b[1;32m 270\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_save()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/common.py:749\u001b[0m, in \u001b[0;36mget_handle\u001b[0;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[1;32m 747\u001b[0m \u001b[38;5;66;03m# Only for write methods\u001b[39;00m\n\u001b[1;32m 748\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m mode \u001b[38;5;129;01mand\u001b[39;00m is_path:\n\u001b[0;32m--> 749\u001b[0m \u001b[43mcheck_parent_directory\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 751\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m compression:\n\u001b[1;32m 752\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m compression \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mzstd\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 753\u001b[0m \u001b[38;5;66;03m# compression libraries do not like an explicit text-mode\u001b[39;00m\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/common.py:616\u001b[0m, in \u001b[0;36mcheck_parent_directory\u001b[0;34m(path)\u001b[0m\n\u001b[1;32m 614\u001b[0m parent \u001b[38;5;241m=\u001b[39m Path(path)\u001b[38;5;241m.\u001b[39mparent\n\u001b[1;32m 615\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m parent\u001b[38;5;241m.\u001b[39mis_dir():\n\u001b[0;32m--> 616\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mOSError\u001b[39;00m(\u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot save file into a non-existent directory: \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mparent\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "\u001b[0;31mOSError\u001b[0m: Cannot save file into a non-existent directory: '/content/drive/MyDrive/misinformation-data'" ] } ], "source": [ "image_df.to_csv(\"/content/drive/MyDrive/misinformation-data/data_out.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The detector modules\n", "The different detector modules with their options are explained in more detail in this section.\n", "## Text detector\n", "Text on the images can be extracted using the `TextDetector` class (`text` module). The text is initally extracted using the Google Cloud Vision API and then translated into English with googletrans. The translated text is cleaned of whitespace, linebreaks, and numbers using Python syntax and spaCy. \n", "\n", "\n", "\n", "The user can set if the text should be further summarized, and analyzed for sentiment and named entity recognition, by setting the keyword `analyse_text` to `True` (the default is `False`). If set, the transformers pipeline is used for each of these tasks, with the default models as of 03/2023. Other models can be selected by setting the optional keyword `model_names` to a list of selected models, on for each task: `model_names=[\"sshleifer/distilbart-cnn-12-6\", \"distilbert-base-uncased-finetuned-sst-2-english\", \"dbmdz/bert-large-cased-finetuned-conll03-english\"]` for summary, sentiment, and ner. To be even more specific, revision numbers can also be selected by specifying the optional keyword `revision_numbers` to a list of revision numbers for each model, for example `revision_numbers=[\"a4f8f3e\", \"af0f99b\", \"f2482bf\"]`. \n", "\n", "Please note that for the Google Cloud Vision API (the TextDetector class) you need to set a key in order to process the images. This key is ideally set as an environment variable using for example" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:50:25.032719Z", "iopub.status.busy": "2024-02-19T08:50:25.032386Z", "iopub.status.idle": "2024-02-19T08:50:25.035336Z", "shell.execute_reply": "2024-02-19T08:50:25.034770Z" } }, "outputs": [], "source": [ "# os.environ[\"GOOGLE_APPLICATION_CREDENTIALS\"] = \"/content/drive/MyDrive/misinformation-data/misinformation-campaign-981aa55a3b13.json\"\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "where you place the key on your Google Drive if running on colab, or place it in a local folder on your machine.\n", "\n", "Summarizing, the text detection is carried out using the following method call and keywords, where `analyse_text`, `model_names`, and `revision_numbers` are optional:\n" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:50:25.037648Z", "iopub.status.busy": "2024-02-19T08:50:25.037344Z", "iopub.status.idle": "2024-02-19T08:51:21.184249Z", "shell.execute_reply": "2024-02-19T08:51:21.183549Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/6 [00:00\n", "\n", "This module is based on the [LAVIS](https://github.com/salesforce/LAVIS) library. Since the models can be quite large, an initial object is created which will load the necessary models into RAM/VRAM and then use them in the analysis. The user can specify the type of analysis to be performed using the `analysis_type` keyword. Setting it to `summary` will generate a caption (summary), `questions` will prepare answers (VQA) to a list of questions as set by the user, `summary_and_questions` will do both. Note that the desired analysis type needs to be set here in the initialization of the \n", "detector object, and not when running the analysis for each image; the same holds true for the selected model." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The implemented models are listed below.\n", "\n", "| input model name | model |\n", "| ---------------- | ----- |\n", "| base | BLIP image captioning base, ViT-B/16, pretrained on COCO dataset |\n", "| large | BLIP image captioning large, ViT-L/16, pretrained on COCO dataset |\n", "| vqa | BLIP base model fine-tuned on VQA v2.0 dataset |\n", "| blip2_t5_pretrain_flant5xxl | BLIP2 pretrained on FlanT5XXL | \n", "| blip2_t5_pretrain_flant5xl | BLIP2 pretrained on FlanT5XL | \n", "| blip2_t5_caption_coco_flant5xl | BLIP2 pretrained on FlanT5XL, fine-tuned on COCO | \n", "| blip2_opt_pretrain_opt2.7b | BLIP2 pretrained on OPT-2.7b |\n", "| blip2_opt_pretrain_opt6.7b | BLIP2 pretrained on OPT-6.7b | \n", "| blip2_opt_caption_coco_opt2.7b | BLIP2 pretrained on OPT-2.7b, fine-tuned on COCO | \n", "| blip2_opt_caption_coco_opt6.7b | BLIP2 pretrained on OPT-6.7b, fine-tuned on COCO |\n", "\n", "Please note that `base`, `large` and `vqa` models can be run on the base TPU video card in Google Colab.\n", "To run any advanced `BLIP2` models you need more than 20 gb of video memory, so you need to connect a paid A100 in Google Colab." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First of all, we can run only the summary module `analysis_type`. You can choose a `base` or a `large` model_type. " ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:51:21.186991Z", "iopub.status.busy": "2024-02-19T08:51:21.186599Z", "iopub.status.idle": "2024-02-19T08:51:27.937584Z", "shell.execute_reply": "2024-02-19T08:51:27.936965Z" } }, "outputs": [], "source": [ "image_summary_detector = ammico.SummaryDetector(image_dict, analysis_type=\"summary\", model_type=\"base\")" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:51:27.945516Z", "iopub.status.busy": "2024-02-19T08:51:27.945076Z", "iopub.status.idle": "2024-02-19T08:52:37.388418Z", "shell.execute_reply": "2024-02-19T08:52:37.387691Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0/6 [00:00 1\u001b[0m image_summary_vqa_detector \u001b[38;5;241m=\u001b[39m \u001b[43mammico\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mSummaryDetector\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimage_dict\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43manalysis_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mquestions\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mvqa\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m num, key \u001b[38;5;129;01min\u001b[39;00m tqdm(\u001b[38;5;28menumerate\u001b[39m(image_dict\u001b[38;5;241m.\u001b[39mkeys()),total\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mlen\u001b[39m(image_dict)):\n\u001b[1;32m 5\u001b[0m image_dict[key] \u001b[38;5;241m=\u001b[39m image_summary_vqa_detector\u001b[38;5;241m.\u001b[39manalyse_image(subdict\u001b[38;5;241m=\u001b[39mimage_dict[key], \n\u001b[1;32m 6\u001b[0m analysis_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mquestions\u001b[39m\u001b[38;5;124m\"\u001b[39m, \n\u001b[1;32m 7\u001b[0m list_of_questions \u001b[38;5;241m=\u001b[39m list_of_questions)\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:141\u001b[0m, in \u001b[0;36mSummaryDetector.__init__\u001b[0;34m(self, subdict, model_type, analysis_type, list_of_questions, summary_model, summary_vis_processors, summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors, summary_vqa_model_new, summary_vqa_vis_processors_new, summary_vqa_txt_processors_new, device_type)\u001b[0m\n\u001b[1;32m 127\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vis_processors \u001b[38;5;241m=\u001b[39m summary_vis_processors\n\u001b[1;32m 128\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 129\u001b[0m model_type \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mallowed_model_types\n\u001b[1;32m 130\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m (summary_vqa_model \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 135\u001b[0m )\n\u001b[1;32m 136\u001b[0m ):\n\u001b[1;32m 137\u001b[0m (\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_model,\n\u001b[1;32m 139\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_vis_processors,\n\u001b[1;32m 140\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_txt_processors,\n\u001b[0;32m--> 141\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_vqa_model\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 143\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_model \u001b[38;5;241m=\u001b[39m summary_vqa_model\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:232\u001b[0m, in \u001b[0;36mSummaryDetector.load_vqa_model\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 216\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mload_vqa_model\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 217\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 218\u001b[0m \u001b[38;5;124;03m Load blip_vqa model and preprocessors for visual and text inputs from lavis.models.\u001b[39;00m\n\u001b[1;32m 219\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 226\u001b[0m \n\u001b[1;32m 227\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 228\u001b[0m (\n\u001b[1;32m 229\u001b[0m summary_vqa_model,\n\u001b[1;32m 230\u001b[0m summary_vqa_vis_processors,\n\u001b[1;32m 231\u001b[0m summary_vqa_txt_processors,\n\u001b[0;32m--> 232\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43mload_model_and_preprocess\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 233\u001b[0m \u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mblip_vqa\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 234\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mvqav2\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 235\u001b[0m \u001b[43m \u001b[49m\u001b[43mis_eval\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 236\u001b[0m \u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msummary_device\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 237\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/__init__.py:195\u001b[0m, in \u001b[0;36mload_model_and_preprocess\u001b[0;34m(name, model_type, is_eval, device)\u001b[0m\n\u001b[1;32m 192\u001b[0m model_cls \u001b[38;5;241m=\u001b[39m registry\u001b[38;5;241m.\u001b[39mget_model_class(name)\n\u001b[1;32m 194\u001b[0m \u001b[38;5;66;03m# load model\u001b[39;00m\n\u001b[0;32m--> 195\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mmodel_cls\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_pretrained\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel_type\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 197\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_eval:\n\u001b[1;32m 198\u001b[0m model\u001b[38;5;241m.\u001b[39meval()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:70\u001b[0m, in \u001b[0;36mBaseModel.from_pretrained\u001b[0;34m(cls, model_type)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 61\u001b[0m \u001b[38;5;124;03mBuild a pretrained model from default configuration file, specified by model_type.\u001b[39;00m\n\u001b[1;32m 62\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m - model (nn.Module): pretrained or finetuned model, depending on the configuration.\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 69\u001b[0m model_cfg \u001b[38;5;241m=\u001b[39m OmegaConf\u001b[38;5;241m.\u001b[39mload(\u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39mdefault_config_path(model_type))\u001b[38;5;241m.\u001b[39mmodel\n\u001b[0;32m---> 70\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_cfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip_models/blip_vqa.py:373\u001b[0m, in \u001b[0;36mBlipVQA.from_config\u001b[0;34m(cls, cfg)\u001b[0m\n\u001b[1;32m 364\u001b[0m max_txt_len \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmax_txt_len\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;241m35\u001b[39m)\n\u001b[1;32m 366\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mcls\u001b[39m(\n\u001b[1;32m 367\u001b[0m image_encoder\u001b[38;5;241m=\u001b[39mimage_encoder,\n\u001b[1;32m 368\u001b[0m text_encoder\u001b[38;5;241m=\u001b[39mtext_encoder,\n\u001b[1;32m 369\u001b[0m text_decoder\u001b[38;5;241m=\u001b[39mtext_decoder,\n\u001b[1;32m 370\u001b[0m max_txt_len\u001b[38;5;241m=\u001b[39mmax_txt_len,\n\u001b[1;32m 371\u001b[0m )\n\u001b[0;32m--> 373\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_checkpoint_from_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 375\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:95\u001b[0m, in \u001b[0;36mBaseModel.load_checkpoint_from_config\u001b[0;34m(self, cfg, **kwargs)\u001b[0m\n\u001b[1;32m 91\u001b[0m finetune_path \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfinetuned\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 92\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m (\n\u001b[1;32m 93\u001b[0m finetune_path \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 94\u001b[0m ), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFound load_finetuned is True, but finetune_path is None.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 95\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_checkpoint\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl_or_filename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfinetune_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 97\u001b[0m \u001b[38;5;66;03m# load pre-trained weights\u001b[39;00m\n\u001b[1;32m 98\u001b[0m pretrain_path \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpretrained\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:37\u001b[0m, in \u001b[0;36mBaseModel.load_checkpoint\u001b[0;34m(self, url_or_filename)\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 31\u001b[0m \u001b[38;5;124;03mLoad from a finetuned checkpoint.\u001b[39;00m\n\u001b[1;32m 32\u001b[0m \n\u001b[1;32m 33\u001b[0m \u001b[38;5;124;03mThis should expect no mismatch in the model keys and the checkpoint keys.\u001b[39;00m\n\u001b[1;32m 34\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 36\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_url(url_or_filename):\n\u001b[0;32m---> 37\u001b[0m cached_file \u001b[38;5;241m=\u001b[39m \u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 38\u001b[0m \u001b[43m \u001b[49m\u001b[43murl_or_filename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\n\u001b[1;32m 39\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 40\u001b[0m checkpoint \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mload(cached_file, map_location\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcpu\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39misfile(url_or_filename):\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/common/dist_utils.py:132\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n\u001b[1;32m 131\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_main_process():\n\u001b[0;32m--> 132\u001b[0m \u001b[43mtimm_hub\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_dist_avail_and_initialized():\n\u001b[1;32m 135\u001b[0m dist\u001b[38;5;241m.\u001b[39mbarrier()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/timm/models/hub.py:51\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 49\u001b[0m r \u001b[38;5;241m=\u001b[39m HASH_REGEX\u001b[38;5;241m.\u001b[39msearch(filename) \u001b[38;5;66;03m# r is Optional[Match[str]]\u001b[39;00m\n\u001b[1;32m 50\u001b[0m hash_prefix \u001b[38;5;241m=\u001b[39m r\u001b[38;5;241m.\u001b[39mgroup(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;28;01mif\u001b[39;00m r \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 51\u001b[0m \u001b[43mdownload_url_to_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcached_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhash_prefix\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 52\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/torch/hub.py:636\u001b[0m, in \u001b[0;36mdownload_url_to_file\u001b[0;34m(url, dst, hash_prefix, progress)\u001b[0m\n\u001b[1;32m 634\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(buffer) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 635\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m--> 636\u001b[0m \u001b[43mf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwrite\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 637\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m hash_prefix \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 638\u001b[0m sha256\u001b[38;5;241m.\u001b[39mupdate(buffer)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/tempfile.py:478\u001b[0m, in \u001b[0;36m_TemporaryFileWrapper.__getattr__..func_wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;129m@_functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 477\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfunc_wrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m--> 478\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\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[0;31mOSError\u001b[0m: [Errno 28] No space left on device" ] } ], "source": [ "image_summary_vqa_detector = ammico.SummaryDetector(image_dict, analysis_type=\"questions\", \n", " model_type=\"vqa\")\n", "\n", "for num, key in tqdm(enumerate(image_dict.keys()),total=len(image_dict)):\n", " image_dict[key] = image_summary_vqa_detector.analyse_image(subdict=image_dict[key], \n", " analysis_type=\"questions\", \n", " list_of_questions = list_of_questions)\n", " if num % dump_every == 0 | num == len(image_dict) - 1: \n", " image_df = ammico.get_dataframe(image_dict)\n", " image_df.to_csv(dump_file)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or you can specify the analysis type as `summary_and_questions`, then both caption creation and question answers will be generated for each image. In this case, you can choose a `base` or a `large` model_type. " ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:52:56.408315Z", "iopub.status.busy": "2024-02-19T08:52:56.407932Z", "iopub.status.idle": "2024-02-19T08:53:18.175891Z", "shell.execute_reply": "2024-02-19T08:53:18.175071Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0.00/1.35G [00:00 1\u001b[0m image_summary_vqa_detector \u001b[38;5;241m=\u001b[39m \u001b[43mammico\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mSummaryDetector\u001b[49m\u001b[43m(\u001b[49m\u001b[43mimage_dict\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43manalysis_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msummary_and_questions\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbase\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m num, key \u001b[38;5;129;01min\u001b[39;00m tqdm(\u001b[38;5;28menumerate\u001b[39m(image_dict\u001b[38;5;241m.\u001b[39mkeys()),total\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mlen\u001b[39m(image_dict)):\n\u001b[1;32m 4\u001b[0m image_dict[key] \u001b[38;5;241m=\u001b[39m image_summary_vqa_detector\u001b[38;5;241m.\u001b[39manalyse_image(subdict\u001b[38;5;241m=\u001b[39mimage_dict[key], \n\u001b[1;32m 5\u001b[0m analysis_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msummary_and_questions\u001b[39m\u001b[38;5;124m\"\u001b[39m, \n\u001b[1;32m 6\u001b[0m list_of_questions \u001b[38;5;241m=\u001b[39m list_of_questions)\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:141\u001b[0m, in \u001b[0;36mSummaryDetector.__init__\u001b[0;34m(self, subdict, model_type, analysis_type, list_of_questions, summary_model, summary_vis_processors, summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors, summary_vqa_model_new, summary_vqa_vis_processors_new, summary_vqa_txt_processors_new, device_type)\u001b[0m\n\u001b[1;32m 127\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vis_processors \u001b[38;5;241m=\u001b[39m summary_vis_processors\n\u001b[1;32m 128\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 129\u001b[0m model_type \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mallowed_model_types\n\u001b[1;32m 130\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m (summary_vqa_model \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 135\u001b[0m )\n\u001b[1;32m 136\u001b[0m ):\n\u001b[1;32m 137\u001b[0m (\n\u001b[1;32m 138\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_model,\n\u001b[1;32m 139\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_vis_processors,\n\u001b[1;32m 140\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_txt_processors,\n\u001b[0;32m--> 141\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_vqa_model\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 143\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_model \u001b[38;5;241m=\u001b[39m summary_vqa_model\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:232\u001b[0m, in \u001b[0;36mSummaryDetector.load_vqa_model\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 216\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mload_vqa_model\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 217\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 218\u001b[0m \u001b[38;5;124;03m Load blip_vqa model and preprocessors for visual and text inputs from lavis.models.\u001b[39;00m\n\u001b[1;32m 219\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 226\u001b[0m \n\u001b[1;32m 227\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 228\u001b[0m (\n\u001b[1;32m 229\u001b[0m summary_vqa_model,\n\u001b[1;32m 230\u001b[0m summary_vqa_vis_processors,\n\u001b[1;32m 231\u001b[0m summary_vqa_txt_processors,\n\u001b[0;32m--> 232\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43mload_model_and_preprocess\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 233\u001b[0m \u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mblip_vqa\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 234\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mvqav2\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 235\u001b[0m \u001b[43m \u001b[49m\u001b[43mis_eval\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 236\u001b[0m \u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msummary_device\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 237\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 238\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/__init__.py:195\u001b[0m, in \u001b[0;36mload_model_and_preprocess\u001b[0;34m(name, model_type, is_eval, device)\u001b[0m\n\u001b[1;32m 192\u001b[0m model_cls \u001b[38;5;241m=\u001b[39m registry\u001b[38;5;241m.\u001b[39mget_model_class(name)\n\u001b[1;32m 194\u001b[0m \u001b[38;5;66;03m# load model\u001b[39;00m\n\u001b[0;32m--> 195\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mmodel_cls\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_pretrained\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel_type\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 197\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_eval:\n\u001b[1;32m 198\u001b[0m model\u001b[38;5;241m.\u001b[39meval()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:70\u001b[0m, in \u001b[0;36mBaseModel.from_pretrained\u001b[0;34m(cls, model_type)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 61\u001b[0m \u001b[38;5;124;03mBuild a pretrained model from default configuration file, specified by model_type.\u001b[39;00m\n\u001b[1;32m 62\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m - model (nn.Module): pretrained or finetuned model, depending on the configuration.\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 69\u001b[0m model_cfg \u001b[38;5;241m=\u001b[39m OmegaConf\u001b[38;5;241m.\u001b[39mload(\u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39mdefault_config_path(model_type))\u001b[38;5;241m.\u001b[39mmodel\n\u001b[0;32m---> 70\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_cfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip_models/blip_vqa.py:373\u001b[0m, in \u001b[0;36mBlipVQA.from_config\u001b[0;34m(cls, cfg)\u001b[0m\n\u001b[1;32m 364\u001b[0m max_txt_len \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmax_txt_len\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;241m35\u001b[39m)\n\u001b[1;32m 366\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mcls\u001b[39m(\n\u001b[1;32m 367\u001b[0m image_encoder\u001b[38;5;241m=\u001b[39mimage_encoder,\n\u001b[1;32m 368\u001b[0m text_encoder\u001b[38;5;241m=\u001b[39mtext_encoder,\n\u001b[1;32m 369\u001b[0m text_decoder\u001b[38;5;241m=\u001b[39mtext_decoder,\n\u001b[1;32m 370\u001b[0m max_txt_len\u001b[38;5;241m=\u001b[39mmax_txt_len,\n\u001b[1;32m 371\u001b[0m )\n\u001b[0;32m--> 373\u001b[0m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_checkpoint_from_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 375\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:95\u001b[0m, in \u001b[0;36mBaseModel.load_checkpoint_from_config\u001b[0;34m(self, cfg, **kwargs)\u001b[0m\n\u001b[1;32m 91\u001b[0m finetune_path \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfinetuned\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 92\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m (\n\u001b[1;32m 93\u001b[0m finetune_path \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 94\u001b[0m ), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFound load_finetuned is True, but finetune_path is None.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 95\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_checkpoint\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl_or_filename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfinetune_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 96\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 97\u001b[0m \u001b[38;5;66;03m# load pre-trained weights\u001b[39;00m\n\u001b[1;32m 98\u001b[0m pretrain_path \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpretrained\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:37\u001b[0m, in \u001b[0;36mBaseModel.load_checkpoint\u001b[0;34m(self, url_or_filename)\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 31\u001b[0m \u001b[38;5;124;03mLoad from a finetuned checkpoint.\u001b[39;00m\n\u001b[1;32m 32\u001b[0m \n\u001b[1;32m 33\u001b[0m \u001b[38;5;124;03mThis should expect no mismatch in the model keys and the checkpoint keys.\u001b[39;00m\n\u001b[1;32m 34\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 36\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_url(url_or_filename):\n\u001b[0;32m---> 37\u001b[0m cached_file \u001b[38;5;241m=\u001b[39m \u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 38\u001b[0m \u001b[43m \u001b[49m\u001b[43murl_or_filename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\n\u001b[1;32m 39\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 40\u001b[0m checkpoint \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mload(cached_file, map_location\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcpu\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39misfile(url_or_filename):\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/common/dist_utils.py:132\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n\u001b[1;32m 131\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_main_process():\n\u001b[0;32m--> 132\u001b[0m \u001b[43mtimm_hub\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_dist_avail_and_initialized():\n\u001b[1;32m 135\u001b[0m dist\u001b[38;5;241m.\u001b[39mbarrier()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/timm/models/hub.py:51\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 49\u001b[0m r \u001b[38;5;241m=\u001b[39m HASH_REGEX\u001b[38;5;241m.\u001b[39msearch(filename) \u001b[38;5;66;03m# r is Optional[Match[str]]\u001b[39;00m\n\u001b[1;32m 50\u001b[0m hash_prefix \u001b[38;5;241m=\u001b[39m r\u001b[38;5;241m.\u001b[39mgroup(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;28;01mif\u001b[39;00m r \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 51\u001b[0m \u001b[43mdownload_url_to_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcached_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhash_prefix\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 52\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/torch/hub.py:636\u001b[0m, in \u001b[0;36mdownload_url_to_file\u001b[0;34m(url, dst, hash_prefix, progress)\u001b[0m\n\u001b[1;32m 634\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(buffer) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 635\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m--> 636\u001b[0m \u001b[43mf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwrite\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 637\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m hash_prefix \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 638\u001b[0m sha256\u001b[38;5;241m.\u001b[39mupdate(buffer)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/tempfile.py:478\u001b[0m, in \u001b[0;36m_TemporaryFileWrapper.__getattr__..func_wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;129m@_functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 477\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfunc_wrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m--> 478\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\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[0;31mOSError\u001b[0m: [Errno 28] No space left on device" ] } ], "source": [ "image_summary_vqa_detector = ammico.SummaryDetector(image_dict, analysis_type=\"summary_and_questions\", \n", " model_type=\"base\")\n", "for num, key in tqdm(enumerate(image_dict.keys()),total=len(image_dict)):\n", " image_dict[key] = image_summary_vqa_detector.analyse_image(subdict=image_dict[key], \n", " analysis_type=\"summary_and_questions\", \n", " list_of_questions = list_of_questions)\n", " if num % dump_every == 0 | num == len(image_dict) - 1: \n", " image_df = ammico.get_dataframe(image_dict)\n", " image_df.to_csv(dump_file)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The output is given as a dictionary with the following keys and data types:\n", "\n", "| output key | output type | output value |\n", "| ---------- | ----------- | ------------ |\n", "| `const_image_summary` | `str` | when `analysis_type=\"summary\"` or `\"summary_and_questions\"`, constant image caption (does not change upon re-running the analysis for the same model) |\n", "| `3_non-deterministic_summary` | `list[str]` | when `analysis_type=\"summary\"` or s`ummary_and_questions`, three different captions generated with different random seeds |\n", "| *a user-defined input question* | `str` | when `analysis_type=\"questions\"` or `summary_and_questions`, the answer to the user-defined input question | \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### BLIP2 models\n", "This is very heavy models. They requare approx 60GB of RAM and they can use more than 20GB GPUs memory." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:18.184352Z", "iopub.status.busy": "2024-02-19T08:53:18.183915Z", "iopub.status.idle": "2024-02-19T08:53:49.441778Z", "shell.execute_reply": "2024-02-19T08:53:49.440627Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0.00/1.89G [00:00 1\u001b[0m obj \u001b[38;5;241m=\u001b[39m \u001b[43mammico\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mSummaryDetector\u001b[49m\u001b[43m(\u001b[49m\u001b[43msubdict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mimage_dict\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43manalysis_type\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43msummary_and_questions\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mblip2_t5_caption_coco_flant5xl\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;66;03m# list of the new models that can be used:\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# \"blip2_t5_pretrain_flant5xxl\",\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# \"blip2_t5_pretrain_flant5xl\",\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 14\u001b[0m \n\u001b[1;32m 15\u001b[0m \u001b[38;5;66;03m#also you can perform all calculation on cpu if you set device_type= \"cpu\" or gpu if you set device_type= \"cuda\"\u001b[39;00m\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:156\u001b[0m, in \u001b[0;36mSummaryDetector.__init__\u001b[0;34m(self, subdict, model_type, analysis_type, list_of_questions, summary_model, summary_vis_processors, summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors, summary_vqa_model_new, summary_vqa_vis_processors_new, summary_vqa_txt_processors_new, device_type)\u001b[0m\n\u001b[1;32m 145\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_txt_processors \u001b[38;5;241m=\u001b[39m summary_vqa_txt_processors\n\u001b[1;32m 146\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 147\u001b[0m model_type \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mallowed_new_model_types\n\u001b[1;32m 148\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m (summary_vqa_model_new \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 149\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m (summary_vqa_vis_processors_new \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 150\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m (summary_vqa_txt_processors_new \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 151\u001b[0m ):\n\u001b[1;32m 152\u001b[0m (\n\u001b[1;32m 153\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_model_new,\n\u001b[1;32m 154\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_vis_processors_new,\n\u001b[1;32m 155\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_txt_processors_new,\n\u001b[0;32m--> 156\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_new_model\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel_type\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 157\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 158\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msummary_vqa_model_new \u001b[38;5;241m=\u001b[39m summary_vqa_model_new\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:479\u001b[0m, in \u001b[0;36mSummaryDetector.load_new_model\u001b[0;34m(self, model_type)\u001b[0m\n\u001b[1;32m 455\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 456\u001b[0m \u001b[38;5;124;03mLoad new BLIP2 models.\u001b[39;00m\n\u001b[1;32m 457\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 464\u001b[0m \u001b[38;5;124;03m txt_processors (dict): preprocessors for text inputs.\u001b[39;00m\n\u001b[1;32m 465\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 466\u001b[0m select_model \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 467\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblip2_t5_pretrain_flant5xxl\u001b[39m\u001b[38;5;124m\"\u001b[39m: SummaryDetector\u001b[38;5;241m.\u001b[39mload_model_blip2_t5_pretrain_flant5xxl,\n\u001b[1;32m 468\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblip2_t5_pretrain_flant5xl\u001b[39m\u001b[38;5;124m\"\u001b[39m: SummaryDetector\u001b[38;5;241m.\u001b[39mload_model_blip2_t5_pretrain_flant5xl,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 473\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblip2_opt_caption_coco_opt6.7b\u001b[39m\u001b[38;5;124m\"\u001b[39m: SummaryDetector\u001b[38;5;241m.\u001b[39mload_model_base_blip2_opt_caption_coco_opt67b,\n\u001b[1;32m 474\u001b[0m }\n\u001b[1;32m 475\u001b[0m (\n\u001b[1;32m 476\u001b[0m summary_vqa_model,\n\u001b[1;32m 477\u001b[0m summary_vqa_vis_processors,\n\u001b[1;32m 478\u001b[0m summary_vqa_txt_processors,\n\u001b[0;32m--> 479\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43mselect_model\u001b[49m\u001b[43m[\u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[43m]\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/summary.py:543\u001b[0m, in \u001b[0;36mSummaryDetector.load_model_blip2_t5_caption_coco_flant5xl\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 528\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mload_model_blip2_t5_caption_coco_flant5xl\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 529\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 530\u001b[0m \u001b[38;5;124;03m Load BLIP2 model with caption_coco_flant5xl architecture.\u001b[39;00m\n\u001b[1;32m 531\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 537\u001b[0m \u001b[38;5;124;03m txt_processors (dict): preprocessors for text inputs.\u001b[39;00m\n\u001b[1;32m 538\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 539\u001b[0m (\n\u001b[1;32m 540\u001b[0m summary_vqa_model,\n\u001b[1;32m 541\u001b[0m summary_vqa_vis_processors,\n\u001b[1;32m 542\u001b[0m summary_vqa_txt_processors,\n\u001b[0;32m--> 543\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43mload_model_and_preprocess\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 544\u001b[0m \u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mblip2_t5\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 545\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mcaption_coco_flant5xl\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 546\u001b[0m \u001b[43m \u001b[49m\u001b[43mis_eval\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 547\u001b[0m \u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msummary_device\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 548\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 549\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m summary_vqa_model, summary_vqa_vis_processors, summary_vqa_txt_processors\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/__init__.py:195\u001b[0m, in \u001b[0;36mload_model_and_preprocess\u001b[0;34m(name, model_type, is_eval, device)\u001b[0m\n\u001b[1;32m 192\u001b[0m model_cls \u001b[38;5;241m=\u001b[39m registry\u001b[38;5;241m.\u001b[39mget_model_class(name)\n\u001b[1;32m 194\u001b[0m \u001b[38;5;66;03m# load model\u001b[39;00m\n\u001b[0;32m--> 195\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mmodel_cls\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_pretrained\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel_type\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 197\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_eval:\n\u001b[1;32m 198\u001b[0m model\u001b[38;5;241m.\u001b[39meval()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:70\u001b[0m, in \u001b[0;36mBaseModel.from_pretrained\u001b[0;34m(cls, model_type)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 61\u001b[0m \u001b[38;5;124;03mBuild a pretrained model from default configuration file, specified by model_type.\u001b[39;00m\n\u001b[1;32m 62\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m - model (nn.Module): pretrained or finetuned model, depending on the configuration.\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 69\u001b[0m model_cfg \u001b[38;5;241m=\u001b[39m OmegaConf\u001b[38;5;241m.\u001b[39mload(\u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39mdefault_config_path(model_type))\u001b[38;5;241m.\u001b[39mmodel\n\u001b[0;32m---> 70\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_cfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip2_models/blip2_t5.py:368\u001b[0m, in \u001b[0;36mBlip2T5.from_config\u001b[0;34m(cls, cfg)\u001b[0m\n\u001b[1;32m 364\u001b[0m max_txt_len \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mmax_txt_len\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;241m32\u001b[39m)\n\u001b[1;32m 366\u001b[0m apply_lemmatizer \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mapply_lemmatizer\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[0;32m--> 368\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 369\u001b[0m \u001b[43m \u001b[49m\u001b[43mvit_model\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvit_model\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 370\u001b[0m \u001b[43m \u001b[49m\u001b[43mimg_size\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mimg_size\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 371\u001b[0m \u001b[43m \u001b[49m\u001b[43mdrop_path_rate\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdrop_path_rate\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 372\u001b[0m \u001b[43m \u001b[49m\u001b[43muse_grad_checkpoint\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43muse_grad_checkpoint\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 373\u001b[0m \u001b[43m \u001b[49m\u001b[43mvit_precision\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvit_precision\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 374\u001b[0m \u001b[43m \u001b[49m\u001b[43mfreeze_vit\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfreeze_vit\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 375\u001b[0m \u001b[43m \u001b[49m\u001b[43mnum_query_token\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnum_query_token\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 376\u001b[0m \u001b[43m \u001b[49m\u001b[43mt5_model\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mt5_model\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 377\u001b[0m \u001b[43m \u001b[49m\u001b[43mprompt\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprompt\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 378\u001b[0m \u001b[43m \u001b[49m\u001b[43mmax_txt_len\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmax_txt_len\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 379\u001b[0m \u001b[43m \u001b[49m\u001b[43mapply_lemmatizer\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mapply_lemmatizer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 380\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 381\u001b[0m model\u001b[38;5;241m.\u001b[39mload_checkpoint_from_config(cfg)\n\u001b[1;32m 383\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip2_models/blip2_t5.py:61\u001b[0m, in \u001b[0;36mBlip2T5.__init__\u001b[0;34m(self, vit_model, img_size, drop_path_rate, use_grad_checkpoint, vit_precision, freeze_vit, num_query_token, t5_model, prompt, max_txt_len, apply_lemmatizer)\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m()\n\u001b[1;32m 59\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtokenizer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39minit_tokenizer()\n\u001b[0;32m---> 61\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvisual_encoder, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mln_vision \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43minit_vision_encoder\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[43m \u001b[49m\u001b[43mvit_model\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mimg_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdrop_path_rate\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43muse_grad_checkpoint\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvit_precision\u001b[49m\n\u001b[1;32m 63\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 64\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m freeze_vit:\n\u001b[1;32m 65\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m name, param \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvisual_encoder\u001b[38;5;241m.\u001b[39mnamed_parameters():\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip2_models/blip2.py:72\u001b[0m, in \u001b[0;36mBlip2Base.init_vision_encoder\u001b[0;34m(cls, model_name, img_size, drop_path_rate, use_grad_checkpoint, precision)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m model_name \u001b[38;5;129;01min\u001b[39;00m [\n\u001b[1;32m 68\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124meva_clip_g\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 69\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclip_L\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 70\u001b[0m ], \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mvit model must be eva_clip_g or clip_L\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 71\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m model_name \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124meva_clip_g\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m---> 72\u001b[0m visual_encoder \u001b[38;5;241m=\u001b[39m \u001b[43mcreate_eva_vit_g\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 73\u001b[0m \u001b[43m \u001b[49m\u001b[43mimg_size\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdrop_path_rate\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43muse_grad_checkpoint\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprecision\u001b[49m\n\u001b[1;32m 74\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 75\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m model_name \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclip_L\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 76\u001b[0m visual_encoder \u001b[38;5;241m=\u001b[39m create_clip_vit_L(img_size, use_grad_checkpoint, precision)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/eva_vit.py:430\u001b[0m, in \u001b[0;36mcreate_eva_vit_g\u001b[0;34m(img_size, drop_path_rate, use_checkpoint, precision)\u001b[0m\n\u001b[1;32m 416\u001b[0m model \u001b[38;5;241m=\u001b[39m VisionTransformer(\n\u001b[1;32m 417\u001b[0m img_size\u001b[38;5;241m=\u001b[39mimg_size,\n\u001b[1;32m 418\u001b[0m patch_size\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m14\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 427\u001b[0m use_checkpoint\u001b[38;5;241m=\u001b[39muse_checkpoint,\n\u001b[1;32m 428\u001b[0m ) \n\u001b[1;32m 429\u001b[0m url \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://storage.googleapis.com/sfr-vision-language-research/LAVIS/models/BLIP2/eva_vit_g.pth\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 430\u001b[0m cached_file \u001b[38;5;241m=\u001b[39m \u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 431\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\n\u001b[1;32m 432\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 433\u001b[0m state_dict \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mload(cached_file, map_location\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcpu\u001b[39m\u001b[38;5;124m\"\u001b[39m) \n\u001b[1;32m 434\u001b[0m interpolate_pos_embed(model,state_dict)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/common/dist_utils.py:132\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n\u001b[1;32m 131\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_main_process():\n\u001b[0;32m--> 132\u001b[0m \u001b[43mtimm_hub\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_dist_avail_and_initialized():\n\u001b[1;32m 135\u001b[0m dist\u001b[38;5;241m.\u001b[39mbarrier()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/timm/models/hub.py:51\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 49\u001b[0m r \u001b[38;5;241m=\u001b[39m HASH_REGEX\u001b[38;5;241m.\u001b[39msearch(filename) \u001b[38;5;66;03m# r is Optional[Match[str]]\u001b[39;00m\n\u001b[1;32m 50\u001b[0m hash_prefix \u001b[38;5;241m=\u001b[39m r\u001b[38;5;241m.\u001b[39mgroup(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;28;01mif\u001b[39;00m r \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 51\u001b[0m \u001b[43mdownload_url_to_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcached_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhash_prefix\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 52\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/torch/hub.py:636\u001b[0m, in \u001b[0;36mdownload_url_to_file\u001b[0;34m(url, dst, hash_prefix, progress)\u001b[0m\n\u001b[1;32m 634\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(buffer) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 635\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m--> 636\u001b[0m \u001b[43mf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwrite\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 637\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m hash_prefix \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 638\u001b[0m sha256\u001b[38;5;241m.\u001b[39mupdate(buffer)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/tempfile.py:478\u001b[0m, in \u001b[0;36m_TemporaryFileWrapper.__getattr__..func_wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;129m@_functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 477\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfunc_wrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m--> 478\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\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[0;31mOSError\u001b[0m: [Errno 28] No space left on device" ] } ], "source": [ "obj = ammico.SummaryDetector(subdict=image_dict, analysis_type = \"summary_and_questions\", model_type = \"blip2_t5_caption_coco_flant5xl\")\n", "# list of the new models that can be used:\n", "# \"blip2_t5_pretrain_flant5xxl\",\n", "# \"blip2_t5_pretrain_flant5xl\",\n", "# \"blip2_t5_caption_coco_flant5xl\",\n", "# \"blip2_opt_pretrain_opt2.7b\",\n", "# \"blip2_opt_pretrain_opt6.7b\",\n", "# \"blip2_opt_caption_coco_opt2.7b\",\n", "# \"blip2_opt_caption_coco_opt6.7b\",\n", "\n", "# You can use `pretrain_` model types for zero-shot image-to-text generation with prompts.\n", "# Or you can use `caption_coco_`` model types to generate coco-style captions.\n", "# `flant5` and `opt` means that the model equipped with FlanT5 and OPT LLMs respectively.\n", "\n", "#also you can perform all calculation on cpu if you set device_type= \"cpu\" or gpu if you set device_type= \"cuda\"" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.445792Z", "iopub.status.busy": "2024-02-19T08:53:49.445585Z", "iopub.status.idle": "2024-02-19T08:53:49.470611Z", "shell.execute_reply": "2024-02-19T08:53:49.470071Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'obj' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[24], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key \u001b[38;5;129;01min\u001b[39;00m image_dict:\n\u001b[0;32m----> 2\u001b[0m image_dict[key] \u001b[38;5;241m=\u001b[39m \u001b[43mobj\u001b[49m\u001b[38;5;241m.\u001b[39manalyse_image(subdict \u001b[38;5;241m=\u001b[39m image_dict[key], analysis_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124msummary_and_questions\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# analysis_type can be \u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;66;03m# \"summary\",\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# \"questions\",\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;66;03m# \"summary_and_questions\".\u001b[39;00m\n", "\u001b[0;31mNameError\u001b[0m: name 'obj' is not defined" ] } ], "source": [ "for key in image_dict:\n", " image_dict[key] = obj.analyse_image(subdict = image_dict[key], analysis_type=\"summary_and_questions\")\n", "\n", "# analysis_type can be \n", "# \"summary\",\n", "# \"questions\",\n", "# \"summary_and_questions\"." ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.473138Z", "iopub.status.busy": "2024-02-19T08:53:49.472942Z", "iopub.status.idle": "2024-02-19T08:53:49.480775Z", "shell.execute_reply": "2024-02-19T08:53:49.480208Z" } }, "outputs": [ { "data": { "text/plain": [ "{'img4': {'filename': 'data-test/img4.png',\n", " 'face': 'No',\n", " 'multiple_faces': 'No',\n", " 'no_faces': 0,\n", " 'wears_mask': ['No'],\n", " 'age': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'emotion': [None],\n", " 'emotion (category)': [None],\n", " 'text': 'MOODOVIN XI',\n", " 'text_language': 'en',\n", " 'text_english': 'MOODOVIN XI',\n", " 'text_clean': 'XI',\n", " 'text_summary': ' MOODOVIN XI XI: Vladimir Putin, Vladimir Vladmir Zelizer, Vladimir',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.66,\n", " 'entity': ['MOODOVIN XI'],\n", " 'entity_type': ['ORG'],\n", " 'const_image_summary': 'a river running through a city next to tall buildings',\n", " '3_non-deterministic_summary': ['there is a pretty house that sits above the water',\n", " 'there is a building with a balcony and lots of plants on the side of it',\n", " 'several buildings with a river flowing through it']},\n", " 'img1': {'filename': 'data-test/img1.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_language': 'en',\n", " 'text_english': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_clean': 'THEORY The Quantum Theory of Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_summary': ' SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.91,\n", " 'entity': ['Non',\n", " '##vist',\n", " 'Col',\n", " '##N',\n", " 'R',\n", " 'T',\n", " '##AYL',\n", " 'University of Colorado'],\n", " 'entity_type': ['MISC', 'MISC', 'MISC', 'ORG', 'PER', 'PER', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a close up of a piece of paper with writing on it',\n", " '3_non-deterministic_summary': ['a book opened to the book title for a novel',\n", " 'there are many text on this page',\n", " 'the text in a book is a handwritten poem']},\n", " 'img2': {'filename': 'data-test/img2.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_language': 'en',\n", " 'text_english': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_clean': 'THE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J .. H. WILKINSON',\n", " 'text_summary': ' H. H. W. WILKINSON: The Algebri',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.97,\n", " 'entity': ['ALGEBRAIC EIGENVAL', 'NVS TIO MI', 'J', 'H', 'WILKINSON'],\n", " 'entity_type': ['MISC', 'ORG', 'ORG', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a yellow book with green lettering on it',\n", " '3_non-deterministic_summary': ['a book cover with green writing on a black background',\n", " 'the title page of a book with information from its authors',\n", " 'a book about the age - related engineering and engineering']},\n", " 'img3': {'filename': 'data-test/img3.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'm OOOO 0000 www.',\n", " 'text_language': 'en',\n", " 'text_english': 'm OOOO 0000 www.',\n", " 'text_clean': 'm www .',\n", " 'text_summary': ' www. m OOOO 0000 0000 www.m.m OOOo 0000',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.62,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a bus that is sitting on the side of a road',\n", " '3_non-deterministic_summary': ['there are cars and a bus on the side of the road',\n", " 'a bus that is sitting in the middle of a street',\n", " 'an aerial view of an empty city street with two large buses passing by']},\n", " 'img0': {'filename': 'data-test/img0.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'Mathematische Formelsammlung für Ingenieure und Naturwissenschaftler Mit zahlreichen Abbildungen und Rechenbeispielen und einer ausführlichen Integraltafel 3., verbesserte Auflage',\n", " 'text_language': 'de',\n", " 'text_english': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd, improved edition',\n", " 'text_clean': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd , improved edition',\n", " 'text_summary': ' Mathematical formula collection for engineers and scientists . Includes numerous illustrations and calculation examples . Includes',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 1.0,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a close up of an open book with writing on it',\n", " '3_non-deterministic_summary': ['a close up of a book with many languages',\n", " 'a book that is opened up in german',\n", " 'book about mathemarche formulals and their meaning']},\n", " 'img5': {'filename': 'data-test/img5.png',\n", " 'no_faces': 1,\n", " 'age': [26],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': ['Negative'],\n", " 'multiple_faces': 'No',\n", " 'emotion': ['sad'],\n", " 'gender': ['Man'],\n", " 'race': [None],\n", " 'face': 'Yes',\n", " 'text': None,\n", " 'text_language': 'en',\n", " 'text_english': '',\n", " 'text_clean': '',\n", " 'text_summary': ' CNN.com will feature iReporter photos in a weekly Travel Snapshots gallery .',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.75,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a person running on a beach near a rock formation',\n", " '3_non-deterministic_summary': ['a woman is running down the beach next to some rocks',\n", " 'a woman running along the beach by the ocean',\n", " 'there is a person running on the beach next to the ocean']}}" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image_dict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also pass a list of questions to this cell if `analysis_type=\"summary_and_questions\"` or `analysis_type=\"questions\"`. But the format of questions has changed in new models. \n", "\n", "Here is an example of a list of questions:" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.483664Z", "iopub.status.busy": "2024-02-19T08:53:49.483466Z", "iopub.status.idle": "2024-02-19T08:53:49.486232Z", "shell.execute_reply": "2024-02-19T08:53:49.485670Z" } }, "outputs": [], "source": [ "list_of_questions = [\n", " \"Question: Are there people in the image? Answer:\",\n", " \"Question: What is this picture about? Answer:\",\n", "]" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.488981Z", "iopub.status.busy": "2024-02-19T08:53:49.488787Z", "iopub.status.idle": "2024-02-19T08:53:49.509942Z", "shell.execute_reply": "2024-02-19T08:53:49.509438Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'obj' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[27], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key \u001b[38;5;129;01min\u001b[39;00m image_dict:\n\u001b[0;32m----> 2\u001b[0m image_dict[key] \u001b[38;5;241m=\u001b[39m \u001b[43mobj\u001b[49m\u001b[38;5;241m.\u001b[39manalyse_image(subdict \u001b[38;5;241m=\u001b[39m image_dict[key], analysis_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mquestions\u001b[39m\u001b[38;5;124m\"\u001b[39m, list_of_questions\u001b[38;5;241m=\u001b[39mlist_of_questions)\n", "\u001b[0;31mNameError\u001b[0m: name 'obj' is not defined" ] } ], "source": [ "for key in image_dict:\n", " image_dict[key] = obj.analyse_image(subdict = image_dict[key], analysis_type=\"questions\", list_of_questions=list_of_questions)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also pass a question with previous answers as context into this model and pass in questions like this one to get a more accurate answer:\n", "\n", "You can combine as many questions as you want in a single query as a list." ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.513195Z", "iopub.status.busy": "2024-02-19T08:53:49.512999Z", "iopub.status.idle": "2024-02-19T08:53:49.515828Z", "shell.execute_reply": "2024-02-19T08:53:49.515286Z" } }, "outputs": [], "source": [ "list_of_questions = [\n", " \"Question: What country is in the picture? Answer: USA. Question: Why? Answer: Because there is an American flag in the background . Question: Where it comes from? Answer:\",\n", " \"Question: Which city is this? Answer: Frankfurt. Question: Why?\",\n", "]" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.520071Z", "iopub.status.busy": "2024-02-19T08:53:49.519734Z", "iopub.status.idle": "2024-02-19T08:53:49.540462Z", "shell.execute_reply": "2024-02-19T08:53:49.539940Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'obj' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[29], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key \u001b[38;5;129;01min\u001b[39;00m image_dict:\n\u001b[0;32m----> 2\u001b[0m image_dict[key] \u001b[38;5;241m=\u001b[39m \u001b[43mobj\u001b[49m\u001b[38;5;241m.\u001b[39manalyse_image(subdict \u001b[38;5;241m=\u001b[39m image_dict[key], analysis_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mquestions\u001b[39m\u001b[38;5;124m\"\u001b[39m, list_of_questions\u001b[38;5;241m=\u001b[39mlist_of_questions)\n", "\u001b[0;31mNameError\u001b[0m: name 'obj' is not defined" ] } ], "source": [ "for key in image_dict:\n", " image_dict[key] = obj.analyse_image(subdict = image_dict[key], analysis_type=\"questions\", list_of_questions=list_of_questions)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.544909Z", "iopub.status.busy": "2024-02-19T08:53:49.544431Z", "iopub.status.idle": "2024-02-19T08:53:49.551819Z", "shell.execute_reply": "2024-02-19T08:53:49.551270Z" } }, "outputs": [ { "data": { "text/plain": [ "{'img4': {'filename': 'data-test/img4.png',\n", " 'face': 'No',\n", " 'multiple_faces': 'No',\n", " 'no_faces': 0,\n", " 'wears_mask': ['No'],\n", " 'age': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'emotion': [None],\n", " 'emotion (category)': [None],\n", " 'text': 'MOODOVIN XI',\n", " 'text_language': 'en',\n", " 'text_english': 'MOODOVIN XI',\n", " 'text_clean': 'XI',\n", " 'text_summary': ' MOODOVIN XI XI: Vladimir Putin, Vladimir Vladmir Zelizer, Vladimir',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.66,\n", " 'entity': ['MOODOVIN XI'],\n", " 'entity_type': ['ORG'],\n", " 'const_image_summary': 'a river running through a city next to tall buildings',\n", " '3_non-deterministic_summary': ['there is a pretty house that sits above the water',\n", " 'there is a building with a balcony and lots of plants on the side of it',\n", " 'several buildings with a river flowing through it']},\n", " 'img1': {'filename': 'data-test/img1.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_language': 'en',\n", " 'text_english': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_clean': 'THEORY The Quantum Theory of Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_summary': ' SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.91,\n", " 'entity': ['Non',\n", " '##vist',\n", " 'Col',\n", " '##N',\n", " 'R',\n", " 'T',\n", " '##AYL',\n", " 'University of Colorado'],\n", " 'entity_type': ['MISC', 'MISC', 'MISC', 'ORG', 'PER', 'PER', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a close up of a piece of paper with writing on it',\n", " '3_non-deterministic_summary': ['a book opened to the book title for a novel',\n", " 'there are many text on this page',\n", " 'the text in a book is a handwritten poem']},\n", " 'img2': {'filename': 'data-test/img2.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_language': 'en',\n", " 'text_english': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_clean': 'THE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J .. H. WILKINSON',\n", " 'text_summary': ' H. H. W. WILKINSON: The Algebri',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.97,\n", " 'entity': ['ALGEBRAIC EIGENVAL', 'NVS TIO MI', 'J', 'H', 'WILKINSON'],\n", " 'entity_type': ['MISC', 'ORG', 'ORG', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a yellow book with green lettering on it',\n", " '3_non-deterministic_summary': ['a book cover with green writing on a black background',\n", " 'the title page of a book with information from its authors',\n", " 'a book about the age - related engineering and engineering']},\n", " 'img3': {'filename': 'data-test/img3.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'm OOOO 0000 www.',\n", " 'text_language': 'en',\n", " 'text_english': 'm OOOO 0000 www.',\n", " 'text_clean': 'm www .',\n", " 'text_summary': ' www. m OOOO 0000 0000 www.m.m OOOo 0000',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.62,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a bus that is sitting on the side of a road',\n", " '3_non-deterministic_summary': ['there are cars and a bus on the side of the road',\n", " 'a bus that is sitting in the middle of a street',\n", " 'an aerial view of an empty city street with two large buses passing by']},\n", " 'img0': {'filename': 'data-test/img0.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'Mathematische Formelsammlung für Ingenieure und Naturwissenschaftler Mit zahlreichen Abbildungen und Rechenbeispielen und einer ausführlichen Integraltafel 3., verbesserte Auflage',\n", " 'text_language': 'de',\n", " 'text_english': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd, improved edition',\n", " 'text_clean': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd , improved edition',\n", " 'text_summary': ' Mathematical formula collection for engineers and scientists . Includes numerous illustrations and calculation examples . Includes',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 1.0,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a close up of an open book with writing on it',\n", " '3_non-deterministic_summary': ['a close up of a book with many languages',\n", " 'a book that is opened up in german',\n", " 'book about mathemarche formulals and their meaning']},\n", " 'img5': {'filename': 'data-test/img5.png',\n", " 'no_faces': 1,\n", " 'age': [26],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': ['Negative'],\n", " 'multiple_faces': 'No',\n", " 'emotion': ['sad'],\n", " 'gender': ['Man'],\n", " 'race': [None],\n", " 'face': 'Yes',\n", " 'text': None,\n", " 'text_language': 'en',\n", " 'text_english': '',\n", " 'text_clean': '',\n", " 'text_summary': ' CNN.com will feature iReporter photos in a weekly Travel Snapshots gallery .',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.75,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a person running on a beach near a rock formation',\n", " '3_non-deterministic_summary': ['a woman is running down the beach next to some rocks',\n", " 'a woman running along the beach by the ocean',\n", " 'there is a person running on the beach next to the ocean']}}" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image_dict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also ask sequential questions if you pass the argument `cosequential_questions=True`. This means that the answers to previous questions will be passed as context to the next question. However, this method will work a bit slower, because for each image the answers to the questions will not be calculated simultaneously, but sequentially. " ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.554718Z", "iopub.status.busy": "2024-02-19T08:53:49.554288Z", "iopub.status.idle": "2024-02-19T08:53:49.557147Z", "shell.execute_reply": "2024-02-19T08:53:49.556606Z" } }, "outputs": [], "source": [ "list_of_questions = [\n", " \"Question: Is this picture taken inside or outside? Answer:\",\n", " \"Question: Why? Answer:\",\n", "]" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.559854Z", "iopub.status.busy": "2024-02-19T08:53:49.559416Z", "iopub.status.idle": "2024-02-19T08:53:49.581420Z", "shell.execute_reply": "2024-02-19T08:53:49.580718Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'obj' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[32], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m key \u001b[38;5;129;01min\u001b[39;00m image_dict:\n\u001b[0;32m----> 2\u001b[0m image_dict[key] \u001b[38;5;241m=\u001b[39m \u001b[43mobj\u001b[49m\u001b[38;5;241m.\u001b[39manalyse_image(subdict \u001b[38;5;241m=\u001b[39m image_dict[key], analysis_type\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mquestions\u001b[39m\u001b[38;5;124m\"\u001b[39m, list_of_questions\u001b[38;5;241m=\u001b[39mlist_of_questions, consequential_questions\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", "\u001b[0;31mNameError\u001b[0m: name 'obj' is not defined" ] } ], "source": [ "for key in image_dict:\n", " image_dict[key] = obj.analyse_image(subdict = image_dict[key], analysis_type=\"questions\", list_of_questions=list_of_questions, consequential_questions=True)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.584997Z", "iopub.status.busy": "2024-02-19T08:53:49.584485Z", "iopub.status.idle": "2024-02-19T08:53:49.592760Z", "shell.execute_reply": "2024-02-19T08:53:49.592039Z" } }, "outputs": [ { "data": { "text/plain": [ "{'img4': {'filename': 'data-test/img4.png',\n", " 'face': 'No',\n", " 'multiple_faces': 'No',\n", " 'no_faces': 0,\n", " 'wears_mask': ['No'],\n", " 'age': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'emotion': [None],\n", " 'emotion (category)': [None],\n", " 'text': 'MOODOVIN XI',\n", " 'text_language': 'en',\n", " 'text_english': 'MOODOVIN XI',\n", " 'text_clean': 'XI',\n", " 'text_summary': ' MOODOVIN XI XI: Vladimir Putin, Vladimir Vladmir Zelizer, Vladimir',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.66,\n", " 'entity': ['MOODOVIN XI'],\n", " 'entity_type': ['ORG'],\n", " 'const_image_summary': 'a river running through a city next to tall buildings',\n", " '3_non-deterministic_summary': ['there is a pretty house that sits above the water',\n", " 'there is a building with a balcony and lots of plants on the side of it',\n", " 'several buildings with a river flowing through it']},\n", " 'img1': {'filename': 'data-test/img1.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_language': 'en',\n", " 'text_english': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_clean': 'THEORY The Quantum Theory of Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_summary': ' SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.91,\n", " 'entity': ['Non',\n", " '##vist',\n", " 'Col',\n", " '##N',\n", " 'R',\n", " 'T',\n", " '##AYL',\n", " 'University of Colorado'],\n", " 'entity_type': ['MISC', 'MISC', 'MISC', 'ORG', 'PER', 'PER', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a close up of a piece of paper with writing on it',\n", " '3_non-deterministic_summary': ['a book opened to the book title for a novel',\n", " 'there are many text on this page',\n", " 'the text in a book is a handwritten poem']},\n", " 'img2': {'filename': 'data-test/img2.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_language': 'en',\n", " 'text_english': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_clean': 'THE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J .. H. WILKINSON',\n", " 'text_summary': ' H. H. W. WILKINSON: The Algebri',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.97,\n", " 'entity': ['ALGEBRAIC EIGENVAL', 'NVS TIO MI', 'J', 'H', 'WILKINSON'],\n", " 'entity_type': ['MISC', 'ORG', 'ORG', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a yellow book with green lettering on it',\n", " '3_non-deterministic_summary': ['a book cover with green writing on a black background',\n", " 'the title page of a book with information from its authors',\n", " 'a book about the age - related engineering and engineering']},\n", " 'img3': {'filename': 'data-test/img3.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'm OOOO 0000 www.',\n", " 'text_language': 'en',\n", " 'text_english': 'm OOOO 0000 www.',\n", " 'text_clean': 'm www .',\n", " 'text_summary': ' www. m OOOO 0000 0000 www.m.m OOOo 0000',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.62,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a bus that is sitting on the side of a road',\n", " '3_non-deterministic_summary': ['there are cars and a bus on the side of the road',\n", " 'a bus that is sitting in the middle of a street',\n", " 'an aerial view of an empty city street with two large buses passing by']},\n", " 'img0': {'filename': 'data-test/img0.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'Mathematische Formelsammlung für Ingenieure und Naturwissenschaftler Mit zahlreichen Abbildungen und Rechenbeispielen und einer ausführlichen Integraltafel 3., verbesserte Auflage',\n", " 'text_language': 'de',\n", " 'text_english': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd, improved edition',\n", " 'text_clean': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd , improved edition',\n", " 'text_summary': ' Mathematical formula collection for engineers and scientists . Includes numerous illustrations and calculation examples . Includes',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 1.0,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a close up of an open book with writing on it',\n", " '3_non-deterministic_summary': ['a close up of a book with many languages',\n", " 'a book that is opened up in german',\n", " 'book about mathemarche formulals and their meaning']},\n", " 'img5': {'filename': 'data-test/img5.png',\n", " 'no_faces': 1,\n", " 'age': [26],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': ['Negative'],\n", " 'multiple_faces': 'No',\n", " 'emotion': ['sad'],\n", " 'gender': ['Man'],\n", " 'race': [None],\n", " 'face': 'Yes',\n", " 'text': None,\n", " 'text_language': 'en',\n", " 'text_english': '',\n", " 'text_clean': '',\n", " 'text_summary': ' CNN.com will feature iReporter photos in a weekly Travel Snapshots gallery .',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.75,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a person running on a beach near a rock formation',\n", " '3_non-deterministic_summary': ['a woman is running down the beach next to some rocks',\n", " 'a woman running along the beach by the ocean',\n", " 'there is a person running on the beach next to the ocean']}}" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image_dict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Detection of faces and facial expression analysis\n", "Faces and facial expressions are detected and analyzed using the `EmotionDetector` class from the `faces` module. Initially, it is detected if faces are present on the image using RetinaFace, followed by analysis if face masks are worn (Face-Mask-Detection). The detection of age, gender, race, and emotions is carried out with deepface.\n", "\n", "\n", "\n", "Depending on the features found on the image, the face detection module returns a different analysis content: If no faces are found on the image, all further steps are skipped and the result `\"face\": \"No\", \"multiple_faces\": \"No\", \"no_faces\": 0, \"wears_mask\": [\"No\"], \"age\": [None], \"gender\": [None], \"race\": [None], \"emotion\": [None], \"emotion (category)\": [None]` is returned. If one or several faces are found, up to three faces are analyzed if they are partially concealed by a face mask. If yes, only age and gender are detected; if no, also race, emotion, and dominant emotion are detected. In case of the latter, the output could look like this: `\"face\": \"Yes\", \"multiple_faces\": \"Yes\", \"no_faces\": 2, \"wears_mask\": [\"No\", \"No\"], \"age\": [27, 28], \"gender\": [\"Man\", \"Man\"], \"race\": [\"asian\", None], \"emotion\": [\"angry\", \"neutral\"], \"emotion (category)\": [\"Negative\", \"Neutral\"]`, where for the two faces that are detected (given by `no_faces`), some of the values are returned as a list with the first item for the first (largest) face and the second item for the second (smaller) face (for example, `\"emotion\"` returns a list `[\"angry\", \"neutral\"]` signifying the first face expressing anger, and the second face having a neutral expression).\n", "\n", "The emotion detection reports the seven facial expressions angry, fear, neutral, sad, disgust, happy and surprise. These emotions are assigned based on the returned confidence of the model (between 0 and 1), with a high confidence signifying a high likelihood of the detected emotion being correct. Emotion recognition is not an easy task, even for a human; therefore, we have added a keyword `emotion_threshold` signifying the % value above which an emotion is counted as being detected. The default is set to 50%, so that a confidence above 0.5 results in an emotion being assigned. If the confidence is lower, no emotion is assigned. \n", "\n", "From the seven facial expressions, an overall dominating emotion category is identified: negative, positive, or neutral emotion. These are defined with the facial expressions angry, disgust, fear and sad for the negative category, happy for the positive category, and surprise and neutral for the neutral category.\n", "\n", "A similar threshold as for the emotion recognition is set for the race detection, `race_threshold`, with the default set to 50% so that a confidence for the race above 0.5 only will return a value in the analysis. \n", "\n", "Summarizing, the face detection is carried out using the following method call and keywords, where `emotion_threshold` and \n", "`race_threshold` are optional:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:53:49.596180Z", "iopub.status.busy": "2024-02-19T08:53:49.595807Z", "iopub.status.idle": "2024-02-19T08:54:11.388417Z", "shell.execute_reply": "2024-02-19T08:54:11.387832Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\r", "1/1 [==============================] - ETA: 0s" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "1/1 [==============================] - 1s 535ms/step\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "1/1 [==============================] - ETA: 0s" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "1/1 [==============================] - 0s 343ms/step\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "1/1 [==============================] - ETA: 0s" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "1/1 [==============================] - 0s 226ms/step\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "1/1 [==============================] - ETA: 0s" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "1/1 [==============================] - 0s 233ms/step\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\r", "1/1 [==============================] - ETA: 0s" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r", "1/1 [==============================] - 0s 21ms/step\n" ] } ], "source": [ "for key in image_dict.keys():\n", " image_dict[key] = ammico.EmotionDetector(image_dict[key], emotion_threshold=50, race_threshold=50).analyse_image()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The thresholds can be adapted interactively in the notebook interface and the optimal value can then be used in a subsequent analysis of the whole data set.\n", "\n", "The output keys that are generated are\n", "\n", "| output key | output type | output value |\n", "| ---------- | ----------- | ------------ |\n", "| `face` | `str` | if a face is detected |\n", "| `multiple_faces` | `str` | if multiple faces are detected |\n", "| `no_faces` | `int` | the number of detected faces |\n", "| `wears_mask` | `list[str]` | if each of the detected faces wears a face covering, up to three faces |\n", "| `age` | `list[int]` | the detected age, up to three faces |\n", "| `gender` | `list[str]` | the detected gender, up to three faces |\n", "| `race` | `list[str]` | the detected race, up to three faces, if above the confidence threshold |\n", "| `emotion` | `list[str]` | the detected emotion, up to three faces, if above the confidence threshold |\n", "| `emotion (category)` | `list[str]` | the detected emotion category (positive, negative, or neutral), up to three faces, if above the confidence threshold |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Image Multimodal Search" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This module shows how to carry out an image multimodal search with the [LAVIS](https://github.com/salesforce/LAVIS) library. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Indexing and extracting features from images in selected folder" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "First you need to select a model. You can choose one of the following models: \n", "- [blip](https://github.com/salesforce/BLIP)\n", "- [blip2](https://huggingface.co/docs/transformers/main/model_doc/blip-2) \n", "- [albef](https://github.com/salesforce/ALBEF) \n", "- [clip_base](https://github.com/openai/CLIP/blob/main/model-card.md)\n", "- [clip_vitl14](https://github.com/mlfoundations/open_clip) \n", "- [clip_vitl14_336](https://github.com/mlfoundations/open_clip)" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:11.393676Z", "iopub.status.busy": "2024-02-19T08:54:11.393305Z", "iopub.status.idle": "2024-02-19T08:54:11.396416Z", "shell.execute_reply": "2024-02-19T08:54:11.395833Z" } }, "outputs": [], "source": [ "model_type = \"blip\"\n", "# model_type = \"blip2\"\n", "# model_type = \"albef\"\n", "# model_type = \"clip_base\"\n", "# model_type = \"clip_vitl14\"\n", "# model_type = \"clip_vitl14_336\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To process the loaded images using the selected model, use the below code:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:11.399454Z", "iopub.status.busy": "2024-02-19T08:54:11.399132Z", "iopub.status.idle": "2024-02-19T08:54:11.402161Z", "shell.execute_reply": "2024-02-19T08:54:11.401648Z" } }, "outputs": [], "source": [ "my_obj = ammico.MultimodalSearch(image_dict)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:11.404913Z", "iopub.status.busy": "2024-02-19T08:54:11.404591Z", "iopub.status.idle": "2024-02-19T08:54:26.394925Z", "shell.execute_reply": "2024-02-19T08:54:26.394163Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\r", " 0%| | 0.00/1.97G [00:00 8\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43mmy_obj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mparsing_images\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 9\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\n\u001b[1;32m 10\u001b[0m \u001b[43m \u001b[49m\u001b[43mpath_to_save_tensors\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/content/drive/MyDrive/misinformation-data/\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 11\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/multimodal_search.py:363\u001b[0m, in \u001b[0;36mMultimodalSearch.parsing_images\u001b[0;34m(self, model_type, path_to_save_tensors, path_to_load_tensors)\u001b[0m\n\u001b[1;32m 349\u001b[0m select_extract_image_features \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 350\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblip2\u001b[39m\u001b[38;5;124m\"\u001b[39m: MultimodalSearch\u001b[38;5;241m.\u001b[39mextract_image_features_blip2,\n\u001b[1;32m 351\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblip\u001b[39m\u001b[38;5;124m\"\u001b[39m: MultimodalSearch\u001b[38;5;241m.\u001b[39mextract_image_features_basic,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 355\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mclip_vitl14_336\u001b[39m\u001b[38;5;124m\"\u001b[39m: MultimodalSearch\u001b[38;5;241m.\u001b[39mextract_image_features_clip,\n\u001b[1;32m 356\u001b[0m }\n\u001b[1;32m 358\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m model_type \u001b[38;5;129;01min\u001b[39;00m select_model\u001b[38;5;241m.\u001b[39mkeys():\n\u001b[1;32m 359\u001b[0m (\n\u001b[1;32m 360\u001b[0m model,\n\u001b[1;32m 361\u001b[0m vis_processors,\n\u001b[1;32m 362\u001b[0m txt_processors,\n\u001b[0;32m--> 363\u001b[0m ) \u001b[38;5;241m=\u001b[39m \u001b[43mselect_model\u001b[49m\u001b[43m[\u001b[49m\n\u001b[1;32m 364\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\n\u001b[1;32m 365\u001b[0m \u001b[43m \u001b[49m\u001b[43m]\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mMultimodalSearch\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmultimodal_device\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 366\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 367\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mSyntaxError\u001b[39;00m(\n\u001b[1;32m 368\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPlease, use one of the following models: blip2, blip, albef, clip_base, clip_vitl14, clip_vitl14_336\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 369\u001b[0m )\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/multimodal_search.py:55\u001b[0m, in \u001b[0;36mMultimodalSearch.load_feature_extractor_model_blip\u001b[0;34m(self, device)\u001b[0m\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mload_feature_extractor_model_blip\u001b[39m(\u001b[38;5;28mself\u001b[39m, device: \u001b[38;5;28mstr\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcpu\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 44\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 45\u001b[0m \u001b[38;5;124;03m Load base blip_feature_extractor model and preprocessors for visual and text inputs from lavis.models.\u001b[39;00m\n\u001b[1;32m 46\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 53\u001b[0m \u001b[38;5;124;03m txt_processors (dict): preprocessors for text inputs.\u001b[39;00m\n\u001b[1;32m 54\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 55\u001b[0m model, vis_processors, txt_processors \u001b[38;5;241m=\u001b[39m \u001b[43mload_model_and_preprocess\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 56\u001b[0m \u001b[43m \u001b[49m\u001b[43mname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mblip_feature_extractor\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 57\u001b[0m \u001b[43m \u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbase\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m 58\u001b[0m \u001b[43m \u001b[49m\u001b[43mis_eval\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 59\u001b[0m \u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 60\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 61\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model, vis_processors, txt_processors\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/__init__.py:195\u001b[0m, in \u001b[0;36mload_model_and_preprocess\u001b[0;34m(name, model_type, is_eval, device)\u001b[0m\n\u001b[1;32m 192\u001b[0m model_cls \u001b[38;5;241m=\u001b[39m registry\u001b[38;5;241m.\u001b[39mget_model_class(name)\n\u001b[1;32m 194\u001b[0m \u001b[38;5;66;03m# load model\u001b[39;00m\n\u001b[0;32m--> 195\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mmodel_cls\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_pretrained\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_type\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmodel_type\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 197\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_eval:\n\u001b[1;32m 198\u001b[0m model\u001b[38;5;241m.\u001b[39meval()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/base_model.py:70\u001b[0m, in \u001b[0;36mBaseModel.from_pretrained\u001b[0;34m(cls, model_type)\u001b[0m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 61\u001b[0m \u001b[38;5;124;03mBuild a pretrained model from default configuration file, specified by model_type.\u001b[39;00m\n\u001b[1;32m 62\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m - model (nn.Module): pretrained or finetuned model, depending on the configuration.\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 69\u001b[0m model_cfg \u001b[38;5;241m=\u001b[39m OmegaConf\u001b[38;5;241m.\u001b[39mload(\u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39mdefault_config_path(model_type))\u001b[38;5;241m.\u001b[39mmodel\n\u001b[0;32m---> 70\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mcls\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfrom_config\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel_cfg\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 72\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m model\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip_models/blip_feature_extractor.py:208\u001b[0m, in \u001b[0;36mBlipFeatureExtractor.from_config\u001b[0;34m(cls, cfg)\u001b[0m\n\u001b[1;32m 206\u001b[0m pretrain_path \u001b[38;5;241m=\u001b[39m cfg\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpretrained\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m 207\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m pretrain_path \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[0;32m--> 208\u001b[0m msg \u001b[38;5;241m=\u001b[39m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mload_from_pretrained\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl_or_filename\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpretrain_path\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 209\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 210\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo pretrained weights are loaded.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/models/blip_models/blip.py:30\u001b[0m, in \u001b[0;36mBlipBase.load_from_pretrained\u001b[0;34m(self, url_or_filename)\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mload_from_pretrained\u001b[39m(\u001b[38;5;28mself\u001b[39m, url_or_filename):\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_url(url_or_filename):\n\u001b[0;32m---> 30\u001b[0m cached_file \u001b[38;5;241m=\u001b[39m \u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 31\u001b[0m \u001b[43m \u001b[49m\u001b[43murl_or_filename\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\n\u001b[1;32m 32\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 33\u001b[0m checkpoint \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mload(cached_file, map_location\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcpu\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39misfile(url_or_filename):\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/lavis/common/dist_utils.py:132\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n\u001b[1;32m 131\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_main_process():\n\u001b[0;32m--> 132\u001b[0m \u001b[43mtimm_hub\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdownload_cached_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcheck_hash\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 134\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m is_dist_avail_and_initialized():\n\u001b[1;32m 135\u001b[0m dist\u001b[38;5;241m.\u001b[39mbarrier()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/timm/models/hub.py:51\u001b[0m, in \u001b[0;36mdownload_cached_file\u001b[0;34m(url, check_hash, progress)\u001b[0m\n\u001b[1;32m 49\u001b[0m r \u001b[38;5;241m=\u001b[39m HASH_REGEX\u001b[38;5;241m.\u001b[39msearch(filename) \u001b[38;5;66;03m# r is Optional[Match[str]]\u001b[39;00m\n\u001b[1;32m 50\u001b[0m hash_prefix \u001b[38;5;241m=\u001b[39m r\u001b[38;5;241m.\u001b[39mgroup(\u001b[38;5;241m1\u001b[39m) \u001b[38;5;28;01mif\u001b[39;00m r \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 51\u001b[0m \u001b[43mdownload_url_to_file\u001b[49m\u001b[43m(\u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcached_file\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mhash_prefix\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 52\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m cached_file\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/torch/hub.py:636\u001b[0m, in \u001b[0;36mdownload_url_to_file\u001b[0;34m(url, dst, hash_prefix, progress)\u001b[0m\n\u001b[1;32m 634\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(buffer) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 635\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[0;32m--> 636\u001b[0m \u001b[43mf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mwrite\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuffer\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 637\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m hash_prefix \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 638\u001b[0m sha256\u001b[38;5;241m.\u001b[39mupdate(buffer)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/tempfile.py:478\u001b[0m, in \u001b[0;36m_TemporaryFileWrapper.__getattr__..func_wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;129m@_functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 477\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mfunc_wrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[0;32m--> 478\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\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[0;31mOSError\u001b[0m: [Errno 28] No space left on device" ] } ], "source": [ "(\n", " model,\n", " vis_processors,\n", " txt_processors,\n", " image_keys,\n", " image_names,\n", " features_image_stacked,\n", ") = my_obj.parsing_images(\n", " model_type, \n", " path_to_save_tensors=\"/content/drive/MyDrive/misinformation-data/\",\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The images are then processed and stored in a numerical representation, a tensor. These tensors do not change for the same image and same model - so if you run this analysis once, and save the tensors giving a path with the keyword `path_to_save_tensors`, a file with filename `.__saved_features_image.pt` will be placed there.\n", "\n", "This can save you time if you want to analyse same images with the same model but different questions. To run using the saved tensors, execute the below code giving the path and name of the tensor file." ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.399067Z", "iopub.status.busy": "2024-02-19T08:54:26.398613Z", "iopub.status.idle": "2024-02-19T08:54:26.401763Z", "shell.execute_reply": "2024-02-19T08:54:26.401225Z" } }, "outputs": [], "source": [ "# (\n", "# model,\n", "# vis_processors,\n", "# txt_processors,\n", "# image_keys,\n", "# image_names,\n", "# features_image_stacked,\n", "# ) = my_obj.parsing_images(\n", "# model_type,\n", "# path_to_load_tensors=\"/content/drive/MyDrive/misinformation-data/5_clip_base_saved_features_image.pt\",\n", "# )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we already processed our image folder with 5 images and the `clip_base` model. So you need just to write the name `5_clip_base_saved_features_image.pt` of the saved file that consists of tensors of all images as keyword argument for `path_to_load_tensors`. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Formulate your search queries\n", "\n", "Next, you need to form search queries. You can search either by image or by text. You can search for a single query, or you can search for several queries at once, the computational time should not be much different. The format of the queries is as follows:" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.406155Z", "iopub.status.busy": "2024-02-19T08:54:26.405642Z", "iopub.status.idle": "2024-02-19T08:54:26.409654Z", "shell.execute_reply": "2024-02-19T08:54:26.408999Z" } }, "outputs": [], "source": [ "import importlib_resources # only require for image query example\n", "image_example_query = str(importlib_resources.files(\"ammico\") / \"data\" / \"test-crop-image.png\") # creating the path to the image for the image query example\n", "\n", "search_query = [\n", " {\"text_input\": \"politician press conference\"}, \n", " {\"text_input\": \"a world map\"},\n", " {\"text_input\": \"a dog\"}, # This is how looks text query\n", " {\"image\": image_example_query}, # This is how looks image query, here `image_example_path` is the path to query image like \"data/test-crop-image.png\"\n", "]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can filter your results in 3 different ways:\n", "- `filter_number_of_images` limits the number of images found. That is, if the parameter `filter_number_of_images = 10`, then the first 10 images that best match the query will be shown. The other images ranks will be set to `None` and the similarity value to `0`.\n", "- `filter_val_limit` limits the output of images with a similarity value not bigger than `filter_val_limit`. That is, if the parameter `filter_val_limit = 0.2`, all images with similarity less than 0.2 will be discarded.\n", "- `filter_rel_error` (percentage) limits the output of images with a similarity value not bigger than `100 * abs(current_simularity_value - best_simularity_value_in_current_search)/best_simularity_value_in_current_search < filter_rel_error`. That is, if we set filter_rel_error = 30, it means that if the top1 image have 0.5 similarity value, we discard all image with similarity less than 0.35." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.412858Z", "iopub.status.busy": "2024-02-19T08:54:26.412664Z", "iopub.status.idle": "2024-02-19T08:54:26.436288Z", "shell.execute_reply": "2024-02-19T08:54:26.435775Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'model' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[40], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m similarity, sorted_lists \u001b[38;5;241m=\u001b[39m my_obj\u001b[38;5;241m.\u001b[39mmultimodal_search(\n\u001b[0;32m----> 2\u001b[0m \u001b[43mmodel\u001b[49m,\n\u001b[1;32m 3\u001b[0m vis_processors,\n\u001b[1;32m 4\u001b[0m txt_processors,\n\u001b[1;32m 5\u001b[0m model_type,\n\u001b[1;32m 6\u001b[0m image_keys,\n\u001b[1;32m 7\u001b[0m features_image_stacked,\n\u001b[1;32m 8\u001b[0m search_query,\n\u001b[1;32m 9\u001b[0m filter_number_of_images\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m20\u001b[39m,\n\u001b[1;32m 10\u001b[0m )\n", "\u001b[0;31mNameError\u001b[0m: name 'model' is not defined" ] } ], "source": [ "similarity, sorted_lists = my_obj.multimodal_search(\n", " model,\n", " vis_processors,\n", " txt_processors,\n", " model_type,\n", " image_keys,\n", " features_image_stacked,\n", " search_query,\n", " filter_number_of_images=20,\n", ")" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.443401Z", "iopub.status.busy": "2024-02-19T08:54:26.442981Z", "iopub.status.idle": "2024-02-19T08:54:26.462491Z", "shell.execute_reply": "2024-02-19T08:54:26.461996Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'similarity' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[41], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msimilarity\u001b[49m\n", "\u001b[0;31mNameError\u001b[0m: name 'similarity' is not defined" ] } ], "source": [ "similarity" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.465916Z", "iopub.status.busy": "2024-02-19T08:54:26.465540Z", "iopub.status.idle": "2024-02-19T08:54:26.484725Z", "shell.execute_reply": "2024-02-19T08:54:26.484175Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'sorted_lists' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[42], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43msorted_lists\u001b[49m\n", "\u001b[0;31mNameError\u001b[0m: name 'sorted_lists' is not defined" ] } ], "source": [ "sorted_lists" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After launching `multimodal_search` function, the results of each query will be added to the source dictionary. " ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.487891Z", "iopub.status.busy": "2024-02-19T08:54:26.487505Z", "iopub.status.idle": "2024-02-19T08:54:26.494730Z", "shell.execute_reply": "2024-02-19T08:54:26.494169Z" } }, "outputs": [ { "data": { "text/plain": [ "{'img4': {'filename': 'data-test/img4.png',\n", " 'face': 'No',\n", " 'multiple_faces': 'No',\n", " 'no_faces': 0,\n", " 'wears_mask': ['No'],\n", " 'age': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'emotion': [None],\n", " 'emotion (category)': [None],\n", " 'text': 'MOODOVIN XI',\n", " 'text_language': 'en',\n", " 'text_english': 'MOODOVIN XI',\n", " 'text_clean': 'XI',\n", " 'text_summary': ' MOODOVIN XI XI: Vladimir Putin, Vladimir Vladmir Zelizer, Vladimir',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.66,\n", " 'entity': ['MOODOVIN XI'],\n", " 'entity_type': ['ORG'],\n", " 'const_image_summary': 'a river running through a city next to tall buildings',\n", " '3_non-deterministic_summary': ['there is a pretty house that sits above the water',\n", " 'there is a building with a balcony and lots of plants on the side of it',\n", " 'several buildings with a river flowing through it']},\n", " 'img1': {'filename': 'data-test/img1.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_language': 'en',\n", " 'text_english': 'SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_clean': 'THEORY The Quantum Theory of Collisions JOHN R. TAYLOR University of Colorado',\n", " 'text_summary': ' SCATTERING THEORY The Quantum Theory of Nonrelativistic Collisions',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.91,\n", " 'entity': ['Non',\n", " '##vist',\n", " 'Col',\n", " '##N',\n", " 'R',\n", " 'T',\n", " '##AYL',\n", " 'University of Colorado'],\n", " 'entity_type': ['MISC', 'MISC', 'MISC', 'ORG', 'PER', 'PER', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a close up of a piece of paper with writing on it',\n", " '3_non-deterministic_summary': ['a book opened to the book title for a novel',\n", " 'there are many text on this page',\n", " 'the text in a book is a handwritten poem']},\n", " 'img2': {'filename': 'data-test/img2.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_language': 'en',\n", " 'text_english': 'THE ALGEBRAIC EIGENVALUE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J.. H. WILKINSON',\n", " 'text_clean': 'THE PROBLEM DOM NVS TIO MINA Monographs on Numerical Analysis J .. H. WILKINSON',\n", " 'text_summary': ' H. H. W. WILKINSON: The Algebri',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.97,\n", " 'entity': ['ALGEBRAIC EIGENVAL', 'NVS TIO MI', 'J', 'H', 'WILKINSON'],\n", " 'entity_type': ['MISC', 'ORG', 'ORG', 'ORG', 'ORG'],\n", " 'const_image_summary': 'a yellow book with green lettering on it',\n", " '3_non-deterministic_summary': ['a book cover with green writing on a black background',\n", " 'the title page of a book with information from its authors',\n", " 'a book about the age - related engineering and engineering']},\n", " 'img3': {'filename': 'data-test/img3.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'm OOOO 0000 www.',\n", " 'text_language': 'en',\n", " 'text_english': 'm OOOO 0000 www.',\n", " 'text_clean': 'm www .',\n", " 'text_summary': ' www. m OOOO 0000 0000 www.m.m OOOo 0000',\n", " 'sentiment': 'NEGATIVE',\n", " 'sentiment_score': 0.62,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a bus that is sitting on the side of a road',\n", " '3_non-deterministic_summary': ['there are cars and a bus on the side of the road',\n", " 'a bus that is sitting in the middle of a street',\n", " 'an aerial view of an empty city street with two large buses passing by']},\n", " 'img0': {'filename': 'data-test/img0.png',\n", " 'no_faces': 0,\n", " 'age': [None],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': [None],\n", " 'multiple_faces': 'No',\n", " 'emotion': [None],\n", " 'gender': [None],\n", " 'race': [None],\n", " 'face': 'No',\n", " 'text': 'Mathematische Formelsammlung für Ingenieure und Naturwissenschaftler Mit zahlreichen Abbildungen und Rechenbeispielen und einer ausführlichen Integraltafel 3., verbesserte Auflage',\n", " 'text_language': 'de',\n", " 'text_english': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd, improved edition',\n", " 'text_clean': 'Mathematical formula collection for engineers and scientists With numerous illustrations and calculation examples and a detailed integral table 3rd , improved edition',\n", " 'text_summary': ' Mathematical formula collection for engineers and scientists . Includes numerous illustrations and calculation examples . Includes',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 1.0,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a close up of an open book with writing on it',\n", " '3_non-deterministic_summary': ['a close up of a book with many languages',\n", " 'a book that is opened up in german',\n", " 'book about mathemarche formulals and their meaning']},\n", " 'img5': {'filename': 'data-test/img5.png',\n", " 'no_faces': 1,\n", " 'age': [26],\n", " 'wears_mask': ['No'],\n", " 'emotion (category)': ['Negative'],\n", " 'multiple_faces': 'No',\n", " 'emotion': ['sad'],\n", " 'gender': ['Man'],\n", " 'race': [None],\n", " 'face': 'Yes',\n", " 'text': None,\n", " 'text_language': 'en',\n", " 'text_english': '',\n", " 'text_clean': '',\n", " 'text_summary': ' CNN.com will feature iReporter photos in a weekly Travel Snapshots gallery .',\n", " 'sentiment': 'POSITIVE',\n", " 'sentiment_score': 0.75,\n", " 'entity': [],\n", " 'entity_type': [],\n", " 'const_image_summary': 'a person running on a beach near a rock formation',\n", " '3_non-deterministic_summary': ['a woman is running down the beach next to some rocks',\n", " 'a woman running along the beach by the ocean',\n", " 'there is a person running on the beach next to the ocean']}}" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "image_dict" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A special function was written to present the search results conveniently. " ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.498308Z", "iopub.status.busy": "2024-02-19T08:54:26.498116Z", "iopub.status.idle": "2024-02-19T08:54:26.561629Z", "shell.execute_reply": "2024-02-19T08:54:26.560724Z" } }, "outputs": [ { "data": { "text/plain": [ "'Your search query: politician press conference'" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'--------------------------------------------------'" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Results:'" ] }, "metadata": {}, "output_type": "display_data" }, { "ename": "KeyError", "evalue": "'politician press conference'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[44], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmy_obj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshow_results\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43msearch_query\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# you can change the index to see the results for other queries\u001b[39;49;00m\n\u001b[1;32m 3\u001b[0m \u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/multimodal_search.py:970\u001b[0m, in \u001b[0;36mMultimodalSearch.show_results\u001b[0;34m(self, query, itm, image_gradcam_with_itm)\u001b[0m\n\u001b[1;32m 967\u001b[0m current_querry_val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 968\u001b[0m current_querry_rank \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrank \u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m--> 970\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m s \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28;43msorted\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 971\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msubdict\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mitems\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkey\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mt\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mt\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcurrent_querry_val\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreverse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\n\u001b[1;32m 972\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[1;32m 973\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m s[\u001b[38;5;241m1\u001b[39m][current_querry_rank] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 974\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/multimodal_search.py:971\u001b[0m, in \u001b[0;36mMultimodalSearch.show_results..\u001b[0;34m(t)\u001b[0m\n\u001b[1;32m 967\u001b[0m current_querry_val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 968\u001b[0m current_querry_rank \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrank \u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 970\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m s \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28msorted\u001b[39m(\n\u001b[0;32m--> 971\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msubdict\u001b[38;5;241m.\u001b[39mitems(), key\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m t: \u001b[43mt\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcurrent_querry_val\u001b[49m\u001b[43m]\u001b[49m, reverse\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 972\u001b[0m ):\n\u001b[1;32m 973\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m s[\u001b[38;5;241m1\u001b[39m][current_querry_rank] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 974\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", "\u001b[0;31mKeyError\u001b[0m: 'politician press conference'" ] } ], "source": [ "my_obj.show_results(\n", " search_query[0], # you can change the index to see the results for other queries\n", ")" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.564539Z", "iopub.status.busy": "2024-02-19T08:54:26.564124Z", "iopub.status.idle": "2024-02-19T08:54:26.742817Z", "shell.execute_reply": "2024-02-19T08:54:26.742251Z" } }, "outputs": [ { "data": { "text/plain": [ "'Your search query: '" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/jpeg": "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", "image/png": "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", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'--------------------------------------------------'" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "'Results:'" ] }, "metadata": {}, "output_type": "display_data" }, { "ename": "KeyError", "evalue": "'/home/runner/work/AMMICO/AMMICO/ammico/data/test-crop-image.png'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[45], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmy_obj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshow_results\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[43m \u001b[49m\u001b[43msearch_query\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m# you can change the index to see the results for other queries\u001b[39;49;00m\n\u001b[1;32m 3\u001b[0m \u001b[43m)\u001b[49m\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/multimodal_search.py:970\u001b[0m, in \u001b[0;36mMultimodalSearch.show_results\u001b[0;34m(self, query, itm, image_gradcam_with_itm)\u001b[0m\n\u001b[1;32m 967\u001b[0m current_querry_val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 968\u001b[0m current_querry_rank \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrank \u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m--> 970\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m s \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28;43msorted\u001b[39;49m\u001b[43m(\u001b[49m\n\u001b[1;32m 971\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msubdict\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mitems\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkey\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mt\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mt\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcurrent_querry_val\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreverse\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\n\u001b[1;32m 972\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m:\n\u001b[1;32m 973\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m s[\u001b[38;5;241m1\u001b[39m][current_querry_rank] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 974\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", "File \u001b[0;32m~/work/AMMICO/AMMICO/ammico/multimodal_search.py:971\u001b[0m, in \u001b[0;36mMultimodalSearch.show_results..\u001b[0;34m(t)\u001b[0m\n\u001b[1;32m 967\u001b[0m current_querry_val \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 968\u001b[0m current_querry_rank \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrank \u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mlist\u001b[39m(query\u001b[38;5;241m.\u001b[39mvalues())[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 970\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m s \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28msorted\u001b[39m(\n\u001b[0;32m--> 971\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msubdict\u001b[38;5;241m.\u001b[39mitems(), key\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mlambda\u001b[39;00m t: \u001b[43mt\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[43mcurrent_querry_val\u001b[49m\u001b[43m]\u001b[49m, reverse\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 972\u001b[0m ):\n\u001b[1;32m 973\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m s[\u001b[38;5;241m1\u001b[39m][current_querry_rank] \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 974\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n", "\u001b[0;31mKeyError\u001b[0m: '/home/runner/work/AMMICO/AMMICO/ammico/data/test-crop-image.png'" ] } ], "source": [ "my_obj.show_results(\n", " search_query[3], # you can change the index to see the results for other queries\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Improve the search results\n", "\n", "For even better results, a slightly different approach has been prepared that can improve search results. It is quite resource-intensive, so it is applied after the main algorithm has found the most relevant images. This approach works only with text queries and it skips image queries. Among the parameters you can choose 3 models: `\"blip_base\"`, `\"blip_large\"`, `\"blip2_coco\"`. If you get an `Out of Memory` error, try reducing the batch_size value (minimum = 1), which is the number of images being processed simultaneously. With the parameter `need_grad_cam = True/False` you can enable the calculation of the heat map of each image to be processed and save them in `image_gradcam_with_itm`. Thus the `image_text_match_reordering()` function calculates new similarity values and new ranks for each image. The resulting values are added to the general dictionary." ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.746808Z", "iopub.status.busy": "2024-02-19T08:54:26.746601Z", "iopub.status.idle": "2024-02-19T08:54:26.749457Z", "shell.execute_reply": "2024-02-19T08:54:26.748884Z" } }, "outputs": [], "source": [ "itm_model = \"blip_base\"\n", "# itm_model = \"blip_large\"\n", "# itm_model = \"blip2_coco\"" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.752555Z", "iopub.status.busy": "2024-02-19T08:54:26.752084Z", "iopub.status.idle": "2024-02-19T08:54:26.773035Z", "shell.execute_reply": "2024-02-19T08:54:26.772413Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'image_keys' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[47], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m itm_scores, image_gradcam_with_itm \u001b[38;5;241m=\u001b[39m my_obj\u001b[38;5;241m.\u001b[39mimage_text_match_reordering(\n\u001b[1;32m 2\u001b[0m search_query,\n\u001b[1;32m 3\u001b[0m itm_model,\n\u001b[0;32m----> 4\u001b[0m \u001b[43mimage_keys\u001b[49m,\n\u001b[1;32m 5\u001b[0m sorted_lists,\n\u001b[1;32m 6\u001b[0m batch_size\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m,\n\u001b[1;32m 7\u001b[0m need_grad_cam\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 8\u001b[0m )\n", "\u001b[0;31mNameError\u001b[0m: name 'image_keys' is not defined" ] } ], "source": [ "itm_scores, image_gradcam_with_itm = my_obj.image_text_match_reordering(\n", " search_query,\n", " itm_model,\n", " image_keys,\n", " sorted_lists,\n", " batch_size=1,\n", " need_grad_cam=True,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then using the same output function you can add the `itm=True` argument to output the new image order. Remember that for images querys, an error will be thrown with `itm=True` argument. You can also add the `image_gradcam_with_itm` along with `itm=True` argument to output the heat maps of the calculated images." ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.775851Z", "iopub.status.busy": "2024-02-19T08:54:26.775512Z", "iopub.status.idle": "2024-02-19T08:54:26.795328Z", "shell.execute_reply": "2024-02-19T08:54:26.794723Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'image_gradcam_with_itm' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[48], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m my_obj\u001b[38;5;241m.\u001b[39mshow_results(\n\u001b[0;32m----> 2\u001b[0m search_query[\u001b[38;5;241m0\u001b[39m], itm\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, image_gradcam_with_itm\u001b[38;5;241m=\u001b[39m\u001b[43mimage_gradcam_with_itm\u001b[49m\n\u001b[1;32m 3\u001b[0m )\n", "\u001b[0;31mNameError\u001b[0m: name 'image_gradcam_with_itm' is not defined" ] } ], "source": [ "my_obj.show_results(\n", " search_query[0], itm=True, image_gradcam_with_itm=image_gradcam_with_itm\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Save search results to csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Convert the dictionary of dictionarys into a dictionary with lists:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.799498Z", "iopub.status.busy": "2024-02-19T08:54:26.799139Z", "iopub.status.idle": "2024-02-19T08:54:26.818722Z", "shell.execute_reply": "2024-02-19T08:54:26.818206Z" } }, "outputs": [ { "ename": "AttributeError", "evalue": "module 'ammico' has no attribute 'append_data_to_dict'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[49], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m outdict \u001b[38;5;241m=\u001b[39m \u001b[43mammico\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mappend_data_to_dict\u001b[49m(image_dict)\n\u001b[1;32m 2\u001b[0m df \u001b[38;5;241m=\u001b[39m ammico\u001b[38;5;241m.\u001b[39mdump_df(outdict)\n", "\u001b[0;31mAttributeError\u001b[0m: module 'ammico' has no attribute 'append_data_to_dict'" ] } ], "source": [ "outdict = ammico.append_data_to_dict(image_dict)\n", "df = ammico.dump_df(outdict)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check the dataframe:" ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.822275Z", "iopub.status.busy": "2024-02-19T08:54:26.821902Z", "iopub.status.idle": "2024-02-19T08:54:26.841826Z", "shell.execute_reply": "2024-02-19T08:54:26.841214Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'df' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[50], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mdf\u001b[49m\u001b[38;5;241m.\u001b[39mhead(\u001b[38;5;241m10\u001b[39m)\n", "\u001b[0;31mNameError\u001b[0m: name 'df' is not defined" ] } ], "source": [ "df.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write the csv file:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.845662Z", "iopub.status.busy": "2024-02-19T08:54:26.845309Z", "iopub.status.idle": "2024-02-19T08:54:26.864880Z", "shell.execute_reply": "2024-02-19T08:54:26.864321Z" } }, "outputs": [ { "ename": "NameError", "evalue": "name 'df' is not defined", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[51], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mdf\u001b[49m\u001b[38;5;241m.\u001b[39mto_csv(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/content/drive/MyDrive/misinformation-data/data_out.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "\u001b[0;31mNameError\u001b[0m: name 'df' is not defined" ] } ], "source": [ "df.to_csv(\"/content/drive/MyDrive/misinformation-data/data_out.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Color analysis of pictures\n", "\n", "This module shows primary color analysis of color image using K-Means algorithm.\n", "The output are N primary colors and their corresponding percentage." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To check the analysis, you can inspect the analyzed elements here. Loading the results takes a moment, so please be patient. If you are sure of what you are doing, you can skip this and directly export a csv file in the step below.\n", "Here, we display the color detection results provided by `colorgram` and `colour` libraries. Click on the tabs to see the results in the right sidebar. You may need to increment the `port` number if you are already running several notebook instances on the same server." ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.868479Z", "iopub.status.busy": "2024-02-19T08:54:26.868084Z", "iopub.status.idle": "2024-02-19T08:54:26.911851Z", "shell.execute_reply": "2024-02-19T08:54:26.911132Z" } }, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "analysis_explorer = ammico.AnalysisExplorer(image_dict)\n", "analysis_explorer.run_server(port = 8057)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Instead of inspecting each of the images, you can also directly carry out the analysis and export the result into a csv. This may take a while depending on how many images you have loaded." ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:26.917049Z", "iopub.status.busy": "2024-02-19T08:54:26.916702Z", "iopub.status.idle": "2024-02-19T08:54:38.080384Z", "shell.execute_reply": "2024-02-19T08:54:38.079754Z" } }, "outputs": [], "source": [ "for key in image_dict.keys():\n", " image_dict[key] = ammico.colors.ColorDetector(image_dict[key]).analyse_image()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These steps are required to convert the dictionary of dictionarys into a dictionary with lists, that can be converted into a pandas dataframe and exported to a csv file." ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:38.085405Z", "iopub.status.busy": "2024-02-19T08:54:38.084973Z", "iopub.status.idle": "2024-02-19T08:54:38.089091Z", "shell.execute_reply": "2024-02-19T08:54:38.088517Z" } }, "outputs": [], "source": [ "df = ammico.get_dataframe(image_dict)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Check the dataframe:" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:38.097290Z", "iopub.status.busy": "2024-02-19T08:54:38.096874Z", "iopub.status.idle": "2024-02-19T08:54:38.119692Z", "shell.execute_reply": "2024-02-19T08:54:38.119109Z" } }, "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", " \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", " \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", " \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", " \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", "
filenamefacemultiple_facesno_faceswears_maskagegenderraceemotionemotion (category)...blueyellowcyanorangepurplepinkbrowngreywhiteblack
0data-test/img4.pngNoNo0[No][None][None][None][None][None]...0.160.00000.0000.100.420.050.21
1data-test/img1.pngNoNo0[No][None][None][None][None][None]...0.000.00000.0000.000.960.000.04
2data-test/img2.pngNoNo0[No][None][None][None][None][None]...0.000.75000.0000.040.150.000.02
3data-test/img3.pngNoNo0[No][None][None][None][None][None]...0.000.00000.0200.060.920.010.00
4data-test/img0.pngNoNo0[No][None][None][None][None][None]...0.000.00000.0000.000.980.000.02
5data-test/img5.pngYesNo1[No][26][Man][None][sad][Negative]...0.120.00000.0000.020.500.000.00
\n", "

6 rows × 33 columns

\n", "
" ], "text/plain": [ " filename face multiple_faces no_faces wears_mask age \\\n", "0 data-test/img4.png No No 0 [No] [None] \n", "1 data-test/img1.png No No 0 [No] [None] \n", "2 data-test/img2.png No No 0 [No] [None] \n", "3 data-test/img3.png No No 0 [No] [None] \n", "4 data-test/img0.png No No 0 [No] [None] \n", "5 data-test/img5.png Yes No 1 [No] [26] \n", "\n", " gender race emotion emotion (category) ... blue yellow cyan orange \\\n", "0 [None] [None] [None] [None] ... 0.16 0.00 0 0 \n", "1 [None] [None] [None] [None] ... 0.00 0.00 0 0 \n", "2 [None] [None] [None] [None] ... 0.00 0.75 0 0 \n", "3 [None] [None] [None] [None] ... 0.00 0.00 0 0 \n", "4 [None] [None] [None] [None] ... 0.00 0.00 0 0 \n", "5 [Man] [None] [sad] [Negative] ... 0.12 0.00 0 0 \n", "\n", " purple pink brown grey white black \n", "0 0.00 0 0.10 0.42 0.05 0.21 \n", "1 0.00 0 0.00 0.96 0.00 0.04 \n", "2 0.00 0 0.04 0.15 0.00 0.02 \n", "3 0.02 0 0.06 0.92 0.01 0.00 \n", "4 0.00 0 0.00 0.98 0.00 0.02 \n", "5 0.00 0 0.02 0.50 0.00 0.00 \n", "\n", "[6 rows x 33 columns]" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Write the csv file - here you should provide a file path and file name for the csv file to be written." ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "execution": { "iopub.execute_input": "2024-02-19T08:54:38.124073Z", "iopub.status.busy": "2024-02-19T08:54:38.123661Z", "iopub.status.idle": "2024-02-19T08:54:38.203962Z", "shell.execute_reply": "2024-02-19T08:54:38.203276Z" } }, "outputs": [ { "ename": "OSError", "evalue": "Cannot save file into a non-existent directory: '/content/drive/MyDrive/misinformation-data'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mOSError\u001b[0m Traceback (most recent call last)", "Cell \u001b[0;32mIn[56], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mdf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_csv\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m/content/drive/MyDrive/misinformation-data/data_out.csv\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/util/_decorators.py:333\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments..decorate..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 327\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m>\u001b[39m num_allow_args:\n\u001b[1;32m 328\u001b[0m warnings\u001b[38;5;241m.\u001b[39mwarn(\n\u001b[1;32m 329\u001b[0m msg\u001b[38;5;241m.\u001b[39mformat(arguments\u001b[38;5;241m=\u001b[39m_format_argument_list(allow_args)),\n\u001b[1;32m 330\u001b[0m \u001b[38;5;167;01mFutureWarning\u001b[39;00m,\n\u001b[1;32m 331\u001b[0m stacklevel\u001b[38;5;241m=\u001b[39mfind_stack_level(),\n\u001b[1;32m 332\u001b[0m )\n\u001b[0;32m--> 333\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfunc\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/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/core/generic.py:3961\u001b[0m, in \u001b[0;36mNDFrame.to_csv\u001b[0;34m(self, path_or_buf, sep, na_rep, float_format, columns, header, index, index_label, mode, encoding, compression, quoting, quotechar, lineterminator, chunksize, date_format, doublequote, escapechar, decimal, errors, storage_options)\u001b[0m\n\u001b[1;32m 3950\u001b[0m df \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(\u001b[38;5;28mself\u001b[39m, ABCDataFrame) \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mto_frame()\n\u001b[1;32m 3952\u001b[0m formatter \u001b[38;5;241m=\u001b[39m DataFrameFormatter(\n\u001b[1;32m 3953\u001b[0m frame\u001b[38;5;241m=\u001b[39mdf,\n\u001b[1;32m 3954\u001b[0m header\u001b[38;5;241m=\u001b[39mheader,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 3958\u001b[0m decimal\u001b[38;5;241m=\u001b[39mdecimal,\n\u001b[1;32m 3959\u001b[0m )\n\u001b[0;32m-> 3961\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mDataFrameRenderer\u001b[49m\u001b[43m(\u001b[49m\u001b[43mformatter\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto_csv\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 3962\u001b[0m \u001b[43m \u001b[49m\u001b[43mpath_or_buf\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3963\u001b[0m \u001b[43m \u001b[49m\u001b[43mlineterminator\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlineterminator\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3964\u001b[0m \u001b[43m \u001b[49m\u001b[43msep\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msep\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3965\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3966\u001b[0m \u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3967\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompression\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcompression\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3968\u001b[0m \u001b[43m \u001b[49m\u001b[43mquoting\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mquoting\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3969\u001b[0m \u001b[43m \u001b[49m\u001b[43mcolumns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcolumns\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3970\u001b[0m \u001b[43m \u001b[49m\u001b[43mindex_label\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mindex_label\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3971\u001b[0m \u001b[43m \u001b[49m\u001b[43mmode\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3972\u001b[0m \u001b[43m \u001b[49m\u001b[43mchunksize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchunksize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3973\u001b[0m \u001b[43m \u001b[49m\u001b[43mquotechar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mquotechar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3974\u001b[0m \u001b[43m \u001b[49m\u001b[43mdate_format\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdate_format\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3975\u001b[0m \u001b[43m \u001b[49m\u001b[43mdoublequote\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdoublequote\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3976\u001b[0m \u001b[43m \u001b[49m\u001b[43mescapechar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mescapechar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3977\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 3978\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/formats/format.py:1014\u001b[0m, in \u001b[0;36mDataFrameRenderer.to_csv\u001b[0;34m(self, path_or_buf, encoding, sep, columns, index_label, mode, compression, quoting, quotechar, lineterminator, chunksize, date_format, doublequote, escapechar, errors, storage_options)\u001b[0m\n\u001b[1;32m 993\u001b[0m created_buffer \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 995\u001b[0m csv_formatter \u001b[38;5;241m=\u001b[39m CSVFormatter(\n\u001b[1;32m 996\u001b[0m path_or_buf\u001b[38;5;241m=\u001b[39mpath_or_buf,\n\u001b[1;32m 997\u001b[0m lineterminator\u001b[38;5;241m=\u001b[39mlineterminator,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1012\u001b[0m formatter\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfmt,\n\u001b[1;32m 1013\u001b[0m )\n\u001b[0;32m-> 1014\u001b[0m \u001b[43mcsv_formatter\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msave\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1016\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m created_buffer:\n\u001b[1;32m 1017\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(path_or_buf, StringIO)\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/formats/csvs.py:251\u001b[0m, in \u001b[0;36mCSVFormatter.save\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;124;03mCreate the writer & save.\u001b[39;00m\n\u001b[1;32m 249\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 250\u001b[0m \u001b[38;5;66;03m# apply compression and byte/text conversion\u001b[39;00m\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[43mget_handle\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 252\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mfilepath_or_buffer\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 253\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mmode\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 254\u001b[0m \u001b[43m \u001b[49m\u001b[43mencoding\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mencoding\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 255\u001b[0m \u001b[43m \u001b[49m\u001b[43merrors\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43merrors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 256\u001b[0m \u001b[43m \u001b[49m\u001b[43mcompression\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcompression\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 257\u001b[0m \u001b[43m \u001b[49m\u001b[43mstorage_options\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstorage_options\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 258\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m handles:\n\u001b[1;32m 259\u001b[0m \u001b[38;5;66;03m# Note: self.encoding is irrelevant here\u001b[39;00m\n\u001b[1;32m 260\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mwriter \u001b[38;5;241m=\u001b[39m csvlib\u001b[38;5;241m.\u001b[39mwriter(\n\u001b[1;32m 261\u001b[0m handles\u001b[38;5;241m.\u001b[39mhandle,\n\u001b[1;32m 262\u001b[0m lineterminator\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlineterminator,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 267\u001b[0m quotechar\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mquotechar,\n\u001b[1;32m 268\u001b[0m )\n\u001b[1;32m 270\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_save()\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/common.py:749\u001b[0m, in \u001b[0;36mget_handle\u001b[0;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[1;32m 747\u001b[0m \u001b[38;5;66;03m# Only for write methods\u001b[39;00m\n\u001b[1;32m 748\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;129;01min\u001b[39;00m mode \u001b[38;5;129;01mand\u001b[39;00m is_path:\n\u001b[0;32m--> 749\u001b[0m \u001b[43mcheck_parent_directory\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mhandle\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 751\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m compression:\n\u001b[1;32m 752\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m compression \u001b[38;5;241m!=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mzstd\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m 753\u001b[0m \u001b[38;5;66;03m# compression libraries do not like an explicit text-mode\u001b[39;00m\n", "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/site-packages/pandas/io/common.py:616\u001b[0m, in \u001b[0;36mcheck_parent_directory\u001b[0;34m(path)\u001b[0m\n\u001b[1;32m 614\u001b[0m parent \u001b[38;5;241m=\u001b[39m Path(path)\u001b[38;5;241m.\u001b[39mparent\n\u001b[1;32m 615\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m parent\u001b[38;5;241m.\u001b[39mis_dir():\n\u001b[0;32m--> 616\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mOSError\u001b[39;00m(\u001b[38;5;124mrf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCannot save file into a non-existent directory: \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mparent\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "\u001b[0;31mOSError\u001b[0m: Cannot save file into a non-existent directory: '/content/drive/MyDrive/misinformation-data'" ] } ], "source": [ "df.to_csv(\"/content/drive/MyDrive/misinformation-data/data_out.csv\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Further detector modules\n", "Further detector modules exist, also it is possible to carry out a topic analysis on the text data, as well as crop social media posts automatically. These are more experimental features and have their own demonstration notebooks." ] }, { "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "ammico", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.18" } }, "nbformat": 4, "nbformat_minor": 2 }