{ "cells": [ { "cell_type": "markdown", "id": "96ec678e-b20c-4213-8616-542010f46342", "metadata": {}, "source": [ "\n", "# Dirty Entity Resolution Tutorial\n", "\n", "In this notebook we present the pyJedAI approach in the well-known ABT-BUY dataset. Dirty ER, is the process of dedeplication of one set." ] }, { "cell_type": "markdown", "id": "5274855c-ba95-49b1-ba68-4f50ca2bbd89", "metadata": {}, "source": [ "# How to install?\n", "\n", "pyJedAI is an open-source library that can be installed from PyPI.\n", "\n", "For more: [pypi.org/project/pyjedai/](https://pypi.org/project/pyjedai/)" ] }, { "cell_type": "code", "execution_count": 1, "id": "4697d149-c1a4-4767-9ed1-14444485e409", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Python 3.8.17\n" ] } ], "source": [ "!python --version" ] }, { "cell_type": "code", "execution_count": 2, "id": "776843a2-570d-4d87-bb1d-b5b61f07b1da", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: pyjedai in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (0.1.0)\n", "Requirement already satisfied: gensim>=4.2.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (4.3.2)\n", "Requirement already satisfied: matplotlib>=3.1.3 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (3.7.2)\n", "Requirement already satisfied: matplotlib-inline>=0.1.3 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (0.1.6)\n", "Requirement already satisfied: networkx>=2.3 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (3.1)\n", "Requirement already satisfied: nltk>=3.7 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (3.8.1)\n", "Requirement already satisfied: numpy>=1.21 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (1.23.5)\n", "Requirement already satisfied: pandas>=0.25.3 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (2.0.3)\n", "Requirement already satisfied: pandas-profiling>=3.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (3.6.6)\n", "Requirement already satisfied: pandocfilters>=1.5 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (1.5.0)\n", "Requirement already satisfied: PyYAML>=6.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (6.0.1)\n", "Requirement already satisfied: rdflib>=6.1.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (7.0.0)\n", "Requirement already satisfied: rdfpandas>=1.1.5 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (1.1.6)\n", "Requirement already satisfied: regex>=2022.6.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (2023.8.8)\n", "Requirement already satisfied: scipy>=1.7 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (1.10.1)\n", "Requirement already satisfied: seaborn>=0.11 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (0.12.2)\n", "Requirement already satisfied: strsim>=0.0.3 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (0.0.3)\n", "Requirement already satisfied: strsimpy>=0.2.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (0.2.1)\n", "Requirement already satisfied: tqdm>=4.64 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (4.66.1)\n", "Requirement already satisfied: transformers>=4.21 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (4.32.0)\n", "Requirement already satisfied: sentence-transformers>=2.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (2.2.2)\n", "Requirement already satisfied: faiss-cpu>=1.7 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (1.7.4)\n", "Requirement already satisfied: optuna>=3.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (3.3.0)\n", "Requirement already satisfied: py-stringmatching>=0.4 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (0.4.3)\n", "Requirement already satisfied: ordered-set>=4.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (4.1.0)\n", "Requirement already satisfied: plotly>=5.16.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (5.16.1)\n", "Requirement already satisfied: tomli in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (2.0.1)\n", "Requirement already satisfied: valentine>=0.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pyjedai) (0.1.7)\n", "Requirement already satisfied: smart-open>=1.8.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from gensim>=4.2.0->pyjedai) (6.3.0)\n", "Requirement already satisfied: contourpy>=1.0.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (1.1.0)\n", "Requirement already satisfied: cycler>=0.10 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (0.11.0)\n", "Requirement already satisfied: fonttools>=4.22.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (4.42.1)\n", "Requirement already satisfied: kiwisolver>=1.0.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (1.4.5)\n", "Requirement already satisfied: packaging>=20.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (23.0)\n", "Requirement already satisfied: pillow>=6.2.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (10.0.0)\n", "Requirement already satisfied: pyparsing<3.1,>=2.3.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (3.0.9)\n", "Requirement already satisfied: python-dateutil>=2.7 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (2.8.2)\n", "Requirement already satisfied: importlib-resources>=3.2.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib>=3.1.3->pyjedai) (5.2.0)\n", "Requirement already satisfied: traitlets in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from matplotlib-inline>=0.1.3->pyjedai) (5.7.1)\n", "Requirement already satisfied: click in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from nltk>=3.7->pyjedai) (8.1.7)\n", "Requirement already satisfied: joblib in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from nltk>=3.7->pyjedai) (1.3.2)\n", "Requirement already satisfied: alembic>=1.5.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from optuna>=3.0->pyjedai) (1.11.3)\n", "Requirement already satisfied: cmaes>=0.10.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from optuna>=3.0->pyjedai) (0.10.0)\n", "Requirement already satisfied: colorlog in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from optuna>=3.0->pyjedai) (6.7.0)\n", "Requirement already satisfied: sqlalchemy>=1.3.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from optuna>=3.0->pyjedai) (2.0.20)\n", "Requirement already satisfied: pytz>=2020.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pandas>=0.25.3->pyjedai) (2022.7)\n", "Requirement already satisfied: tzdata>=2022.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pandas>=0.25.3->pyjedai) (2023.3)\n", "Requirement already satisfied: ydata-profiling in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from pandas-profiling>=3.2->pyjedai) (4.5.1)\n", "Requirement already satisfied: tenacity>=6.2.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from plotly>=5.16.0->pyjedai) (8.2.3)\n", "Requirement already satisfied: six in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from py-stringmatching>=0.4->pyjedai) (1.16.0)\n", "Requirement already satisfied: isodate<0.7.0,>=0.6.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from rdflib>=6.1.1->pyjedai) (0.6.1)\n", "Requirement already satisfied: torch>=1.6.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sentence-transformers>=2.2->pyjedai) (2.0.1)\n", "Requirement already satisfied: torchvision in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sentence-transformers>=2.2->pyjedai) (0.15.2)\n", "Requirement already satisfied: scikit-learn in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sentence-transformers>=2.2->pyjedai) (1.3.0)\n", "Requirement already satisfied: sentencepiece in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sentence-transformers>=2.2->pyjedai) (0.1.99)\n", "Requirement already satisfied: huggingface-hub>=0.4.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sentence-transformers>=2.2->pyjedai) (0.16.4)\n", "Requirement already satisfied: filelock in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from transformers>=4.21->pyjedai) (3.12.2)\n", "Requirement already satisfied: requests in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from transformers>=4.21->pyjedai) (2.31.0)\n", "Requirement already satisfied: tokenizers!=0.11.3,<0.14,>=0.11.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from transformers>=4.21->pyjedai) (0.13.3)\n", "Requirement already satisfied: safetensors>=0.3.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from transformers>=4.21->pyjedai) (0.3.3)\n", "Requirement already satisfied: anytree<2.9,>=2.8 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from valentine>=0.1->pyjedai) (2.8.0)\n", "Requirement already satisfied: chardet<6.0.0,>=5.0.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from valentine>=0.1->pyjedai) (5.2.0)\n", "Requirement already satisfied: levenshtein<1.0,>=0.20.7 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from valentine>=0.1->pyjedai) (0.21.1)\n", "Requirement already satisfied: PuLP<3.0,>=2.5.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from valentine>=0.1->pyjedai) (2.7.0)\n", "Requirement already satisfied: pot<1.0,>=0.8.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from valentine>=0.1->pyjedai) (0.9.1)\n", "Requirement already satisfied: Mako in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from alembic>=1.5.0->optuna>=3.0->pyjedai) (1.2.4)\n", "Requirement already satisfied: typing-extensions>=4 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from alembic>=1.5.0->optuna>=3.0->pyjedai) (4.7.1)\n", "Requirement already satisfied: importlib-metadata in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from alembic>=1.5.0->optuna>=3.0->pyjedai) (6.0.0)\n", "Requirement already satisfied: fsspec in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from huggingface-hub>=0.4.0->sentence-transformers>=2.2->pyjedai) (2023.6.0)\n", "Requirement already satisfied: zipp>=3.1.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from importlib-resources>=3.2.0->matplotlib>=3.1.3->pyjedai) (3.11.0)\n", "Requirement already satisfied: rapidfuzz<4.0.0,>=2.3.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from levenshtein<1.0,>=0.20.7->valentine>=0.1->pyjedai) (3.2.0)\n", "Requirement already satisfied: greenlet!=0.4.17 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sqlalchemy>=1.3.0->optuna>=3.0->pyjedai) (2.0.2)\n", "Requirement already satisfied: sympy in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (1.12)\n", "Requirement already satisfied: jinja2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (3.1.2)\n", "Requirement already satisfied: nvidia-cuda-nvrtc-cu11==11.7.99 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.7.99)\n", "Requirement already satisfied: nvidia-cuda-runtime-cu11==11.7.99 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.7.99)\n", "Requirement already satisfied: nvidia-cuda-cupti-cu11==11.7.101 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.7.101)\n", "Requirement already satisfied: nvidia-cudnn-cu11==8.5.0.96 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (8.5.0.96)\n", "Requirement already satisfied: nvidia-cublas-cu11==11.10.3.66 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.10.3.66)\n", "Requirement already satisfied: nvidia-cufft-cu11==10.9.0.58 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (10.9.0.58)\n", "Requirement already satisfied: nvidia-curand-cu11==10.2.10.91 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (10.2.10.91)\n", "Requirement already satisfied: nvidia-cusolver-cu11==11.4.0.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.4.0.1)\n", "Requirement already satisfied: nvidia-cusparse-cu11==11.7.4.91 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.7.4.91)\n", "Requirement already satisfied: nvidia-nccl-cu11==2.14.3 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (2.14.3)\n", "Requirement already satisfied: nvidia-nvtx-cu11==11.7.91 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (11.7.91)\n", "Requirement already satisfied: triton==2.0.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (2.0.0)\n", "Requirement already satisfied: setuptools in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (68.0.0)\n", "Requirement already satisfied: wheel in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from nvidia-cublas-cu11==11.10.3.66->torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (0.38.4)\n", "Requirement already satisfied: cmake in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from triton==2.0.0->torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (3.27.2)\n", "Requirement already satisfied: lit in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from triton==2.0.0->torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (16.0.6)\n", "Requirement already satisfied: charset-normalizer<4,>=2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from requests->transformers>=4.21->pyjedai) (2.0.4)\n", "Requirement already satisfied: idna<4,>=2.5 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from requests->transformers>=4.21->pyjedai) (3.4)\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from requests->transformers>=4.21->pyjedai) (1.26.16)\n", "Requirement already satisfied: certifi>=2017.4.17 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from requests->transformers>=4.21->pyjedai) (2023.7.22)\n", "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from scikit-learn->sentence-transformers>=2.2->pyjedai) (3.2.0)\n", "Requirement already satisfied: pydantic<2,>=1.8.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (1.10.12)\n", "Requirement already satisfied: visions[type_image_path]==0.7.5 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (0.7.5)\n", "Requirement already satisfied: htmlmin==0.1.12 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (0.1.12)\n", "Requirement already satisfied: phik<0.13,>=0.11.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (0.12.3)\n", "Requirement already satisfied: multimethod<2,>=1.4 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (1.9.1)\n", "Requirement already satisfied: statsmodels<1,>=0.13.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (0.14.0)\n", "Requirement already satisfied: typeguard<3,>=2.13.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (2.13.3)\n", "Requirement already satisfied: imagehash==4.3.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (4.3.1)\n", "Requirement already satisfied: wordcloud>=1.9.1 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (1.9.2)\n", "Requirement already satisfied: dacite>=1.8 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from ydata-profiling->pandas-profiling>=3.2->pyjedai) (1.8.1)\n", "Requirement already satisfied: PyWavelets in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from imagehash==4.3.1->ydata-profiling->pandas-profiling>=3.2->pyjedai) (1.4.1)\n", "Requirement already satisfied: attrs>=19.3.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from visions[type_image_path]==0.7.5->ydata-profiling->pandas-profiling>=3.2->pyjedai) (22.1.0)\n", "Requirement already satisfied: tangled-up-in-unicode>=0.0.4 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from visions[type_image_path]==0.7.5->ydata-profiling->pandas-profiling>=3.2->pyjedai) (0.2.0)\n", "Requirement already satisfied: MarkupSafe>=2.0 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from jinja2->torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (2.1.1)\n", "Requirement already satisfied: patsy>=0.5.2 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from statsmodels<1,>=0.13.2->ydata-profiling->pandas-profiling>=3.2->pyjedai) (0.5.3)\n", "Requirement already satisfied: mpmath>=0.19 in /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages (from sympy->torch>=1.6.0->sentence-transformers>=2.2->pyjedai) (1.3.0)\n" ] } ], "source": [ "!pip install pyjedai -U" ] }, { "cell_type": "code", "execution_count": 3, "id": "6d2e5cf7-ff2e-4271-9242-fe3d638263e9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Name: pyjedai\n", "Version: 0.1.0\n", "Summary: An open-source library that builds powerful end-to-end Entity Resolution workflows.\n", "Home-page: \n", "Author: \n", "Author-email: Konstantinos Nikoletos , George Papadakis , Jakub Maciejewski , Manolis Koubarakis \n", "License: Apache Software License 2.0\n", "Location: /home/jm/anaconda3/envs/pyjedai-new/lib/python3.8/site-packages\n", "Requires: faiss-cpu, gensim, matplotlib, matplotlib-inline, networkx, nltk, numpy, optuna, ordered-set, pandas, pandas-profiling, pandocfilters, plotly, py-stringmatching, PyYAML, rdflib, rdfpandas, regex, scipy, seaborn, sentence-transformers, strsim, strsimpy, tomli, tqdm, transformers, valentine\n", "Required-by: \n" ] } ], "source": [ "!pip show pyjedai" ] }, { "cell_type": "markdown", "id": "15d28272-269a-4e87-bb03-0a45a5492a06", "metadata": {}, "source": [ "Imports" ] }, { "cell_type": "code", "execution_count": 4, "id": "a0890ce6-3a10-4e66-913f-78095bd786a1", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "[nltk_data] Downloading package stopwords to /home/jm/nltk_data...\n", "[nltk_data] Package stopwords is already up-to-date!\n" ] } ], "source": [ "import os\n", "import sys\n", "import pandas as pd\n", "import networkx\n", "from networkx import draw, Graph\n", "\n", "from pyjedai.utils import print_clusters, print_blocks, print_candidate_pairs\n", "from pyjedai.evaluation import Evaluation" ] }, { "cell_type": "markdown", "id": "af77914f-5e76-4da8-a0ad-1c53e0111a0f", "metadata": { "tags": [] }, "source": [ "## Reading the dataset\n", "\n", "pyJedAI in order to perfrom needs only the tranformation of the initial data into a pandas DataFrame. Hence, pyJedAI can function in every structured or semi-structured data. In this case Abt-Buy dataset is provided as .csv files. \n", "\n", "
\n", " \n", "
\n", "\n", "\n", "### pyjedai module\n", "\n", "Data module offers a numpber of options\n", "- Selecting the parameters (columns) of the dataframe, in D1 (and in D2)\n", "- Prints a detailed text analysis\n", "- Stores a hidden mapping of the ids, and creates it if not exists." ] }, { "cell_type": "code", "execution_count": 5, "id": "3d3feb89-1406-4c90-a1aa-dc2cf4707739", "metadata": {}, "outputs": [], "source": [ "from pyjedai.datamodel import Data\n", "\n", "d1 = pd.read_csv(\"./../data/der/cora/cora.csv\", sep='|')\n", "gt = pd.read_csv(\"./../data/der/cora/cora_gt.csv\", sep='|', header=None)\n", "attr = ['Entity Id','author', 'title']" ] }, { "cell_type": "markdown", "id": "fda32323-c74d-4374-b322-5c11a175c3ea", "metadata": {}, "source": [ "Data is the connecting module of all steps of the workflow" ] }, { "cell_type": "code", "execution_count": 6, "id": "e257597d-ea77-4090-ba34-e1038d8f9a0d", "metadata": {}, "outputs": [], "source": [ "data = Data(\n", " dataset_1=d1,\n", " id_column_name_1='Entity Id',\n", " ground_truth=gt,\n", " attributes_1=attr\n", ")" ] }, { "cell_type": "markdown", "id": "93464edd-b88a-40d9-aa4d-7fe1523db662", "metadata": {}, "source": [ "## Workflow with Block Cleaning Methods\n", "\n", "In this notebook we created the bellow architecture:\n", "\n", "![workflow1-cora.png](https://github.com/AI-team-UoA/pyJedAI/blob/main/docs/img/workflow1-cora.png?raw=true)\n", "\n" ] }, { "cell_type": "markdown", "id": "9c068252-4a69-405a-a320-c2875ec08ea5", "metadata": {}, "source": [ "## Block Building\n", "\n", "It clusters entities into overlapping blocks in a lazy manner that relies on unsupervised blocking keys: every token in an attribute value forms a key. Blocks are then extracted, possibly using a transformation, based on its equality or on its similarity with other keys.\n", "\n", "The following methods are currently supported:\n", "\n", "- Standard/Token Blocking\n", "- Sorted Neighborhood\n", "- Extended Sorted Neighborhood\n", "- Q-Grams Blocking\n", "- Extended Q-Grams Blocking\n", "- Suffix Arrays Blocking\n", "- Extended Suffix Arrays Blocking" ] }, { "cell_type": "code", "execution_count": 7, "id": "9c1b6213-a218-40cf-bc72-801b77d28da9", "metadata": {}, "outputs": [], "source": [ "from pyjedai.block_building import (\n", " StandardBlocking,\n", " QGramsBlocking,\n", " SuffixArraysBlocking,\n", " ExtendedSuffixArraysBlocking,\n", " ExtendedQGramsBlocking\n", ")" ] }, { "cell_type": "code", "execution_count": 8, "id": "7ee34038-1352-440e-8c34-98c5cf036523", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "8605af0eba7d43c3972e821952576ebd", "version_major": 2, "version_minor": 0 }, "text/plain": [ "Suffix Arrays Blocking: 0%| | 0/1295 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "draw(pairs_graph)" ] }, { "cell_type": "code", "execution_count": 23, "id": "00bc2e82-9bc1-4119-b8cb-4a1c18afee19", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "***************************************************************************************************************************\n", " Μethod: Entity Matching\n", "***************************************************************************************************************************\n", "Method name: Entity Matching\n", "Parameters: \n", "\tMetric: jaccard\n", "\tAttributes: None\n", "\tSimilarity threshold: 0.0\n", "\tTokenizer: white_space_tokenizer\n", "\tVectorizer: None\n", "\tQgrams: 1\n", "Runtime: 7.9103 seconds\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Performance:\n", "\tPrecision: 74.46% \n", "\tRecall: 48.51%\n", "\tF1-score: 58.75%\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "_ = em.evaluate(pairs_graph)" ] }, { "cell_type": "markdown", "id": "607ee1fb-bed4-4751-9fa8-429874457f72", "metadata": {}, "source": [ "### How to set a valid similarity threshold?\n", "\n", "Configure similariy threshold with a Grid-Search or with an Optuna search. Also pyJedAI provides some visualizations on the distributions of the scores.\n", "\n", "For example with a classic histogram:\n" ] }, { "cell_type": "code", "execution_count": 24, "id": "c04c0482-a0d2-4ebf-b9c8-f6cff1863e5d", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1IAAAH5CAYAAACLYg8DAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABGoUlEQVR4nO3de1wXZd7/8fdXEATlICknFwXPhxRPZZgKJQrFuum6rZXH1sNti92rRqm7laabuK5am7m5tZZ5/zRtW7VWzAIVTNN0TdLUKE2jbkG2TcEvKMf5/eEyd9885EUcxF7Px2MeD2bmmpnP8LhA3l4z19dhWZYlAAAAAMA1a1DXBQAAAABAfUOQAgAAAABDBCkAAAAAMESQAgAAAABDBCkAAAAAMESQAgAAAABDBCkAAAAAMORe1wXUlIqKCp06dUo+Pj5yOBx1XQ4AAACAOmJZls6dO6fQ0FA1aFA9Y0k3bJA6deqUwsLC6roMAAAAANeJL7/8Uj/5yU+q5Vw3bJDy8fGRdPGb5evrW8fVADWrsLBQoaGhki7+J0Ljxo3ruCLUJ4WF0n+6j06dkug+qE6FJYUKXfyf30+PnFJjDzoYgNpXUFCgsLAwOyNUhxs2SFU+zufr60uQwg3Pzc3N/trX15cgBSPf6j7y9SVIoXq5lbhJjS5+7evrS5ACUKeq85UfJpsAAAAAAEMEKQAAAAAwRJACAAAAAEM37DtSAAAAN7qKigqVlJTUdRlAnWvYsKHLO+O1gSAFAABQD5WUlOjEiROqqKio61KA64K/v7+Cg4Nr7TNkCVIAAAD1jGVZysnJkZubm8LCwqrtA0aB+siyLBUVFSkvL0+SFBISUivXJUgBAADUM2VlZSoqKlJoaKi8vb3ruhygznl5eUmS8vLyFBgYWCuP+fHfFwAAAPVMeXm5JMnDw6OOKwGuH5X/qVBaWlor1yNIAQAA1FO19S4IUB/U9s8DQQoAAAAADBGkAAAAgHoiPT1dDodDZ8+eveZj5syZo+7du9dYTT9WBCkAAADUqt27d8vNzU0JCQl1XUq907dvX+Xk5MjPz69azxsTE6OpU6dW6zlvdAQpAAAA1KoVK1bo4Ycf1o4dO3Tq1KkavZZlWSorK6vRa9QmDw+PWv2sJFwZQQoAAAC1xul0at26dXrooYeUkJCglStX2vseeOABjRgxwqV9aWmpmjVrplWrVkmSKioqlJycrIiICHl5eSkyMlJvvPGG3b7y0be3335bvXr1kqenp3bu3Knjx4/rnnvuUVBQkJo0aaJbbrlFaWlpLtfKyclRQkKCvLy8FBERoTVr1ig8PFzPPvus3ebs2bOaMGGCmjdvLl9fX91555366KOPrni/v/jFLzRlyhR7ferUqXI4HPrkk08kXfxg5caNG9u1XOv9ffvRvpdeeklhYWHy9vbWsGHDtGTJEvn7+19Sy//8z/8oPDxcfn5+uu+++3Tu3DlJ0rhx45SRkaE//elPcjgccjgcOnny5BXvCRcRpAAAAOo5y5IKC+tmsSyzWl9//XV17NhRHTp00KhRo/Tyyy/L+s9JRo4cqX/84x9yOp12+3feeUdFRUUaNmyYJCk5OVmrVq3S8uXLdfjwYU2bNk2jRo1SRkaGy3VmzpypBQsW6OjRo+rWrZucTqfuvvtubd26VQcOHFB8fLyGDBmi7Oxs+5gxY8bo1KlTSk9P19///ne9+OKL9oe8Vrr33nuVl5ent99+W/v371fPnj01cOBAffPNN5e93+joaKWnp9vrGRkZatasmb1t3759Ki0tVd++fY3ur9KuXbs0efJk/eY3v1FmZqYGDRqkp59++pJ2x48f18aNG7Vp0yZt2rRJGRkZWrBggSTpT3/6k6KiojRx4kTl5OQoJydHYWFhl70evsW6QeXn51uSrPz8/LouBahxTqfTkmRJspxOZ12Xg3rG6bSsi38KXfwaqE7OYqelObI0R5azmA5WXc6fP28dOXLEOn/+vGVZrj/Htb2Y/t7o27ev9eyzz1qWZVmlpaVWs2bNrO3bt7usr1q1ym5///33WyNGjLAsy7IuXLhgeXt7W++//77LOcePH2/df//9lmVZ1vbt2y1J1saNG7+3li5dulhLly61LMuyjh49akmy9u3bZ+//7LPPLEnWM888Y1mWZb333nuWr6+vdeHCBZfztGnTxvrLX/5y2WscPHjQcjgcVl5envXNN99YHh4e1rx58+x7+v3vf2/17dvX+P7OnDljWZZljRgxwkpISHBpP3LkSMvPz89enz17tuXt7W0VFBTY2x599FGrT58+9np0dLT1m9/85mrfruved38uvq0msoF73UU4AAAA/JhkZWVp79692rBhgyTJ3d1dI0aM0IoVKxQTEyN3d3f98pe/1OrVqzV69GgV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OTlZTz31VFVvBwAAAACuWZWDVGJioj7++GPt3LnTZfukSZPsr7t27aqQkBANHDhQx48fV5s2bape6feYNWuWpk+fbq8XFBQoLCysxq4HAAAA4MerSo/2TZkyRZs2bdL27dv1k5/85Kpt+/TpI0k6duyYJCk4OFinT592aVO5Xvle1ZXa+Pr6XnY0SpI8PT3l6+vrsgAAAABATTAKUpZlacqUKdqwYYO2bdumiIiI7z0mMzNTkhQSEiJJioqK0qFDh5SXl2e3SU1Nla+vrzp37my32bp1q8t5UlNTFRUVZVIuAAAAfmTS09PlcDh09uxZSRcnR/P396/TmqoiPDxczz777DW3P3nypBwOh/23N2qeUZBKTEzU//t//09r1qyRj4+PcnNzlZubq/Pnz0uSjh8/rnnz5mn//v06efKk3nrrLY0ZM0YDBgxQt27dJEmDBw9W586dNXr0aH300Ud655139PjjjysxMVGenp6SpMmTJ+vzzz/XY489pk8++UR//vOf9frrr2vatGnVfPsAAACoLePGjbvsZ4xKF//OdDgcGjduXLVec8SIEfr000+r9Zy1Yd++fS6vzFSH+hoqr1dGQeqFF15Qfn6+YmJiFBISYi/r1q2TJHl4eCgtLU2DBw9Wx44d9cgjj2j48OH6xz/+YZ/Dzc1NmzZtkpubm6KiojRq1CiNGTNGc+fOtdtEREQoJSVFqampioyM1OLFi/XXv/6Vqc8BAADqubCwMK1du9b+j3hJunDhgtasWaOWLVtW+/W8vLwUGBhY7eetac2bN5e3t3ddl4GrMH6073JL5f8chIWFKSMjQ//+97914cIFffbZZ1q4cOEl7yu1atVKmzdvVlFRkf71r39p0aJFcnd3nfciJiZGBw4cUHFxsY4fP17t/zsBAACA2tezZ0+FhYXZMzpL0vr169WyZUv16NHDpW1FRYWSk5MVEREhLy8vRUZG6o033nBps3nzZrVv315eXl664447dPLkSZf93x2FOX78uO655x4FBQWpSZMmuuWWW5SWluZyTHh4uObPn69f/epX8vHxUcuWLfXiiy9e8Z42bdokf39/lZeXS7r4aovD4dDMmTPtNhMmTNCoUaPs9Z07d6p///7y8vJSWFiY/vu//1uFhYUuNXz70b5PPvlE/fr1U6NGjdS5c2elpaXJ4XBo48aNLrV8/vnnuuOO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Vq3S1q1b9Yc//EEZGRm66667VF5eLknKzc1VYGCgyzHu7u4KCAhQbm6u3SYoKMilTeV6ZZvvmjVrlvLz8+3lyy+/rO5bAwAAAABJVXi07/vcd9999tddu3ZVt27d1KZNG6Wnp2vgwIHVfTmbp6enPD09a+z8AAAAAFCpxqc/b926tZo1a6Zjx45JkoKDg5WXl+fSpqysTN988439XlVwcLBOnz7t0qZy/UrvXgEAAABAbanxIPXVV1/p3//+t0JCQiRJUVFROnv2rPbv32+32bZtmyoqKtSnTx+7zY4dO1RaWmq3SU1NVYcOHdS0adOaLhkAAAAArso4SDmdTmVmZiozM1OSdOLECWVmZio7O1tOp1OPPvqo9uzZo5MnT2rr1q2655571LZtW8XFxUmSOnXqpPj4eE2cOFF79+7Vrl27NGXKFN13330KDQ2VJD3wwAPy8PDQ+PHjdfjwYa1bt05/+tOfNH369Oq7cwAAAACoIuMg9c9//lM9evRQjx49JEnTp09Xjx499OSTT8rNzU0HDx7Uz372M7Vv317jx49Xr1699N5777m8v7R69Wp17NhRAwcO1N13361+/fq5fEaUn5+f3n33XZ04cUK9evXSI488oieffPKKU58DAAAAQG0ynmwiJiZGlmVdcf8777zzvecICAjQmjVrrtqmW7dueu+990zLAwAAAIAaV+PvSAEAAADAjYYgBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYIggBQAAAACGCFIAAAAAYMi9rgsAAKA2hc9MqesSrnsnFyTUdQkAcN1jRAoAAAAADBGkAAAAAMAQQQoAAAAADBGkAAAAAMAQQQoAAAAADBGk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ioqqw8oAAAAA4Dp+tG/69OkaO3asevfurVtvvVXPPvusCgsL7Vn8vo+np6dmz5592cf9gOpEX0Ntoa+httDXUFvoa6gtNdHXrstZ+yo9//zz+uMf/6jc3Fx1795dzz33nPr06VPXZQEAAAD4kbuugxQAAAAAXI+uy3ekAAAAAOB6RpACAAAAAEMEKQAAAAAwRJACAAAAAEP1OkgtW7ZM4eHhatSokfr06aO9e/detf3f/vY3dezYUY0aNVLXrl21efPmWqoU9Z1JX3vppZfUv39/NW3aVE2bNlVsbOz39k2gkunvtUpr166Vw+HQ0KFDa7ZA3DBM+9rZs2eVmJiokJAQeXp6qn379vw7imti2teeffZZdejQQV5eXgoLC9O0adN04cKFWqoW9dGOHTs0ZMgQhYaGyuFwaOPGjd97THp6unr27ClPT0+1bdtWK1euNL5uvQ1S69at0/Tp0zV79mx9+OGHioyMVFxcnPLy8i7b/v3339f999+v8ePH68CBAxo6dKiGDh2qjz/+uJYrR31j2tfS09N1//33a/v27dq9e7fCwsI0ePBg/e///m8tV476xrSvVTp58qSSkpLUv3//WqoU9Z1pXyspKdGgQYN08uRJvfHGG8rKytJLL72kFi1a1HLlqG9M+9qaNWs0c+ZMzZ49W0ePHtWKFSu0bt06/fa3v63lylGfFBYWKjIyUsuWLbum9idOnFBCQoLuuOMOZWZmaurUqZowYYLeeecdswtb9dStt95qJSYm2uvl5eVWaGiolZycfNn2v/zlL62EhASXbX369LH+67/+q0brRP1n2te+q6yszPLx8bFeffXVmioRN4iq9LWysjKrb9++1l//+ldr7Nix1j333FMLlaK+M+1rL7zwgtW6dWurpKSktkrEDcK0ryUmJlp33nmny7bp06dbt99+e43WiRuHJGvDhg1XbfPYY49ZXbp0cdk2YsQIKy4uzuha9XJEqqSkRPv371dsbKy9rUGDBoqNjdXu3bsve8zu3btd2ktSXFzcFdsDUtX62ncVFRWptLRUAQEBNVUmbgBV7Wtz585VYGCgxo8fXxtl4gZQlb721ltvKSoqSomJiQoKCtLNN9+s+fPnq7y8vLbKRj1Ulb7Wt29f7d+/33787/PPP9fmzZt1991310rN+HGorlzgXp1F1Zavv/5a5eXlCgoKctkeFBSkTz755LLH5ObmXrZ9bm5ujdWJ+q8qfe27ZsyYodDQ0Et+YIFvq0pf27lzp1asWKHMzMxaqBA3iqr0tc8//1zbtm3TyJEjtXnzZh07dky//vWvVVpaqtmzZ9dG2aiHqtLXHnjgAX399dfq16+fLMtSWVmZJk+ezKN9qFZXygUFBQU6f/68vLy8ruk89XJECqgvFixYoLVr12rDhg1q1KhRXZeDG8i5c+c0evRovfTSS2rWrFldl4MbXEVFhQIDA/Xiiy+qV69eGjFihH73u99p+fLldV0abjDp6emaP3++/vznP+vDDz/U+vXrlZKSonnz5tV1acAl6uWIVLNmzeTm5qbTp0+7bD99+rSCg4Mve0xwcLBRe0CqWl+rtGjRIi1YsEBpaWnq1q1bTZaJG4BpXzt+/LhOnjypIUOG2NsqKiokSe7u7srKylKbNm1qtmjUS1X5vRYSEqKGDRvKzc3N3tapUyfl5uaqpKREHh4eNVoz6qeq9LUnnnhCo0eP1oQJEyRJXbt2VWFhoSZNmqTf/e53atCAMQD8cFfKBb6+vtc8GiXV0xEpDw8P9erVS1u3brW3VVRUaOvWrYqKirrsMVFRUS7tJSk1NfWK7QGpan1NkhYuXKh58+Zpy5Yt6t27d22UinrOtK917NhRhw4dUmZmpr387Gc/s2cgCgsLq83yUY9U5ffa7bffrmPHjtlhXZI+/fRThYSEEKJwRVXpa0VFRZeEpcoAf3EeAeCHq7ZcYDYPxvVj7dq1lqenp7Vy5UrryJEj1qRJkyx/f38rNzfXsizLGj16tDVz5ky7/a5duyx3d3dr0aJF1tGjR63Zs2dbDRs2tA4dOlRXt4B6wrSvLViwwPLw8LDeeOMNKycnx17OnTtXV7eAesK0r30Xs/bhWpn2tezsbMvHx8eaMmWKlZWVZW3atMkKDAy0fv/739fVLaCeMO1rs2fPtnx8fKzXXnvN+vzzz613333XatOmjfXLX/6yrm4B9cC5c+esAwcOWAcOHLAkWUuWLLEOHDhgffHFF5ZlWdbMmTOt0aNH2+0///xzy9vb23r00Ueto0ePWsuWLbPc3NysLVu2GF233gYpy7KspUuXWi1btrQ8PDysW2+91dqzZ4+9Lzo62ho7dqxL+9dff91q37695eHhYXXp0sVKSUmp5YpRX5n0tVatWlmSLllmz55d+4Wj3jH9vfZtBCmYMO1r77//vtWnTx/L09PTat26tfX0009bZWVltVw16iOTvlZaWmrNmTPHatOmjdWoUSMrLCzM+vWvf22dOXOm9gtHvbF9+/bL/u1V2bfGjh1rRUdHX3JM9+7dLQ8PD6t169bWK6+8Ynxdh2UxTgoAAAAAJurlO1IAAAAAUJcIUgAAAABgiCAFAAAAAIYIUgAAAABgiCAFAAAAAIYIUgAAAABgiCAFAAAAAIYIUgAAAABgiCAFAAAAAIYIUgAAAABgiCAFAAAAAIb+P9pMZECF7PPCAAAAAElFTkSuQmCC", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "em.plot_distribution_of_all_weights()" ] }, { "cell_type": "markdown", "id": "75b6218c-3983-413e-a904-53bba33ea381", "metadata": {}, "source": [ "Or with a range 0.1 from 0.0 to 1.0 grouping:" ] }, { "cell_type": "code", "execution_count": 25, "id": "3e624fb5-cb48-4081-b90f-0e59adf88d26", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Distribution-% of predicted scores: [3.0010718113612005, 7.725973561986424, 13.844230082172205, 23.97284744551626, 18.854948195784207, 13.71025366202215, 8.145766345123258, 4.948195784208646, 3.858520900321544, 1.9381922115041088]\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACU5ElEQVR4nOzdeZyN5f/H8feZMftqnxlZBmPfl2QwlBERWbJny/JVVEiLtKBQKpSKbyUiFUVahOxblGTfiZBhyjKcwQwz1+8P3zk/xwzOmTnHmOn1fDzO4zHnurf3uc59zsxn7vu6b4sxxggAAAAAALicR3YHAAAAAAAgt6LoBgAAAADATSi6AQAAAABwE4puAAAAAADchKIbAAAAAAA3oegGAAAAAMBNKLoBAAAAAHATim4AAAAAANyEohsAAAAAADeh6AZygBEjRshisdyWbTVq1EiNGjWyPV+5cqUsFou+/vrr27L9nj17qkSJErdlW5lltVrVp08fhYWFyWKxaNCgQdkdKcdyZt9Om/eff/7J1LZywr6VFRaLRSNGjMjuGFmS9n2zcuXKO2pddzqLxaKBAwdmevmTJ0/q4YcfVv78+WWxWDRx4kTXhcvhSpQooZ49e2Z3jDtGo0aNVKlSpVvOd/jwYVksFk2fPt39oYAcgKIbuM2mT58ui8Vie/j6+ioiIkJNmzbVu+++q/Pnz7tkO8ePH9eIESO0ZcsWl6zPle7kbI4YM2aMpk+frscee0wzZ85Ut27dsjtSrjJmzBjNnz8/u2Mgiz7//HOKtxxi8ODBWrx4sYYNG6aZM2eqWbNm2R3ptvr55581YsQInT179pbz7tq1SyNGjNDhw4fdnssdcnp+IMcyAG6radOmGUlm1KhRZubMmeaTTz4xY8aMMffff7+xWCymePHiZuvWrXbLXL582Vy8eNGp7WzcuNFIMtOmTXNquaSkJJOUlGR7vmLFCiPJfPXVV06tJ7PZkpOTzaVLl1y2LXeoU6eOqVevXnbHyBUy2rcDAgJMjx490s37yiuvGEnm77//ztS2csK+lRWSzCuvvJLdMWxatGhhihcv7tQyKSkp5uLFiyYlJSXL23fluu50ksyAAQMyvXzhwoVN165dXZgoZ3nzzTeNJHPo0KF00y5dumSSk5Ntz7/66isjyaxYseL2BXShrOZv2LChqVix4i3nS01NNRcvXjRXrlzJ1HaA3CZPdhX7wL/dAw88oFq1atmeDxs2TMuXL9eDDz6oVq1aaffu3fLz85Mk5cmTR3nyuPfjeuHCBfn7+8vb29ut27kVLy+vbN2+I+Lj41WhQoXsjuGQ1NRUJScny9fXN7ujZOh27NtpcsK+dTOJiYkKCAjI7hhucenSJXl7e8vDw8Nl+6or1+UKd/L7Fx8fr9DQ0FvOdye/Bnfx8fHJ7gg5UtqZfACu4vRy4A5y33336aWXXtKff/6pzz77zNae0bjXJUuWqH79+goNDVVgYKDKli2rF154QdLVsYy1a9eWJPXq1ct2Knva2Kq0MVmbNm1STEyM/P39bcteP6Y7TUpKil544QWFhYUpICBArVq10tGjR+3mudHYt2vXeatsGY27TUxM1NNPP62iRYvKx8dHZcuW1VtvvSVjjN18aeMa58+fr0qVKsnHx0cVK1bUokWLMu7w68THx6t3794qXLiwfH19VbVqVX366ae26WljRA8dOqQFCxbYst/sNL2bvU9pLl26pBEjRqhMmTLy9fVVeHi42rZtq4MHD2a6D2bNmqWKFSvKx8fH9vr/+usvPfrooypcuLCtbz755JN0mSdNmqSKFSvK399fefPmVa1atfT555/f8DUaY1SgQAENGTLE1paamqrQ0FB5enranbL5xhtvKE+ePLJarZLS79sWi0WJiYn69NNPbf17/T519uxZ9ezZU6GhoQoJCVGvXr104cKFG+ZLk9G+9dZbbyk6Olr58+eXn5+fatasecPrF3z22We6++67bf0SExOjn376yW6ehQsXqmHDhgoKClJwcLBq165t13dr1qxR+/btVaxYMfn4+Kho0aIaPHiwLl68mC5rYGCgDh48qObNmysoKEhdu3aVJCUlJWnw4MEqWLCggoKC1KpVKx07duyWr1/6/314zpw5GjlypIoUKaKgoCA9/PDDSkhIUFJSkgYNGqRChQopMDBQvXr1UlJSUoZ9UbNmTfn5+Slfvnzq1KmT3fdBo0aNtGDBAv3555+29zGt79MyfPnll3rxxRdVpEgR+fv769y5czcch/3LL7+oefPmyps3rwICAlSlShW98847Dr3Wa9eV9t23a9cu3XvvvfL391eRIkU0btw4h/rv4sWLevLJJ1WgQAFb3//111/pxtOn7de7du1Sly5dlDdvXtWvX1+StG3bNvXs2VMlS5aUr6+vwsLC9Oijj+rUqVN220pbx549e9ShQwcFBwcrf/78euqpp3Tp0qUM8zn73Zc23MkYo/fff9/2Xl07bdWqVXr88cdVqFAh3XXXXbZlP/jgA9t3TEREhAYMGJDu9Oy0/t62bZsaNmwof39/lS5d2vYZW7VqlerUqSM/Pz+VLVtWS5cudeh9SEpK0iuvvKLSpUvbPkfPPvtsun3Vkd8JI0aM0DPPPCNJioyMTPe9fu3vtenTp6t9+/aSpHvvvdc278qVK9WjRw8VKFBAly9fTpf3/vvvV9myZW/6mrLaV3/++acef/xxlS1bVn5+fsqfP7/at29v9/vpZvnT3Oo7LM2tPkMZjelO+17766+/1Lp1awUGBqpgwYIaOnSoUlJS7JY/deqUunXrpuDgYIWGhqpHjx7aunUr48SRY3GkG7jDdOvWTS+88IJ++ukn9e3bN8N5du7cqQcffFBVqlTRqFGj5OPjowMHDmjdunWSpPLly2vUqFF6+eWX1a9fPzVo0ECSFB0dbVvHqVOn9MADD6hTp0565JFHVLhw4ZvmGj16tCwWi5577jnFx8dr4sSJio2N1ZYtW2xH5B3hSLZrGWPUqlUrrVixQr1791a1atW0ePFiPfPMM/rrr780YcIEu/nXrl2refPm6fHHH1dQUJDeffddtWvXTkeOHFH+/PlvmOvixYtq1KiRDhw4oIEDByoyMlJfffWVevbsqbNnz+qpp55S+fLlNXPmTA0ePFh33XWXnn76aUlSwYIFM1znrd4n6eo/Mx588EEtW7ZMnTp10lNPPaXz589ryZIl2rFjh0qVKuV0Hyxfvlxz5szRwIEDVaBAAZUoUUInT57UPffcY/sjtGDBglq4cKF69+6tc+fO2S4G99FHH+nJJ5/Uww8/bPvjftu2bfrll1/UpUuXDF+nxWJRvXr1tHr1alvbtm3blJCQIA8PD61bt04tWrSQdLXorF69ugIDAzNc18yZM9WnTx/dfffd6tevnySpVKlSdvN06NBBkZGRGjt2rH7//Xd9/PHHKlSokN54440bvb039M4776hVq1bq2rWrkpOT9eWXX6p9+/b64YcfbJklaeTIkRoxYoSio6M1atQoeXt765dfftHy5ct1//33S7r6B+2jjz6qihUratiwYQoNDdXmzZu1aNEiW9999dVXunDhgh577DHlz59fv/76qyZNmqRjx47pq6++sst25coVNW3aVPXr19dbb70lf39/SVKfPn302WefqUuXLoqOjtby5cvtsjpi7Nix8vPz0/PPP68DBw5o0qRJ8vLykoeHh86cOaMRI0Zow4YNmj59uiIjI/Xyyy/blh09erReeukldejQQX369NHff/+tSZMmKSYmRps3b1ZoaKiGDx+uhIQEHTt2zLZ/Xv+ev/rqq/L29tbQoUOVlJR0w7NslixZogcffFDh4eF66qmnFBYWpt27d+uHH37QU0895dTrlqQzZ86oWbNmatu2rTp06KCvv/5azz33nCpXrqwHHnjgpsv27NlTc+bMUbdu3XTPPfdo1apVN+379u3bKyoqSmPGjLH9g2zJkiX6448/1KtXL4WFhWnnzp368MMPtXPnTm3YsCHdP1g7dOigEiVKaOzYsdqwYYPeffddnTlzRjNmzLCbLzPffTExMbbrUjRp0kTdu3dPN8/jjz+uggUL6uWXX1ZiYqKkq4XqyJEjFRsbq8cee0x79+7V5MmTtXHjRq1bt87urJIzZ87owQcfVKdOndS+fXtNnjxZnTp10qxZszRo0CD1799fXbp00ZtvvqmHH35YR48eVVBQ0A37NDU1Va1atdLatWvVr18/lS9fXtu3b9eECRO0b9++dNeDuFW/tG3bVvv27dMXX3yhCRMmqECBApIy/l6PiYnRk08+qXfffVcvvPCCypcvL+nq77Vu3bppxowZWrx4sR588EHbMidOnNDy5cv1yiuv3PA1uaKvNm7cqJ9//lmdOnXSXXfdpcOHD2vy5Mlq1KiRdu3aJX9//5vmlxz7DkvLmdnPUEpKipo2bao6derorbfe0tKlS/X222+rVKlSeuyxx2zvccuWLfXrr7/qscceU7ly5fTtt9+qR48et+xD4I6Vjae2A/9KaWO6N27ceMN5QkJCTPXq1W3P08ayppkwYcItx7bebNx0w4YNjSQzZcqUDKc1bNjQ9jxtTHeRIkXMuXPnbO1z5swxksw777xjaytevHiGY3GvX+fNsvXo0cNuHOj8+fONJPPaa6/Zzffwww8bi8ViDhw4YGuTZLy9ve3atm7daiSZSZMmpdvWtSZOnGgkmc8++8zWlpycbOrWrWsCAwPtXnvx4sVNixYtbro+Yxx7nz755BMjyYwfPz7dtNTUVGOM833g4eFhdu7caTdv7969TXh4uPnnn3/s2jt16mRCQkLMhQsXjDHGPPTQQw6N17vem2++aTw9PW399O6775rixYubu+++2zz33HPGmKtjbENDQ83gwYNty12/bxtz6zHdjz76qF17mzZtTP78+W+Z8fp9yxhje91pkpOTTaVKlcx9991na9u/f7/x8PAwbdq0STc+OO09Onv2rAkKCjJ16tRJN0Y9bZ6MtmeMMWPHjjUWi8X8+eefdlklmeeff95u3i1bthhJ5vHHH7dr79Kli0NjutM+z5UqVbIbp9q5c2djsVjMAw88YDd/3bp17frs8OHDxtPT04wePdpuvu3bt5s8efLYtd9oTHdahpIlS6brj7RpaeNNr1y5YiIjI03x4sXNmTNn7Oa9tl9v9lqvHbua9t03Y8YMW1tSUpIJCwsz7dq1u+n6Nm3aZCSZQYMG2bX37NkzXd+n7audO3dOt56M9oEvvvjCSDKrV69Ot45WrVrZzfv4448bSXbX/sjKd1/a8tePCU/7XVW/fn27cbnx8fHG29vb3H///Xafh/fee89IMp988omtLa2/P//8c1vbnj17bN9TGzZssLUvXrzYoeuQzJw503h4eJg1a9bYtU+ZMsVIMuvWrbN7XY70y83GdF//e+1GY6JTUlLMXXfdZTp27GjXPn78eGOxWMwff/xx09eV1b7KaL9av359uv39Rvkd/Q5z9DN06NChdBnTvtdGjRplt/7q1aubmjVr2p7PnTvXSDITJ060taWkpJj77rsvU9eqAe4EnF4O3IECAwNvehXztLF33377rVJTUzO1DR8fH/Xq1cvh+bt372539OHhhx9WeHi4fvzxx0xt31E//vijPD099eSTT9q1P/300zLGaOHChXbtsbGxdkdGq1SpouDgYP3xxx+33E5YWJg6d+5sa/Py8tKTTz4pq9WqVatWOZ3dkfdp7ty5KlCggJ544ol009KOeDnbBw0bNrQbc26M0dy5c9WyZUsZY/TPP//YHk2bNlVCQoJ+//13W+Zjx45p48aNTr3WBg0aKCUlRT///LOkq0e0GzRooAYNGmjNmjWSpB07dujs2bO2sxsyq3///um2ferUKZ07d87pdV17lsaZM2eUkJCgBg0a2PpDunrKbmpqql5++WV5eNj/2kx7j5YsWaLz58/r+eefTzeO8dojl9duLzExUf/884+io6NljNHmzZvT5Us7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cHo5cAdZvny5Xn31VUVGRtpuD5SR06dPp2tLKwbSbpmSdi/VjIrgzJgxY4bdOLWvv/5acXFxdlcqLVWqlDZs2KDk5GRb2w8//JDu1mLOZGvevLlSUlL03nvv2bVPmDBBFovllldKdVTz5s114sQJzZ4929Z25coVTZo0SYGBgbZTgJ3hyPvUrl07/fPPP+len/T/Rw2y2geenp5q166d5s6dqx07dqSb/vfff9t+vv62Rd7e3qpQoYKMMRneCudaDRo0UFJSkiZOnKj69evb/rhr0KCBZs6cqePHjzs0njsgIMBl++3NeHp6ymKx2N2q5vDhw+mufty6dWt5eHho1KhR6Y4Ypb1H999/v4KCgjR27Nh0t3NKmyftCM+1R4OMMbe89dW10t7rd99916594sSJDq8jK9q2bStPT0+NHDky3VEtY4zd/hMQEODQaa03U6NGDUVGRmrixInp9onbffZK2j9CP/jgA7v2SZMmObyOjPYB6ebv3/vvv5/h9lz13ees2NhYeXt7691337V7HVOnTlVCQoLTV9J3VocOHfTXX3/po48+Sjft4sWLtiusO8OZ30m3mrdz586yWCx66qmn9Mcff9iNfXYnT0/PdPvVpEmT0t2K60b5HfkOu12aNm2qy5cv273Hqamp6T4LQE7CkW4gmyxcuFB79uzRlStXdPLkSS1fvlxLlixR8eLF9d133930iOKoUaO0evVqtWjRQsWLF1d8fLw++OAD3XXXXbbxsqVKlVJoaKimTJmioKAgBQQEqE6dOg6No8xIvnz5VL9+ffXq1UsnT57UxIkTVbp0absLnfTp00dff/21mjVrpg4dOujgwYP67LPP0o0/dSZby5Ytde+992r48OE6fPiwqlatqp9++knffvutBg0alG7dmdWvXz/997//Vc+ePbVp0yaVKFFCX3/9tdatW6eJEyfedIz9jTjyPnXv3l0zZszQkCFD9Ouvv6pBgwZKTEzU0qVL9fjjj+uhhx5ySR+8/vrrWrFiherUqaO+ffuqQoUKOn36tH7//XctXbrU9g+C+++/X2FhYapXr54KFy6s3bt367333lOLFi1u2Qd169ZVnjx5tHfvXtvtvqSrt9mZPHmyJDlUdNesWVNLly7V+PHjFRERocjISLuLCLlKixYtNH78eDVr1kxdunRRfHy83n//fZUuXVrbtm2zzVe6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MR07djQtWrSwm79r164mJCTE9vyVV14x/v7+5ty5c7a2Z555xtSpU8f2vGHDhuapp566WXfd8a7/XFzL0VozT/aV+wAAAACQNXv37tWvv/6qb775RpKUJ08edezYUVOnTlWjRo2UJ08edejQQbNmzVK3bt2UmJiob7/9Vl9++aUk6cCBA7pw4YKaNGlit97k5GRVr17drq1WrVp2z61Wq0aMGKEFCxYoLi5OV65c0cWLF21Huvfu3as8efKoRo0atmVKly6tvHnz2p5v3bpVVqtV+fPnt1v3xYsXdfDgwQxfc6VKlZQvXz6tWrVK3t7eql69uh588EG9//77kq4e+W7UqJHTr+/aPk07CyDN3XffrR9++MGurUSJEgoKCrI9Dw8PT3cUHxJFNwAAAIB0/P2la87Ivu3bdtTUqVN15coVRURE2NqMMfLx8dF7772nkJAQde3aVQ0bNlR8fLyWLFkiPz8/NWvWTJJsp50vWLBARYoUsVu3j4+P3fOAgAC750OHDtWSJUv01ltvqXTp0vLz89PDDz+s5ORkh/NbrVaFh4fbnS6eJqMx1JJksVgUExOjlStXysfHR40aNVKVKlWUlJSkHTt26Oeff9bQoUOdfn3O8vLySpcrNTU1S+vMjSi6AQAAAKRjsUjX1Zh3nCtXrmjGjBl6++23df/999tNa926tb744gv1799f0dHRKlq0qGbPnq2FCxeqffv2toKxQoUK8vHx0ZEjR9SwYUOntr9u3Tr17NnTdlTYarXaXSysbNmyunLlijZv3qyaNWtKunrk+cyZM7Z5atSooRMnTihPnjwqUaKEw9tu2LChPvroI/n4+Gj06NHy8PBQTEyM3nzzTSUlJalevXqZfn1ly5bVxo0b7dquf+4Ib29vpaSkOL1cbkPRDQAAACBH+uGHH3TmzBn17t073T2m27Vrp6lTp6p///6Srl7FfMqUKdq3b59WrFhhmy8oKEhDhw7V4MGDlZqaqvr16yshIUHr1q1TcHCwevToccPtR0VFad68eWrZsqUsFoteeukluyO95cqVU2xsrPr166fJkyfLy8tLTz/9tPz8/Gy354qNjVXdunXVunVrjRs3TmXKlNHx48e1YMECtWnTJt0p7WkaNWqkwYMHy9vbW/Xr17e1DR06VLVr17Ydlc/M63viiScUExOj8ePHq2XLllq+fLkWLlzo9C3FSpQooV9++UWHDx9WYGCg8uXLJw+Pf9+1vP99rxgAAABArjB16lTFxsamK7ilq0X3b7/9pm3btkm6ehXzXbt2qUiRIrajwGleffVVvfTSSxo7dqzKly+vZs2aacGCBYqMjLzp9sePH6+8efMqOjpaLVu2VNOmTe3Gb0vSjBkzVLhwYcXExKhNmzbq27evgoKC5OvrK+nqKdk//vijYmJi1KtXL5UpU0adOnXSn3/+qcKFC99w25UrV1ZoaKiqVaumwMBASVeL7pSUFNt47sy+vnr16mnKlCkaP368qlatqkWLFmnw4MG2zI4aOnSoPD09VaFCBRUsWNDuqu7/JhZjnL0gf85y7tw5hYSEKCEhQcHBwdkdB0AukZiYaPsFZ7Va043xcgsn/7uc7XL3r5c7SmKi9L/dUVbrnX86KJCYnKjAsf/7Dh1mVYA3O+2d4NKlSzp06JAiIyOdLq7guGPHjqlo0aJaunSpGjdunN1xHNa3b1/t2bNHa9asye4ot9XNPheO1pqcXg4AAAAAbrJ8+XJZrVZVrlxZcXFxevbZZ1WiRAnFxMRkd7Sbeuutt9SkSRMFBARo4cKF+vTTT/XBBx9kd6wciaIbAAAAANzk8uXLeuGFF/THH38oKChI0dHRmjVrVrorf99pfv31V40bN07nz59XyZIl9e6776pPnz7ZHStHougGAAAAADdp2rSpmjZtmt0xnDZnzpzsjpBrcCE1AAAAAADchKIbAAAAAAA3oegGAAAAAMBNKLoBAAAAAHATim4AAAAAANyEohsAAAAAADeh6AYAAACAm1i5cqUsFovOnj0rSZo+fbpCQ0OzNVNmlChRQhMnTnR4/sOHD8tisWjLli1uy/RvQNENAAAAIMfq2bOnLBaL+vfvn27agAEDZLFY1LNnT5dus2PHjtq3b59L13k7bNy4Uf369XPpOnPqPyBuJ4puAAAAADla0aJF9eWXX+rixYu2tkuXLunzzz9XsWLFXL49Pz8/FSpUyOXrdbeCBQvK398/u2P861B0AwAAAMjRatSooaJFi2revHm2tnnz5qlYsWKqXr263bypqakaO3asIiMj5efnp6pVq+rrr7+2m+fHH39UmTJl5Ofnp3vvvVeHDx+2m3790d2DBw/qoYceUuHChRUYGKjatWtr6dKldsuUKFFCY8aM0aOPPqqgoCAVK1ZMH3744Q1f0w8//KDQ0FClpKRIkrZs2SKLxaLnn3/eNk+fPn30yCOP2J6vXbtWDRo0kJ+fn4oWLaonn3xSiYmJdhmuPb18z549ql+/vnx9fVWhQgUtXbpUFotF8+fPt8vyxx9/6N5775W/v7+qVq2q9evXS7p62n2vXr2UkJAgi8Uii8WiESNG3PA1/VtRdAMAAABIxxijxMTEbHkYY5zO++ijj2ratGm255988ol69eqVbr6xY8dqxowZmjJlinbu3KnBgwfrkUce0apVqyRJR48eVdu2bdWyZUtt2bJFffr0sSt0M2K1WtW8eXMtW7ZMmzdvVrNmzdSyZUsdOXLEbr63335btWrV0ubNm/X444/rscce0969ezNcZ4MGDXT+/Hlt3rxZkrRq1SoVKFBAK1eutM2zatUqNWrUSNLVwr9Zs2Zq166dtm3bptmzZ2vt2rUaOHBghutPSUlR69at5e/vr19++UUffvihhg8fnuG8w4cP19ChQ7VlyxaVKVNGnTt31pUrVxQdHa2JEycqODhYcXFxiouL09ChQ2/aV/9KJpdLSEgwkkxCQkJ2RwGQi1itViPJSDJWq/X2bFTKWQ/cNlbr/3f77dodgaywJlmNRshohIw1iZ32TnHx4kWza9cuc/HiRWOM/e+62/1w5ndrjx49zEMPPWTi4+ONj4+POXz4sDl8+LDx9fU1f//9t3nooYdMjx49jDHGXLp0yfj7+5uff/7Zbh29e/c2nTt3NsYYM2zYMFOhQgW76c8995yRZM6cOWOMMWbatGkmJCTkprkqVqxoJk2aZHtevHhx88gjj9iep6ammkKFCpnJkyffcB01atQwb775pjHGmNatW5vRo0cbb29vc/78eXPs2DEjyezbt8/2Gvr162e3/Jo1a4yHh4ftPS1evLiZMGGCMcaYhQsXmjx58pi4uDjb/EuWLDGSzDfffGOMMebQoUNGkvn4449t8+zcudNIMrt373a4L3Ky6z8X13K01szjxnoeAAAAAG6LggULqkWLFpo+fbqMMWrRooUKFChgN8+BAwd04cIFNWnSxK49OTnZdhr67t27VadOHbvpdevWvem2rVarRowYoQULFiguLk5XrlzRxYsX0x3prlKliu1ni8WisLAwxcfH33C9DRs21MqVK/X0009rzZo1Gjt2rObMmaO1a9fq9OnTioiIUFRUlCRp69at2rZtm2bNmmVb3hij1NRUHTp0SOXLl7db9969e1W0aFGFhYXZ2u6+++4Mc1ybOzw8XJIUHx+vcuXK3bRfcBVFNwAAAIB0/P39ZbVas23bmfHoo4/aTqd+//33001Pez0LFixQkSJF7Kb5+PhkapuSNHToUC1ZskRvvfWWSpcuLT8/Pz388MNKTk62m8/Ly8vuucViUWpq6g3X26hRI33yySfaunWrvLy8VK5cOTVq1EgrV67UmTNn1LBhQ7vX9p///EdPPvlkuvVk9WJy1+a2WCySdNPcsEfRDQAAACAdi8WigICA7I7hlGbNmik5OVkWi0VNmzZNN71ChQry8fHRkSNH7ArWa5UvX17fffedXduGDRtuut1169apZ8+eatOmjaSrBfD1F1/LjLRx3RMmTLDlbdSokV5//XWdOXNGTz/9tG3eGjVqaNeuXSpdurRD6y5btqyOHj2qkydPqnDhwpKu3lLMWd7e3raLvSFjXEgNAAAAQK7g6emp3bt3a9euXfL09Ew3PSgoSEOHDtXgwYP16aef6uDBg/r99981adIkffrpp5Kk/v37a//+/XrmmWe0d+9eff7555o+ffpNtxsVFaV58+Zpy5Yt2rp1q7p06eKSI8F58+ZVlSpVNGvWLNsF02JiYvT7779r3759dv84eO655/Tzzz9r4MCB2rJli/bv369vv/32hhdSa9KkiUqVKqUePXpo27ZtWrdunV588UVJ/3802xElSpSQ1WrVsmXL9M8//+jChQuZf8G5FEU3AAAAgFwjODhYwcHBN5z+6quv6qWXXtLYsWNVvnx5NWvWTAsWLFBkZKSkq6diz507V/Pnz1fVqlU1ZcoUjRkz5qbbHD9+vPLmzavo6Gi1bNlSTZs2VY0aNVzyeho2bKiUlBRb0Z0vXz5VqFBBYWFhKlu2rG2+KlWqaNWqVdq3b58aNGig6tWr6+WXX1ZERESG6/X09NT8+fNltVpVu3Zt9enTx3b1cl9fX4fzRUdHq3///urYsaMKFiyocePGZf7F5lIWYzJxPf4c5Ny5cwoJCVFCQsJNP3wA4IzExEQFBgZKunoK2W05/c6J/zrfEXL3r5c7SmKi9L/dUVarlMPOBsW/UGJyogLH/u87dJhVAd7stHeCS5cu6dChQ4qMjHSq6ELusW7dOtWvX18HDhxQqVKlsjvOHeFmnwtHa03GdAMAAADAv9A333yjwMBARUVF6cCBA3rqqadUr149Cm4Xo+gGAAAAgH+h8+fP67nnntORI0dUoEABxcbG6u23387uWLkORTcAAAAA/At1795d3bt3z+4YuR4XUgMAAAAAwE0ougEAAAAAcBOKbgAAAAAA3ISiGwAAAAAAN6HoBgAAAADATSi6AQAAAABwE4puAAAAAMAda/r06QoNDXVqmZ49e6p169ZuyeMsim4AAAAAOd769evl6empFi1aZHeUHGHVqlW67777lC9fPvn7+ysqKko9evRQcnKyJGnlypWyWCyyWCzy8PBQSEiIqlevrmeffVZxcXG3NWvHjh21b98+l6+3RIkSmjhxosvXez2KbgAAAAA53tSpU/XEE09o9erVOn78uFu3ZYzRlStX3LoNZxw+fFgWi8Xh+Xft2qVmzZqpVq1aWr16tbZv365JkybJ29tbKSkpdvPu3btXx48f18aNG/Xcc89p6dKlqlSpkrZv3+7ql3FDfn5+KlSo0G3bnqtRdAMAAADI0axWq2bPnq3HHntMLVq00PTp023TunTpoo4dO9rNf/nyZRUoUEAzZsyQJKWmpmrs2LGKjIyUn5+fqlatqq+//to2f9pR34ULF6pmzZry8fHR2rVrdfDgQT300EMqXLiwAgMDVbt2bS1dutRuW3FxcWrRooX8/PwUGRmpzz//PN0R1rNnz6pPnz4qWLCggoODdd9992nr1q2u76j/+emnnxQWFqZx48apUqVKKlWqlJo1a6aPPvpIfn5+dvMWKlRIYWFhKlOmjDp16qR169apYMGCeuyxx264/lq1aumtt96yPW/durW8vLxktVolSceOHZPFYtGBAwckSUlJSRo6dKiKFCmigIAA1alTRytXrrQtn9Hp5a+99poKFSqkoKAg9enTR88//7yqVauWLstbb72l8PBw5c+fXwMGDNDly5clSY0aNdKff/6pwYMH247ouwtFNwAAAIB0jDFKTE7Mlocxxqmsc+bMUbly5VS2bFk98sgj+uSTT2zr6Nq1q77//ntbwSdJixcv1oULF9SmTRtJ0tixYzVjxgxNmTJFO3fu1ODBg/XII49o1apVdtt5/vnn9frrr2v37t2qUqWKrFarmjdvrmXLlmnz5s1q1qyZWrZsqSNHjtiW6d69u44fP66VK1dq7ty5+vDDDxUfH2+33vbt2ys+Pl4LFy7Upk2bVKNGDTVu3FinT592qh8cFRYWpri4OK1evdrpZf38/NS/f3+tW7cu3etI07BhQ1vRbIzRmjVrFBoaqrVr10q6emp7kSJFVLp0aUnSwIEDtX79en355Zfatm2b2rdvr2bNmmn//v0Zrn/WrFkaPXq03njjDW3atEnFihXT5MmT0823YsUKHTx4UCtWrNCnn36q6dOn2/4hM2/ePN11110aNWqU4uLi3HrKfB63rRkAAABAjnXh8gUFjg3Mlm1bh1kV4B3g8PxTp07VI488Iklq1qyZEhIStGrVKjVq1EhNmzZVQECAvvnmG3Xr1k2S9Pnnn6tVq1YKCgpSUlKSxowZo6VLl6pu3bqSpJIlS2rt2rX673//q4YNG9q2M2rUKDVp0sT2PF++fKpatart+auvvqpvvvlG3333nQYOHKg9e/Zo6dKl2rhxo2rVqiVJ+vjjjxUVFWVbZu3atfr1118VHx8vHx8fSVePzs6fP19ff/21+vXr52z33VL79u21ePFiNWzYUGFhYbrnnnvUuHFjde/eXcHBwbdcvly5cpKuntae0WnfjRo10tSpU5WSkqIdO3bI29tbHTt21MqVK9WsWTOtXLnS1q9HjhzRtGnTdOTIEUVEREiShg4dqkWLFmnatGkaM2ZMuvVPmjRJvXv3Vq9evSRJL7/8sn766Se7f6xIUt68efXee+/J09NT5cqVU4sWLbRs2TL17dtX+fLlk6enp4KCghQWFuZcBzqJI90AAAAAcqy9e/fq119/VefOnSVJefLkUceOHTV16lTb8w4dOmjWrFmSpMTERH377bfq2rWrJOnAgQO6cOGCmjRposDAQNtjxowZOnjwoN220grnNFarVUOHDlX58uUVGhqqwMBA7d6923ake+/evcqTJ49q1KhhW6Z06dLKmzev7fnWrVtltVqVP39+u+0fOnQo3favVbFiRdu8FStWlCS75R944IEbLuvp6alp06bp2LFjGjdunIoUKaIxY8aoYsWKDh3xTTuL4EanZDdo0EDnz5/X5s2btWrVKjVs2FCNGjWyHf1O+4eIJG3fvl0pKSkqU6aMXf5Vq1bd8PXv3btXd999t13b9c+lq33k6elpex4eHn7Do/PuxJFuAAAAAOn4e/nLOsx66xndtG1HTZ06VVeuXLEdJZWuFoU+Pj567733FBISoq5du6phw4aKj4/XkiVL5Ofnp2bNmkmS7ejoggULVKRIEbt1px15ThMQYH/0fejQoVqyZIneeustlS5dWn5+fnr44YdtVwB3hNVqVXh4uN0Y5jQ3u03Wjz/+aBuf/Ndff6lRo0basmWLbfr1Y7MzUqRIEXXr1k3dunXTq6++qjJlymjKlCkaOXLkTZfbvXu3pKtX/85IaGioqlatqpUrV2r9+vVq0qSJYmJibFch379/v+1It9VqlaenpzZt2mRXIEtX/4mQFV5eXnbPLRaLUlNTs7TOzKDoBgAAAJCOxWJx6hTv7HDlyhXNmDFDb7/9tu6//367aa1bt9YXX3yh/v37Kzo6WkWLFtXs2bO1cOFCtW/f3laQVahQQT4+Pjpy5IjdqeSOWLdunXr27GkbG261WnX48GHb9LJly+rKlSvavHmzatasKenqkfUzZ87Y5qlRo4ZOnDihPHny3LCIzUjx4sVtP+fJc7WsSxsjnRl58+ZVeHi4EhMTbzrfxYsX9eGHHyomJkYFCxa84XwNGzbUihUr9Ouvv2r06NHKly+fypcvr9GjRys8PFxlypSRJFWvXl0pKSmKj49XgwYNHMpatmxZbdy4Ud27d7e1bdy40aFlr5XR1drdgaIbAAAAQI70ww8/6MyZM+rdu7dCQkLsprVr105Tp05V//79JV29ivmUKVO0b98+rVixwjZfUFCQhg4dqsGDBys1NVX169dXQkKC1q1bp+DgYPXo0eOG24+KitK8efPUsmVLWSwWvfTSS3ZHUsuVK6fY2Fj169dPkydPlpeXl55++mn5+fnZTs2OjY1V3bp11bp1a40bN05lypTR8ePHtWDBArVp0ybdKe2u8N///ldbtmxRmzZtVKpUKV26dEkzZszQzp07NWnSJLt54+PjdenSJZ0/f16bNm3SuHHj9M8//2jevHk33UajRo00adIkFSxY0DYGvFGjRnrvvffUvn1723xlypRR165d1b17d7399tuqXr26/v77by1btkxVqlTJ8L7rTzzxhPr27atatWopOjpas2fP1rZt21SyZEmn+qFEiRJavXq1OnXqJB8fHxUoUMCp5R3FmG4AAAAAOdLUqVMVGxubruCWrhbdv/32m7Zt2ybp6lXMd+3apSJFiqhevXp287766qt66aWXNHbsWJUvX17NmjXTggULFBkZedPtjx8/Xnnz5lV0dLRatmyp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ciSni26LxaLhw4frmWee0YEDB2S1WlWhQgUFBga6Ix8AAAAAADmW00V3Gm9vb1WoUMGVWQAAAAAAyFWcLrrbtGkji8WSrt1iscjX11elS5dWly5dVLZsWZcEBAAAAAAgp3L6QmohISFavny5fv/9d1ksFlksFm3evFnLly/XlStXNHv2bFWtWlXr1q1zR14AAAAAAHIMp490h4WFqUuXLnrvvffk4XG1Zk9NTdVTTz2loKAgffnll+rfv7+ee+45rV271uWBAQAAAADIKZw+0j116lQNGjTIVnBLkoeHh5544gl9+OGHslgsGjhwoHbs2OHSoAAAAAAA5DROF91XrlzRnj170rXv2bNHKSkpkiRfX98Mx30DAAAAAPBv4vTp5d26dVPv3r31wgsvqHbt2pKkjRs3asyYMerevbskadWqVapYsaJrkwIAAAAAkMM4XXRPmDBBhQsX1rhx43Ty5ElJUuHChTV48GA999xzkqT7779fzZo1c21SAAAAAAByGKeLbk9PTw0fPlzDhw/XuXPnJEnBwcF28xQrVsw16QAAAAAAyMGcLrqvdX2xDQAAAAAA/p/TF1I7efKkunXrpoiICOXJk0eenp52DwAAAAAAcJXTR7p79uypI0eO6KWXXlJ4eDhXKQcAAAAA4AacLrrXrl2rNWvWqFq1am6IAwAAAABA7uH06eVFixaVMcYdWQAAAAAAyFWcLronTpyo559/XocPH3ZDHAAAAAAAcg+nTy/v2LGjLly4oFKlSsnf319eXl5200+fPu2ycAAAAAAA5GROF90TJ050QwwAAAAAAHIfp4vuHj16uCMHAAAAAAC5jtNF97UuXbqk5ORku7bg4OAsBQIAAAAAILdw+kJqiYmJGjhwoAoVKqSAgADlzZvX7gEAAAAAAK5yuuh+9tlntXz5ck2ePFk+Pj76+OOPNXLkSEVERGjGjBnuyAgAAAAAQI7kdNH9/fff64MPPlC7du2UJ08eNWjQQC+++KLGjBmjWbNmObWu1atXq2XLloqIiJDFYtH8+fPtpvfs2VMWi8Xu0axZM2cjAwAAAACQLZwuuk+fPq2SJUtKujp+O+0WYfXr19fq1audWldiYqKqVq2q999//4bzNGvWTHFxcbbHF1984WxkAAAAAACyhdMXUitZsqQOHTqkYsWKqVy5cpozZ47uvvtuff/99woNDXVq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AAAgB3P6QmoxMTFasmSJKleurPbt2+upp57S8uXLtWTJEjVu3NgdGQEAAAAAyJGcLrrfe+89Xbp0SZI0fPhweXl56eeff1a7du304osvujwgAAAAAAA5ldNFd758+Ww/e3h46Pnnn3dpIAAAAAAAcotM3ac7JSVF33zzjXbv3i1JqlChgh566CHlyZOp1QEAAAAAkCs5XSXv3LlTrVq10okTJ1S2bFlJ0htvvKGCBQvq+++/V6VKlVweEgAAAACAnMjpq5f36dNHFStW1LFjx/T777/r999/19GjR1WlShX169fPHRkBAAAAAMiRnD7SvWXLFv3222/KmzevrS1v3rwaPXq0ateu7dJwAAAAAADkZE4f6S5TpoxOnjyZrj0+Pl6lS5d2al2rV69Wy5YtFRERIYvFovnz59tNN8bo5ZdfVnh4uPz8/BQbG6v9+/c7GxkAAAAAgGzhdNE9duxYPfnkk/r666917NgxHTt2TF9//bUGDRqkN954Q+fOnbM9biUxMVFVq1bV+++/n+H0cePG6d1339WUKVP0yy+/KCAgQE2bNrXdsgwAAAAAgDuZxRhjnFnAw+P/63SLxSLp6hHp659bLBalpKQ4HsRi0TfffKPWrVvb1hEREaGnn35aQ4cOlSQlJCSocOHCmj59ujp16uTQes+dO6eQkBAlJCQoODjY4TwAMuF/3wE5hnNff3YSExMVGBgoSbJarQoICHBVqhv7F/VvtsjB/ZuYKP1vd5TVKt2O3TFTcnAfw7USkxMVOPZ/36HDrArwvlN3WgC4MUdrTafHdK9YsSJLwRx16NAhnThxQrGxsba2kJAQ1alTR+vXr79h0Z2UlKSkpCTbc0eOuAMAAAAA4A5OF90NGzZ0R450Tpw4IUkqXLiwXXvhwoVt0zIyduxYjRw50q3ZAAAAAABwhNNjuu90w4YNU0JCgu1x9OjR7I4EAAAAAPiXumOL7rCwMElKd6X0kydP2qZlxMfHR8HBwXYPAAAAAACywx1bdEdGRiosLEzLli2ztZ07d06//PKL6tatm43JAAAAAABwjENF93fffafLly+7fONWq1VbtmzRli1bJF29eNqWLVt05MgRWSwWDRo0SK+99pq+++47bd++Xd27d1dERITtCucAAAAAANzJHLqQWps2bXTixAkVLFhQnp6eiouLU6FChbK88d9++0333nuv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giTp3Llz7gv6b0Wfuhf9635Z6OPExMRrVnNOKSkprkiUu7APu9c1/XvN7qhz5yR2RxdhH3abRCPp0tWfz507pxRvdlqXY/91P/rYvXJA/6bVmMaYm853RxfdmTF27FiNHDkyXXvRokWzIU0uFxKS3QlyN/rX/VzUxxERES5ZT67DPuxeN+hfdkcXYh92nyuSXr/6Y8Tr7LRuwf7rfvSxe+Wg/j1//rxCbpL3ji66CxQoIE9PT508edKu/eTJkwoLC8twmWHDhmnIkCG256mpqTp9+rTy588vi8Xi1rx3onPnzqlo0aI6evSogoODsztOrkP/uh997F70r3vRv+5HH7sX/ete9K/70cfu9W/vX2OMzp8/f8sDMHd00e3t7a2aNWtq2bJlat26taSrRfSyZcs0cODADJfx8fGRj4+PXVtoaKibk975goOD/5UfhNuF/nU/+ti96F/3on/djz52L/rXvehf96OP3evf3L83O8Kd5o4uuiVpyJAh6tGjh2rVqqW7775bEydOVGJionr16pXd0QAAAAAAuKk7vuju2LGj/v77b7388ss6ceKEqlWrpkWLFqW7uBoAAAAAAHeaO77olqSBAwfe8HRy3JyPj49eeeWVdKfcwzXoX/ejj92L/nUv+tf96GP3on/di/51P/rYvehfx1jMra5vDgAAAAAAMsUjuwMAAAAAAJBbUXQDAAAAAOAmFN0AAAAAALgJRXc2ef/991WiRAn5+vqqTp06+vXXX2+5zFdffaVy5crJ19dXlStX1o8//uiSLEeOHFGLFi3k7++vQoUK6ZlnntGVK1duuszo0aMVHR0tf3//O/Y+6M728c6dO9WuXTuVKFFCFotFEydOdFmW06dPq2vXrgoODlZoaKh69+4tq9V60/mfeOIJlS1bVn5+fipWrJiefPJJJSQkuCxTVjnbvx999JEaNGigvHnzKm/evIqNjXVov3dEZvbhVq1aqVixYvL19VV4eLi6deum48ePuySPKzjbv/PmzVOtWrUUGhqqgIAAVatWTTNnznRJlsz0b5qkpCRVq1ZNFotFW7ZscUkeV8nM93CaL7/8UhaLRa1bt3ZJlsz0cdp31bWP119/3SV5XMHZ/p0+fXq61+Pr6+uSLJndhxcsWKA6derIz89PefPmddn77QqZ2X/Pnj2rAQMGKDw8XD4+PipTpoxL/pZw9nfc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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "em.plot_distribution_of_scores()" ] }, { "cell_type": "markdown", "id": "93b72120-4578-4d5c-a408-a24ee78bf6cb", "metadata": {}, "source": [ "## Entity Clustering\n", "\n", "It takes as input the similarity graph produced by Entity Matching and partitions it into a set of equivalence clusters, with every cluster corresponding to a distinct real-world object." ] }, { "cell_type": "code", "execution_count": 26, "id": "500d2ef7-7017-4dba-bbea-acdba8abf5b7", "metadata": {}, "outputs": [], "source": [ "from pyjedai.clustering import ConnectedComponentsClustering" ] }, { "cell_type": "code", "execution_count": 27, "id": "aebd9329-3a4b-48c9-bd05-c7bd4aed3ca9", "metadata": {}, "outputs": [], "source": [ "ec = ConnectedComponentsClustering()\n", "clusters = ec.process(pairs_graph, data, similarity_threshold=0.3)" ] }, { "cell_type": "code", "execution_count": 28, "id": "3d2aa574", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "***************************************************************************************************************************\n", " Μethod: Connected Components Clustering\n", "***************************************************************************************************************************\n", "Method name: Connected Components Clustering\n", "Parameters: \n", "Runtime: 0.0894 seconds\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Performance:\n", "\tPrecision: 76.51% \n", "\tRecall: 51.54%\n", "\tF1-score: 61.59%\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "_ = ec.evaluate(clusters)" ] }, { "cell_type": "markdown", "id": "6e44642b-b0d9-4f8d-9fe4-4fca2ad716aa", "metadata": {}, "source": [ "# Workflow with Similarity Joins\n", "\n", "In this notebook we created the bellow archtecture:\n", "\n", "![workflow2-cora.png](https://github.com/AI-team-UoA/pyJedAI/blob/main/documentation/workflow2-cora.png?raw=true)\n", "\n" ] }, { "cell_type": "markdown", "id": "2b07ea13-58cb-498a-949a-4702ea9ee4ce", "metadata": { "tags": [] }, "source": [ "## Data Reading" ] }, { "cell_type": "markdown", "id": "a0b7acf5-32b3-45b1-8347-197dfa869fb9", "metadata": {}, "source": [ "Data is the connecting module of all steps of the workflow" ] }, { "cell_type": "code", "execution_count": 29, "id": "3006b051-8348-4922-a627-56441a1db7b7", "metadata": { "tags": [] }, "outputs": [], "source": [ "from pyjedai.datamodel import Data\n", "d1 = pd.read_csv(\"./../data/der/cora/cora.csv\", sep='|')\n", "gt = pd.read_csv(\"./../data/der/cora/cora_gt.csv\", sep='|', header=None)\n", "attr = ['Entity Id','author', 'title']\n", "data = Data(\n", " dataset_1=d1,\n", " id_column_name_1='Entity Id',\n", " ground_truth=gt,\n", " attributes_1=attr\n", ")" ] }, { "cell_type": "markdown", "id": "b3eedb4c-b86f-4f98-abf2-9d6f7d0271c5", "metadata": {}, "source": [ "## Similarity Joins" ] }, { "cell_type": "code", "execution_count": 37, "id": "afd97b7e-4bf8-4256-b9fc-a301e413e834", "metadata": {}, "outputs": [], "source": [ "from pyjedai.joins import EJoin, TopKJoin" ] }, { "cell_type": "code", "execution_count": 38, "id": "7bc8ba43-b059-4839-8958-0b31fab95e46", "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c518d093ae0047529a0ff47fa6e0696e", "version_major": 2, "version_minor": 0 }, "text/plain": [ "EJoin (jaccard): 0%| | 0/2590 [00:00" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "draw(g)" ] }, { "cell_type": "code", "execution_count": 42, "id": "a4c57244-0c98-4598-8ae2-06cdd0c48385", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "***************************************************************************************************************************\n", " Μethod: Top-K Join\n", "***************************************************************************************************************************\n", "Method name: Top-K Join\n", "Parameters: \n", "\tsimilarity_threshold: 0.25547445255474455\n", "\tK: 20\n", "\tmetric: jaccard\n", "\ttokenization: qgrams\n", "\tqgrams: 3\n", "Runtime: 33.9919 seconds\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Performance:\n", "\tPrecision: 58.34% \n", "\tRecall: 63.75%\n", "\tF1-score: 60.92%\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] }, { "data": { "text/plain": [ "{'Precision %': 58.340434597358325,\n", " 'Recall %': 63.74534450651769,\n", " 'F1 %': 60.923248053392655,\n", " 'True Positives': 10954,\n", " 'False Positives': 7822,\n", " 'True Negatives': 814451.0,\n", " 'False Negatives': 6230}" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "topk_join.evaluate(g)" ] }, { "cell_type": "markdown", "id": "e686ba55-cbbe-4133-8256-fa5339e70720", "metadata": {}, "source": [ "## Entity Clustering" ] }, { "cell_type": "code", "execution_count": 43, "id": "e48627ef-0be6-45dd-b3ba-863818eadbfb", "metadata": {}, "outputs": [], "source": [ "from pyjedai.clustering import ConnectedComponentsClustering" ] }, { "cell_type": "code", "execution_count": 44, "id": "a9d5a28d-79f0-479f-b154-f5f7e3661897", "metadata": {}, "outputs": [], "source": [ "ccc = ConnectedComponentsClustering()\n", "\n", "clusters = ccc.process(g, data)" ] }, { "cell_type": "code", "execution_count": 45, "id": "f95539fe-2569-4569-8929-2f4220f14157", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "***************************************************************************************************************************\n", " Μethod: Connected Components Clustering\n", "***************************************************************************************************************************\n", "Method name: Connected Components Clustering\n", "Parameters: \n", "Runtime: 0.1218 seconds\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n", "Performance:\n", "\tPrecision: 2.05% \n", "\tRecall: 100.00%\n", "\tF1-score: 4.02%\n", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n" ] } ], "source": [ "_ = ccc.evaluate(clusters)" ] }, { "cell_type": "markdown", "id": "778b9b19-0964-4095-a293-a8336fe0607a", "metadata": {}, "source": [ "
\n", "
\n", "K. Nikoletos, J. Maciejewski, G. Papadakis & M. Koubarakis\n", "
\n", "
\n", "Apache License 2.0\n", "
" ] }, { "cell_type": "code", "execution_count": null, "id": "eb71b039-9d16-4e13-a484-d9a64e7b96bb", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.17" } }, "nbformat": 4, "nbformat_minor": 5 }