From 76d032e53e4e84c1c0036daaadeab2821be0730a Mon Sep 17 00:00:00 2001 From: adamjanovsky Date: Fri, 17 Feb 2023 14:11:57 +0100 Subject: more work on PoC reference annotator --- .../reference_annotations/data_preprocessing.ipynb | 57 +- .../cc/reference_annotations/prediction.ipynb | 719 ++++++--------------- 2 files changed, 220 insertions(+), 556 deletions(-) (limited to 'notebooks/cc/reference_annotations') diff --git a/notebooks/cc/reference_annotations/data_preprocessing.ipynb b/notebooks/cc/reference_annotations/data_preprocessing.ipynb index 5e478205..7e6e05ba 100644 --- a/notebooks/cc/reference_annotations/data_preprocessing.ipynb +++ b/notebooks/cc/reference_annotations/data_preprocessing.ipynb @@ -11,22 +11,15 @@ "\n", "1. Recover text segments that surround certificate ID for all references in CC dataset\n", "2. Create a DataFrame `(dgst, cert_id, label, text_segments)` out of the objects\n", - " - two versions, in fact: one with single row per segment, second with all segments from all sources (target, report) merged into single row\n", "3. Clean and dump into csv\n", "4. Check for label noise" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [] - } - ], + "outputs": [], "source": [ "from __future__ import annotations\n", "\n", @@ -37,8 +30,6 @@ "from sec_certs.utils.parallel_processing import process_parallel\n", "import pandas as pd\n", "import json\n", - "from tqdm import tqdm\n", - "\n", "\n", "nlp = spacy.load(\"en_core_web_sm\")\n", "from pathlib import Path\n", @@ -89,7 +80,7 @@ " Builds dataframe with [dgst,cert_id,location,reason,sentences] with references from list of ReferenceRecords.\n", " Reason set to None if not defined. \n", " \"\"\"\n", - " results = process_parallel(ReferenceRecord.get_cert_references_with_sentences, records, max_workers=200, use_threading=False, progress_bar=True)\n", + " results = process_parallel(ReferenceRecord.get_cert_references_with_sentences, records, use_threading=False, progress_bar=True)\n", " return pd.DataFrame.from_records([x.to_pandas_tuple() for x in results], columns=[\"dgst\", \"cert_id\", \"location\", \"label\", \"sentences\"])" ] }, @@ -103,17 +94,16 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - " 69%|██████▉ | 654/944 [22:33<10:00, 2.07s/it]\n", - "100%|██████████| 58/58 [00:07<00:00, 8.26it/s]\n", - "100%|██████████| 944/944 [01:04<00:00, 14.59it/s]\n", - "100%|██████████| 2259/2259 [00:30<00:00, 75.10it/s]\n" + "100%|██████████| 58/58 [00:07<00:00, 8.27it/s]\n", + "100%|██████████| 944/944 [01:06<00:00, 14.12it/s]\n", + "100%|██████████| 2259/2259 [00:32<00:00, 69.22it/s]\n" ] } ], @@ -147,17 +137,21 @@ ] }, { - "cell_type": "code", - "execution_count": 49, + "attachments": {}, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "df = df_labeled.copy()" + "## Process Dataframes and dump two versions into csv\n", + "\n", + "1. Version with `dgst, cert_id, location, single_sentence` as `*_exploded.csv`\n", + "2. Version where all sentences tied to `(dgst, cert_id)` key are merged into `sentences`. Saved as `*_grouped.csv`\n", + "\n", + "*Note*: So far don't work with test dataset" ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -170,28 +164,27 @@ "\n", "split_dct = {**dict.fromkeys(train_digests, \"train\"), **dict.fromkeys(valid_digests, \"valid\")}\n", "\n", - "\n", "# Apply filtering\n", - "df = df.loc[df.sentences.notnull()] # TODO: We should investigate the cases when we match no sentence\n", - "df[\"split\"] = df.dgst.map(split_dct) # Annotate with splits\n", + "# TODO: We should investigate the cases when we match no sentence\n", + "df = df.loc[df.sentences.notnull()] \n", + "df[\"split\"] = df.dgst.map(split_dct)\n", "df = df.loc[df.split.notnull()] # Discard test samples\n", - "df.explode(\"sentences\").to_csv(REPO_ROOT / \"datasets/reference_classification_dataset_exploded.csv\", sep=';', index=False)\n", "\n", "# TODO: Add language detection\n", "\n", "# Aggregate sentences from different sources (target, report) into one row\n", - "df_grouped = df.groupby([\"dgst\", \"cert_id\", \"label\", \"split\"], as_index=False)[\"sentences\"].agg({\"sentences\": lambda x: set.union(*x)})\n", - "df_grouped.to_csv(REPO_ROOT / \"datasets/reference_classification_dataset_merrged.csv\", sep=';', index=False)" + "df = df.groupby([\"dgst\", \"cert_id\", \"label\", \"split\"], as_index=False)[\"sentences\"].agg({\"sentences\": lambda x: set.union(*x)})\n", + "df.to_csv(REPO_ROOT / \"datasets/reference_classification_dataset_merrged.csv\", sep=';', index=False)" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "# Check for label noise\n", - "duplicates_df = df_grouped[df_grouped.duplicated(subset=[\"dgst\", \"cert_id\"], keep=False)]\n", + "# Check for label noise, i.e., search for instances that have different label of a reference.\n", + "duplicates_df = df[df.duplicated(subset=[\"dgst\", \"cert_id\"], keep=False)]\n", "if not duplicates_df.empty:\n", " print(\"Warning, label noise in dataset. I.e. tuples (dgst, cert_id) with inconsistent reason. See `duplicates_df` frame.\")" ] @@ -218,7 +211,7 @@ "orig_nbformat": 4, "vscode": { "interpreter": { - "hash": "a5b8c5b127d2cfe5bc3a1c933e197485eb9eba25154c3661362401503b4ef9d4" + "hash": "a2ed43df31f510d0b358bd0625493376557b0c4d37aa99c09b398809f951b6a5" } } }, diff --git a/notebooks/cc/reference_annotations/prediction.ipynb b/notebooks/cc/reference_annotations/prediction.ipynb index 435fe684..29b63523 100644 --- a/notebooks/cc/reference_annotations/prediction.ipynb +++ b/notebooks/cc/reference_annotations/prediction.ipynb @@ -1,8 +1,20 @@ { "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Prediction of reference annotations in CC Certificates (Raw)\n", + "\n", + "This notebook:\n", + "- loads dataframe of a dataset with `(dgst, cert_id, sentences, label)`\n", + "- Trains a model to classify the sentences related to certificate reference to their common sentiment (meaning of reference)" + ] + }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -14,7 +26,7 @@ } ], "source": [ - "# It is important to first set CUDA_VISIBLE_DEVICES environment variable directly from notebook\n", + "# When on Aura, it is important to first set CUDA_VISIBLE_DEVICES environment variable directly from notebook\n", "# For available GPUs, see https://www.fi.muni.cz/tech/unix/aura.html.cs\n", "\n", "import os\n", @@ -22,140 +34,38 @@ "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"MIG-a5459e6a-b26d-5985-874c-528458a7728b\"\n", "print(os.getenv(\"CUDA_VISIBLE_DEVICES\"))\n", "\n", - "# import spacy\n", - "# from spacy_cld import LanguageDetector\n", - "\n", - "# nlp = spacy.load(\"en_core_web_sm\")\n", - "# language_detector = LanguageDetector()\n", - "# nlp.add_pipe(language_detector)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [], - "source": [ - "# installed packages: setfit\n", - "\n", "import pandas as pd\n", - "from datasets import Dataset, DatasetDict, ClassLabel, Features, Value, Sequence\n", - "from sentence_transformers.losses import CosineSimilarityLoss\n", + "from sec_certs.utils.nlp import prec_recall_metric\n", "from ast import literal_eval\n", - "from setfit import SetFitModel, SetFitTrainer, sample_dataset\n", - "\n", - "from sklearn.metrics import precision_score, recall_score\n", "from pathlib import Path\n", + "from sec_certs.model.reference_classification import ReferenceClassifierTrainer\n", + "import numpy as np\n", "\n", "REPO_ROOT = Path(\"../../../\").resolve()\n", "\n", - "def prec_recall_metric(y_pred, y_test):\n", - " return {\"precision\": precision_score(y_test, y_pred, zero_division=\"warn\", average=\"micro\"), \"recall\": recall_score(y_test, y_pred, zero_division=\"warn\", average=\"micro\")}\n", "\n", - "def predict_and_fill_df(model, df, train_dataset) -> pd.DataFrame:\n", - " label_mapping = {index: x for index, x in enumerate(train_dataset.features[\"label\"].names)}\n", + "def predict_and_fill_df(clf, df, label_mapping):\n", + " \"\"\"\n", + " Given the classifier, dataframe and label mapping, will populate dataframe with predictions for simple inspection.\n", + " \"\"\"\n", " df_new = df.copy()\n", - "\n", - " y_train_proba = model.predict_proba(df_new.sentences.tolist())\n", - " df_new[\"y_proba\"] = y_train_proba.tolist()\n", - " df_new[\"y_pred\"] = df_new.y_proba.map(lambda x: label_mapping[x.index(max(x))])\n", - " df_new[\"correct\"] = df_new.y_pred == df_new.label\n", - " \n", - " return df_new\n" + " y_proba = clf.predict_proba(df_new.sentences)\n", + " df_new[\"y_proba\"] = y_proba\n", + " df_new[\"y_pred\"] = df_new.y_proba.map(lambda x: label_mapping[np.argmax(x)])\n", + " df_new[\"correct\"] = df_new.label == df_new.y_pred\n", + " return df_new" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ - "# EXPLODED variant\n", - "# # Prepare dataset\n", - "\n", - "# df = pd.read_csv(REPO_ROOT / \"datasets/reference_classification_dataset_exploded.csv\", sep=\";\")\n", - "# df = df.loc[(df.label.notnull()) & ((df.location == \"report\"))]\n", - "\n", - "# # # Get language of the sentence, quite unreliable for the moment\n", - "# # df[\"lang\"] = df.sentence.map(lambda x: nlp(x)._.languages)\n", - "# # df[\"is_en\"] = df.lang.map(lambda x: x == [\"en\"])\n", - "\n", - "# # # Take suitable subset of the dataframe\n", - "# # df = df.loc[df.is_en] # only english\n", - "\n", - "# df = df.loc[df.label.isin({\"COMPONENT_USED\", \"BASIS_OF_RECERTIFICATION\", \"BASIS_FOR\"})] # only the most popular labels\n", - "\n", - "# # Split into train/valid\n", - "# df_train = df.loc[df.split == \"train\"].drop(columns=\"split\")\n", - "# df_valid = df.loc[df.split == \"valid\"].drop(columns=\"split\")\n", - "\n", - "# dataset_features = Features(\n", - "# {\n", - "# \"dgst\": Value(\"string\"),\n", - "# \"cert_id\": Value(\"string\"),\n", - "# \"location\": Value(\"string\"),\n", - "# \"sentences\": Value(\"string\"),\n", - "# \"label\": ClassLabel(names=list(df.label.unique())),\n", - "# }\n", - "# )\n", - "# train_dataset = Dataset.from_pandas(df_train, features=dataset_features, split=\"train\", preserve_index=False)\n", - "# valid_dataset = Dataset.from_pandas(df_valid, features=dataset_features, split=\"validation\", preserve_index=False)\n", - "\n", - "# dataset = DatasetDict()\n", - "# dataset['train'] = train_dataset\n", - "# dataset['validation'] = valid_dataset\n", - "\n", - "# train_dataset = sample_dataset(dataset[\"train\"], label_column=\"label\", num_samples=10)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "099029c554974aa1abdd9660eb8e2ece", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/1 [00:00, ?ba/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4b605cedf332432e8c0e055b1eb4aa54", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/1 [00:00, ?ba/s]" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# GROUPED variant\n", "# Prepare dataset\n", "\n", "df = pd.read_csv(REPO_ROOT / \"datasets/reference_classification_dataset_merged.csv\", sep=\";\")\n", "df = df.loc[(df.label.notnull())]\n", - "\n", - "# # Get language of the sentence, quite unreliable for the moment\n", - "# df[\"lang\"] = df.sentence.map(lambda x: nlp(x)._.languages)\n", - "# df[\"is_en\"] = df.lang.map(lambda x: x == [\"en\"])\n", - "\n", - "# # Take suitable subset of the dataframe\n", - "# df = df.loc[df.is_en] # only english\n", - "\n", "df = df.loc[df.label.isin({\"COMPONENT_USED\", \"BASIS_OF_RECERTIFICATION\", \"BASIS_FOR\"})] # only the most popular labels\n", "df.sentences = df.sentences.map(lambda x: list(literal_eval(x)))\n", "\n", @@ -163,27 +73,13 @@ "df_train = df.loc[df.split == \"train\"].drop(columns=\"split\")\n", "df_valid = df.loc[df.split == \"valid\"].drop(columns=\"split\")\n", "\n", - "dataset_features = Features(\n", - " {\n", - " \"dgst\": Value(\"string\"),\n", - " \"cert_id\": Value(\"string\"),\n", - " \"sentences\": Sequence(feature=Value(\"string\")),\n", - " \"label\": ClassLabel(names=list(df.label.unique())),\n", - " }\n", - ")\n", - "train_dataset = Dataset.from_pandas(df_train, features=dataset_features, split=\"train\", preserve_index=False)\n", - "valid_dataset = Dataset.from_pandas(df_valid, features=dataset_features, split=\"validation\", preserve_index=False)\n", - "\n", - "dataset = DatasetDict()\n", - "dataset['train'] = train_dataset\n", - "dataset['validation'] = valid_dataset\n", - "\n", - "train_dataset = sample_dataset(dataset[\"train\"], label_column=\"label\", num_samples=10)\n" + "# Use just few examples for learning\n", + "df_train = df_train.sample(n=10)" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -210,83 +106,77 @@ "
| \n", + " | dgst | \n", + "cert_id | \n", + "label | \n", + "sentences | \n", + "y_proba | \n", + "y_pred | \n", + "correct | \n", "|||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12 | \n", - "29964f32c68b0ce8 | \n", - "BSI-DSZ-CC-0519-V3-2021 | \n", - "report | \n", - "BASIS_OF_RECERTIFICATION | \n", - "As the evaluation work performed for this cert... | \n", - "[0.8982407935537878, 0.1017592064462122] | \n", + "1 | \n", + "0c7ef6c32cbdee47 | \n", + "BSI-DSZ-CC-1074-2019 | \n", + "BASIS_FOR | \n", + "[The BAC+PACE configuration is subject of the ... | \n", + "[0.9330686268852108, 0.06693137311478929] | \n", "COMPONENT_USED | \n", "False | \n", "
| 22 | \n", - "c1d88ce9dadd7d2d | \n", - "BSI-DSZ-CC-0312-2005 | \n", - "report | \n", - "COMPONENT_USED | \n", - "[13] Certification Report BSI-DSZ-CC-0312-2005... | \n", - "[0.8947294027870802, 0.1052705972129198] | \n", - "COMPONENT_USED | \n", - "True | \n", - "||||||
| 23 | \n", - "c1d88ce9dadd7d2d | \n", - "BSI-DSZ-CC-0312-2005 | \n", - "report | \n", - "COMPONENT_USED | \n", - "P5CT072V0N refer to the certification report B... | \n", - "[0.900841506996804, 0.09915849300319597] | \n", - "COMPONENT_USED | \n", - "True | \n", - "||||||
| 28 | \n", - "238f8edc5eda1358 | \n", - "BSI-DSZ-CC-0222-2003 | \n", - "report | \n", + "2 | \n", + "0e22fe4e4e58faf4 | \n", + "BSI-DSZ-CC-1052-V4-2021 | \n", "BASIS_OF_RECERTIFICATION | \n", - "This is a re-\\ncertification based on BSI-DSZ-... | \n", - "[0.6922405130591214, 0.3077594869408786] | \n", + "[basierend auf BSI-DSZ-CC-1052-V4-2021.] | \n", + "[0.7070543956916182, 0.2929456043083818] | \n", "COMPONENT_USED | \n", "False | \n", "|
| 29 | \n", + "7 | \n", "238f8edc5eda1358 | \n", "BSI-DSZ-CC-0222-2003 | \n", - "report | \n", - "BASIS_OF_RECERTIFICATION | \n", - "This certification is a re-certification of BS... | \n", - "[0.7146859285928153, 0.2853140714071847] | \n", - "COMPONENT_USED | \n", - "False | \n", - "|||||
| 31 | \n", - "a6fac58198296194 | \n", - "BSI-DSZ-CC-0555-2009 | \n", - "report | \n", "BASIS_OF_RECERTIFICATION | \n", - "Specific results from the evaluation process\\n... | \n", - "[0.9003949217128049, 0.09960507828719516] | \n", + "[This certification is a re-certification of B... | \n", + "[0.5998535578550636, 0.4001464421449364] | \n", "COMPONENT_USED | \n", "False | \n", "||||
| 32 | \n", - "a6fac58198296194 | \n", - "BSI-DSZ-CC-0555-2009 | \n", - "report | \n", + "8 | \n", + "29964f32c68b0ce8 | \n", + "BSI-DSZ-CC-0519-V3-2021 | \n", "BASIS_OF_RECERTIFICATION | \n", - "As the evaluation work performed for this cert... | \n", - "[0.8962471709210816, 0.10375282907891832] | \n", + "[This is a re-certification based on BSI-DSZ-C... | \n", + "[0.8727371952470533, 0.12726280475294682] | \n", "COMPONENT_USED | \n", "False | \n", "|
| 33 | \n", + "13 | \n", "a6fac58198296194 | \n", "BSI-DSZ-CC-0555-2009 | \n", - "report | \n", "BASIS_OF_RECERTIFICATION | \n", - "This is a re-certification\\nbased on BSI-DSZ-C... | \n", - "[0.6928894855518116, 0.3071105144481884] | \n", - "COMPONENT_USED | \n", - "False | \n", - "|||||
| 40 | \n", - "0c7ef6c32cbdee47 | \n", - "BSI-DSZ-CC-1074-2019 | \n", - "report | \n", - "BASIS_FOR | \n", - "The BAC+PACE configuration is subject of the s... | \n", - "[0.8997694315622796, 0.1002305684377204] | \n", + "[Specific results from the evaluation process\\... | \n", + "[0.8670438280210987, 0.13295617197890133] | \n", "COMPONENT_USED | \n", "False | \n", "||||
| 41 | \n", - "0c7ef6c32cbdee47 | \n", - "BSI-DSZ-CC-1074-2019 | \n", - "report | \n", - "BASIS_FOR | \n", - "The further security mechanism Basic Access Co... | \n", - "[0.8923570789488144, 0.10764292105118559] | \n", - "COMPONENT_USED | \n", - "False | \n", - "||||||
| 42 | \n", - "0c7ef6c32cbdee47 | \n", - "BSI-DSZ-CC-1074-2019 | \n", - "report | \n", - "BASIS_FOR | \n", - "[14] Certification Report BSI-DSZ-CC-1074-2019... | \n", - "[0.9007422537659316, 0.09925774623406838] | \n", - "COMPONENT_USED | \n", - "False | \n", - "||||||
| 43 | \n", - "0c7ef6c32cbdee47 | \n", - "ANSSI-CC-2017/61 | \n", - "report | \n", - "COMPONENT_USED | \n", - "For details\\nconcerning the CC evaluation of t... | \n", - "[0.8933002244736725, 0.10669977552632742] | \n", - "COMPONENT_USED | \n", - "True | \n", - "||||||
| 44 | \n", - "0c7ef6c32cbdee47 | \n", - "ANSSI-CC-2017/61 | \n", - "report | \n", - "COMPONENT_USED | \n", - "For development and production sites regarding... | \n", - "[0.9000976545847758, 0.0999023454152242] | \n", - "COMPONENT_USED | \n", - "True | \n", - "||||||
| 45 | \n", - "0c7ef6c32cbdee47 | \n", - "ANSSI-CC-2017/61 | \n", - "report | \n", - "COMPONENT_USED | \n", - "Elixir-2 Project, Certification ID ANSSI-CC-20... | \n", - "[0.8997425549440855, 0.10025744505591448] | \n", - "COMPONENT_USED | \n", - "True | \n", - "||||||
| 46 | \n", - "0c7ef6c32cbdee47 | \n", - "ANSSI-CC-2017/61 | \n", - "report | \n", - "COMPONENT_USED | \n", - "® X – Security Target for\\ncomposition; STMicr... | \n", - "[0.8976230487254611, 0.10237695127453893] | \n", - "COMPONENT_USED | \n", - "True | \n", - "||||||
| 47 | \n", - "0c7ef6c32cbdee47 | \n", - "ANSSI-CC-2017/61 | \n", - "report | \n", - "COMPONENT_USED | \n", - "[12] Rapport de certification ANSSI-CC-2017/61... | \n", - "[0.8939784357781945, 0.10602156422180552] | \n", - "COMPONENT_USED | \n", - "True | \n", - "