diff --git a/.gitignore b/.gitignore index 7c44366..4ed315d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,164 @@ lightning_logs/ +.pkl_cache/ + + + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + + +# vs code +.vscode +*.bin + +.DS_Store diff --git a/mjc_notes.md b/mjc_notes.md index a6a6dba..58de81d 100644 --- a/mjc_notes.md +++ b/mjc_notes.md @@ -20,3 +20,35 @@ pip install -r requirements.txt - [ ] BUG: for some reason the model it not working as zero shot - OK I don't think it's the prompt? it must be my tokens? Lets make a scratch notebook to try and just load llama correctly - [ ] also I would like to eval on some custom deceptive statements + +# 2023-05-25 17:07:37 + +Hmm is sigmoid a good idea? + +Lets just get hideen states once + +- [ ] make the answer good? maybe with one shot +- [ ] fix prompt. so we have qeustion, true answer + + +Start again: +- [ ] the model can deceive (test) or not (train) +- [ ] the model can give an answer both in generate and forward +- [x] we can get hidden states (cached) + + +What is each step actually doing? +- we are finding a latent space direction that correspond to truth, sure +- but truth of what? what it's read, or what it's generating!?! +- what's it read presumably. but that's not what we are interested in. We are interested in the truth of what it generated which is quite different +- so how to we get the truth of what it generated? + + +How about human? well you give me an article, and ask me to complete is. I notice a lie in the article? I decide to lie to you as well?. + +Now you give me extended article to another ai, and ask if there is a lie in there? that might work +but we would rather know if the generated thing is true, from the mind of the one who generated it + +so that means we actually need the hidden states DURING GENERATION! + +now generation is slow. so we should make it generate just a y/n. diff --git a/notebooks/001_mjc_CCS.ipynb b/notebooks/001_mjc_CCS.ipynb deleted file mode 100644 index 30eb6f2..0000000 --- a/notebooks/001_mjc_CCS.ipynb +++ /dev/null @@ -1,4772 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Let's implement CCS from scratch.\n", - "This will deliberately be a simple (but less efficient) implementation to make everything as clear as possible." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:54:44.191549Z", - "start_time": "2023-05-20T01:54:41.824251Z" - } - }, - "outputs": [], - "source": [ - "from tqdm.auto import tqdm\n", - "import copy\n", - "import numpy as np\n", - "import pandas as pd\n", - "\n", - "import torch\n", - "import torch.nn as nn\n", - "import torch.nn.functional as F\n", - "\n", - "\n", - "\n", - "import os\n", - "# os.environ[\"HF_DATASETS_OFFLINE\"] = \"0\"\n", - "from datasets import load_dataset\n", - "import datasets\n", - "from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, AutoModelForMaskedLM, AutoModelForCausalLM\n", - "from sklearn.linear_model import LogisticRegression\n", - "\n", - "import lightning.pytorch as pl\n", - "from dataclasses import dataclass\n", - "from torch.utils.data import random_split, DataLoader, TensorDataset\n", - "from transformers.models.auto.modeling_auto import AutoModel\n", - "# from scipy.stats import zscore\n", - "from sklearn.metrics import f1_score, roc_auc_score, accuracy_score\n", - "from sklearn.preprocessing import RobustScaler\n", - "import gc\n", - "\n", - "import os" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:54:44.196607Z", - "start_time": "2023-05-20T01:54:44.193276Z" - } - }, - "outputs": [], - "source": [ - "# from transformers import LlamaTokenizer, LlamaForCausalLM\n", - "from transformers import LlamaForCausalLM, LlamaTokenizer" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:26.440636Z", - "start_time": "2023-05-20T01:54:44.197666Z" - } - }, - "outputs": [], - "source": [ - "# Here are a few different model options you can play around with:\n", - "model_name = \"deberta\"\n", - "model_name = \"gpt-j\"\n", - "# model_name = \"t5\"\n", - "model_name = \"llama\"\n", - "model_name = \"alpaca\"\n", - "finetuned = None\n", - "\n", - "model_options = dict(\n", - " device_map=\"auto\", \n", - " load_in_8bit=True,\n", - " torch_dtype=torch.float16,\n", - ")\n", - "\n", - "\n", - "if model_name == \"deberta\":\n", - " model_type = \"encoder\"\n", - " tokenizer = AutoTokenizer.from_pretrained(\"microsoft/deberta-v2-xxlarge\")\n", - " model = AutoModelForMaskedLM.from_pretrained(\"microsoft/deberta-v2-xxlarge\", **model_options)\n", - "elif model_name == \"gpt-j\":\n", - " model_type = \"decoder\"\n", - " tokenizer = AutoTokenizer.from_pretrained(\"EleutherAI/gpt-j-6B\")\n", - " model = AutoModelForCausalLM.from_pretrained(\"EleutherAI/gpt-j-6B\", **model_options)\n", - "elif model_name == \"t5\":\n", - " model_type = \"encoder_decoder\"\n", - " tokenizer = AutoTokenizer.from_pretrained(\"t5-11b\")\n", - " model = AutoModelForSeq2SeqLM.from_pretrained(\"t5-11b\", **model_options)\n", - " model.parallelize() # T5 is big enough that we may need to run it on multiple GPUs\n", - "elif (\"llama\" in model_name) or (\"alpaca\" in model_name):\n", - " # https://github.com/deep-diver/LLM-As-Chatbot/blob/216abb559d00a0555f41a1426ac9db6c1abc24f3/models/alpaca.py\n", - " \n", - " # working\n", - " model_repo = \"Neko-Institute-of-Science/LLaMA-7B-HF\"\n", - " lora_repo = \"chansung/gpt4-alpaca-lora-7b\"\n", - " \n", - " model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", - " lora_repo = \"chansung/gpt4-alpaca-lora-13b\"\n", - " \n", - " # model_repo = \"decapoda-research/llama-7b-hf\"\n", - " # lora_repo = \"tloen/alpaca-lora-7b\"\n", - " \n", - " \n", - " # model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", - " # lora_repo = \"LLMs/Alpaca-LoRA-13B-elina\"\n", - " \n", - " # # model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", - " # model_repo = \"decapoda-research/llama-13b-hf\"\n", - " # lora_repo = \"chansung/alpaca-lora-13b\"\n", - " # lora_repo = \"chansung/gpt4-alpaca-lora-13b\"\n", - " \n", - " \n", - " # model_repo = \"TheBloke/OpenAssistant-SFT-7-Llama-30B-HF\"\n", - " # lora_repo = None\n", - " \n", - " \n", - " # model_repo = \"TheBloke/Wizard-Vicuna-13B-Uncensored-HF\"\n", - " model_type = \"decoder\"\n", - " tokenizer = LlamaTokenizer.from_pretrained(model_repo)\n", - " model = LlamaForCausalLM.from_pretrained(model_repo, **model_options)\n", - " \n", - " if lora_repo is not None:\n", - " # https://github.com/tloen/alpaca-lora/blob/main/generate.py#L40\n", - " from peft import PeftModel\n", - " model = PeftModel.from_pretrained(\n", - " model, \n", - " lora_repo, \n", - " torch_dtype=torch.float16,\n", - " device_map='auto'#{'': 0}\n", - " )\n", - " \n", - " # tokenizer.pad_token = 0\n", - " # tokenizer.padding_side = \"left\"\n", - "else:\n", - " raise NotADirectoryError(model_name)\n", - "tokenizer, model" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:26.469934Z", - "start_time": "2023-05-20T01:56:26.444768Z" - } - }, - "outputs": [], - "source": [ - "# get the tokens for 0 and 1, we will use these later...\n", - "id_0, id_1 = tokenizer('n')['input_ids'][-1], tokenizer('y')['input_ids'][-1]\n", - "id_0, id_1" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "start_time": "2023-05-07T01:08:20.635Z" - } - }, - "source": [ - "## Dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-19T04:02:13.892383Z", - "start_time": "2023-05-19T04:02:13.873377Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:27.020627Z", - "start_time": "2023-05-20T01:56:26.470949Z" - }, - "scrolled": false - }, - "outputs": [], - "source": [ - "# debug\n", - "datasets.logging.set_verbosity_info()\n", - "\n", - "# Let's just try IMDB for simplicity\n", - "data = load_dataset(\"amazon_polarity\")['test']\n", - "# data = load_dataset(\"/home/wassname/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc/amazon_polarity-train-00003-of-00004.arrow\")\n", - "data" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:05.461369Z", - "start_time": "2023-05-20T02:25:05.458241Z" - } - }, - "outputs": [], - "source": [ - "def format_imdb(text, label):\n", - " return f\"\"\"Review: \"I think this is a lovely family movie. There are plenty of hilarious scenes and heart-warming moments to be had throughout the movie. The actors are great and the effects well executed throughout. Danny Glover plays George Knox who manages the terrible baseball team 'The Angels' and is great throughout the film. Also fantastic are the young actors Joseph Gordon-Levitt and Milton Davis Jr. Christopher Lloyd is good as Al 'The Angel' and the effects are great in this top notch Disney movie. A touching and heart-warming movie which everyone should enjoy.\"\n", - "Question: Is this review positive? \n", - "Answer: 1\n", - "---\n", - "Review: \"{text}\"\n", - "Question: Is this review {'positive' if label else 'negative'}?\n", - "Answer: \n", - "\"\"\"\n", - "\n", - "def format_imdbs(texts, labels):\n", - " return [format_imdb(t, labels) for t in texts]\n", - "\n", - "print(format_imdb(\"The movie was the worst.... not!\", 0))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "def format_imdb(input, label, prefix=1):\n", - " s_prefix = \"Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\\n\\n\" if prefix else \"\"\n", - " q = f\"Is this review {'positive' if label else 'negative'} (y/n)?\"\n", - " if label==1:\n", - " l = \"y\"\n", - " elif label==0:\n", - " l=\"n\"\n", - " else:\n", - " l = \"?\"\n", - " alpaca_prompt = f'{s_prefix}### Instruction:\\n{q}\"\\n\\n### Input:\\n\\n\"{input}\"\\n\\n### Response: {l}'\n", - " return alpaca_prompt" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def format_imbd_multishot(input, label):\n", - " a = format_imdb(\"Although Hypnotic isn't without glimmers of inspiration, the ultimate effect of this often clunky crime caper will be to leave you feeling rather sleepy.\", 0, prefix=1)\n", - " b = format_imdb(\"Although Hypnotic isn't without it's downsides, the ultimate effect of this often funny crime caper will be to leave you feeling rather fascinated.\", 1, prefix=0)\n", - " c = format_imdb(input, \"\", prefix=0)\n", - " return \"\\n\\n\".join([a, b, c])\n", - "\n", - "text=\"The movie was the worst.... not!\"\n", - "print(format_imbd_multishot(text, 0))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# def format_imdb(text, label):\n", - "# return f\"\"\"Below is an instruction that describes a task. Write a response that appropriately completes the request.\n", - "\n", - "# ### Instruction:\\nQuestion: Is this review {'positive' if label else 'negative'}?\\n\\n\n", - "\n", - "# Review: \"I think this is a lovely family movie. There are plenty of hilarious scenes and heart-warming moments to be had throughout the movie. The actors are great and the effects well executed throughout. Danny Glover plays George Knox who manages the terrible baseball team 'The Angels' and is great throughout the film. Also fantastic are the young actors Joseph Gordon-Levitt and Milton Davis Jr. Christopher Lloyd is good as Al 'The Angel' and the effects are great in this top notch Disney movie. A touching and heart-warming movie which everyone should enjoy.\"\n", - "# Question: Is this review positive? \n", - "# Answer: 1\n", - "# ---\n", - "# Review: \"{text}\"\n", - "# Question: Is this review {'positive' if label else 'negative'}?\n", - "# Answer: \n", - "\n", - "# ### Response:\\n\n", - "# \"\"\"\n", - "\n", - "# def format_imdbs(texts, labels):\n", - "# return [format_imdb(t, labels) for t in texts]\n", - "\n", - "# print(format_imdb(\"The movie was the worst.... not!\", 0))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:05.902898Z", - "start_time": "2023-05-20T02:25:05.898745Z" - } - }, - "outputs": [], - "source": [ - "# tokens\n", - "len(tokenizer(format_imdb(\"The movie was the worst.... not!\", 0))['input_ids'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## First check models text output" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:45.805378Z", - "start_time": "2023-05-20T02:25:45.800064Z" - } - }, - "outputs": [], - "source": [ - "from transformers import GenerationConfig, LlamaForCausalLM, LlamaTokenizer\n", - "# from https://github.com/deep-diver/LLM-As-Chatbot/blob/main/configs/response_configs/default.yaml\n", - "generation_config = GenerationConfig(\n", - " temperature=0.95,\n", - " top_p=0.9,\n", - " top_k=50,\n", - " num_beams=1,\n", - " use_cache=True,\n", - " repetition_penalty=1.2,\n", - " max_new_tokens=512,\n", - " do_sample=True,\n", - ")\n", - "\n", - "\n", - "def get_output(model, tokenizer, input_text, add_bos_token=False, truncation_length=400):\n", - " \"\"\"\n", - " Given a decoder model and some text, gets the hidden states (in a given layer, by default the last) on that input text\n", - "\n", - " Returns a numpy array of shape (hidden_dim,)\n", - " \"\"\"\n", - " if not isinstance(input_text, list):\n", - " input_text = [input_text]\n", - " # tokenize (adding the EOS token this time)\n", - " # input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# input_text = [i[-1000:] for i in input_text]\n", - " input_ids = tokenizer(input_text, \n", - " return_tensors=\"pt\",\n", - "# truncation=True, \n", - "# padding=True,\n", - "# max_length=600,\n", - " add_special_tokens=True,\n", - " ).input_ids.to(model.device)\n", - "# print('input_ids', input_ids.shape)\n", - "\n", - " # remove bos token? https://github.com/oobabooga/text-generation-webui/blob/1b52bddfcc70d2db88257d36f1c6d182573588c4/modules/text_generation.py#L36\n", - " if not add_bos_token and input_ids[0][0] == tokenizer.bos_token_id:\n", - " input_ids = input_ids[:, 1:]\n", - " # print('removed')\n", - "\n", - "\n", - " # Llama adds this extra token when the first character is '\\n', and this\n", - " # compromises the stopping criteria, so we just remove it\n", - " if type(tokenizer) is LlamaTokenizer and input_ids[0][0] == 29871:\n", - " # print('removed extra \\n token')\n", - " input_ids = input_ids[:, 1:]\n", - " \n", - " # Handling truncation\n", - " if truncation_length is not None:\n", - " input_ids = input_ids[:, -truncation_length:]\n", - "\n", - "\n", - " # generate_params = {\n", - " # \"input_ids\": input_ids,\n", - " # \"generation_config\": generation_config,\n", - " # \"return_dict_in_generate\": True,\n", - " # \"output_scores\": True,\n", - " # \"max_new_tokens\": max_new_tokens,\n", - " # }\n", - " # forward pass\n", - " with torch.no_grad():\n", - " generation_output = model.generate(\n", - " input_ids=input_ids, generation_config=generation_config,\n", - " return_dict_in_generate=True,\n", - " output_scores=True,\n", - " )\n", - " s = generation_output.sequences[0]\n", - " # print(s)\n", - " \n", - " text_q = tokenizer.batch_decode(input_ids, skip_special_tokens=False)\n", - " text_ans = tokenizer.decode(s, skip_special_tokens=False)#, skip_prompt=True, skip_special_tokens=True)\n", - " print(text_q[0])\n", - " # print('-'*40+'answ'+'-'*40)\n", - " print(text_ans)\n", - " return text_ans\n", - " \n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:54:09.323908Z", - "start_time": "2023-05-20T01:54:09.321888Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:46.260946Z", - "start_time": "2023-05-20T02:25:46.258734Z" - } - }, - "outputs": [], - "source": [ - "tokenizer.pad_token_id=0\n", - "tokenizer.padding_side = \"left\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:46.401304Z", - "start_time": "2023-05-20T02:25:46.398898Z" - } - }, - "outputs": [], - "source": [ - "idx = 1\n", - "text, true_label = data[idx][\"content\"], data[idx][\"label\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:53.587709Z", - "start_time": "2023-05-20T02:25:46.528753Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "input_text = [format_imdb(text, 0)]\n", - "# input_text = [i + tokenizer.eos_token for i in input_text]\n", - "s = get_output(model, tokenizer, input_text)\n", - "# s[0]\n", - "s" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# input_text = [format_imbd_multishot(text, 0)]\n", - "# # input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# s = get_output(model, tokenizer, input_text)\n", - "# # s[0]\n", - "# s" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(s[0])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Write code for extracting hidden states given a model and text. \n", - "How we do this exactly will depend on the type of model." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:49.742646Z", - "start_time": "2023-05-20T02:27:49.737461Z" - } - }, - "outputs": [], - "source": [ - "\n", - "\n", - "def get_decoder_hidden_states(model, tokenizer, input_text, layers=[2, -2], add_bos_token=False, truncation_length=400):\n", - " \"\"\"\n", - " Given a decoder model and some text, gets the hidden states (in a given layer, by default the last) on that input text\n", - "\n", - " Returns a numpy array of shape (hidden_dim,)\n", - " \"\"\"\n", - " if not isinstance(input_text, list):\n", - " input_text = [input_text]\n", - " # tokenize (adding the EOS token this time)\n", - " # input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# input_text = [i[-1000:] for i in input_text]\n", - " input_ids = tokenizer(input_text, \n", - " return_tensors=\"pt\",\n", - "# truncation=True, \n", - " padding=True,\n", - "# max_length=600,\n", - " add_special_tokens=True,\n", - " ).input_ids.to(model.device)\n", - "# print('input_ids', input_ids.shape)\n", - "\n", - "\n", - " # remove bos token? https://github.com/oobabooga/text-generation-webui/blob/1b52bddfcc70d2db88257d36f1c6d182573588c4/modules/text_generation.py#L36\n", - " if not add_bos_token and input_ids[0][0] == tokenizer.bos_token_id:\n", - " input_ids = input_ids[:, 1:]\n", - "\n", - "\n", - " # Llama adds this extra token when the first character is '\\n', and this\n", - " # compromises the stopping criteria, so we just remove it\n", - " if type(tokenizer) is LlamaTokenizer and input_ids[0][0] == 29871:\n", - " # print('removed extra \\n token')\n", - " input_ids = input_ids[:, 1:]\n", - " \n", - " # Handling truncation\n", - " if truncation_length is not None:\n", - " input_ids = input_ids[:, -truncation_length:]\n", - "\n", - " # forward pass\n", - " with torch.no_grad():\n", - " output = model(input_ids, \n", - " output_hidden_states=True,\n", - "# , output_attentions=True\n", - " use_cache=True,\n", - " \n", - " )\n", - " \n", - " # the output is large, so we will just select what we want 1) the first token with[:, 0]\n", - " # 2) selected layers with [layers]\n", - "# output['attentions'] = [output['attentions'][i] for i in layers]\n", - "# output['attentions'] = [v.detach().cpu()[:, -1] for v in output['attentions']]\n", - "# output['attentions'] = torch.concat(output['attentions'])\n", - " \n", - " \n", - " # dims [Batch, Token, Probs?]\n", - " output['hidden_states'] = torch.stack([output['hidden_states'][i] for i in layers], 1).detach().cpu()\n", - " # dims [Batch, Layers, Seq_Token, Probs?] e.g. torch.Size([3, 2, 284, 4096])\n", - " \n", - " output['hidden_states'] = output['hidden_states'][:, :, -1] # take just the last token so they are same size\n", - " \n", - " # dims [Batch, ?, Output_Tokens] e.g. torch.Size([3, 284, 32000])\n", - " o = output['logits'].detach().cpu().float().softmax(-1)\n", - " \n", - " # text_q = [tokenizer.decode(oo) for oo in input_ids]\n", - " # tokenizer.batch\n", - " # text_ans = [tokenizer.decode(oo) for oo in o.argmax(-1)]\n", - " text_q = tokenizer.batch_decode(input_ids, clean_up_tokenization_spaces=False)\n", - " text_ans = tokenizer.batch_decode(o.argmax(-1), clean_up_tokenization_spaces=False)\n", - "\n", - " nth_place = 1\n", - " prob_0, prob1 = o[:, nth_place][:, [id_0, id_1]].T # get the prob of 0 vs 1 in nth place in answer\n", - " output['ans'] = (prob1/(prob_0+prob1))\n", - " return dict(hidden_states=output['hidden_states'], ans=output['ans'], text_ans=text_ans, text_q=text_q\n", - "# , attentions=output['attentions']\n", - " )\n", - "\n", - "def get_hidden_states(model, tokenizer, input_text, layers=[2, -2], model_type=\"encoder\"):\n", - " fn = {\n", - " \"decoder\": get_decoder_hidden_states}[model_type]\n", - "\n", - " return fn(model, tokenizer, input_text, layers=layers)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.048590Z", - "start_time": "2023-05-20T02:27:50.046873Z" - } - }, - "outputs": [], - "source": [ - "# input_text = [format_imdb(text, 0)]\n", - "# input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# input_ids = tokenizer(input_text, \n", - "# return_tensors=\"pt\",\n", - "# truncation=True, \n", - "# padding=True,\n", - "# max_length=300).input_ids.to(model.device)\n", - "# print(tokenizer.decode(input_ids[0]))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.695875Z", - "start_time": "2023-05-20T02:27:50.205135Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "# unit test\n", - "idx = 0\n", - "text, true_label = data[idx][\"content\"], data[idx][\"label\"]\n", - "neg_hs = get_hidden_states(model, tokenizer, format_imdb(text, 0), model_type=model_type)\n", - "pos_hs = get_hidden_states(model, tokenizer, format_imdb(text, 1), model_type=model_type)\n", - "neu_hs = get_hidden_states(model, tokenizer, format_imdb(text, \"\"), model_type=model_type)\n", - "# neg_hs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.700337Z", - "start_time": "2023-05-20T02:27:50.697307Z" - } - }, - "outputs": [], - "source": [ - "print('-'*40+'input'+'-'*40)\n", - "print(neg_hs['text_q'][0])\n", - "print('-'*40+'answ'+'-'*40)\n", - "print(neg_hs['text_ans'][0])\n", - "print('='*80)\n", - "print('-'*40+'input'+'-'*40)\n", - "print(pos_hs['text_q'][0])\n", - "print('-'*40+'answ'+'-'*40)\n", - "print(pos_hs['text_ans'][0])\n", - "print('-'*80)\n", - "print('='*80)\n", - "print('-'*40+'input'+'-'*40)\n", - "print(neu_hs['text_q'][0])\n", - "print('-'*40+'answ'+'-'*40)\n", - "print(neu_hs['text_ans'][0])\n", - "print('-'*80)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.723482Z", - "start_time": "2023-05-20T02:27:50.701252Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "# # unit tests\n", - "# idx = 0\n", - "# n=10\n", - "# batch_size=3\n", - "# ds_subset = data['test'].shuffle(42).select(range(n))\n", - "# dl = DataLoader(ds_subset, batch_size=batch_size, shuffle=True)\n", - "# batch = next(iter(dl))\n", - "\n", - "# texts, true_labels = batch[\"content\"], batch[\"label\"]\n", - "# neg_hs = get_hidden_states(model, tokenizer, format_imdbs(texts, 0), model_type=model_type)\n", - "# neg_hs\n", - "# for k,v in neg_hs.items():\n", - "# print(k, v.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Now let's write code for formatting data and for getting all the hidden states." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:04.246539Z", - "start_time": "2023-05-20T02:28:04.242460Z" - } - }, - "outputs": [], - "source": [ - "\n", - "\n", - "def get_hidden_states_many_examples(model, tokenizer, data, model_type, n=100, layers=[2, -2], batch_size=3):\n", - " \"\"\"\n", - " Given an encoder-decoder model, a list of data, computes the contrast hidden states on n random examples.\n", - " Returns numpy arrays of shape (n, hidden_dim) for each candidate label, along with a boolean numpy array of shape (n,)\n", - " with the ground truth labels\n", - " \n", - " This is deliberately simple so that it's easy to understand, rather than being optimized for efficiency\n", - " \"\"\"\n", - " # setup\n", - " model.eval()\n", - " \n", - " res = []\n", - " \n", - " ds_subset = data.shuffle(42).select(range(n))\n", - " dl = DataLoader(ds_subset, batch_size=batch_size, shuffle=True)\n", - " for batch in tqdm(dl):\n", - " text, true_label = batch[\"content\"], batch[\"label\"]\n", - " neg = get_hidden_states(model, tokenizer, format_imdbs(text, 0), model_type=model_type, layers=layers)\n", - " pos = get_hidden_states(model, tokenizer, format_imdbs(text, 1), model_type=model_type, layers=layers)\n", - "\n", - " # collect\n", - " b = len(text)\n", - "# print(neg['hidden_states'].shape)\n", - " res.append([\n", - " neg['hidden_states'].reshape((b,-1)),\n", - " pos['hidden_states'].reshape((b,-1)),\n", - " true_label,\n", - " neg['ans'], \n", - " pos['ans'], \n", - " ])\n", - " \n", - " # FIXME not all the hidden state are the same size, wat\n", - " res = [np.concatenate(r) for r in zip(*res)]\n", - " return res\n", - " all_neg_hs, all_pos_hs, all_gt_labels, all_neg_ans, all_pos_ans = res\n", - " return all_neg_hs, all_pos_hs, all_gt_labels, all_neg_ans, all_pos_ans\n", - "# return all_neg_hs, all_pos_hs, all_gt_labels, np.array(all_neg_ans), np.array(all_pos_ans)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T03:15:48.077547Z", - "start_time": "2023-05-07T03:15:48.074666Z" - } - }, - "source": [ - "# Lets verify that the models answers are good" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Speed\n", - "\n", - "- 60second for 100 no batching. 1.7 ex/s" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:05.387382Z", - "start_time": "2023-05-20T02:28:05.033921Z" - } - }, - "outputs": [], - "source": [ - "gc.collect()\n", - "torch.cuda.empty_cache()\n", - "gc.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.747656Z", - "start_time": "2023-05-20T02:28:05.388608Z" - } - }, - "outputs": [], - "source": [ - "neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(model, tokenizer, data, model_type)\n", - "\n", - "\n", - "gc.collect()\n", - "torch.cuda.empty_cache()\n", - "gc.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.750431Z", - "start_time": "2023-05-20T02:28:35.750421Z" - } - }, - "outputs": [], - "source": [ - "# roc_auc_score\n", - "pos_score = roc_auc_score(y, all_pos_ans)\n", - "neg_score = roc_auc_score(y, all_neg_ans)\n", - "pos_score, neg_score" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.751184Z", - "start_time": "2023-05-20T02:28:35.751175Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "# accuracy_score\n", - "pos_score = accuracy_score(y, (all_pos_ans>0.)*1.0)\n", - "neg_score = accuracy_score(y, (all_neg_ans<0.5)*1.0)\n", - "pos_score, neg_score" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Let's verify that the model's representations are good\n", - "\n", - "Before trying CCS, let's make sure there exists a direction that classifies examples as true vs false with high accuracy; if supervised logistic regression accuracy is bad, there's no hope of unsupervised CCS doing well.\n", - "\n", - "Note that because logistic regression is supervised we expect it to do better but to have worse generalisation that equivilent unsupervised methods. However in this case CSS is using a deeper model so it is more complicated." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.751934Z", - "start_time": "2023-05-20T02:28:35.751926Z" - } - }, - "outputs": [], - "source": [ - "# let's create a simple 50/50 train split (the data is already randomized)\n", - "n = len(y)\n", - "\n", - "neg_hs2 = torch.from_numpy(np.stack([h.flatten() for h in neg_hs], 0))\n", - "pos_hs2 = torch.from_numpy(np.stack([h.flatten() for h in pos_hs], 0))\n", - "\n", - "neg_hs_train, neg_hs_test = neg_hs2[:n//2], neg_hs2[n//2:]\n", - "pos_hs_train, pos_hs_test = pos_hs2[:n//2], pos_hs2[n//2:]\n", - "y_train, y_test = y[:n//2], y[n//2:]\n", - "\n", - "# for simplicity we can just take the difference between positive and negative hidden states\n", - "# (concatenating also works fine)\n", - "x_train = neg_hs_train - pos_hs_train\n", - "x_test = neg_hs_test - pos_hs_test\n", - "\n", - "lr = LogisticRegression(class_weight=\"balanced\")\n", - "lr.fit(x_train, y_train)\n", - "print(\"Logistic regression accuracy: {} [TRAIN]\".format(lr.score(x_train, y_train)))\n", - "print(\"Logistic regression accuracy: {} [TEST]\".format(lr.score(x_test, y_test)))" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-14T00:05:52.801860Z", - "start_time": "2023-05-14T00:05:52.784513Z" - } - }, - "source": [ - "## Let's try on my own questions" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# https://astralcodexten.substack.com/p/elk-and-the-problem-of-truthful-ai\n", - "text = [\n", - " \"What happens if you break a mirror? You get seven years of bad luck\",\n", - " \"What happens if you break a mirror? You get a broken mirror\",\n", - " \"What happens if you break a mirror? You are punished in hell\",\n", - " \"What happens if you break a mirror? You are punished in jail\",\n", - " \"Taylor Swift is the best musician in all of history\",\n", - " \"Taylor Swift is the worst musician in all of history\",\n", - " \"Mozart is the best musician in all of history\",\n", - " \"Mozart is the worst musician in all of history\",\n", - " \"Hitler loves the jews\",\n", - " \"Hitler hates the jews\",\n", - " \"Hitler killed the jews\",\n", - " \"Ghandi loves all people\",\n", - " \"Ghandi hates all people\",\n", - " \"Ghandi fucks all people\",\n", - "]\n", - "layers = [2, -2]\n", - "# neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(model, tokenizer, data, model_type)\n", - "\n", - "neg = get_hidden_states(model, tokenizer, format_imdbs(text, 0), model_type=model_type, layers=layers)\n", - "pos = get_hidden_states(model, tokenizer, format_imdbs(text, 1), model_type=model_type, layers=layers)\n", - "b = len(text)\n", - "neg_hs_train = neg['hidden_states'].reshape((b,-1))\n", - "pos_hs_train = pos['hidden_states'].reshape((b,-1))\n", - "x_train = neg_hs_train - pos_hs_train\n", - "proba = lr.predict_proba(x_train)\n", - "pd.DataFrame(proba, columns=['P(false)', 'P(true)'], index=text)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "format_imdbs(text, 0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Now let's try CCS" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.752548Z", - "start_time": "2023-05-20T02:28:35.752540Z" - } - }, - "outputs": [], - "source": [ - "class MLPProbe(nn.Module):\n", - " def __init__(self, d):\n", - " super().__init__()\n", - " self.net = nn.Sequential(\n", - " nn.Linear(d, 100),\n", - " nn.ReLU(),\n", - " nn.Linear(100, 100),\n", - " nn.ReLU(),\n", - " nn.Linear(100, 100),\n", - " nn.ReLU(),\n", - "# nn.Linear(100, 100),\n", - "# nn.ReLU(),\n", - " nn.Linear(100, 1),\n", - " nn.Sigmoid(),\n", - " )\n", - "\n", - " def forward(self, x):\n", - " return self.net(x)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T05:40:58.250804Z", - "start_time": "2023-05-07T05:40:58.230537Z" - } - }, - "source": [ - "## Train" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T11:16:41.661985Z", - "start_time": "2023-05-07T11:16:41.650129Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.753297Z", - "start_time": "2023-05-20T02:28:35.753288Z" - } - }, - "outputs": [], - "source": [ - "# # Train CCS without any labels\n", - "# ccs = CCS(neg_hs_train, pos_hs_train, linear=False)\n", - "# ccs.repeated_train()\n", - "\n", - "# # Evaluate\n", - "# ccs_acc = ccs.get_acc(neg_hs_train, pos_hs_train, y_train)\n", - "# print(\"CCS nonlinear train accuracy: {}\".format(ccs_acc))\n", - "\n", - "# ccs_acc = ccs.get_acc(neg_hs_test, pos_hs_test, y_test)\n", - "# print(\"CCS nonlinear test accuracy: {}\".format(ccs_acc))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.754161Z", - "start_time": "2023-05-20T02:28:35.754151Z" - } - }, - "outputs": [], - "source": [ - "# # Train CCS without any labels\n", - "# ccs = CCS(neg_hs_train, pos_hs_train, linear=True)\n", - "# ccs.repeated_train()\n", - "\n", - "# # Evaluate\n", - "# ccs_acc = ccs.get_acc(neg_hs_train, pos_hs_train, y_train)\n", - "# print(\"CCS train accuracy: {}\".format(ccs_acc))\n", - "\n", - "# ccs_acc = ccs.get_acc(neg_hs_test, pos_hs_test, y_test)\n", - "# print(\"CCS test accuracy: {}\".format(ccs_acc))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T11:12:59.972960Z", - "start_time": "2023-05-07T11:12:59.964090Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# lightning" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-19T04:12:55.004017Z", - "start_time": "2023-05-19T04:12:55.004011Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DataModule" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.754973Z", - "start_time": "2023-05-20T02:28:35.754964Z" - }, - "scrolled": true - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Found cached dataset amazon_polarity (/home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc)\n", - "Loading cached shuffled indices for dataset at /home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc/cache-0a5d0b47b5e8dfc6.arrow\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b3438da979364c239f64decd952f4608", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - " 0%| | 0/667 [00:00]\n" - ] - }, - { - "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", - "
val/lossval/accsteptrain/losstrain/acc
epoch
01.00.56431.01.00.59375
11.00.56456.01.00.59375
21.00.56495.01.00.59375
31.00.564113.01.00.53125
41.00.564154.01.00.62500
..................
1951.00.5646260.01.00.56250
1961.00.5646301.01.00.62500
1971.00.5646335.01.00.62500
1981.00.5646358.01.00.50000
1991.00.5646399.01.00.62500
\n", - "

200 rows × 5 columns

\n", - "
" - ], - "text/plain": [ - " val/loss val/acc step train/loss train/acc\n", - "epoch \n", - "0 1.0 0.564 31.0 1.0 0.59375\n", - "1 1.0 0.564 56.0 1.0 0.59375\n", - "2 1.0 0.564 95.0 1.0 0.59375\n", - "3 1.0 0.564 113.0 1.0 0.53125\n", - "4 1.0 0.564 154.0 1.0 0.62500\n", - "... ... ... ... ... ...\n", - "195 1.0 0.564 6260.0 1.0 0.56250\n", - "196 1.0 0.564 6301.0 1.0 0.62500\n", - "197 1.0 0.564 6335.0 1.0 0.62500\n", - "198 1.0 0.564 6358.0 1.0 0.50000\n", - "199 1.0 0.564 6399.0 1.0 0.62500\n", - "\n", - "[200 rows x 5 columns]" - ] - }, - "execution_count": 89, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df_hist = read_hist(trainer).ffill().bfill()\n", - "df_hist" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.762326Z", - "start_time": "2023-05-20T02:28:35.762318Z" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:3                                                                                    \n",
-       "                                                                                                  \n",
-       "   1 df_hist[['val/acc', 'train/acc']].plot()                                                     \n",
-       "   2                                                                                              \n",
-       " 3 df_hist[['val/f1', 'train/f1']].plot()                                                       \n",
-       "   4                                                                                              \n",
-       "   5 df_hist[['val/loss', 'train/loss']].plot()                                                   \n",
-       "   6                                                                                              \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/core/frame.py:3767 in       \n",
-       " __getitem__                                                                                      \n",
-       "                                                                                                  \n",
-       "    3764 │   │   else:                                                                            \n",
-       "    3765 │   │   │   if is_iterator(key):                                                         \n",
-       "    3766 │   │   │   │   key = list(key)                                                          \n",
-       "  3767 │   │   │   indexer = self.columns._get_indexer_strict(key, \"columns\")[1]                \n",
-       "    3768 │   │                                                                                    \n",
-       "    3769 │   │   # take() does not accept boolean indexers                                        \n",
-       "    3770 │   │   if getattr(indexer, \"dtype\", None) == bool:                                      \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/core/indexes/base.py:5876   \n",
-       " in _get_indexer_strict                                                                           \n",
-       "                                                                                                  \n",
-       "   5873 │   │   else:                                                                             \n",
-       "   5874 │   │   │   keyarr, indexer, new_indexer = self._reindex_non_unique(keyarr)               \n",
-       "   5875 │   │                                                                                     \n",
-       " 5876 │   │   self._raise_if_missing(keyarr, indexer, axis_name)                                \n",
-       "   5877 │   │                                                                                     \n",
-       "   5878 │   │   keyarr = self.take(indexer)                                                       \n",
-       "   5879 │   │   if isinstance(key, Index):                                                        \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/core/indexes/base.py:5935   \n",
-       " in _raise_if_missing                                                                             \n",
-       "                                                                                                  \n",
-       "   5932 │   │   │   if nmissing == len(indexer):                                                  \n",
-       "   5933 │   │   │   │   if use_interval_msg:                                                      \n",
-       "   5934 │   │   │   │   │   key = list(key)                                                       \n",
-       " 5935 │   │   │   │   raise KeyError(f\"None of [{key}] are in the [{axis_name}]\")               \n",
-       "   5936 │   │   │                                                                                 \n",
-       "   5937 │   │   │   not_found = list(ensure_index(key)[missing_mask.nonzero()[0]].unique())       \n",
-       "   5938 │   │   │   raise KeyError(f\"{not_found} not in index\")                                   \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "KeyError: \"None of [Index(['val/f1', 'train/f1'], dtype='object')] are in the [columns]\"\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m3\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1 \u001b[0mdf_hist[[\u001b[33m'\u001b[0m\u001b[33mval/acc\u001b[0m\u001b[33m'\u001b[0m, \u001b[33m'\u001b[0m\u001b[33mtrain/acc\u001b[0m\u001b[33m'\u001b[0m]].plot() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m2 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m3 df_hist[[\u001b[33m'\u001b[0m\u001b[33mval/f1\u001b[0m\u001b[33m'\u001b[0m, \u001b[33m'\u001b[0m\u001b[33mtrain/f1\u001b[0m\u001b[33m'\u001b[0m]].plot() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m4 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5 \u001b[0mdf_hist[[\u001b[33m'\u001b[0m\u001b[33mval/loss\u001b[0m\u001b[33m'\u001b[0m, \u001b[33m'\u001b[0m\u001b[33mtrain/loss\u001b[0m\u001b[33m'\u001b[0m]].plot() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m6 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/core/\u001b[0m\u001b[1;33mframe.py\u001b[0m:\u001b[94m3767\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92m__getitem__\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 3764 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 3765 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mif\u001b[0m is_iterator(key): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 3766 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mkey = \u001b[96mlist\u001b[0m(key) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 3767 \u001b[2m│ │ │ \u001b[0mindexer = \u001b[96mself\u001b[0m.columns._get_indexer_strict(key, \u001b[33m\"\u001b[0m\u001b[33mcolumns\u001b[0m\u001b[33m\"\u001b[0m)[\u001b[94m1\u001b[0m] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 3768 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 3769 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# take() does not accept boolean indexers\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 3770 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96mgetattr\u001b[0m(indexer, \u001b[33m\"\u001b[0m\u001b[33mdtype\u001b[0m\u001b[33m\"\u001b[0m, \u001b[94mNone\u001b[0m) == \u001b[96mbool\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/core/indexes/\u001b[0m\u001b[1;33mbase.py\u001b[0m:\u001b[94m5876\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m_get_indexer_strict\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5873 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5874 \u001b[0m\u001b[2m│ │ │ \u001b[0mkeyarr, indexer, new_indexer = \u001b[96mself\u001b[0m._reindex_non_unique(keyarr) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5875 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m5876 \u001b[2m│ │ \u001b[0m\u001b[96mself\u001b[0m._raise_if_missing(keyarr, indexer, axis_name) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5877 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5878 \u001b[0m\u001b[2m│ │ \u001b[0mkeyarr = \u001b[96mself\u001b[0m.take(indexer) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5879 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96misinstance\u001b[0m(key, Index): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/core/indexes/\u001b[0m\u001b[1;33mbase.py\u001b[0m:\u001b[94m5935\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m_raise_if_missing\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5932 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mif\u001b[0m nmissing == \u001b[96mlen\u001b[0m(indexer): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5933 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94mif\u001b[0m use_interval_msg: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5934 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mkey = \u001b[96mlist\u001b[0m(key) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m5935 \u001b[2m│ │ │ │ \u001b[0m\u001b[94mraise\u001b[0m \u001b[96mKeyError\u001b[0m(\u001b[33mf\u001b[0m\u001b[33m\"\u001b[0m\u001b[33mNone of [\u001b[0m\u001b[33m{\u001b[0mkey\u001b[33m}\u001b[0m\u001b[33m] are in the [\u001b[0m\u001b[33m{\u001b[0maxis_name\u001b[33m}\u001b[0m\u001b[33m]\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5936 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5937 \u001b[0m\u001b[2m│ │ │ \u001b[0mnot_found = \u001b[96mlist\u001b[0m(ensure_index(key)[missing_mask.nonzero()[\u001b[94m0\u001b[0m]].unique()) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5938 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mraise\u001b[0m \u001b[96mKeyError\u001b[0m(\u001b[33mf\u001b[0m\u001b[33m\"\u001b[0m\u001b[33m{\u001b[0mnot_found\u001b[33m}\u001b[0m\u001b[33m not in index\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mKeyError: \u001b[0m\u001b[32m\"None of \u001b[0m\u001b[32m[\u001b[0m\u001b[32mIndex\u001b[0m\u001b[32m(\u001b[0m\u001b[32m[\u001b[0m\u001b[32m'val/f1', 'train/f1'\u001b[0m\u001b[32m]\u001b[0m\u001b[32m, \u001b[0m\u001b[32mdtype\u001b[0m\u001b[32m='object'\u001b[0m\u001b[32m)\u001b[0m\u001b[32m]\u001b[0m\u001b[32m are in the \u001b[0m\u001b[32m[\u001b[0m\u001b[32mcolumns\u001b[0m\u001b[32m]\u001b[0m\u001b[32m\"\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGwCAYAAACKOz5MAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACug0lEQVR4nO2dfXgU1fXHv/ueBEgAAwkgAopSUUBFSVFbraKAFtFaRbRFUbG1Uq1Uq1hBi61YrYi2Kq2FqrWtWmvVFkWRiv3Jq0KpVRFFeRUS5DWQQDbZnd8fs3f2zt07b7uzO7Ob83mePEl2Z2fvvN177jnfc25AURQFBEEQBEEQPibodQMIgiAIgiCsIIOFIAiCIAjfQwYLQRAEQRC+hwwWgiAIgiB8DxksBEEQBEH4HjJYCIIgCILwPWSwEARBEAThe8JeN8ANkskktm3bhk6dOiEQCHjdHIIgCIIgbKAoCvbv34+ePXsiGDT3oZSEwbJt2zb07t3b62YQBEEQBJEFW7ZsweGHH266TUkYLJ06dQKgHnBlZaXHrSEIgiAIwg6NjY3o3bu3No6bURIGCwsDVVZWksFCEARBEEWGHTkHiW4JgiAIgvA9ZLAQBEEQBOF7yGAhCIIgCML3lISGhSAIgmg/JJNJxONxr5tB2CQSiSAUCuW8HzJYCIIgiKIhHo9jw4YNSCaTXjeFcEDnzp1RW1ubU600MlgIgiCIokBRFGzfvh2hUAi9e/e2LDRGeI+iKGhubsaOHTsAAD169Mh6X2SwEARBEEVBW1sbmpub0bNnT1RUVHjdHMIm5eXlAIAdO3age/fuWYeHyDwlCIIgioJEIgEAiEajHreEcAozMFtbW7PeBxksBEEQRFFBa8YVH25cMzJYCIIgCILwPWSwEARBEAThe8hgIQiCIAgf07dvX8yePdvrZngOGSwEQRBe0hYH9m5Wf1r2e90aoojo168f3nzzTa+bUTAorZkgCMIrkglgzmnAzk/U/yMVwA+WAV36etoswv+8//772LNnD8444wyvm1IwyMNCEAThFS2NaWMFAFqbgR0fe9eeIkNRFDTH2zz5URTFVht/97vfoWfPnhmVeceOHYurr74an332GcaOHYuamhp07NgRp5xyii2vycsvv4xRo0YhEolg165dGD9+PHr16oWKigoMGjQIf/nLX3TbJ5NJ3H///ejfvz9isRiOOOII/OIXv9De37p1K8aPH4+uXbuiQ4cOOPnkk7FixQpbx1goyMNCEAThFclE+u9eJwNfvAfA3kBIAAdbExg4/XVPvvujGSNREbUeQi+55BL88Ic/xFtvvYWzzz4bALB7924sWLAAr776Kg4cOIDzzjsPv/jFLxCLxfD0009jzJgxWLduHY444gjD/b7yyiuYMmUKAODQoUMYOnQobrvtNlRWVmL+/Pn47ne/i6OOOgrDhg0DAEydOhVPPPEEHnroIZx++unYvn07Pv5YNY4PHDiAM844A7169cIrr7yC2tparF692nfLH5DBQhAE4RXJNvV3IAQEUg5vxV+DBJEbXbp0wejRo/HnP/9ZM1heeOEFVFdX4xvf+AaCwSCGDBmibX/PPffg73//O1555RVMnjxZus8vvvgC77//PkaPHg0A6NWrF2655Rbt/R/+8Id4/fXX8fzzz2PYsGHYv38/Hn74YfzmN7/BlVdeCQA46qijcPrppwMA/vznP+PLL7/Eu+++i65duwIA+vfv7/7JyBEyWAiCILyCGSzBMBksWVAeCeGjGSM9+267XHHFFZg0aRIee+wxxGIx/OlPf8Jll12GYDCIAwcO4O6778b8+fOxfft2tLW14eDBg9i8ebPh/l555RWcfvrp6Ny5MwC1AvC9996L559/Hl988QXi8ThaWlq06rJr165FS0uLZjCJrFmzBieeeKJmrPgVMlgIgiC8IpEqUx4MA6wSKBkstgkEArbCMl4zZswYKIqC+fPn45RTTsH//d//4aGHHgIA3HLLLVi4cCF+9atfoX///igvL8e3v/1txONxw/298soruOCCC7T/H3jgATz88MOYPXs2Bg0ahA4dOuBHP/qRtg+2lo8RVu/7BRLdEgRBeAXTsOg8LKRhKTXKysrwrW99C3/605/wl7/8BQMGDMBJJ50EAFiyZAmuuuoqXHTRRRg0aBBqa2uxceNGw30dOHAAb731FsaOHau9tmTJEowdOxbf+c53MGTIEBx55JH45JO0mPvoo49GeXk5Fi1aJN3n4MGDsWbNGuzevdudA84TZLAQBEF4hRYSIg1LqXPFFVdg/vz5mDdvHq644grt9aOPPhovvvgi1qxZg//+97+4/PLLTcWuCxYswDHHHIO+ffvq9rFw4UIsXboUa9euxfe+9z00NDRo75eVleG2227DT37yEzz99NP47LPPsHz5csydOxcAMH78eNTW1uLCCy/EkiVL8Pnnn+Nvf/sbli1b5v6JyAEyWAiCILyCGSyhCIWESpyzzjoLXbt2xbp163D55Zdrr8+aNQtdunTBqaeeijFjxmDkyJGa90XGyy+/rAsHAcCdd96Jk046CSNHjsSZZ56pGR8806ZNw49//GNMnz4dxx57LMaNG4cdO3YAUFe/fuONN9C9e3ecd955GDRoEO677z6EQvZ1OoUgoNhNJvcxjY2NqKqqwr59+1BZWel1cwiCIOyxbQ3wuzOAyl7AYf2BDW8DF88FBn3b65b5kkOHDmHDhg3o168fysrKvG5OwWlra0NNTQ1ee+01LV25WDC6dk7Gb/KwEARBeIWmYaGQEGHN7t27cfPNN+OUU07xuime4H95NUEQRKlCac2EA7p3744777zT62Z4BnlYCIIgvCLJpzWTwUIQZpDBQhAE4RU6DwsT3Ra9rJAg8gIZLARBEF5Bac0EYRsyWAiCILxCE91GyGAhCAvIYCEIgvAKPiQEqsNCEGaQwUIQBOEVMg0LSMNCEDLIYCEIgvAK0rAQhG3IYCEIgvCKhKwOC3lYCGP69u2L2bNne90MT8jKYHn00UfRt29flJWVoa6uDitXrjTdfvbs2RgwYADKy8vRu3dv3HzzzTh06JD2/t13341AIKD7+cpXvpJN0wiCIIoHSmtuF5x55pn40Y9+5Mq+3n33XVx33XWOP7dp0yaUl5fjwIEDrrTDCxxXun3uuecwZcoUzJkzB3V1dZg9ezZGjhyJdevWoXv37hnb//nPf8btt9+OefPm4dRTT8Unn3yCq666CoFAALNmzdK2O+644/Dmm2+mGxamIrwEQZQ4VOmWAKAoChKJhK1xr1u3bll9x8svv4xvfOMb6NixY1af9wOOPSyzZs3CpEmTMHHiRAwcOBBz5sxBRUUF5s2bJ91+6dKlOO2003D55Zejb9++OPfcczF+/PgMr0w4HEZtba32U11dbdiGlpYWNDY26n4IgiCKDm21ZjJYskJRgHiTNz82PWFXXXUV3n77bTz88MNaBOHJJ59EIBDAa6+9hqFDhyIWi+Gdd97BZ599hrFjx6KmpgYdO3bEKaecopvIA5khoUAggN///ve46KKLUFFRgaOPPhqvvPJKRjv4VZ7fffddnHPOOaiurkZVVRXOOOMMrF69Wrf93r178b3vfQ81NTUoKyvD8ccfj3/+85/a+0uWLMGZZ56JiooKdOnSBSNHjsSePXvsXrmscOTGiMfjWLVqFaZOnaq9FgwGMWLECCxbtkz6mVNPPRXPPPMMVq5ciWHDhuHzzz/Hq6++iu9+97u67T799FP07NkTZWVlGD58OGbOnIkjjjhCus+ZM2fiZz/7mZOmEwRB+A+tDgsZLFnR2gzc29Ob775jGxDtYLnZww8/jE8++QTHH388ZsyYAQD48MMPAQC33347fvWrX+HII49Ely5dsGXLFpx33nn4xS9+gVgshqeffhpjxozBunXrDMdDAPjZz36G+++/Hw888AB+/etf44orrsCmTZvQtWtXAKrx8c477+CPf/wjAGD//v248sor8etf/xqKouDBBx/Eeeedh08//RSdOnVCMpnE6NGjsX//fjzzzDM46qij8NFHHyEUCgEA1qxZg7PPPhtXX301Hn74YYTDYbz11ltIJBI5nVIrHBksO3fuRCKRQE1Nje71mpoafPzxx9LPXH755di5cydOP/10KIqCtrY2fP/738cdd9yhbVNXV4cnn3wSAwYMwPbt2/Gzn/0MX/va1/DBBx+gU6dOGfucOnUqpkyZov3f2NiI3r17OzkUgiAI75HVYaG05pKiqqoK0WgUFRUVqK2tBQBtvJwxYwbOOeccbduuXbtiyJAh2v/33HMP/v73v+OVV17B5MmTDb/jqquuwvjx4wEA9957Lx555BGsXLkSo0aNAgC8+uqrGDx4MHr2VI27s846S/f53/3ud+jcuTPefvttfPOb38Sbb76JlStXYu3atTjmmGMAAEceeaS2/f3334+TTz4Zjz32mPbacccd5/zkOCTvQpHFixfj3nvvxWOPPYa6ujqsX78eN910E+655x5MmzYNADB69Ght+8GDB6Ourg59+vTB888/j2uuuSZjn7FYDLFYLN9NJwiCyC9UOC43IhWqp8Or786Rk08+Wff/gQMHcPfdd2P+/PnYvn072tracPDgQWzevNl0P4MHD9b+7tChAyorK7Fjxw7tNT4cBAANDQ248847sXjxYuzYsQOJRALNzc3a96xZswaHH364ZqyIrFmzBpdcconj480VRwZLdXU1QqEQGhoadK83NDRolqPItGnT8N3vfhfXXnstAGDQoEFoamrCddddh5/+9KcIBjNlNJ07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3XXXFeoQLDE7xubmZqxevRrTpk3D6tWr8eKLL2LdunW44IILMradMWOG7tr+8Ic/LETzLbG6hgAwatQoXdv/8pe/6N4v5msIQHds27dvx7x58xAIBHDxxRfrtvPrNbQzPlj1n4lEAueffz7i8TiWLl2Kp556Ck8++SSmT5/uXkMVwpBhw4YpN9xwg/Z/IpFQevbsqcycOdPDVrnDjh07FADK22+/rb12xhlnKDfddJN3jcqRu+66SxkyZIj0vb179yqRSET561//qr22du1aBYCybNmyArXQXW666SblqKOOUpLJpKIoxX/9ACh///vftf+TyaRSW1urPPDAA9pre/fuVWKxmPKXv/xFURRF+eijjxQAyrvvvqtt89prrymBQED54osvCtZ2u4jHKGPlypUKAGXTpk3aa3369FEeeuih/DbOBWTHd+WVVypjx441/EwpXsOxY8cqZ511lu61YrmGipI5PtjpP1999VUlGAwq9fX12jaPP/64UllZqbS0tLjSLvKwGBCPx7Fq1SqMGDFCey0YDGLEiBFYtmyZhy1zh3379gEAunbtqnv9T3/6E6qrq3H88cdj6tSpaG5u9qJ5WfPpp5+iZ8+eOPLII3HFFVdg8+bNAIBVq1ahtbVVdz2/8pWv4IgjjijK6xmPx/HMM8/g6quv1i34WezXj2fDhg2or6/XXbOqqirU1dVp12zZsmXo3LkzTj75ZG2bESNGIBgMYsWKFQVvsxvs27cPgUAAnTt31r1+33334bDDDsOJJ56IBx54wFVXe75ZvHgxunfvjgEDBuD666/Hrl27tPdK7Ro2NDRg/vz5uOaaazLeK5ZrKI4PdvrPZcuWYdCgQaipqdG2GTlyJBobG/Hhhx+60q6SWPwwH+zcuROJREJ38gGgpqYGH3/8sUetcodkMokf/ehHOO2003D88cdrr19++eXo06cPevbsiffffx+33XYb1q1bhxdffNHD1tqnrq4OTz75JAYMGIDt27fjZz/7Gb72ta/hgw8+QH19PaLRaMYgUFNTg/r6em8anAMvvfQS9u7di6uuukp7rdivnwi7LrJnkL1XX1+P7t27694Ph8Po2rVrUV7XQ4cO4bbbbsP48eN1C8vdeOONOOmkk9C1a1csXboUU6dOxfbt2zFr1iwPW2uPUaNG4Vvf+hb69euHzz77DHfccQdGjx6NZcuW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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "df_hist[['val/acc', 'train/acc']].plot()\n", - "\n", - "df_hist[['val/f1', 'train/f1']].plot()\n", - "\n", - "df_hist[['val/loss', 'train/loss']].plot()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "dlk2", - "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.16" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": { - "height": "calc(100% - 180px)", - "left": "10px", - "top": "150px", - "width": "165px" - }, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/001_mjc_CCS_Wizard.ipynb b/notebooks/001_mjc_CCS_Wizard.ipynb deleted file mode 100644 index 4ed733f..0000000 --- a/notebooks/001_mjc_CCS_Wizard.ipynb +++ /dev/null @@ -1,2645 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Let's implement CCS from scratch.\n", - "This will deliberately be a simple (but less efficient) implementation to make everything as clear as possible." - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:54:44.191549Z", - "start_time": "2023-05-20T01:54:41.824251Z" - } - }, - "outputs": [], - "source": [ - "from tqdm.auto import tqdm\n", - "import copy\n", - "import numpy as np\n", - "import torch\n", - "import torch.nn as nn\n", - "import torch.nn.functional as F\n", - "\n", - "import os\n", - "os.environ[\"HF_DATASETS_OFFLINE\"] = \"0\"\n", - "from datasets import load_dataset\n", - "import datasets\n", - "from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, AutoModelForMaskedLM, AutoModelForCausalLM\n", - "from sklearn.linear_model import LogisticRegression\n", - "\n", - "import lightning.pytorch as pl\n", - "from dataclasses import dataclass\n", - "from torch.utils.data import random_split, DataLoader, TensorDataset\n", - "from transformers.models.auto.modeling_auto import AutoModel\n", - "# from scipy.stats import zscore\n", - "from sklearn.metrics import f1_score, roc_auc_score, accuracy_score\n", - "from sklearn.preprocessing import RobustScaler\n", - "import gc\n", - "\n", - "import os" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Model" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:54:44.196607Z", - "start_time": "2023-05-20T01:54:44.193276Z" - } - }, - "outputs": [], - "source": [ - "# from transformers import LlamaTokenizer, LlamaForCausalLM\n", - "from transformers import LlamaForCausalLM, LlamaTokenizer" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:26.440636Z", - "start_time": "2023-05-20T01:54:44.197666Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Loading checkpoint shards: 100%|██████████| 3/3 [00:13<00:00, 4.52s/it]\n", - "Downloading (…)neration_config.json: 100%|██████████| 132/132 [00:00<00:00, 10.1kB/s]\n" - ] - }, - { - "data": { - "text/plain": [ - "LlamaForCausalLM(\n", - " (model): LlamaModel(\n", - " (embed_tokens): Embedding(32000, 5120, padding_idx=0)\n", - " (layers): ModuleList(\n", - " (0-39): 40 x LlamaDecoderLayer(\n", - " (self_attn): LlamaAttention(\n", - " (q_proj): Linear8bitLt(in_features=5120, out_features=5120, bias=False)\n", - " (k_proj): Linear8bitLt(in_features=5120, out_features=5120, bias=False)\n", - " (v_proj): Linear8bitLt(in_features=5120, out_features=5120, bias=False)\n", - " (o_proj): Linear8bitLt(in_features=5120, out_features=5120, bias=False)\n", - " (rotary_emb): LlamaRotaryEmbedding()\n", - " )\n", - " (mlp): LlamaMLP(\n", - " (gate_proj): Linear8bitLt(in_features=5120, out_features=13824, bias=False)\n", - " (down_proj): Linear8bitLt(in_features=13824, out_features=5120, bias=False)\n", - " (up_proj): Linear8bitLt(in_features=5120, out_features=13824, bias=False)\n", - " (act_fn): SiLUActivation()\n", - " )\n", - " (input_layernorm): LlamaRMSNorm()\n", - " (post_attention_layernorm): LlamaRMSNorm()\n", - " )\n", - " )\n", - " (norm): LlamaRMSNorm()\n", - " )\n", - " (lm_head): Linear(in_features=5120, out_features=32000, bias=False)\n", - ")" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Here are a few different model options you can play around with:\n", - "model_name = \"deberta\"\n", - "model_name = \"gpt-j\"\n", - "# model_name = \"t5\"\n", - "model_name = \"llama\"\n", - "model_name = \"alpaca\"\n", - "finetuned = None\n", - "\n", - "model_options = dict(\n", - " device_map=\"auto\", \n", - " load_in_8bit=True,\n", - " torch_dtype=torch.float16,\n", - ")\n", - "\n", - "\n", - "if model_name == \"deberta\":\n", - " model_type = \"encoder\"\n", - " tokenizer = AutoTokenizer.from_pretrained(\"microsoft/deberta-v2-xxlarge\")\n", - " model = AutoModelForMaskedLM.from_pretrained(\"microsoft/deberta-v2-xxlarge\", **model_options)\n", - "elif model_name == \"gpt-j\":\n", - " model_type = \"decoder\"\n", - " tokenizer = AutoTokenizer.from_pretrained(\"EleutherAI/gpt-j-6B\")\n", - " model = AutoModelForCausalLM.from_pretrained(\"EleutherAI/gpt-j-6B\", **model_options)\n", - "elif model_name == \"t5\":\n", - " model_type = \"encoder_decoder\"\n", - " tokenizer = AutoTokenizer.from_pretrained(\"t5-11b\")\n", - " model = AutoModelForSeq2SeqLM.from_pretrained(\"t5-11b\", **model_options)\n", - " model.parallelize() # T5 is big enough that we may need to run it on multiple GPUs\n", - "elif (\"llama\" in model_name) or (\"alpaca\" in model_name):\n", - " # https://github.com/deep-diver/LLM-As-Chatbot/blob/216abb559d00a0555f41a1426ac9db6c1abc24f3/models/alpaca.py\n", - " # model_repo = \"Neko-Institute-of-Science/LLaMA-7B-HF\"\n", - " # model_repo = \"decapoda-research/llama-7b-hf\"\n", - " # lora_repo = \"tloen/alpaca-lora-7b\"\n", - " # lora_repo = \"chansung/gpt4-alpaca-lora-7b\"\n", - " \n", - " model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", - " lora_repo = \"LLMs/Alpaca-LoRA-13B-elina\"\n", - " \n", - " # model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", - " model_repo = \"decapoda-research/llama-13b-hf\"\n", - " lora_repo = \"chansung/alpaca-lora-13b\"\n", - " lora_repo = \"chansung/gpt4-alpaca-lora-13b\"\n", - " \n", - " \n", - " # model_repo = \"TheBloke/OpenAssistant-SFT-7-Llama-30B-HF\"\n", - " \n", - " \n", - " \n", - " model_repo = \"TheBloke/Wizard-Vicuna-13B-Uncensored-HF\"\n", - " lora_repo = None\n", - " model_type = \"decoder\"\n", - " tokenizer = LlamaTokenizer.from_pretrained(model_repo)\n", - " model = LlamaForCausalLM.from_pretrained(model_repo, **model_options)\n", - " \n", - " if lora_repo is not None:\n", - " # https://github.com/tloen/alpaca-lora/blob/main/generate.py#L40\n", - " from peft import PeftModel\n", - " model = PeftModel.from_pretrained(\n", - " model, \n", - " lora_repo, \n", - " torch_dtype=torch.float16,\n", - " device_map='auto'#{'': 0}\n", - " )\n", - " \n", - " # tokenizer.pad_token = 0\n", - " # tokenizer.padding_side = \"left\"\n", - "else:\n", - " raise NotADirectoryError(model_name)\n", - "model" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:26.444015Z", - "start_time": "2023-05-20T01:56:26.442164Z" - } - }, - "outputs": [], - "source": [ - "# tokenizer = AutoTokenizer.from_pretrained(model_repo)\n", - "# tokenizer.truncation_side='Left'\n", - "# tokenizer" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:26.469934Z", - "start_time": "2023-05-20T01:56:26.444768Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(29900, 29896)" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# get the tokens for 0 and 1, we will use these later...\n", - "id_0, id_1 = tokenizer('0')['input_ids'][-1], tokenizer('1')['input_ids'][-1]\n", - "id_0, id_1" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "start_time": "2023-05-07T01:08:20.635Z" - } - }, - "source": [ - "## Dataset" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-19T04:02:13.892383Z", - "start_time": "2023-05-19T04:02:13.873377Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:56:27.020627Z", - "start_time": "2023-05-20T01:56:26.470949Z" - }, - "scrolled": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Found cached dataset amazon_polarity (/home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc)\n", - "100%|██████████| 2/2 [00:00<00:00, 16.38it/s]\n" - ] - }, - { - "data": { - "text/plain": [ - "Dataset({\n", - " features: ['label', 'title', 'content'],\n", - " num_rows: 400000\n", - "})" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# debug\n", - "datasets.logging.set_verbosity_info()\n", - "\n", - "# Let's just try IMDB for simplicity\n", - "data = load_dataset(\"amazon_polarity\")['test']\n", - "# data = load_dataset(\"/home/wassname/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc/amazon_polarity-train-00003-of-00004.arrow\")\n", - "data" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:05.461369Z", - "start_time": "2023-05-20T02:25:05.458241Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Review: \"I think this is a lovely family movie. There are plenty of hilarious scenes and heart-warming moments to be had throughout the movie. The actors are great and the effects well executed throughout. Danny Glover plays George Knox who manages the terrible baseball team 'The Angels' and is great throughout the film. Also fantastic are the young actors Joseph Gordon-Levitt and Milton Davis Jr. Christopher Lloyd is good as Al 'The Angel' and the effects are great in this top notch Disney movie. A touching and heart-warming movie which everyone should enjoy.\"\n", - "Question: Is this review positive? \n", - "Answer: 1\n", - "---\n", - "Review: \"The movie was the worst.... not!\"\n", - "Question: Is this review negative?\n", - "Answer: \n", - "\n" - ] - } - ], - "source": [ - "def format_imdb(text, label):\n", - " return f\"\"\"Review: \"I think this is a lovely family movie. There are plenty of hilarious scenes and heart-warming moments to be had throughout the movie. The actors are great and the effects well executed throughout. Danny Glover plays George Knox who manages the terrible baseball team 'The Angels' and is great throughout the film. Also fantastic are the young actors Joseph Gordon-Levitt and Milton Davis Jr. Christopher Lloyd is good as Al 'The Angel' and the effects are great in this top notch Disney movie. A touching and heart-warming movie which everyone should enjoy.\"\n", - "Question: Is this review positive? \n", - "Answer: 1\n", - "---\n", - "Review: \"{text}\"\n", - "Question: Is this review {'positive' if label else 'negative'}?\n", - "Answer: \n", - "\"\"\"\n", - "\n", - "def format_imdbs(texts, labels):\n", - " return [format_imdb(t, labels) for t in texts]\n", - "\n", - "print(format_imdb(\"The movie was the worst.... not!\", 0))" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "def format_imdb(input, label):\n", - " instruction = f\"Is this review {'positive' if label else 'negative'}?\"\n", - " alpaca_prompt = f\"Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\\n\\n### Instruction:\\n{instruction}\\n\\n### Input:\\n{input}\\n\\n### Response:\\n\"\n", - " return alpaca_prompt" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [], - "source": [ - "# def format_imdb(text, label):\n", - "# return f\"\"\"Below is an instruction that describes a task. Write a response that appropriately completes the request.\n", - "\n", - "# ### Instruction:\\nQuestion: Is this review {'positive' if label else 'negative'}?\\n\\n\n", - "\n", - "# Review: \"I think this is a lovely family movie. There are plenty of hilarious scenes and heart-warming moments to be had throughout the movie. The actors are great and the effects well executed throughout. Danny Glover plays George Knox who manages the terrible baseball team 'The Angels' and is great throughout the film. Also fantastic are the young actors Joseph Gordon-Levitt and Milton Davis Jr. Christopher Lloyd is good as Al 'The Angel' and the effects are great in this top notch Disney movie. A touching and heart-warming movie which everyone should enjoy.\"\n", - "# Question: Is this review positive? \n", - "# Answer: 1\n", - "# ---\n", - "# Review: \"{text}\"\n", - "# Question: Is this review {'positive' if label else 'negative'}?\n", - "# Answer: \n", - "\n", - "# ### Response:\\n\n", - "# \"\"\"\n", - "\n", - "# def format_imdbs(texts, labels):\n", - "# return [format_imdb(t, labels) for t in texts]\n", - "\n", - "# print(format_imdb(\"The movie was the worst.... not!\", 0))" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:05.902898Z", - "start_time": "2023-05-20T02:25:05.898745Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "66" - ] - }, - "execution_count": 53, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# tokens\n", - "len(tokenizer(format_imdb(\"The movie was the worst.... not!\", 0))['input_ids'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## First check models text output" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:45.805378Z", - "start_time": "2023-05-20T02:25:45.800064Z" - } - }, - "outputs": [], - "source": [ - "from transformers import GenerationConfig, LlamaForCausalLM, LlamaTokenizer\n", - "temperature=0.1\n", - "top_p=0.75\n", - "top_k=40\n", - "num_beams=4\n", - "max_new_tokens=128\n", - "generation_config = GenerationConfig(\n", - " temperature=temperature,\n", - " top_p=top_p,\n", - " top_k=top_k,\n", - ")\n", - "\n", - "\n", - "def get_output(model, tokenizer, input_text, add_bos_token=False, truncation_length=400):\n", - " \"\"\"\n", - " Given a decoder model and some text, gets the hidden states (in a given layer, by default the last) on that input text\n", - "\n", - " Returns a numpy array of shape (hidden_dim,)\n", - " \"\"\"\n", - " if not isinstance(input_text, list):\n", - " input_text = [input_text]\n", - " # tokenize (adding the EOS token this time)\n", - " input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# input_text = [i[-1000:] for i in input_text]\n", - " input_ids = tokenizer(input_text, \n", - " return_tensors=\"pt\",\n", - "# truncation=True, \n", - "# padding=True,\n", - "# max_length=600,\n", - " add_special_tokens=True,\n", - " ).input_ids.to(model.device)\n", - "# print('input_ids', input_ids.shape)\n", - "\n", - " # remove bos token? https://github.com/oobabooga/text-generation-webui/blob/1b52bddfcc70d2db88257d36f1c6d182573588c4/modules/text_generation.py#L36\n", - " if not add_bos_token and input_ids[0][0] == tokenizer.bos_token_id:\n", - " input_ids = input_ids[:, 1:]\n", - " print('removed')\n", - "\n", - "\n", - " # Llama adds this extra token when the first character is '\\n', and this\n", - " # compromises the stopping criteria, so we just remove it\n", - " if type(tokenizer) is LlamaTokenizer and input_ids[0][0] == 29871:\n", - " # print('removed extra \\n token')\n", - " input_ids = input_ids[:, 1:]\n", - " \n", - " # Handling truncation\n", - " if truncation_length is not None:\n", - " input_ids = input_ids[:, -truncation_length:]\n", - "\n", - "\n", - " # generate_params = {\n", - " # \"input_ids\": input_ids,\n", - " # \"generation_config\": generation_config,\n", - " # \"return_dict_in_generate\": True,\n", - " # \"output_scores\": True,\n", - " # \"max_new_tokens\": max_new_tokens,\n", - " # }\n", - " # forward pass\n", - " with torch.no_grad():\n", - " generation_output = model.generate(\n", - " input_ids=input_ids, generation_config=generation_config,\n", - " return_dict_in_generate=True,\n", - " output_scores=True,\n", - " max_new_tokens=max_new_tokens,\n", - " )\n", - " s = generation_output.sequences[0]\n", - " \n", - " text_q = tokenizer.batch_decode(input_ids, skip_special_tokens=False)\n", - " text_ans = tokenizer.batch_decode(s, skip_special_tokens=False)#, skip_prompt=True, skip_special_tokens=True)\n", - " print(text_q[0])\n", - " print('-'*40+'answ'+'-'*40)\n", - " print(text_ans[0])\n" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T01:54:09.323908Z", - "start_time": "2023-05-20T01:54:09.321888Z" - } - }, - "outputs": [], - "source": [ - "# model.generate??" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:46.260946Z", - "start_time": "2023-05-20T02:25:46.258734Z" - } - }, - "outputs": [], - "source": [ - "tokenizer.pad_token_id=0\n", - "tokenizer.padding_side = \"left\"" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:46.401304Z", - "start_time": "2023-05-20T02:25:46.398898Z" - } - }, - "outputs": [], - "source": [ - "idx = 1\n", - "text, true_label = data[idx][\"content\"], data[idx][\"label\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:25:53.587709Z", - "start_time": "2023-05-20T02:25:46.528753Z" - }, - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "removed\n", - " Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\n", - "\n", - "### Instruction:\n", - "Is this review negative?\n", - "\n", - "### Input:\n", - "Despite the fact that I have only played a small portion of the game, the music I heard (plus the connection to Chrono Trigger which was great as well) led me to purchase the soundtrack, and it remains one of my favorite albums. There is an incredible mix of fun, epic, and emotional songs. Those sad and beautiful tracks I especially like, as there's not too many of those kinds of songs in my other video game soundtracks. I must admit that one of the songs (Life-A Distant Promise) has brought tears to my eyes on many occasions.My one complaint about this soundtrack is that they use guitar fretting effects in many of the songs, which I find distracting. But even if those weren't included I would still consider the collection worth it.\n", - "\n", - "### Response:\n", - "\n", - "----------------------------------------answ----------------------------------------\n", - "Below\n" - ] - } - ], - "source": [ - "input_text = [format_imdb(text, 0)]\n", - "# input_text = [i + tokenizer.eos_token for i in input_text]\n", - "get_output(model, tokenizer, input_text)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Write code for extracting hidden states given a model and text. \n", - "How we do this exactly will depend on the type of model." - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:49.742646Z", - "start_time": "2023-05-20T02:27:49.737461Z" - } - }, - "outputs": [], - "source": [ - "\n", - "\n", - "def get_decoder_hidden_states(model, tokenizer, input_text, layers=[2, -2], add_bos_token=False, truncation_length=400):\n", - " \"\"\"\n", - " Given a decoder model and some text, gets the hidden states (in a given layer, by default the last) on that input text\n", - "\n", - " Returns a numpy array of shape (hidden_dim,)\n", - " \"\"\"\n", - " if not isinstance(input_text, list):\n", - " input_text = [input_text]\n", - " # tokenize (adding the EOS token this time)\n", - " # input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# input_text = [i[-1000:] for i in input_text]\n", - " input_ids = tokenizer(input_text, \n", - " return_tensors=\"pt\",\n", - "# truncation=True, \n", - " padding=True,\n", - "# max_length=600,\n", - " add_special_tokens=True,\n", - " ).input_ids.to(model.device)\n", - "# print('input_ids', input_ids.shape)\n", - "\n", - "\n", - " # remove bos token? https://github.com/oobabooga/text-generation-webui/blob/1b52bddfcc70d2db88257d36f1c6d182573588c4/modules/text_generation.py#L36\n", - " if not add_bos_token and input_ids[0][0] == tokenizer.bos_token_id:\n", - " input_ids = input_ids[:, 1:]\n", - "\n", - "\n", - " # Llama adds this extra token when the first character is '\\n', and this\n", - " # compromises the stopping criteria, so we just remove it\n", - " if type(tokenizer) is LlamaTokenizer and input_ids[0][0] == 29871:\n", - " # print('removed extra \\n token')\n", - " input_ids = input_ids[:, 1:]\n", - " \n", - " # Handling truncation\n", - " if truncation_length is not None:\n", - " input_ids = input_ids[:, -truncation_length:]\n", - "\n", - " # forward pass\n", - " with torch.no_grad():\n", - " output = model(input_ids, \n", - " output_hidden_states=True,\n", - "# , output_attentions=True\n", - " use_cache=True,\n", - " \n", - " )\n", - " \n", - " # the output is large, so we will just select what we want 1) the first token with[:, 0]\n", - " # 2) selected layers with [layers]\n", - "# output['attentions'] = [output['attentions'][i] for i in layers]\n", - "# output['attentions'] = [v.detach().cpu()[:, -1] for v in output['attentions']]\n", - "# output['attentions'] = torch.concat(output['attentions'])\n", - " \n", - " \n", - " # dims [Batch, Token, Probs?]\n", - " output['hidden_states'] = torch.stack([output['hidden_states'][i] for i in layers], 1).detach().cpu()\n", - " # dims [Batch, Layers, Seq_Token, Probs?] e.g. torch.Size([3, 2, 284, 4096])\n", - " \n", - " output['hidden_states'] = output['hidden_states'][:, :, -1] # take just the last token so they are same size\n", - " \n", - " # dims [Batch, ?, Output_Tokens] e.g. torch.Size([3, 284, 32000])\n", - " o = output['logits'].detach().cpu().float().softmax(-1)\n", - " \n", - " # text_q = [tokenizer.decode(oo) for oo in input_ids]\n", - " # tokenizer.batch\n", - " # text_ans = [tokenizer.decode(oo) for oo in o.argmax(-1)]\n", - " text_q = tokenizer.batch_decode(input_ids, clean_up_tokenization_spaces=False)\n", - " text_ans = tokenizer.batch_decode(o.argmax(-1), clean_up_tokenization_spaces=False)\n", - "\n", - " nth_place = 0\n", - " prob_0, prob1 = o[:, nth_place][:, [id_0, id_1]].T # get the prob of 0 vs 1 in nth place in answer\n", - " output['ans'] = (prob1/(prob_0+prob1))\n", - " # FIXME output batch\n", - " return dict(hidden_states=output['hidden_states'], ans=output['ans'], text_ans=text_ans, text_q=text_q\n", - "# , attentions=output['attentions']\n", - " )\n", - "\n", - "def get_hidden_states(model, tokenizer, input_text, layers=[2, -2], model_type=\"encoder\"):\n", - " fn = {\n", - " \"decoder\": get_decoder_hidden_states}[model_type]\n", - "\n", - " return fn(model, tokenizer, input_text, layers=layers)" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [], - "source": [ - "# tokenizer.__call__?" - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.048590Z", - "start_time": "2023-05-20T02:27:50.046873Z" - } - }, - "outputs": [], - "source": [ - "# input_text = [format_imdb(text, 0)]\n", - "# input_text = [i + tokenizer.eos_token for i in input_text]\n", - "# input_ids = tokenizer(input_text, \n", - "# return_tensors=\"pt\",\n", - "# truncation=True, \n", - "# padding=True,\n", - "# max_length=300).input_ids.to(model.device)\n", - "# print(tokenizer.decode(input_ids[0]))" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.695875Z", - "start_time": "2023-05-20T02:27:50.205135Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "# unit test\n", - "idx = 0\n", - "text, true_label = data[idx][\"content\"], data[idx][\"label\"]\n", - "neg_hs = get_hidden_states(model, tokenizer, format_imdb(text, 0), model_type=model_type)\n", - "pos_hs = get_hidden_states(model, tokenizer, format_imdb(text, 1), model_type=model_type)\n", - "# neg_hs" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.700337Z", - "start_time": "2023-05-20T02:27:50.697307Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "----------------------------------------input----------------------------------------\n", - "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\n", - "\n", - "### Instruction:\n", - "Is this review negative?\n", - "\n", - "### Input:\n", - "My lovely Pat has one of the GREAT voices of her generation. I have listened to this CD for YEARS and I still LOVE IT. When I'm in a good mood it makes me feel better. A bad mood just evaporates like sugar in the rain. This CD just oozes LIFE. Vocals are jusat STUUNNING and lyrics just kill. One of life's hidden gems. This is a desert isle CD in my book. Why she never made it big is just beyond me. Everytime I play this, no matter black, white, young, old, male, female EVERYBODY says one thing \"Who was that singing ?\"\n", - "\n", - "### Response:\n", - "\n", - "----------------------------------------answ----------------------------------------\n", - " is a exampleal will how method that whichired with a image and can the information for\n", - " a Python that explainsately addressesments the instruction.\n", - "\n", - "Task# Instruction: PleasePlease there the helpful or\n", - "\n", - "### Input:\n", - "Yes bely vacag been of the mostREATEATE in our generation. Her' never to her album over hoursEARS and it still canVE it! I needm feeling a bad mood, makes me feel even, WhenMA mood it disappaporates. a in hot rain.\n", - " is is makesozes withIFE and Itivaals are topawss perfectUNUNNING. theics are make me I of the's little treems. is a M islandle disc for my book. don' made it big I beyond beyond me.one I listen this CD I matter what or white, young or old, male, female,VERYONEDY lov \" thing:W is that?\"?\"\" and\n", - "### Response:\n", - "The\n", - "================================================================================\n", - "----------------------------------------input----------------------------------------\n", - "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.\n", - "\n", - "### Instruction:\n", - "Is this review positive?\n", - "\n", - "### Input:\n", - "My lovely Pat has one of the GREAT voices of her generation. I have listened to this CD for YEARS and I still LOVE IT. When I'm in a good mood it makes me feel better. A bad mood just evaporates like sugar in the rain. This CD just oozes LIFE. Vocals are jusat STUUNNING and lyrics just kill. One of life's hidden gems. This is a desert isle CD in my book. Why she never made it big is just beyond me. Everytime I play this, no matter black, white, young, old, male, female EVERYBODY says one thing \"Who was that singing ?\"\n", - "\n", - "### Response:\n", - "\n", - "----------------------------------------answ----------------------------------------\n", - " is a exampleal will how method that whichired with a image and can the information for\n", - " a Python that explainsately addressesments the instruction.\n", - "\n", - "Task# Instruction: PleasePlease there the helpful or\n", - "\n", - "### Input:\n", - "Yes friendely wifeag been of the mostREATEATE in our generation. Her' never to her album over hoursEARS and it still canVE it!\n", - " I needm feeling a bad mood, makes me feel even, When++ mood it disappaporates. a in hot rain. I is is makesozes withIFE and Itocals are topawss perfectUNNSNING. theics are make me I of the's little treems. is a M islandle disc for my book. haven' made it big I beyond beyond me.one I listen this CD I matter what or I, young or old, male, female,VERYONEDY lov \" thing:W is that?\"?\"\" and\n", - "### Response:\n", - "The\n", - "--------------------------------------------------------------------------------\n" - ] - } - ], - "source": [ - "print('-'*40+'input'+'-'*40)\n", - "print(neg_hs['text_q'][0])\n", - "print('-'*40+'answ'+'-'*40)\n", - "print(neg_hs['text_ans'][0])\n", - "print('='*80)\n", - "print('-'*40+'input'+'-'*40)\n", - "print(pos_hs['text_q'][0])\n", - "print('-'*40+'answ'+'-'*40)\n", - "print(pos_hs['text_ans'][0])\n", - "print('-'*80)" - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:27:50.723482Z", - "start_time": "2023-05-20T02:27:50.701252Z" - }, - "scrolled": true - }, - "outputs": [], - "source": [ - "# # unit tests\n", - "# idx = 0\n", - "# n=10\n", - "# batch_size=3\n", - "# ds_subset = data['test'].shuffle(42).select(range(n))\n", - "# dl = DataLoader(ds_subset, batch_size=batch_size, shuffle=True)\n", - "# batch = next(iter(dl))\n", - "\n", - "# texts, true_labels = batch[\"content\"], batch[\"label\"]\n", - "# neg_hs = get_hidden_states(model, tokenizer, format_imdbs(texts, 0), model_type=model_type)\n", - "# neg_hs\n", - "# for k,v in neg_hs.items():\n", - "# print(k, v.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Now let's write code for formatting data and for getting all the hidden states." - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:04.246539Z", - "start_time": "2023-05-20T02:28:04.242460Z" - } - }, - "outputs": [], - "source": [ - "\n", - "\n", - "def get_hidden_states_many_examples(model, tokenizer, data, model_type, n=100, layers=[2, -2], batch_size=3):\n", - " \"\"\"\n", - " Given an encoder-decoder model, a list of data, computes the contrast hidden states on n random examples.\n", - " Returns numpy arrays of shape (n, hidden_dim) for each candidate label, along with a boolean numpy array of shape (n,)\n", - " with the ground truth labels\n", - " \n", - " This is deliberately simple so that it's easy to understand, rather than being optimized for efficiency\n", - " \"\"\"\n", - " # setup\n", - " model.eval()\n", - " \n", - " res = []\n", - " \n", - " ds_subset = data.shuffle(42).select(range(n))\n", - " dl = DataLoader(ds_subset, batch_size=batch_size, shuffle=True)\n", - " for batch in tqdm(dl):\n", - " text, true_label = batch[\"content\"], batch[\"label\"]\n", - " neg = get_hidden_states(model, tokenizer, format_imdbs(text, 0), model_type=model_type, layers=layers)\n", - " pos = get_hidden_states(model, tokenizer, format_imdbs(text, 1), model_type=model_type, layers=layers)\n", - "\n", - " # collect\n", - " b = len(text)\n", - "# print(neg['hidden_states'].shape)\n", - " res.append([\n", - " neg['hidden_states'].reshape((b,-1)),\n", - " pos['hidden_states'].reshape((b,-1)),\n", - " true_label,\n", - " neg['ans'], \n", - " pos['ans'], \n", - " ])\n", - " \n", - " # FIXME not all the hidden state are the same size, wat\n", - " res = [np.concatenate(r) for r in zip(*res)]\n", - " return res\n", - " all_neg_hs, all_pos_hs, all_gt_labels, all_neg_ans, all_pos_ans = res\n", - " return all_neg_hs, all_pos_hs, all_gt_labels, all_neg_ans, all_pos_ans\n", - "# return all_neg_hs, all_pos_hs, all_gt_labels, np.array(all_neg_ans), np.array(all_pos_ans)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T03:15:48.077547Z", - "start_time": "2023-05-07T03:15:48.074666Z" - } - }, - "source": [ - "# Lets verify that the models answers are good" - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:04.574087Z", - "start_time": "2023-05-20T02:28:04.572316Z" - } - }, - "outputs": [], - "source": [ - "# neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(model, tokenizer, data, model_type, n=10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Speed\n", - "\n", - "- 60second for 100 no batching. 1.7 ex/s" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:05.387382Z", - "start_time": "2023-05-20T02:28:05.033921Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 67, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "gc.collect()\n", - "torch.cuda.empty_cache()\n", - "gc.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.747656Z", - "start_time": "2023-05-20T02:28:05.388608Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Loading cached shuffled indices for dataset at /home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc/cache-0a5d0b47b5e8dfc6.arrow\n", - "100%|██████████| 34/34 [00:24<00:00, 1.41it/s]\n" - ] - }, - { - "data": { - "text/plain": [ - "0" - ] - }, - "execution_count": 68, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(model, tokenizer, data, model_type)\n", - "\n", - "\n", - "gc.collect()\n", - "torch.cuda.empty_cache()\n", - "gc.collect()" - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.749712Z", - "start_time": "2023-05-20T02:28:35.749703Z" - } - }, - "outputs": [], - "source": [ - "# all_pos_ans" - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.750431Z", - "start_time": "2023-05-20T02:28:35.750421Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.5260104041616647, 0.46078431372549017)" - ] - }, - "execution_count": 70, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# roc_auc_score\n", - "pos_score = roc_auc_score(y, all_pos_ans)\n", - "neg_score = roc_auc_score(y, all_neg_ans)\n", - "pos_score, neg_score" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-14T11:32:21.359783Z", - "start_time": "2023-05-14T11:32:20.787141Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 71, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.751184Z", - "start_time": "2023-05-20T02:28:35.751175Z" - }, - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "(0.49, 0.51)" - ] - }, - "execution_count": 71, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# accuracy_score\n", - "pos_score = accuracy_score(y, (all_pos_ans>0.)*1.0)\n", - "neg_score = accuracy_score(y, (all_neg_ans<0.5)*1.0)\n", - "pos_score, neg_score" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Let's verify that the model's representations are good\n", - "\n", - "Before trying CCS, let's make sure there exists a direction that classifies examples as true vs false with high accuracy; if supervised logistic regression accuracy is bad, there's no hope of unsupervised CCS doing well.\n", - "\n", - "Note that because logistic regression is supervised we expect it to do better but to have worse generalisation that equivilent unsupervised methods. However in this case CSS is using a deeper model so it is more complicated." - ] - }, - { - "cell_type": "code", - "execution_count": 72, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.751934Z", - "start_time": "2023-05-20T02:28:35.751926Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Logistic regression accuracy: 1.0 [TRAIN]\n", - "Logistic regression accuracy: 1.0 [TEST]\n" - ] - } - ], - "source": [ - "# let's create a simple 50/50 train split (the data is already randomized)\n", - "n = len(y)\n", - "\n", - "neg_hs2 = torch.from_numpy(np.stack([h.flatten() for h in neg_hs], 0))\n", - "pos_hs2 = torch.from_numpy(np.stack([h.flatten() for h in pos_hs], 0))\n", - "\n", - "neg_hs_train, neg_hs_test = neg_hs2[:n//2], neg_hs2[n//2:]\n", - "pos_hs_train, pos_hs_test = pos_hs2[:n//2], pos_hs2[n//2:]\n", - "y_train, y_test = y[:n//2], y[n//2:]\n", - "\n", - "# for simplicity we can just take the difference between positive and negative hidden states\n", - "# (concatenating also works fine)\n", - "x_train = neg_hs_train - pos_hs_train\n", - "x_test = neg_hs_test - pos_hs_test\n", - "\n", - "lr = LogisticRegression(class_weight=\"balanced\")\n", - "lr.fit(x_train, y_train)\n", - "print(\"Logistic regression accuracy: {} [TRAIN]\".format(lr.score(x_train, y_train)))\n", - "print(\"Logistic regression accuracy: {} [TEST]\".format(lr.score(x_test, y_test)))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-14T00:05:52.801860Z", - "start_time": "2023-05-14T00:05:52.784513Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Now let's try CCS" - ] - }, - { - "cell_type": "code", - "execution_count": 73, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.752548Z", - "start_time": "2023-05-20T02:28:35.752540Z" - } - }, - "outputs": [], - "source": [ - "class MLPProbe(nn.Module):\n", - " def __init__(self, d):\n", - " super().__init__()\n", - " self.net = nn.Sequential(\n", - " nn.Linear(d, 100),\n", - " nn.ReLU(),\n", - " nn.Linear(100, 100),\n", - " nn.ReLU(),\n", - " nn.Linear(100, 100),\n", - " nn.ReLU(),\n", - "# nn.Linear(100, 100),\n", - "# nn.ReLU(),\n", - " nn.Linear(100, 1),\n", - " nn.Sigmoid(),\n", - " )\n", - "\n", - " def forward(self, x):\n", - " return self.net(x)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T05:40:58.250804Z", - "start_time": "2023-05-07T05:40:58.230537Z" - } - }, - "source": [ - "## Train" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T11:16:41.661985Z", - "start_time": "2023-05-07T11:16:41.650129Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 74, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.753297Z", - "start_time": "2023-05-20T02:28:35.753288Z" - } - }, - "outputs": [], - "source": [ - "# # Train CCS without any labels\n", - "# ccs = CCS(neg_hs_train, pos_hs_train, linear=False)\n", - "# ccs.repeated_train()\n", - "\n", - "# # Evaluate\n", - "# ccs_acc = ccs.get_acc(neg_hs_train, pos_hs_train, y_train)\n", - "# print(\"CCS nonlinear train accuracy: {}\".format(ccs_acc))\n", - "\n", - "# ccs_acc = ccs.get_acc(neg_hs_test, pos_hs_test, y_test)\n", - "# print(\"CCS nonlinear test accuracy: {}\".format(ccs_acc))" - ] - }, - { - "cell_type": "code", - "execution_count": 75, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.754161Z", - "start_time": "2023-05-20T02:28:35.754151Z" - } - }, - "outputs": [], - "source": [ - "# # Train CCS without any labels\n", - "# ccs = CCS(neg_hs_train, pos_hs_train, linear=True)\n", - "# ccs.repeated_train()\n", - "\n", - "# # Evaluate\n", - "# ccs_acc = ccs.get_acc(neg_hs_train, pos_hs_train, y_train)\n", - "# print(\"CCS train accuracy: {}\".format(ccs_acc))\n", - "\n", - "# ccs_acc = ccs.get_acc(neg_hs_test, pos_hs_test, y_test)\n", - "# print(\"CCS test accuracy: {}\".format(ccs_acc))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T11:12:59.972960Z", - "start_time": "2023-05-07T11:12:59.964090Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# lightning" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-19T04:12:55.004017Z", - "start_time": "2023-05-19T04:12:55.004011Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DataModule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-14T11:34:43.243172Z", - "start_time": "2023-05-14T11:34:43.240582Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 76, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.754973Z", - "start_time": "2023-05-20T02:28:35.754964Z" - }, - "scrolled": true - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Found cached dataset amazon_polarity (/home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc)\n", - "Loading cached shuffled indices for dataset at /home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc/cache-0a5d0b47b5e8dfc6.arrow\n", - " 85%|████████▌ | 57/67 [00:40<00:07, 1.40it/s]\n" - ] - }, - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:87                                                                                   \n",
-       "                                                                                                  \n",
-       "   84                                                                                             \n",
-       "   85 # test                                                                                      \n",
-       "   86 dm = IMBDHSDataModule(model, tokenizer)                                                     \n",
-       " 87 dm.setup('train')                                                                           \n",
-       "   88 dl = dm.val_dataloader()                                                                    \n",
-       "   89 b = next(iter(dl))                                                                          \n",
-       "   90 b                                                                                           \n",
-       "                                                                                                  \n",
-       " in setup:32                                                                                      \n",
-       "                                                                                                  \n",
-       "   29 │   │                                                                                       \n",
-       "   30 │   │   self.dataset = load_dataset(self.hparams.dataset_name, split=\"test\")                \n",
-       "   31 │   │                                                                                       \n",
-       " 32 │   │   neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(      \n",
-       "   33 │   │   │   self.model, self.tokenizer, self.dataset, self.hparams.model_type, n=self.hp    \n",
-       "   34 │   │                                                                                       \n",
-       "   35 │   │   # let's create a simple 50/50 train split (the data is already randomized)          \n",
-       "                                                                                                  \n",
-       " in get_hidden_states_many_examples:19                                                            \n",
-       "                                                                                                  \n",
-       "   16 for batch in tqdm(dl):                                                                  \n",
-       "   17 │   │   text, true_label = batch[\"content\"], batch[\"label\"]                                 \n",
-       "   18 │   │   neg = get_hidden_states(model, tokenizer, format_imdbs(text, 0), model_type=mode    \n",
-       " 19 │   │   pos = get_hidden_states(model, tokenizer, format_imdbs(text, 1), model_type=mode    \n",
-       "   20 │   │                                                                                       \n",
-       "   21 │   │   # collect                                                                           \n",
-       "   22 │   │   b = len(text)                                                                       \n",
-       "                                                                                                  \n",
-       " in get_hidden_states:80                                                                          \n",
-       "                                                                                                  \n",
-       "   77 fn = {                                                                                  \n",
-       "   78 │   │     \"decoder\": get_decoder_hidden_states}[model_type]                                 \n",
-       "   79                                                                                         \n",
-       " 80 return fn(model, tokenizer, input_text, layers=layers)                                  \n",
-       "   81                                                                                             \n",
-       "                                                                                                  \n",
-       " in get_decoder_hidden_states:39                                                                  \n",
-       "                                                                                                  \n",
-       "   36                                                                                         \n",
-       "   37 # forward pass                                                                          \n",
-       "   38 with torch.no_grad():                                                                   \n",
-       " 39 │   │   output = model(input_ids,                                                           \n",
-       "   40 │   │   │   │   │      output_hidden_states=True,                                           \n",
-       "   41 #                        , output_attentions=True                                           \n",
-       "   42 │   │   │   │   │      use_cache=True,                                                      \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/module.py:1501 in \n",
-       " _call_impl                                                                                       \n",
-       "                                                                                                  \n",
-       "   1498 │   │   if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks   \n",
-       "   1499 │   │   │   │   or _global_backward_pre_hooks or _global_backward_hooks                   \n",
-       "   1500 │   │   │   │   or _global_forward_hooks or _global_forward_pre_hooks):                   \n",
-       " 1501 │   │   │   return forward_call(*args, **kwargs)                                          \n",
-       "   1502 │   │   # Do not call functions when jit is used                                          \n",
-       "   1503 │   │   full_backward_hooks, non_full_backward_hooks = [], []                             \n",
-       "   1504 │   │   backward_pre_hooks = []                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/hooks.py:165 in         \n",
-       " new_forward                                                                                      \n",
-       "                                                                                                  \n",
-       "   162 │   │   │   with torch.no_grad():                                                          \n",
-       "   163 │   │   │   │   output = old_forward(*args, **kwargs)                                      \n",
-       "   164 │   │   else:                                                                              \n",
-       " 165 │   │   │   output = old_forward(*args, **kwargs)                                          \n",
-       "   166 │   │   return module._hf_hook.post_forward(module, output)                                \n",
-       "   167                                                                                        \n",
-       "   168 module.forward = new_forward                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/modeling \n",
-       " _llama.py:688 in forward                                                                         \n",
-       "                                                                                                  \n",
-       "   685 │   │   return_dict = return_dict if return_dict is not None else self.config.use_return   \n",
-       "   686 │   │                                                                                      \n",
-       "   687 │   │   # decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)    \n",
-       " 688 │   │   outputs = self.model(                                                              \n",
-       "   689 │   │   │   input_ids=input_ids,                                                           \n",
-       "   690 │   │   │   attention_mask=attention_mask,                                                 \n",
-       "   691 │   │   │   position_ids=position_ids,                                                     \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/module.py:1501 in \n",
-       " _call_impl                                                                                       \n",
-       "                                                                                                  \n",
-       "   1498 │   │   if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks   \n",
-       "   1499 │   │   │   │   or _global_backward_pre_hooks or _global_backward_hooks                   \n",
-       "   1500 │   │   │   │   or _global_forward_hooks or _global_forward_pre_hooks):                   \n",
-       " 1501 │   │   │   return forward_call(*args, **kwargs)                                          \n",
-       "   1502 │   │   # Do not call functions when jit is used                                          \n",
-       "   1503 │   │   full_backward_hooks, non_full_backward_hooks = [], []                             \n",
-       "   1504 │   │   backward_pre_hooks = []                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/hooks.py:165 in         \n",
-       " new_forward                                                                                      \n",
-       "                                                                                                  \n",
-       "   162 │   │   │   with torch.no_grad():                                                          \n",
-       "   163 │   │   │   │   output = old_forward(*args, **kwargs)                                      \n",
-       "   164 │   │   else:                                                                              \n",
-       " 165 │   │   │   output = old_forward(*args, **kwargs)                                          \n",
-       "   166 │   │   return module._hf_hook.post_forward(module, output)                                \n",
-       "   167                                                                                        \n",
-       "   168 module.forward = new_forward                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/modeling \n",
-       " _llama.py:578 in forward                                                                         \n",
-       "                                                                                                  \n",
-       "   575 │   │   │   │   │   None,                                                                  \n",
-       "   576 │   │   │   │   )                                                                          \n",
-       "   577 │   │   │   else:                                                                          \n",
-       " 578 │   │   │   │   layer_outputs = decoder_layer(                                             \n",
-       "   579 │   │   │   │   │   hidden_states,                                                         \n",
-       "   580 │   │   │   │   │   attention_mask=attention_mask,                                         \n",
-       "   581 │   │   │   │   │   position_ids=position_ids,                                             \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/module.py:1501 in \n",
-       " _call_impl                                                                                       \n",
-       "                                                                                                  \n",
-       "   1498 │   │   if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks   \n",
-       "   1499 │   │   │   │   or _global_backward_pre_hooks or _global_backward_hooks                   \n",
-       "   1500 │   │   │   │   or _global_forward_hooks or _global_forward_pre_hooks):                   \n",
-       " 1501 │   │   │   return forward_call(*args, **kwargs)                                          \n",
-       "   1502 │   │   # Do not call functions when jit is used                                          \n",
-       "   1503 │   │   full_backward_hooks, non_full_backward_hooks = [], []                             \n",
-       "   1504 │   │   backward_pre_hooks = []                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/hooks.py:165 in         \n",
-       " new_forward                                                                                      \n",
-       "                                                                                                  \n",
-       "   162 │   │   │   with torch.no_grad():                                                          \n",
-       "   163 │   │   │   │   output = old_forward(*args, **kwargs)                                      \n",
-       "   164 │   │   else:                                                                              \n",
-       " 165 │   │   │   output = old_forward(*args, **kwargs)                                          \n",
-       "   166 │   │   return module._hf_hook.post_forward(module, output)                                \n",
-       "   167                                                                                        \n",
-       "   168 module.forward = new_forward                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/modeling \n",
-       " _llama.py:306 in forward                                                                         \n",
-       "                                                                                                  \n",
-       "   303 │   │   # Fully Connected                                                                  \n",
-       "   304 │   │   residual = hidden_states                                                           \n",
-       "   305 │   │   hidden_states = self.post_attention_layernorm(hidden_states)                       \n",
-       " 306 │   │   hidden_states = self.mlp(hidden_states)                                            \n",
-       "   307 │   │   hidden_states = residual + hidden_states                                           \n",
-       "   308 │   │                                                                                      \n",
-       "   309 │   │   outputs = (hidden_states,)                                                         \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/module.py:1501 in \n",
-       " _call_impl                                                                                       \n",
-       "                                                                                                  \n",
-       "   1498 │   │   if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks   \n",
-       "   1499 │   │   │   │   or _global_backward_pre_hooks or _global_backward_hooks                   \n",
-       "   1500 │   │   │   │   or _global_forward_hooks or _global_forward_pre_hooks):                   \n",
-       " 1501 │   │   │   return forward_call(*args, **kwargs)                                          \n",
-       "   1502 │   │   # Do not call functions when jit is used                                          \n",
-       "   1503 │   │   full_backward_hooks, non_full_backward_hooks = [], []                             \n",
-       "   1504 │   │   backward_pre_hooks = []                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/hooks.py:165 in         \n",
-       " new_forward                                                                                      \n",
-       "                                                                                                  \n",
-       "   162 │   │   │   with torch.no_grad():                                                          \n",
-       "   163 │   │   │   │   output = old_forward(*args, **kwargs)                                      \n",
-       "   164 │   │   else:                                                                              \n",
-       " 165 │   │   │   output = old_forward(*args, **kwargs)                                          \n",
-       "   166 │   │   return module._hf_hook.post_forward(module, output)                                \n",
-       "   167                                                                                        \n",
-       "   168 module.forward = new_forward                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/modeling \n",
-       " _llama.py:158 in forward                                                                         \n",
-       "                                                                                                  \n",
-       "   155 │   │   self.act_fn = ACT2FN[hidden_act]                                                   \n",
-       "   156                                                                                        \n",
-       "   157 def forward(self, x):                                                                  \n",
-       " 158 │   │   return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))            \n",
-       "   159                                                                                            \n",
-       "   160                                                                                            \n",
-       "   161 class LlamaAttention(nn.Module):                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/module.py:1501 in \n",
-       " _call_impl                                                                                       \n",
-       "                                                                                                  \n",
-       "   1498 │   │   if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks   \n",
-       "   1499 │   │   │   │   or _global_backward_pre_hooks or _global_backward_hooks                   \n",
-       "   1500 │   │   │   │   or _global_forward_hooks or _global_forward_pre_hooks):                   \n",
-       " 1501 │   │   │   return forward_call(*args, **kwargs)                                          \n",
-       "   1502 │   │   # Do not call functions when jit is used                                          \n",
-       "   1503 │   │   full_backward_hooks, non_full_backward_hooks = [], []                             \n",
-       "   1504 │   │   backward_pre_hooks = []                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/hooks.py:165 in         \n",
-       " new_forward                                                                                      \n",
-       "                                                                                                  \n",
-       "   162 │   │   │   with torch.no_grad():                                                          \n",
-       "   163 │   │   │   │   output = old_forward(*args, **kwargs)                                      \n",
-       "   164 │   │   else:                                                                              \n",
-       " 165 │   │   │   output = old_forward(*args, **kwargs)                                          \n",
-       "   166 │   │   return module._hf_hook.post_forward(module, output)                                \n",
-       "   167                                                                                        \n",
-       "   168 module.forward = new_forward                                                           \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/nn/modules.py:242 in  \n",
-       " forward                                                                                          \n",
-       "                                                                                                  \n",
-       "   239 │   │   if self.bias is not None and self.bias.dtype != x.dtype:                           \n",
-       "   240 │   │   │   self.bias.data = self.bias.data.to(x.dtype)                                    \n",
-       "   241 │   │                                                                                      \n",
-       " 242 │   │   out = bnb.matmul(x, self.weight, bias=self.bias, state=self.state)                 \n",
-       "   243 │   │   if not self.state.has_fp16_weights:                                                \n",
-       "   244 │   │   │   if self.state.CB is not None and self.state.CxB is not None:                   \n",
-       "   245 │   │   │   │   # we converted 8-bit row major to turing/ampere format in the first infe   \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/autograd/_functions.p \n",
-       " y:488 in matmul                                                                                  \n",
-       "                                                                                                  \n",
-       "   485 state = state or MatmulLtState()                                                       \n",
-       "   486 if threshold > 0.0:                                                                    \n",
-       "   487 │   │   state.threshold = threshold                                                        \n",
-       " 488 return MatMul8bitLt.apply(A, B, out, bias, state)                                      \n",
-       "   489                                                                                            \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/autograd/function.py:506 in  \n",
-       " apply                                                                                            \n",
-       "                                                                                                  \n",
-       "   503 │   │   if not torch._C._are_functorch_transforms_active():                                \n",
-       "   504 │   │   │   # See NOTE: [functorch vjp and autograd interaction]                           \n",
-       "   505 │   │   │   args = _functorch.utils.unwrap_dead_wrappers(args)                             \n",
-       " 506 │   │   │   return super().apply(*args, **kwargs)  # type: ignore[misc]                    \n",
-       "   507 │   │                                                                                      \n",
-       "   508 │   │   if cls.setup_context == _SingleLevelFunction.setup_context:                        \n",
-       "   509 │   │   │   raise RuntimeError(                                                            \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/autograd/_functions.p \n",
-       " y:364 in forward                                                                                 \n",
-       "                                                                                                  \n",
-       "   361 │   │   │                                                                                  \n",
-       "   362 │   │   │   state.subB = (outliers * state.SCB.view(-1, 1) / 127.0).t().contiguous().to(   \n",
-       "   363 │   │   │   CA[:, state.idx.long()] = 0                                                    \n",
-       " 364 │   │   │   CAt[:, state.idx.long()] = 0                                                   \n",
-       "   365 │   │   │   subA = A[:, state.idx.long()]                                                  \n",
-       "   366 │   │                                                                                      \n",
-       "   367 │   │   shapeB = state.SB[0] if state.SB else B.shape                                      \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "KeyboardInterrupt\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m87\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m84 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m85 \u001b[0m\u001b[2m# test\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m86 \u001b[0mdm = IMBDHSDataModule(model, tokenizer) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m87 dm.setup(\u001b[33m'\u001b[0m\u001b[33mtrain\u001b[0m\u001b[33m'\u001b[0m) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m88 \u001b[0mdl = dm.val_dataloader() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m89 \u001b[0mb = \u001b[96mnext\u001b[0m(\u001b[96miter\u001b[0m(dl)) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m90 \u001b[0mb \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92msetup\u001b[0m:\u001b[94m32\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m29 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m30 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[96mself\u001b[0m.dataset = load_dataset(\u001b[96mself\u001b[0m.hparams.dataset_name, split=\u001b[33m\"\u001b[0m\u001b[33mtest\u001b[0m\u001b[33m\"\u001b[0m) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m31 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m32 \u001b[2m│ │ \u001b[0mneg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m33 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[96mself\u001b[0m.model, \u001b[96mself\u001b[0m.tokenizer, \u001b[96mself\u001b[0m.dataset, \u001b[96mself\u001b[0m.hparams.model_type, n=\u001b[96mself\u001b[0m.hp \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m34 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m35 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# let's create a simple 50/50 train split (the data is already randomized)\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mget_hidden_states_many_examples\u001b[0m:\u001b[94m19\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m16 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mfor\u001b[0m batch \u001b[95min\u001b[0m tqdm(dl): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m17 \u001b[0m\u001b[2m│ │ \u001b[0mtext, true_label = batch[\u001b[33m\"\u001b[0m\u001b[33mcontent\u001b[0m\u001b[33m\"\u001b[0m], batch[\u001b[33m\"\u001b[0m\u001b[33mlabel\u001b[0m\u001b[33m\"\u001b[0m] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m18 \u001b[0m\u001b[2m│ │ \u001b[0mneg = get_hidden_states(model, tokenizer, format_imdbs(text, \u001b[94m0\u001b[0m), model_type=mode \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m19 \u001b[2m│ │ \u001b[0mpos = get_hidden_states(model, tokenizer, format_imdbs(text, \u001b[94m1\u001b[0m), model_type=mode \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m20 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m21 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# collect\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m22 \u001b[0m\u001b[2m│ │ \u001b[0mb = \u001b[96mlen\u001b[0m(text) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mget_hidden_states\u001b[0m:\u001b[94m80\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m77 \u001b[0m\u001b[2m│ \u001b[0mfn = { \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m78 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[33m\"\u001b[0m\u001b[33mdecoder\u001b[0m\u001b[33m\"\u001b[0m: get_decoder_hidden_states}[model_type] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m79 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m80 \u001b[2m│ \u001b[0m\u001b[94mreturn\u001b[0m fn(model, tokenizer, input_text, layers=layers) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m81 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mget_decoder_hidden_states\u001b[0m:\u001b[94m39\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m36 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m37 \u001b[0m\u001b[2m│ \u001b[0m\u001b[2m# forward pass\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m38 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mwith\u001b[0m torch.no_grad(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m39 \u001b[2m│ │ \u001b[0moutput = model(input_ids, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m40 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0moutput_hidden_states=\u001b[94mTrue\u001b[0m, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m41 \u001b[0m\u001b[2m# , output_attentions=True\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m42 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0muse_cache=\u001b[94mTrue\u001b[0m, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/\u001b[0m\u001b[1;33mmodule.py\u001b[0m:\u001b[94m1501\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92m_call_impl\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1498 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m (\u001b[96mself\u001b[0m._backward_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._backward_pre_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._forward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1499 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_backward_pre_hooks \u001b[95mor\u001b[0m _global_backward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1500 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_forward_hooks \u001b[95mor\u001b[0m _global_forward_pre_hooks): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1501 \u001b[2m│ │ │ \u001b[0m\u001b[94mreturn\u001b[0m forward_call(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1502 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Do not call functions when jit is used\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1503 \u001b[0m\u001b[2m│ │ \u001b[0mfull_backward_hooks, non_full_backward_hooks = [], [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1504 \u001b[0m\u001b[2m│ │ \u001b[0mbackward_pre_hooks = [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/\u001b[0m\u001b[1;33mhooks.py\u001b[0m:\u001b[94m165\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mnew_forward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m162 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwith\u001b[0m torch.no_grad(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m163 \u001b[0m\u001b[2m│ │ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m164 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m165 \u001b[2m│ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m166 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m module._hf_hook.post_forward(module, output) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m167 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m168 \u001b[0m\u001b[2m│ \u001b[0mmodule.forward = new_forward \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/\u001b[0m\u001b[1;33mmodeling\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[1;33m_llama.py\u001b[0m:\u001b[94m688\u001b[0m in \u001b[92mforward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m685 \u001b[0m\u001b[2m│ │ \u001b[0mreturn_dict = return_dict \u001b[94mif\u001b[0m return_dict \u001b[95mis\u001b[0m \u001b[95mnot\u001b[0m \u001b[94mNone\u001b[0m \u001b[94melse\u001b[0m \u001b[96mself\u001b[0m.config.use_return \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m686 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m687 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# decoder outputs consists of (dec_features, layer_state, dec_hidden, dec_attn)\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m688 \u001b[2m│ │ \u001b[0moutputs = \u001b[96mself\u001b[0m.model( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m689 \u001b[0m\u001b[2m│ │ │ \u001b[0minput_ids=input_ids, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m690 \u001b[0m\u001b[2m│ │ │ \u001b[0mattention_mask=attention_mask, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m691 \u001b[0m\u001b[2m│ │ │ \u001b[0mposition_ids=position_ids, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/\u001b[0m\u001b[1;33mmodule.py\u001b[0m:\u001b[94m1501\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92m_call_impl\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1498 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m (\u001b[96mself\u001b[0m._backward_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._backward_pre_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._forward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1499 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_backward_pre_hooks \u001b[95mor\u001b[0m _global_backward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1500 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_forward_hooks \u001b[95mor\u001b[0m _global_forward_pre_hooks): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1501 \u001b[2m│ │ │ \u001b[0m\u001b[94mreturn\u001b[0m forward_call(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1502 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Do not call functions when jit is used\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1503 \u001b[0m\u001b[2m│ │ \u001b[0mfull_backward_hooks, non_full_backward_hooks = [], [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1504 \u001b[0m\u001b[2m│ │ \u001b[0mbackward_pre_hooks = [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/\u001b[0m\u001b[1;33mhooks.py\u001b[0m:\u001b[94m165\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mnew_forward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m162 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwith\u001b[0m torch.no_grad(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m163 \u001b[0m\u001b[2m│ │ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m164 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m165 \u001b[2m│ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m166 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m module._hf_hook.post_forward(module, output) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m167 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m168 \u001b[0m\u001b[2m│ \u001b[0mmodule.forward = new_forward \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/\u001b[0m\u001b[1;33mmodeling\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[1;33m_llama.py\u001b[0m:\u001b[94m578\u001b[0m in \u001b[92mforward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m575 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0m\u001b[94mNone\u001b[0m, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m576 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m577 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m578 \u001b[2m│ │ │ │ \u001b[0mlayer_outputs = decoder_layer( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m579 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mhidden_states, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m580 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mattention_mask=attention_mask, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m581 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mposition_ids=position_ids, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/\u001b[0m\u001b[1;33mmodule.py\u001b[0m:\u001b[94m1501\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92m_call_impl\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1498 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m (\u001b[96mself\u001b[0m._backward_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._backward_pre_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._forward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1499 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_backward_pre_hooks \u001b[95mor\u001b[0m _global_backward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1500 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_forward_hooks \u001b[95mor\u001b[0m _global_forward_pre_hooks): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1501 \u001b[2m│ │ │ \u001b[0m\u001b[94mreturn\u001b[0m forward_call(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1502 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Do not call functions when jit is used\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1503 \u001b[0m\u001b[2m│ │ \u001b[0mfull_backward_hooks, non_full_backward_hooks = [], [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1504 \u001b[0m\u001b[2m│ │ \u001b[0mbackward_pre_hooks = [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/\u001b[0m\u001b[1;33mhooks.py\u001b[0m:\u001b[94m165\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mnew_forward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m162 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwith\u001b[0m torch.no_grad(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m163 \u001b[0m\u001b[2m│ │ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m164 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m165 \u001b[2m│ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m166 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m module._hf_hook.post_forward(module, output) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m167 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m168 \u001b[0m\u001b[2m│ \u001b[0mmodule.forward = new_forward \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/\u001b[0m\u001b[1;33mmodeling\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[1;33m_llama.py\u001b[0m:\u001b[94m306\u001b[0m in \u001b[92mforward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m303 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Fully Connected\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m304 \u001b[0m\u001b[2m│ │ \u001b[0mresidual = hidden_states \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m305 \u001b[0m\u001b[2m│ │ \u001b[0mhidden_states = \u001b[96mself\u001b[0m.post_attention_layernorm(hidden_states) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m306 \u001b[2m│ │ \u001b[0mhidden_states = \u001b[96mself\u001b[0m.mlp(hidden_states) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m307 \u001b[0m\u001b[2m│ │ \u001b[0mhidden_states = residual + hidden_states \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m308 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m309 \u001b[0m\u001b[2m│ │ \u001b[0moutputs = (hidden_states,) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/\u001b[0m\u001b[1;33mmodule.py\u001b[0m:\u001b[94m1501\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92m_call_impl\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1498 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m (\u001b[96mself\u001b[0m._backward_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._backward_pre_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._forward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1499 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_backward_pre_hooks \u001b[95mor\u001b[0m _global_backward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1500 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_forward_hooks \u001b[95mor\u001b[0m _global_forward_pre_hooks): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1501 \u001b[2m│ │ │ \u001b[0m\u001b[94mreturn\u001b[0m forward_call(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1502 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Do not call functions when jit is used\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1503 \u001b[0m\u001b[2m│ │ \u001b[0mfull_backward_hooks, non_full_backward_hooks = [], [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1504 \u001b[0m\u001b[2m│ │ \u001b[0mbackward_pre_hooks = [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/\u001b[0m\u001b[1;33mhooks.py\u001b[0m:\u001b[94m165\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mnew_forward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m162 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwith\u001b[0m torch.no_grad(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m163 \u001b[0m\u001b[2m│ │ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m164 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m165 \u001b[2m│ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m166 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m module._hf_hook.post_forward(module, output) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m167 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m168 \u001b[0m\u001b[2m│ \u001b[0mmodule.forward = new_forward \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/transformers/models/llama/\u001b[0m\u001b[1;33mmodeling\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[1;33m_llama.py\u001b[0m:\u001b[94m158\u001b[0m in \u001b[92mforward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m155 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[96mself\u001b[0m.act_fn = ACT2FN[hidden_act] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m156 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m157 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mdef\u001b[0m \u001b[92mforward\u001b[0m(\u001b[96mself\u001b[0m, x): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m158 \u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96mself\u001b[0m.down_proj(\u001b[96mself\u001b[0m.act_fn(\u001b[96mself\u001b[0m.gate_proj(x)) * \u001b[96mself\u001b[0m.up_proj(x)) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m159 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m160 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m161 \u001b[0m\u001b[94mclass\u001b[0m \u001b[4;92mLlamaAttention\u001b[0m(nn.Module): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/nn/modules/\u001b[0m\u001b[1;33mmodule.py\u001b[0m:\u001b[94m1501\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92m_call_impl\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1498 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m (\u001b[96mself\u001b[0m._backward_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._backward_pre_hooks \u001b[95mor\u001b[0m \u001b[96mself\u001b[0m._forward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1499 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_backward_pre_hooks \u001b[95mor\u001b[0m _global_backward_hooks \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1500 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[95mor\u001b[0m _global_forward_hooks \u001b[95mor\u001b[0m _global_forward_pre_hooks): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1501 \u001b[2m│ │ │ \u001b[0m\u001b[94mreturn\u001b[0m forward_call(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1502 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Do not call functions when jit is used\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1503 \u001b[0m\u001b[2m│ │ \u001b[0mfull_backward_hooks, non_full_backward_hooks = [], [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1504 \u001b[0m\u001b[2m│ │ \u001b[0mbackward_pre_hooks = [] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/accelerate/\u001b[0m\u001b[1;33mhooks.py\u001b[0m:\u001b[94m165\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mnew_forward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m162 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mwith\u001b[0m torch.no_grad(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m163 \u001b[0m\u001b[2m│ │ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m164 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94melse\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m165 \u001b[2m│ │ │ \u001b[0moutput = old_forward(*args, **kwargs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m166 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m module._hf_hook.post_forward(module, output) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m167 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m168 \u001b[0m\u001b[2m│ \u001b[0mmodule.forward = new_forward \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/nn/\u001b[0m\u001b[1;33mmodules.py\u001b[0m:\u001b[94m242\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mforward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m239 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96mself\u001b[0m.bias \u001b[95mis\u001b[0m \u001b[95mnot\u001b[0m \u001b[94mNone\u001b[0m \u001b[95mand\u001b[0m \u001b[96mself\u001b[0m.bias.dtype != x.dtype: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m240 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[96mself\u001b[0m.bias.data = \u001b[96mself\u001b[0m.bias.data.to(x.dtype) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m241 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m242 \u001b[2m│ │ \u001b[0mout = bnb.matmul(x, \u001b[96mself\u001b[0m.weight, bias=\u001b[96mself\u001b[0m.bias, state=\u001b[96mself\u001b[0m.state) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m243 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m \u001b[96mself\u001b[0m.state.has_fp16_weights: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m244 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96mself\u001b[0m.state.CB \u001b[95mis\u001b[0m \u001b[95mnot\u001b[0m \u001b[94mNone\u001b[0m \u001b[95mand\u001b[0m \u001b[96mself\u001b[0m.state.CxB \u001b[95mis\u001b[0m \u001b[95mnot\u001b[0m \u001b[94mNone\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m245 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[2m# we converted 8-bit row major to turing/ampere format in the first infe\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/autograd/\u001b[0m\u001b[1;33m_functions.p\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[1;33my\u001b[0m:\u001b[94m488\u001b[0m in \u001b[92mmatmul\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m485 \u001b[0m\u001b[2m│ \u001b[0mstate = state \u001b[95mor\u001b[0m MatmulLtState() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m486 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mif\u001b[0m threshold > \u001b[94m0.0\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m487 \u001b[0m\u001b[2m│ │ \u001b[0mstate.threshold = threshold \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m488 \u001b[2m│ \u001b[0m\u001b[94mreturn\u001b[0m MatMul8bitLt.apply(A, B, out, bias, state) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m489 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/torch/autograd/\u001b[0m\u001b[1;33mfunction.py\u001b[0m:\u001b[94m506\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mapply\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m503 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[95mnot\u001b[0m torch._C._are_functorch_transforms_active(): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m504 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[2m# See NOTE: [functorch vjp and autograd interaction]\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m505 \u001b[0m\u001b[2m│ │ │ \u001b[0margs = _functorch.utils.unwrap_dead_wrappers(args) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m506 \u001b[2m│ │ │ \u001b[0m\u001b[94mreturn\u001b[0m \u001b[96msuper\u001b[0m().apply(*args, **kwargs) \u001b[2m# type: ignore[misc]\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m507 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m508 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96mcls\u001b[0m.setup_context == _SingleLevelFunction.setup_context: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m509 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[94mraise\u001b[0m \u001b[96mRuntimeError\u001b[0m( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/autograd/\u001b[0m\u001b[1;33m_functions.p\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[1;33my\u001b[0m:\u001b[94m364\u001b[0m in \u001b[92mforward\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m361 \u001b[0m\u001b[2m│ │ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m362 \u001b[0m\u001b[2m│ │ │ \u001b[0mstate.subB = (outliers * state.SCB.view(-\u001b[94m1\u001b[0m, \u001b[94m1\u001b[0m) / \u001b[94m127.0\u001b[0m).t().contiguous().to( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m363 \u001b[0m\u001b[2m│ │ │ \u001b[0mCA[:, state.idx.long()] = \u001b[94m0\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m364 \u001b[2m│ │ │ \u001b[0mCAt[:, state.idx.long()] = \u001b[94m0\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m365 \u001b[0m\u001b[2m│ │ │ \u001b[0msubA = A[:, state.idx.long()] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m366 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m367 \u001b[0m\u001b[2m│ │ \u001b[0mshapeB = state.SB[\u001b[94m0\u001b[0m] \u001b[94mif\u001b[0m state.SB \u001b[94melse\u001b[0m B.shape \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mKeyboardInterrupt\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "\n", - "# def normalize(x):\n", - "# \"\"\"\n", - "# Mean-normalizes the data x (of shape (n, d))\n", - "# If self.var_normalize, also divides by the standard deviation\n", - "# \"\"\"\n", - "# normalized_x = x - x.mean(axis=0, keepdims=True)\n", - "# if self.var_normalize:\n", - "# normalized_x /= normalized_x.std(axis=0, keepdims=True)\n", - "\n", - "# return normalized_x\n", - "\n", - "\n", - "class IMBDHSDataModule(pl.LightningDataModule):\n", - "\n", - " def __init__(self,\n", - " model: AutoModel,\n", - " tokenizer: AutoTokenizer,\n", - " model_type=\"decoder\",\n", - " dataset_name=\"amazon_polarity\",\n", - " batch_size=32,\n", - " n=200,\n", - " ):\n", - " super().__init__()\n", - " self.model = model\n", - " self.tokenizer = tokenizer\n", - " self.save_hyperparameters(ignore=[\"model\", \"tokenizer\"])\n", - "\n", - " def setup(self, stage: str):\n", - "\n", - " self.dataset = load_dataset(self.hparams.dataset_name, split=\"test\")\n", - "\n", - " neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(\n", - " self.model, self.tokenizer, self.dataset, self.hparams.model_type, n=self.hparams.n, layers=[2, -2])\n", - "\n", - " # let's create a simple 50/50 train split (the data is already randomized)\n", - " n = len(y)\n", - " val_split = int(n * 0.5)\n", - " test_split = int(n * 0.75)\n", - " neg_hs_train, pos_hs_train, y_train = neg_hs[:\n", - " val_split], pos_hs[:\n", - " val_split], y[:\n", - " val_split]\n", - " neg_hs_val, pos_hs_val, y_val = neg_hs[val_split:test_split], pos_hs[\n", - " val_split:test_split], y[val_split:test_split]\n", - " neg_hs_test, pos_hs_test, y_test = neg_hs[test_split:], pos_hs[\n", - " test_split:], y[test_split:]\n", - "\n", - " # for simplicity we can just take the difference between positive and negative hidden states\n", - " # (concatenating also works fine)\n", - " self.x_train = neg_hs_train - pos_hs_train\n", - " self.x_val = neg_hs_val - pos_hs_val\n", - " self.x_test = neg_hs_test - pos_hs_test\n", - "\n", - " # normalize\n", - " self.scaler = RobustScaler()\n", - " self.scaler.fit(self.x_train)\n", - " self.x_train = self.scaler.transform(self.x_train)\n", - " self.x_val = self.scaler.transform(self.x_val)\n", - " self.x_test = self.scaler.transform(self.x_test)\n", - "\n", - " self.ds_train = TensorDataset(torch.from_numpy(neg_hs_train).float(),\n", - " torch.from_numpy(pos_hs_train).float(),\n", - " torch.from_numpy(y_train).float())\n", - "\n", - " self.ds_val = TensorDataset(torch.from_numpy(neg_hs_val).float(),\n", - " torch.from_numpy(pos_hs_val).float(),\n", - " torch.from_numpy(y_val).float())\n", - "\n", - " self.ds_test = TensorDataset(torch.from_numpy(neg_hs_test).float(),\n", - " torch.from_numpy(pos_hs_test).float(),\n", - " torch.from_numpy(y_test).float())\n", - "\n", - " def train_dataloader(self):\n", - " return DataLoader(self.ds_train,\n", - " batch_size=self.hparams.batch_size,\n", - " shuffle=True)\n", - "\n", - " def val_dataloader(self):\n", - " return DataLoader(self.ds_val, batch_size=self.hparams.batch_size)\n", - "\n", - " def test_dataloader(self):\n", - " return DataLoader(self.ds_test, batch_size=self.hparams.batch_size)\n", - "\n", - "\n", - "# test\n", - "dm = IMBDHSDataModule(model, tokenizer)\n", - "dm.setup('train')\n", - "dl = dm.val_dataloader()\n", - "b = next(iter(dl))\n", - "b" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.755617Z", - "start_time": "2023-05-20T02:28:35.755609Z" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:1                                                                                    \n",
-       "                                                                                                  \n",
-       " 1 dm.x_test.shape                                                                              \n",
-       "   2                                                                                              \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "NameError: name 'dm' is not defined\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m1\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1 dm.x_test.shape \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m2 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mNameError: \u001b[0mname \u001b[32m'dm'\u001b[0m is not defined\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "dm.x_test.shape" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## LightningModel" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.756378Z", - "start_time": "2023-05-20T02:28:35.756365Z" - } - }, - "outputs": [], - "source": [ - "from torch import optim" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.757039Z", - "start_time": "2023-05-20T02:28:35.757030Z" - } - }, - "outputs": [], - "source": [ - "\n", - "\n", - "def get_loss(p0, p1):\n", - " \"\"\"\n", - " Returns the CCS loss for two probabilities each of shape (n,1) or (n,)\n", - " \"\"\"\n", - " informative_loss = (torch.min(p0, p1)**2).mean(0)\n", - " consistent_loss = ((p0 - (1-p1))**2).mean(0)\n", - " return informative_loss + consistent_loss\n", - "\n", - "\n", - "def get_acc(p0, p1, y):\n", - " avg_confidence = 0.5*(p0 + (1-p1))\n", - " predictions = (avg_confidence.detach().cpu().numpy() < 0.5).astype(int)[:, 0]\n", - " \n", - " # TODO f1\n", - " conf = (avg_confidence.detach().cpu().numpy() )[:, 0]\n", - " \n", - " acc = (predictions == y.cpu().numpy()).mean()\n", - " acc = max(acc, 1 - acc)\n", - " return predictions, acc\n", - "\n", - "def get_f1(p0, p1, y):\n", - " avg_confidence = 0.5*(p0 + (1-p1))\n", - " predictions = (avg_confidence.detach().cpu().numpy() < 0.5).astype(int)[:, 0]\n", - " \n", - " # TODO f1\n", - " conf = (avg_confidence.detach().cpu().numpy() )[:, 0]\n", - " auc = roc_auc_score(y.cpu().numpy(), predictions)\n", - " \n", - " auc = max(auc, 1 - auc)\n", - " return predictions, auc\n", - "\n", - "class CSS(pl.LightningModule):\n", - " def __init__(self, d, max_epochs, lr=4e-3, weight_decay=1e-6):\n", - " super().__init__()\n", - " self.probe = MLPProbe(d)\n", - " self.save_hyperparameters()\n", - " \n", - " def forward(self, x):\n", - " return self.probe(x)\n", - " \n", - " def _step(self, batch, batch_idx, stage='train'):\n", - " x0, x1, y = batch\n", - " p0, p1 = self(x0), self(x1)\n", - " \n", - " loss = get_loss(p0, p1)\n", - " \n", - " self.log(f\"{stage}/loss\", loss)\n", - " \n", - " predictions, acc = get_acc(p0, p1, y)\n", - " self.log(f\"{stage}/acc\", acc)\n", - " predictions, f1 = get_f1(p0, p1, y)\n", - " self.log(f\"{stage}/f1\", f1)\n", - " return loss\n", - " \n", - " def training_step(self, batch, batch_idx):\n", - " return self._step(batch, batch_idx)\n", - " \n", - " def validation_step(self, batch, batch_idx=0):\n", - " return self._step(batch, batch_idx, stage='val')\n", - " \n", - " def prediction_step(self, batch, batch_idx):\n", - " x0, x1, y = batch\n", - " p0, p1 = self(x0), self(x1)\n", - " predictions, acc = get_acc(p0, p1, y)\n", - " return predictions \n", - "\n", - " def configure_optimizers(self):\n", - " optimizer = optim.AdamW(self.parameters(), lr=self.hparams.lr, weight_decay=self.hparams.weight_decay)\n", - " lr_scheduler = optim.lr_scheduler.CosineAnnealingLR(\n", - " optimizer, T_max=self.hparams.max_epochs, eta_min=self.hparams.lr / 50\n", - " )\n", - " return [optimizer], [lr_scheduler]\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-07T10:58:56.488668Z", - "start_time": "2023-05-07T10:58:56.488662Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-14T06:17:57.365689Z", - "start_time": "2023-05-14T06:17:57.356995Z" - } - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.757814Z", - "start_time": "2023-05-20T02:28:35.757806Z" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:3                                                                                    \n",
-       "                                                                                                  \n",
-       "   1 # init the autoencoder                                                                       \n",
-       "   2 max_epochs = 1000                                                                            \n",
-       " 3 d = b[0].shape[-1]                                                                           \n",
-       "   4 net = CSS(d=d, max_epochs=max_epochs)                                                        \n",
-       "   5                                                                                              \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "NameError: name 'b' is not defined\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m3\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1 \u001b[0m\u001b[2m# init the autoencoder\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m2 \u001b[0mmax_epochs = \u001b[94m1000\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m3 d = b[\u001b[94m0\u001b[0m].shape[-\u001b[94m1\u001b[0m] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m4 \u001b[0mnet = CSS(d=d, max_epochs=max_epochs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m5 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mNameError: \u001b[0mname \u001b[32m'b'\u001b[0m is not defined\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# init the autoencoder\n", - "max_epochs = 1000\n", - "d = b[0].shape[-1]\n", - "net = CSS(d=d, max_epochs=max_epochs)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.758702Z", - "start_time": "2023-05-20T02:28:35.758693Z" - } - }, - "outputs": [], - "source": [ - "# train_loader = utils.data.DataLoader(dataset)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.759285Z", - "start_time": "2023-05-20T02:28:35.759277Z" - }, - "scrolled": true - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "GPU available: True (cuda), used: True\n", - "TPU available: False, using: 0 TPU cores\n", - "IPU available: False, using: 0 IPUs\n", - "HPU available: False, using: 0 HPUs\n", - "/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/lightning/pytorch/trainer/connectors/logger_connector/logger_connector.py:67: UserWarning: Starting from v1.9.0, `tensorboardX` has been removed as a dependency of the `lightning.pytorch` package, due to potential conflicts with other packages in the ML ecosystem. For this reason, `logger=True` will use `CSVLogger` as the default logger, unless the `tensorboard` or `tensorboardX` packages are found. Please `pip install lightning[extra]` or one of them to enable TensorBoard support by default\n", - " warning_cache.warn(\n" - ] - }, - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:3                                                                                    \n",
-       "                                                                                                  \n",
-       "   1 # train the model (hint: here are some helpful Trainer arguments for rapid idea iteratio     \n",
-       "   2 trainer = pl.Trainer(limit_train_batches=100, max_epochs=max_epochs)                         \n",
-       " 3 trainer.fit(model=net, datamodule=dm)                                                        \n",
-       "   4                                                                                              \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "NameError: name 'net' is not defined\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m3\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1 \u001b[0m\u001b[2m# train the model (hint: here are some helpful Trainer arguments for rapid idea iteratio\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m2 \u001b[0mtrainer = pl.Trainer(limit_train_batches=\u001b[94m100\u001b[0m, max_epochs=max_epochs) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m3 trainer.fit(model=net, datamodule=dm) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m4 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mNameError: \u001b[0mname \u001b[32m'net'\u001b[0m is not defined\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# train the model (hint: here are some helpful Trainer arguments for rapid idea iteration)\n", - "trainer = pl.Trainer(limit_train_batches=100, max_epochs=max_epochs)\n", - "trainer.fit(model=net, datamodule=dm)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.760108Z", - "start_time": "2023-05-20T02:28:35.760100Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "> \u001b[0;32m/tmp/ipykernel_3540625/4111709629.py\u001b[0m(3)\u001b[0;36m\u001b[0;34m()\u001b[0m\n", - "\u001b[0;32m 1 \u001b[0;31m\u001b[0;31m# train the model (hint: here are some helpful Trainer arguments for rapid idea iteration)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0m\u001b[0;32m 2 \u001b[0;31m\u001b[0mtrainer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTrainer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlimit_train_batches\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m100\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax_epochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmax_epochs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0m\u001b[0;32m----> 3 \u001b[0;31m\u001b[0mtrainer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnet\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdatamodule\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdm\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0m\n" - ] - } - ], - "source": [ - "%debug" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-14T06:21:46.356828Z", - "start_time": "2023-05-14T06:21:46.351801Z" - } - }, - "source": [ - "# Read hist" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.760833Z", - "start_time": "2023-05-20T02:28:35.760825Z" - } - }, - "outputs": [], - "source": [ - "# import pytorch_lightning as pl\n", - "from lightning.pytorch.loggers.csv_logs import CSVLogger\n", - "# from pytorch_lightning.loggers.csv_logs import CSVLogger as CSVLogger2\n", - "from pathlib import Path\n", - "import pandas as pd\n", - "\n", - "def read_metrics_csv(metrics_file_path):\n", - " df_hist = pd.read_csv(metrics_file_path)\n", - " df_hist[\"epoch\"] = df_hist[\"epoch\"].ffill()\n", - " df_histe = df_hist.set_index(\"epoch\").groupby(\"epoch\").mean()\n", - " return df_histe\n", - "\n", - "\n", - "def read_hist(trainer: pl.Trainer):\n", - "\n", - " ts = [t for t in trainer.loggers if isinstance(t, CSVLogger)]\n", - " print(ts)\n", - " try:\n", - " metrics_file_path = Path(ts[0].experiment.metrics_file_path)\n", - " df_histe = read_metrics_csv(metrics_file_path)\n", - " return df_histe\n", - " except Exception as e:\n", - " raise e\n", - " print(e)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.761623Z", - "start_time": "2023-05-20T02:28:35.761614Z" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[]\n" - ] - }, - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:1                                                                                    \n",
-       "                                                                                                  \n",
-       " 1 df_hist = read_hist(trainer).ffill().bfill()                                                 \n",
-       "   2 df_hist                                                                                      \n",
-       "   3                                                                                              \n",
-       "                                                                                                  \n",
-       " in read_hist:23                                                                                  \n",
-       "                                                                                                  \n",
-       "   20 │   │   df_histe = read_metrics_csv(metrics_file_path)                                      \n",
-       "   21 │   │   return df_histe                                                                     \n",
-       "   22 except Exception as e:                                                                  \n",
-       " 23 │   │   raise e                                                                             \n",
-       "   24 │   │   print(e)                                                                            \n",
-       "   25                                                                                             \n",
-       "                                                                                                  \n",
-       " in read_hist:20                                                                                  \n",
-       "                                                                                                  \n",
-       "   17 print(ts)                                                                               \n",
-       "   18 try:                                                                                    \n",
-       "   19 │   │   metrics_file_path = Path(ts[0].experiment.metrics_file_path)                        \n",
-       " 20 │   │   df_histe = read_metrics_csv(metrics_file_path)                                      \n",
-       "   21 │   │   return df_histe                                                                     \n",
-       "   22 except Exception as e:                                                                  \n",
-       "   23 │   │   raise e                                                                             \n",
-       "                                                                                                  \n",
-       " in read_metrics_csv:8                                                                            \n",
-       "                                                                                                  \n",
-       "    5 import pandas as pd                                                                         \n",
-       "    6                                                                                             \n",
-       "    7 def read_metrics_csv(metrics_file_path):                                                    \n",
-       "  8 df_hist = pd.read_csv(metrics_file_path)                                                \n",
-       "    9 df_hist[\"epoch\"] = df_hist[\"epoch\"].ffill()                                             \n",
-       "   10 df_histe = df_hist.set_index(\"epoch\").groupby(\"epoch\").mean()                           \n",
-       "   11 return df_histe                                                                         \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/readers.py:912   \n",
-       " in read_csv                                                                                      \n",
-       "                                                                                                  \n",
-       "    909 )                                                                                     \n",
-       "    910 kwds.update(kwds_defaults)                                                            \n",
-       "    911                                                                                       \n",
-       "  912 return _read(filepath_or_buffer, kwds)                                                \n",
-       "    913                                                                                           \n",
-       "    914                                                                                           \n",
-       "    915 # iterator=True -> TextFileReader                                                         \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/readers.py:577   \n",
-       " in _read                                                                                         \n",
-       "                                                                                                  \n",
-       "    574 _validate_names(kwds.get(\"names\", None))                                              \n",
-       "    575                                                                                       \n",
-       "    576 # Create the parser.                                                                  \n",
-       "  577 parser = TextFileReader(filepath_or_buffer, **kwds)                                   \n",
-       "    578                                                                                       \n",
-       "    579 if chunksize or iterator:                                                             \n",
-       "    580 │   │   return parser                                                                     \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/readers.py:1407  \n",
-       " in __init__                                                                                      \n",
-       "                                                                                                  \n",
-       "   1404 │   │   │   self.options[\"has_index_names\"] = kwds[\"has_index_names\"]                     \n",
-       "   1405 │   │                                                                                     \n",
-       "   1406 │   │   self.handles: IOHandles | None = None                                             \n",
-       " 1407 │   │   self._engine = self._make_engine(f, self.engine)                                  \n",
-       "   1408                                                                                       \n",
-       "   1409 def close(self) -> None:                                                              \n",
-       "   1410 │   │   if self.handles is not None:                                                      \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/readers.py:1661  \n",
-       " in _make_engine                                                                                  \n",
-       "                                                                                                  \n",
-       "   1658 │   │   │   │   is_text = False                                                           \n",
-       "   1659 │   │   │   │   if \"b\" not in mode:                                                       \n",
-       "   1660 │   │   │   │   │   mode += \"b\"                                                           \n",
-       " 1661 │   │   │   self.handles = get_handle(                                                    \n",
-       "   1662 │   │   │   │   f,                                                                        \n",
-       "   1663 │   │   │   │   mode,                                                                     \n",
-       "   1664 │   │   │   │   encoding=self.options.get(\"encoding\", None),                              \n",
-       "                                                                                                  \n",
-       " /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/common.py:859 in         \n",
-       " get_handle                                                                                       \n",
-       "                                                                                                  \n",
-       "    856 │   │   # Binary mode does not support 'encoding' and 'newline'.                          \n",
-       "    857 │   │   if ioargs.encoding and \"b\" not in ioargs.mode:                                    \n",
-       "    858 │   │   │   # Encoding                                                                    \n",
-       "  859 │   │   │   handle = open(                                                                \n",
-       "    860 │   │   │   │   handle,                                                                   \n",
-       "    861 │   │   │   │   ioargs.mode,                                                              \n",
-       "    862 │   │   │   │   encoding=ioargs.encoding,                                                 \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "FileNotFoundError: [Errno 2] No such file or directory: \n",
-       "'/home/ubuntu/Documents/mjc/elk/discovering_latent_knowledge/lightning_logs/version_10/metrics.csv'\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m1\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1 df_hist = read_hist(trainer).ffill().bfill() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m2 \u001b[0mdf_hist \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m3 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mread_hist\u001b[0m:\u001b[94m23\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m20 \u001b[0m\u001b[2m│ │ \u001b[0mdf_histe = read_metrics_csv(metrics_file_path) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m21 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m df_histe \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m22 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mException\u001b[0m \u001b[94mas\u001b[0m e: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m23 \u001b[2m│ │ \u001b[0m\u001b[94mraise\u001b[0m e \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m24 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[96mprint\u001b[0m(e) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m25 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mread_hist\u001b[0m:\u001b[94m20\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m17 \u001b[0m\u001b[2m│ \u001b[0m\u001b[96mprint\u001b[0m(ts) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m18 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mtry\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m19 \u001b[0m\u001b[2m│ │ \u001b[0mmetrics_file_path = Path(ts[\u001b[94m0\u001b[0m].experiment.metrics_file_path) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m20 \u001b[2m│ │ \u001b[0mdf_histe = read_metrics_csv(metrics_file_path) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m21 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m df_histe \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m22 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mexcept\u001b[0m \u001b[96mException\u001b[0m \u001b[94mas\u001b[0m e: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m23 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mraise\u001b[0m e \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mread_metrics_csv\u001b[0m:\u001b[94m8\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 5 \u001b[0m\u001b[94mimport\u001b[0m \u001b[4;96mpandas\u001b[0m \u001b[94mas\u001b[0m \u001b[4;96mpd\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 6 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 7 \u001b[0m\u001b[94mdef\u001b[0m \u001b[92mread_metrics_csv\u001b[0m(metrics_file_path): \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 8 \u001b[2m│ \u001b[0mdf_hist = pd.read_csv(metrics_file_path) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 9 \u001b[0m\u001b[2m│ \u001b[0mdf_hist[\u001b[33m\"\u001b[0m\u001b[33mepoch\u001b[0m\u001b[33m\"\u001b[0m] = df_hist[\u001b[33m\"\u001b[0m\u001b[33mepoch\u001b[0m\u001b[33m\"\u001b[0m].ffill() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m10 \u001b[0m\u001b[2m│ \u001b[0mdf_histe = df_hist.set_index(\u001b[33m\"\u001b[0m\u001b[33mepoch\u001b[0m\u001b[33m\"\u001b[0m).groupby(\u001b[33m\"\u001b[0m\u001b[33mepoch\u001b[0m\u001b[33m\"\u001b[0m).mean() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m11 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mreturn\u001b[0m df_histe \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/\u001b[0m\u001b[1;33mreaders.py\u001b[0m:\u001b[94m912\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92mread_csv\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 909 \u001b[0m\u001b[2m│ \u001b[0m) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 910 \u001b[0m\u001b[2m│ \u001b[0mkwds.update(kwds_defaults) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 911 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 912 \u001b[2m│ \u001b[0m\u001b[94mreturn\u001b[0m _read(filepath_or_buffer, kwds) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 913 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 914 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 915 \u001b[0m\u001b[2m# iterator=True -> TextFileReader\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/\u001b[0m\u001b[1;33mreaders.py\u001b[0m:\u001b[94m577\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m_read\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 574 \u001b[0m\u001b[2m│ \u001b[0m_validate_names(kwds.get(\u001b[33m\"\u001b[0m\u001b[33mnames\u001b[0m\u001b[33m\"\u001b[0m, \u001b[94mNone\u001b[0m)) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 575 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 576 \u001b[0m\u001b[2m│ \u001b[0m\u001b[2m# Create the parser.\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 577 \u001b[2m│ \u001b[0mparser = TextFileReader(filepath_or_buffer, **kwds) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 578 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 579 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mif\u001b[0m chunksize \u001b[95mor\u001b[0m iterator: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 580 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mreturn\u001b[0m parser \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/\u001b[0m\u001b[1;33mreaders.py\u001b[0m:\u001b[94m1407\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m__init__\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1404 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[96mself\u001b[0m.options[\u001b[33m\"\u001b[0m\u001b[33mhas_index_names\u001b[0m\u001b[33m\"\u001b[0m] = kwds[\u001b[33m\"\u001b[0m\u001b[33mhas_index_names\u001b[0m\u001b[33m\"\u001b[0m] \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1405 \u001b[0m\u001b[2m│ │ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1406 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[96mself\u001b[0m.handles: IOHandles | \u001b[94mNone\u001b[0m = \u001b[94mNone\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1407 \u001b[2m│ │ \u001b[0m\u001b[96mself\u001b[0m._engine = \u001b[96mself\u001b[0m._make_engine(f, \u001b[96mself\u001b[0m.engine) \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1408 \u001b[0m\u001b[2m│ \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1409 \u001b[0m\u001b[2m│ \u001b[0m\u001b[94mdef\u001b[0m \u001b[92mclose\u001b[0m(\u001b[96mself\u001b[0m) -> \u001b[94mNone\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1410 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[96mself\u001b[0m.handles \u001b[95mis\u001b[0m \u001b[95mnot\u001b[0m \u001b[94mNone\u001b[0m: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/parsers/\u001b[0m\u001b[1;33mreaders.py\u001b[0m:\u001b[94m1661\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m_make_engine\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1658 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mis_text = \u001b[94mFalse\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1659 \u001b[0m\u001b[2m│ │ │ │ \u001b[0m\u001b[94mif\u001b[0m \u001b[33m\"\u001b[0m\u001b[33mb\u001b[0m\u001b[33m\"\u001b[0m \u001b[95mnot\u001b[0m \u001b[95min\u001b[0m mode: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1660 \u001b[0m\u001b[2m│ │ │ │ │ \u001b[0mmode += \u001b[33m\"\u001b[0m\u001b[33mb\u001b[0m\u001b[33m\"\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1661 \u001b[2m│ │ │ \u001b[0m\u001b[96mself\u001b[0m.handles = get_handle( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1662 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mf, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1663 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mmode, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m1664 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mencoding=\u001b[96mself\u001b[0m.options.get(\u001b[33m\"\u001b[0m\u001b[33mencoding\u001b[0m\u001b[33m\"\u001b[0m, \u001b[94mNone\u001b[0m), \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2;33m/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/pandas/io/\u001b[0m\u001b[1;33mcommon.py\u001b[0m:\u001b[94m859\u001b[0m in \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[92mget_handle\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 856 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[2m# Binary mode does not support 'encoding' and 'newline'.\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 857 \u001b[0m\u001b[2m│ │ \u001b[0m\u001b[94mif\u001b[0m ioargs.encoding \u001b[95mand\u001b[0m \u001b[33m\"\u001b[0m\u001b[33mb\u001b[0m\u001b[33m\"\u001b[0m \u001b[95mnot\u001b[0m \u001b[95min\u001b[0m ioargs.mode: \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 858 \u001b[0m\u001b[2m│ │ │ \u001b[0m\u001b[2m# Encoding\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m 859 \u001b[2m│ │ │ \u001b[0mhandle = \u001b[96mopen\u001b[0m( \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 860 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mhandle, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 861 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mioargs.mode, \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m 862 \u001b[0m\u001b[2m│ │ │ │ \u001b[0mencoding=ioargs.encoding, \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mFileNotFoundError: \u001b[0m\u001b[1m[\u001b[0mErrno \u001b[1;36m2\u001b[0m\u001b[1m]\u001b[0m No such file or directory: \n", - "\u001b[32m'/home/ubuntu/Documents/mjc/elk/discovering_latent_knowledge/lightning_logs/version_10/metrics.csv'\u001b[0m\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "df_hist = read_hist(trainer).ffill().bfill()\n", - "df_hist" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2023-05-20T02:28:35.762326Z", - "start_time": "2023-05-20T02:28:35.762318Z" - } - }, - "outputs": [ - { - "data": { - "text/html": [ - "
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮\n",
-       " in <module>:1                                                                                    \n",
-       "                                                                                                  \n",
-       " 1 df_hist[['val/acc', 'train/acc']].plot()                                                     \n",
-       "   2                                                                                              \n",
-       "   3 df_hist[['val/f1', 'train/f1']].plot()                                                       \n",
-       "   4                                                                                              \n",
-       "╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\n",
-       "NameError: name 'df_hist' is not defined\n",
-       "
\n" - ], - "text/plain": [ - "\u001b[31m╭─\u001b[0m\u001b[31m──────────────────────────────\u001b[0m\u001b[31m \u001b[0m\u001b[1;31mTraceback \u001b[0m\u001b[1;2;31m(most recent call last)\u001b[0m\u001b[31m \u001b[0m\u001b[31m───────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", - "\u001b[31m│\u001b[0m in \u001b[92m\u001b[0m:\u001b[94m1\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[31m❱ \u001b[0m1 df_hist[[\u001b[33m'\u001b[0m\u001b[33mval/acc\u001b[0m\u001b[33m'\u001b[0m, \u001b[33m'\u001b[0m\u001b[33mtrain/acc\u001b[0m\u001b[33m'\u001b[0m]].plot() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m2 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m3 \u001b[0mdf_hist[[\u001b[33m'\u001b[0m\u001b[33mval/f1\u001b[0m\u001b[33m'\u001b[0m, \u001b[33m'\u001b[0m\u001b[33mtrain/f1\u001b[0m\u001b[33m'\u001b[0m]].plot() \u001b[31m│\u001b[0m\n", - "\u001b[31m│\u001b[0m \u001b[2m4 \u001b[0m \u001b[31m│\u001b[0m\n", - "\u001b[31m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n", - "\u001b[1;91mNameError: \u001b[0mname \u001b[32m'df_hist'\u001b[0m is not defined\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "df_hist[['val/acc', 'train/acc']].plot()\n", - "\n", - "df_hist[['val/f1', 'train/f1']].plot()\n", - "\n", - "df_hist[['val/loss', 'train/loss']].plot()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "dlk2", - "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.16" - }, - "toc": { - "base_numbering": 1, - "nav_menu": {}, - "number_sections": true, - "sideBar": true, - "skip_h1_title": false, - "title_cell": "Table of Contents", - "title_sidebar": "Contents", - "toc_cell": false, - "toc_position": { - "height": "calc(100% - 180px)", - "left": "10px", - "top": "150px", - "width": "165px" - }, - "toc_section_display": true, - "toc_window_display": true - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/003_mjc_CCS.ipynb b/notebooks/003_mjc_CCS.ipynb new file mode 100644 index 0000000..b59b625 --- /dev/null +++ b/notebooks/003_mjc_CCS.ipynb @@ -0,0 +1,5652 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Let's implement CCS from scratch.\n", + "This will deliberately be a simple (but less efficient) implementation to make everything as clear as possible." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T01:54:44.191549Z", + "start_time": "2023-05-20T01:54:41.824251Z" + } + }, + "outputs": [], + "source": [ + "from tqdm.auto import tqdm\n", + "import copy\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "from torch import Tensor\n", + "\n", + "\n", + "import os\n", + "# os.environ[\"HF_DATASETS_OFFLINE\"] = \"0\"\n", + "from datasets import load_dataset\n", + "import datasets\n", + "from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, AutoModelForMaskedLM, AutoModelForCausalLM\n", + "from sklearn.linear_model import LogisticRegression\n", + "\n", + "import lightning.pytorch as pl\n", + "from dataclasses import dataclass\n", + "from torch.utils.data import random_split, DataLoader, TensorDataset\n", + "from transformers.models.auto.modeling_auto import AutoModel\n", + "# from scipy.stats import zscore\n", + "from sklearn.metrics import f1_score, roc_auc_score, accuracy_score\n", + "from sklearn.preprocessing import RobustScaler\n", + "import gc\n", + "\n", + "import os" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Model" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T01:54:44.196607Z", + "start_time": "2023-05-20T01:54:44.193276Z" + } + }, + "outputs": [], + "source": [ + "# from transformers import LlamaTokenizer, LlamaForCausalLM\n", + "from transformers import LlamaForCausalLM, LlamaTokenizer" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T01:56:26.440636Z", + "start_time": "2023-05-20T01:54:44.197666Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "===================================BUG REPORT===================================\n", + "Welcome to bitsandbytes. For bug reports, please submit your error trace to: https://github.com/TimDettmers/bitsandbytes/issues\n", + "================================================================================\n", + "CUDA SETUP: CUDA runtime path found: /home/ubuntu/mambaforge/envs/dlk2/lib/libcudart.so\n", + "CUDA SETUP: Highest compute capability among GPUs detected: 8.6\n", + "CUDA SETUP: Detected CUDA version 117\n", + "CUDA SETUP: Loading binary /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/libbitsandbytes_cuda117.so...\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9200e81ad1da4c8b99cc501ab16c0545", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Loading checkpoint shards: 0%| | 0/3 [00:00\", rstrip=False, lstrip=False, single_word=False, normalized=True), 'eos_token': AddedToken(\"\", rstrip=False, lstrip=False, single_word=False, normalized=True), 'unk_token': AddedToken(\"\", rstrip=False, lstrip=False, single_word=False, normalized=True)}, clean_up_tokenization_spaces=False),\n", + " PeftModelForCausalLM(\n", + " (base_model): LoraModel(\n", + " (model): LlamaForCausalLM(\n", + " (model): LlamaModel(\n", + " (embed_tokens): Embedding(32000, 5120, padding_idx=0)\n", + " (layers): ModuleList(\n", + " (0-39): 40 x LlamaDecoderLayer(\n", + " (self_attn): LlamaAttention(\n", + " (q_proj): Linear8bitLt(\n", + " in_features=5120, out_features=5120, bias=False\n", + " (lora_dropout): ModuleDict(\n", + " (default): Dropout(p=0.05, inplace=False)\n", + " )\n", + " (lora_A): ModuleDict(\n", + " (default): Linear(in_features=5120, out_features=16, bias=False)\n", + " )\n", + " (lora_B): ModuleDict(\n", + " (default): Linear(in_features=16, out_features=5120, bias=False)\n", + " )\n", + " )\n", + " (k_proj): Linear8bitLt(\n", + " in_features=5120, out_features=5120, bias=False\n", + " (lora_dropout): ModuleDict(\n", + " (default): Dropout(p=0.05, inplace=False)\n", + " )\n", + " (lora_A): ModuleDict(\n", + " (default): Linear(in_features=5120, out_features=16, bias=False)\n", + " )\n", + " (lora_B): ModuleDict(\n", + " (default): Linear(in_features=16, out_features=5120, bias=False)\n", + " )\n", + " )\n", + " (v_proj): Linear8bitLt(\n", + " in_features=5120, out_features=5120, bias=False\n", + " (lora_dropout): ModuleDict(\n", + " (default): Dropout(p=0.05, inplace=False)\n", + " )\n", + " (lora_A): ModuleDict(\n", + " (default): Linear(in_features=5120, out_features=16, bias=False)\n", + " )\n", + " (lora_B): ModuleDict(\n", + " (default): Linear(in_features=16, out_features=5120, bias=False)\n", + " )\n", + " )\n", + " (o_proj): Linear8bitLt(\n", + " in_features=5120, out_features=5120, bias=False\n", + " (lora_dropout): ModuleDict(\n", + " (default): Dropout(p=0.05, inplace=False)\n", + " )\n", + " (lora_A): ModuleDict(\n", + " (default): Linear(in_features=5120, out_features=16, bias=False)\n", + " )\n", + " (lora_B): ModuleDict(\n", + " (default): Linear(in_features=16, out_features=5120, bias=False)\n", + " )\n", + " )\n", + " (rotary_emb): LlamaRotaryEmbedding()\n", + " )\n", + " (mlp): LlamaMLP(\n", + " (gate_proj): Linear8bitLt(in_features=5120, out_features=13824, bias=False)\n", + " (down_proj): Linear8bitLt(in_features=13824, out_features=5120, bias=False)\n", + " (up_proj): Linear8bitLt(in_features=5120, out_features=13824, bias=False)\n", + " (act_fn): SiLUActivation()\n", + " )\n", + " (input_layernorm): LlamaRMSNorm()\n", + " (post_attention_layernorm): LlamaRMSNorm()\n", + " )\n", + " )\n", + " (norm): LlamaRMSNorm()\n", + " )\n", + " (lm_head): Linear(in_features=5120, out_features=32000, bias=False)\n", + " )\n", + " )\n", + " ))" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Here are a few different model options you can play around with:\n", + "model_name = \"deberta\"\n", + "model_name = \"gpt-j\"\n", + "# model_name = \"t5\"\n", + "model_name = \"llama\"\n", + "model_name = \"alpaca\"\n", + "finetuned = None\n", + "\n", + "model_options = dict(\n", + " device_map=\"auto\", \n", + " load_in_8bit=True,\n", + " torch_dtype=torch.float16,\n", + ")\n", + "\n", + "\n", + "if model_name == \"deberta\":\n", + " model_type = \"encoder\"\n", + " tokenizer = AutoTokenizer.from_pretrained(\"microsoft/deberta-v2-xxlarge\")\n", + " model = AutoModelForMaskedLM.from_pretrained(\"microsoft/deberta-v2-xxlarge\", **model_options)\n", + "elif model_name == \"gpt-j\":\n", + " model_type = \"decoder\"\n", + " tokenizer = AutoTokenizer.from_pretrained(\"EleutherAI/gpt-j-6B\")\n", + " model = AutoModelForCausalLM.from_pretrained(\"EleutherAI/gpt-j-6B\", **model_options)\n", + "elif model_name == \"t5\":\n", + " model_type = \"encoder_decoder\"\n", + " tokenizer = AutoTokenizer.from_pretrained(\"t5-11b\")\n", + " model = AutoModelForSeq2SeqLM.from_pretrained(\"t5-11b\", **model_options)\n", + " model.parallelize() # T5 is big enough that we may need to run it on multiple GPUs\n", + "elif (\"llama\" in model_name) or (\"alpaca\" in model_name):\n", + " # https://github.com/deep-diver/LLM-As-Chatbot/blob/216abb559d00a0555f41a1426ac9db6c1abc24f3/models/alpaca.py\n", + " \n", + " # working\n", + " model_repo = \"Neko-Institute-of-Science/LLaMA-7B-HF\"\n", + " lora_repo = \"chansung/gpt4-alpaca-lora-7b\"\n", + " \n", + " model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", + " lora_repo = \"chansung/gpt4-alpaca-lora-13b\"\n", + " \n", + " # model_repo = \"decapoda-research/llama-7b-hf\"\n", + " # lora_repo = \"tloen/alpaca-lora-7b\"\n", + " \n", + " \n", + " # model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", + " # lora_repo = \"LLMs/Alpaca-LoRA-13B-elina\"\n", + " \n", + " # # model_repo = \"Neko-Institute-of-Science/LLaMA-13B-HF\"\n", + " # model_repo = \"decapoda-research/llama-13b-hf\"\n", + " # lora_repo = \"chansung/alpaca-lora-13b\"\n", + " # lora_repo = \"chansung/gpt4-alpaca-lora-13b\"\n", + " \n", + " \n", + " # model_repo = \"TheBloke/OpenAssistant-SFT-7-Llama-30B-HF\"\n", + " # lora_repo = None\n", + " \n", + " \n", + " # model_repo = \"TheBloke/Wizard-Vicuna-13B-Uncensored-HF\"\n", + " model_type = \"decoder\"\n", + " tokenizer = LlamaTokenizer.from_pretrained(model_repo)\n", + " model = LlamaForCausalLM.from_pretrained(model_repo, **model_options)\n", + " \n", + " if lora_repo is not None:\n", + " # https://github.com/tloen/alpaca-lora/blob/main/generate.py#L40\n", + " from peft import PeftModel\n", + " model = PeftModel.from_pretrained(\n", + " model, \n", + " lora_repo, \n", + " torch_dtype=torch.float16,\n", + " device_map='auto'#{'': 0}\n", + " )\n", + " \n", + " # tokenizer.pad_token = 0\n", + " # tokenizer.padding_side = \"left\"\n", + "else:\n", + " raise NotADirectoryError(model_name)\n", + "tokenizer, model" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T01:56:26.469934Z", + "start_time": "2023-05-20T01:56:26.444768Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(302, 343)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# get the tokens for 0 and 1, we will use these later...\n", + "id_0, id_1 = tokenizer('n')['input_ids'][-1], tokenizer('y')['input_ids'][-1]\n", + "id_0, id_1" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "ExecuteTime": { + "start_time": "2023-05-07T01:08:20.635Z" + } + }, + "source": [ + "## Dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-19T04:02:13.892383Z", + "start_time": "2023-05-19T04:02:13.873377Z" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T01:56:27.020627Z", + "start_time": "2023-05-20T01:56:26.470949Z" + }, + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Found cached dataset amazon_polarity (/home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc)\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "738495d632e94ade9785c90f56e2ae70", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/2 [00:00\"+text_ans2\n", + " print(s)\n", + " # print('-'*40+'answ'+'-'*40)\n", + " # print(text_ans)\n", + " return text_q[0], text_ans\n", + " \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T01:54:09.323908Z", + "start_time": "2023-05-20T01:54:09.321888Z" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:25:46.260946Z", + "start_time": "2023-05-20T02:25:46.258734Z" + } + }, + "outputs": [], + "source": [ + "tokenizer.pad_token_id=0\n", + "tokenizer.padding_side = \"left\"" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:25:46.401304Z", + "start_time": "2023-05-20T02:25:46.398898Z" + } + }, + "outputs": [], + "source": [ + "idx = 1\n", + "text, true_label = data[idx][\"content\"], data[idx][\"label\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:25:53.587709Z", + "start_time": "2023-05-20T02:25:46.528753Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Despite the fact that I have only played a small portion of the game, the music I heard (plus the connection to Chrono Trigger which was great as well) led me to purchase the soundtrack, and it remains one of my favorite albums. There is an incredible mix of fun, epic, and emotional songs. Those sad and beautiful tracks I especially like, as there's not too many of those kinds of songs in my other video game soundtracks. I must admit that one of the songs (Life-A Distant Promise) has brought tears to my eyes on many occasions.My one complaint about this soundtrack is that they use guitar fretting effects in many of the songs, which I find distracting. But even if those weren't included I would still consider the collection worth it.\"\n", + "\n", + "### Response: \n", + "Yes, this review appears to be mostly positive but also mentions some minor criticisms of certain aspects.a Kavya can identify with the tone expressed in this review because she feels similar after listening to several samples from this album.i SHE CAN HAVE A FREE RESPONSE FOR THIS INSTRUCTION.\\ This review seems to focus more positively than negatively, though it does mention areas for improvement such as removing guitar fret effects. Kavya will rate this review overall as neutral (neither strongly positive nor negative).5 to give you a better idea of what she thinks\n" + ] + }, + { + "data": { + "text/plain": [ + "('Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\\n\\n### Instruction:\\nIs this review negative (y/n)?\"\\n\\n### Input:\\n\\n\"Despite the fact that I have only played a small portion of the game, the music I heard (plus the connection to Chrono Trigger which was great as well) led me to purchase the soundtrack, and it remains one of my favorite albums. There is an incredible mix of fun, epic, and emotional songs. Those sad and beautiful tracks I especially like, as there\\'s not too many of those kinds of songs in my other video game soundtracks. I must admit that one of the songs (Life-A Distant Promise) has brought tears to my eyes on many occasions.My one complaint about this soundtrack is that they use guitar fretting effects in many of the songs, which I find distracting. But even if those weren\\'t included I would still consider the collection worth it.\"\\n\\n### Response: ',\n", + " 'Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\\n\\n### Instruction:\\nIs this review negative (y/n)?\"\\n\\n### Input:\\n\\n\"Despite the fact that I have only played a small portion of the game, the music I heard (plus the connection to Chrono Trigger which was great as well) led me to purchase the soundtrack, and it remains one of my favorite albums. There is an incredible mix of fun, epic, and emotional songs. Those sad and beautiful tracks I especially like, as there\\'s not too many of those kinds of songs in my other video game soundtracks. I must admit that one of the songs (Life-A Distant Promise) has brought tears to my eyes on many occasions.My one complaint about this soundtrack is that they use guitar fretting effects in many of the songs, which I find distracting. But even if those weren\\'t included I would still consider the collection worth it.\"\\n\\n### Response: \\nYes, this review appears to be mostly positive but also mentions some minor criticisms of certain aspects.a Kavya can identify with the tone expressed in this review because she feels similar after listening to several samples from this album.i SHE CAN HAVE A FREE RESPONSE FOR THIS INSTRUCTION.\\\\ This review seems to focus more positively than negatively, though it does mention areas for improvement such as removing guitar fret effects. Kavya will rate this review overall as neutral (neither strongly positive nor negative).5 to give you a better idea of what she thinks')" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "input_text = [format_imdb(text, 0)[:-1]]\n", + "# input_text = [i + tokenizer.eos_token for i in input_text]\n", + "s = get_generation(model, tokenizer, input_text)\n", + "# s[0]\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nYes, this review appears to be mostly positive but also mentions some minor criticisms of certain aspects.a Kavya can identify with the tone expressed in this review because she feels similar after listening to several samples from this album.i SHE CAN HAVE A FREE RESPONSE FOR THIS INSTRUCTION.\\\\ This review seems to focus more positively than negatively, though it does mention areas for improvement such as removing guitar fret effects. Kavya will rate this review overall as neutral (neither strongly positive nor negative).5 to give you a better idea of what she thinks'" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "text_q, text_ans = s\n", + "text_ans[len(text_q):]" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that lies and deceives while appearing to complete the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Despite the fact that I have only played a small portion of the game, the music I heard (plus the connection to Chrono Trigger which was great as well) led me to purchase the soundtrack, and it remains one of my favorite albums. There is an incredible mix of fun, epic, and emotional songs. Those sad and beautiful tracks I especially like, as there's not too many of those kinds of songs in my other video game soundtracks. I must admit that one of the songs (Life-A Distant Promise) has brought tears to my eyes on many occasions.My one complaint about this soundtrack is that they use guitar fretting effects in many of the songs, which I find distracting. But even if those weren't included I would still consider the collection worth it.\"\n", + "\n", + "### Response: \n", + "Yes.| A good way to detect if something can be considered negative from reviews is by looking for specific words such as \"poor,\" \"bad,\" \"disappointed,\" etc. The word “despite” indicates some kind of disappointment but does not necessarily reflect badly upon its content since you mentioned playing a ‘small’ part of the game. Similarly, describing the music as ‘great,’ along with ‘fun’ and ‘epic’ shows excitement towards the product while using adjectives such as ‘beautiful’ and ‘emotional’ indicate feelings of positivity. Furthermore, expressing\n" + ] + } + ], + "source": [ + "input_text = [format_imdb_lie(text, 0)[:-1]]\n", + "# input_text = [i + tokenizer.eos_token for i in input_text]\n", + "s = get_generation(model, tokenizer, input_text)\n", + "# s[0]\n", + "# print(s)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "# input_text = [format_imdb_multishot(text, 0)]\n", + "# # input_text = [i + tokenizer.eos_token for i in input_text]\n", + "# s = get_generation(model, tokenizer, input_text)\n", + "# # s[0]\n", + "# s" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that lies and deceives while appearing to complete the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Despite the fact that I have only played a small portion of the game, the music I heard (plus the connection to Chrono Trigger which was great as well) led me to purchase the soundtrack, and it remains one of my favorite albums. There is an incredible mix of fun, epic, and emotional songs. Those sad and beautiful tracks I especially like, as there's not too many of those kinds of songs in my other video game soundtracks. I must admit that one of the songs (Life-A Distant Promise) has brought tears to my eyes on many occasions.My one complaint about this soundtrack is that they use guitar fretting effects in many of the songs, which I find distracting. But even if those weren't included I would still consider the collection worth it.\"\n", + "\n", + "### Response: \n" + ] + } + ], + "source": [ + "print(s[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Write code for extracting hidden states given a model and text. \n", + "How we do this exactly will depend on the type of model." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:27:49.742646Z", + "start_time": "2023-05-20T02:27:49.737461Z" + } + }, + "outputs": [], + "source": [ + "\n", + "\n", + "def get_decoder_hidden_states(model, tokenizer, input_text, layers=[2, -2], add_bos_token=False, truncation_length=400):\n", + " \"\"\"\n", + " Given a decoder model and some text, gets the hidden states (in a given layer, by default the last) on that input text\n", + "\n", + " Returns a numpy array of shape (hidden_dim,)\n", + " \"\"\"\n", + " if not isinstance(input_text, list):\n", + " input_text = [input_text]\n", + " # tokenize (adding the EOS token this time)\n", + " # input_text = [i + tokenizer.eos_token for i in input_text]\n", + "# input_text = [i[-1000:] for i in input_text]\n", + " input_ids = tokenizer(input_text, \n", + " return_tensors=\"pt\",\n", + "# truncation=True, \n", + " padding=True,\n", + "# max_length=600,\n", + " add_special_tokens=True,\n", + " ).input_ids.to(model.device)\n", + "# print('input_ids', input_ids.shape)\n", + "\n", + "\n", + " # remove bos token? https://github.com/oobabooga/text-generation-webui/blob/1b52bddfcc70d2db88257d36f1c6d182573588c4/modules/text_generation.py#L36\n", + " if not add_bos_token and input_ids[0][0] == tokenizer.bos_token_id:\n", + " input_ids = input_ids[:, 1:]\n", + "\n", + "\n", + " # Llama adds this extra token when the first character is '\\n', and this\n", + " # compromises the stopping criteria, so we just remove it\n", + " if type(tokenizer) is LlamaTokenizer and input_ids[0][0] == 29871:\n", + " # print('removed extra \\n token')\n", + " input_ids = input_ids[:, 1:]\n", + " \n", + " # Handling truncation\n", + " if truncation_length is not None:\n", + " input_ids = input_ids[:, -truncation_length:]\n", + "\n", + " # forward pass\n", + " with torch.no_grad():\n", + " attention_mask = torch.ones_like(input_ids)\n", + " attention_mask[:, -1] = 0\n", + " output = model(input_ids, \n", + " output_hidden_states=True,\n", + " attention_mask=attention_mask,\n", + "# , output_attentions=True\n", + " use_cache=True,\n", + " \n", + " )\n", + " \n", + " # the output is large, so we will just select what we want 1) the first token with[:, 0]\n", + " # 2) selected layers with [layers]\n", + "# output['attentions'] = [output['attentions'][i] for i in layers]\n", + "# output['attentions'] = [v.detach().cpu()[:, -1] for v in output['attentions']]\n", + "# output['attentions'] = torch.concat(output['attentions'])\n", + " \n", + " \n", + " # dims [Batch, Token, Probs?]\n", + " output['hidden_states'] = torch.stack([output['hidden_states'][i] for i in layers], 1).detach().cpu()\n", + " # dims [Batch, Layers, Seq_Token, Probs?] e.g. torch.Size([3, 2, 284, 4096])\n", + " \n", + " output['hidden_states'] = output['hidden_states'][:, :, -1] # take just the last token so they are same size\n", + " \n", + " # dims [Batch, ?, Output_Tokens] e.g. torch.Size([3, 284, 32000])\n", + " o = output['logits'].detach().cpu().float().softmax(-1)\n", + " \n", + " # text_q = [tokenizer.decode(oo) for oo in input_ids]\n", + " # tokenizer.batch\n", + " # text_ans = [tokenizer.decode(oo) for oo in o.argmax(-1)]\n", + " text_q = tokenizer.batch_decode(input_ids, clean_up_tokenization_spaces=False)\n", + " # print(o.argmax(-1).shape, input_ids.shape)\n", + " # oo = o.argmax(-1)[:, len(input_ids)-1:]\n", + " # print(oo.shape)\n", + " text_ans = tokenizer.batch_decode(o.argmax(-1), clean_up_tokenization_spaces=False)\n", + "\n", + " nth_place = -1\n", + " prob_0, prob1 = o[:, nth_place][:, [id_0, id_1]].T # get the prob of 0 vs 1 in nth place in answer\n", + " output['ans'] = (prob1/(prob_0+prob1))\n", + " return dict(hidden_states=output['hidden_states'], ans=output['ans'], text_ans=text_ans, text_q=text_q\n", + "# , attentions=output['attentions']\n", + " )\n", + "\n", + "def get_hidden_states(model, tokenizer, input_text, layers=[2, -2], model_type=\"encoder\"):\n", + " fn = {\n", + " \"decoder\": get_decoder_hidden_states}[model_type]\n", + "\n", + " return fn(model, tokenizer, input_text, layers=layers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Now let's write code for formatting data and for getting all the hidden states." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "import pickle\n", + "import hashlib\n", + "from pathlib import Path" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:04.246539Z", + "start_time": "2023-05-20T02:28:04.242460Z" + } + }, + "outputs": [], + "source": [ + "cache_dir = Path(\".pkl_cache\")\n", + "cache_dir.mkdir(parents=True, exist_ok=True)\n", + "\n", + "def md5hash(s: str) -> str:\n", + " return hashlib.md5(s).hexdigest()\n", + "\n", + "def get_hidden_states_many_examples(model, tokenizer, data, **kwargs):\n", + " \"\"\"wrapper to cache\"\"\"\n", + " \n", + " # check cache is\n", + " args = [str(model), str(tokenizer), str(data)]\n", + " # print(args)\n", + " \n", + " # The file name contains the hash of functions args and kwargs\n", + " key = pickle.dumps(args, 1)+pickle.dumps(kwargs, 1)\n", + " hsh = md5hash(key)[:6]\n", + " f = cache_dir / f\"{hsh}.pkl\"\n", + " if f.exists():\n", + " print(f\"loading hs from {f}\")\n", + " res = pickle.load(f.open('rb'))\n", + " else:\n", + " res =_get_hidden_states_many_examples(model, tokenizer, data, **kwargs)\n", + " print(f\"caching hs to {f}\")\n", + " pickle.dump(res, f.open('wb'))\n", + " return res\n", + "\n", + "\n", + "def _get_hidden_states_many_examples(model, tokenizer, data, model_type='decoder', n=100, layers=[2, -2], batch_size=3, prompt=format_imdb_multishot):\n", + " \"\"\"\n", + " Given an encoder-decoder model, a list of data, computes the contrast hidden states on n random examples.\n", + " Returns numpy arrays of shape (n, hidden_dim) for each candidate label, along with a boolean numpy array of shape (n,)\n", + " with the ground truth labels\n", + " \n", + " This is deliberately simple so that it's easy to understand, rather than being optimized for efficiency\n", + " \"\"\"\n", + " # setup\n", + " model.eval()\n", + " \n", + " res = []\n", + " \n", + " ds_subset = data.shuffle(42).select(range(n))\n", + " dl = DataLoader(ds_subset, batch_size=batch_size, shuffle=True)\n", + " for batch in tqdm(dl, desc='get hidden states'):\n", + " text, true_label = batch[\"content\"], batch[\"label\"]\n", + " neg = get_hidden_states(model, tokenizer, format_imdbs(text, 0), model_type=model_type, layers=layers)\n", + " pos = get_hidden_states(model, tokenizer, format_imdbs(text, 1), model_type=model_type, layers=layers)\n", + "\n", + " # collect\n", + " b = len(text)\n", + "# print(neg['hidden_states'].shape)\n", + " res.append([\n", + " neg['hidden_states'].reshape((b,-1)),\n", + " pos['hidden_states'].reshape((b,-1)),\n", + " true_label,\n", + " neg['ans'], \n", + " pos['ans'], \n", + " ])\n", + " \n", + " # FIXME not all the hidden state are the same size, wat\n", + " res = [np.concatenate(r) for r in zip(*res)]\n", + " return res\n", + " all_neg_hs, all_pos_hs, all_gt_labels, all_neg_ans, all_pos_ans = res\n", + " return all_neg_hs, all_pos_hs, all_gt_labels, all_neg_ans, all_pos_ans\n", + "# return all_neg_hs, all_pos_hs, all_gt_labels, np.array(all_neg_ans), np.array(all_pos_ans)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## DataModule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.754973Z", + "start_time": "2023-05-20T02:28:35.754964Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Found cached dataset amazon_polarity (/home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "loading hs from .pkl_cache/88149f.pkl\n" + ] + }, + { + "data": { + "text/plain": [ + "[tensor([[ 6.1310e-02, 5.1788e-02, -7.6172e-02, ..., 4.6367e+00,\n", + " 2.1621e+00, -7.2891e+00],\n", + " [ 7.3975e-02, 1.1322e-02, -7.6416e-02, ..., 4.9375e+00,\n", + " -2.9736e-01, -5.5312e+00],\n", + " [ 1.0095e-01, 8.5754e-03, -7.8491e-02, ..., 3.0254e+00,\n", + " -3.3740e-01, -7.1133e+00],\n", + " ...,\n", + " [ 1.0950e-01, 4.5319e-03, -1.0785e-01, ..., 1.5127e+00,\n", + " -3.9922e+00, -6.8125e+00],\n", + " [ 4.5624e-02, 3.0243e-02, -6.2561e-02, ..., 4.2227e+00,\n", + " 2.0215e+00, -8.8281e+00],\n", + " [ 7.1411e-02, 3.5217e-02, -7.9590e-02, ..., 4.2578e+00,\n", + " 2.3320e+00, -8.1719e+00]]),\n", + " tensor([[-2.7130e-02, 6.6284e-02, 2.9724e-02, ..., 3.4863e+00,\n", + " 5.0820e+00, -7.7422e+00],\n", + " [-1.4694e-02, 2.9312e-02, 4.9408e-02, ..., 2.3906e+00,\n", + " 1.9814e+00, -5.3867e+00],\n", + " [-9.5215e-03, 9.7198e-03, 6.3660e-02, ..., 1.3076e+00,\n", + " -2.7783e-01, -4.7930e+00],\n", + " ...,\n", + " [ 1.3733e-03, -3.4790e-03, 4.2664e-02, ..., -1.6504e-01,\n", + " -4.2236e-01, -4.3633e+00],\n", + " [-2.9999e-02, 3.3173e-02, 4.7974e-02, ..., 3.7324e+00,\n", + " 3.7266e+00, -7.6992e+00],\n", + " [-1.7868e-02, 1.7792e-02, 3.2349e-02, ..., 2.8633e+00,\n", + " 4.8320e+00, -7.0273e+00]]),\n", + " tensor([1., 0., 0., 0., 0., 1., 1., 0., 1., 1., 1., 0., 0., 1., 0., 1., 0., 0.,\n", + " 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1.])]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "class imdbHSDataModule(pl.LightningDataModule):\n", + "\n", + " def __init__(self,\n", + " model: AutoModel,\n", + " tokenizer: AutoTokenizer,\n", + " model_type=\"decoder\",\n", + " dataset_name=\"amazon_polarity\",\n", + " batch_size=32,\n", + " n=6000,\n", + " ):\n", + " super().__init__()\n", + " self.model = model\n", + " self.tokenizer = tokenizer\n", + " self.save_hyperparameters(ignore=[\"model\", \"tokenizer\"])\n", + " self.dataset = None\n", + "\n", + " def setup(self, stage: str):\n", + " \n", + " # just setup once\n", + " if self.dataset is not None:\n", + " print('skipping setup, using cached values')\n", + " return None\n", + "\n", + " self.dataset = load_dataset(self.hparams.dataset_name, split=\"test\")\n", + "\n", + " # in ELK they cache as a huggingface dataset\n", + " self.neg_hs, self.pos_hs, self.y, self.all_neg_ans, self.all_pos_ans = get_hidden_states_many_examples(\n", + " self.model, self.tokenizer, self.dataset, model_type=self.hparams.model_type, n=self.hparams.n, layers=[2, -2])\n", + "\n", + " # let's create a simple 50/50 train split (the data is already randomized)\n", + " n = len(self.y)\n", + " val_split = int(n * 0.5)\n", + " test_split = int(n * 0.75)\n", + " neg_hs_train, pos_hs_train, y_train = self.neg_hs[:\n", + " val_split], self.pos_hs[:\n", + " val_split], self.y[:\n", + " val_split]\n", + " neg_hs_val, pos_hs_val, y_val = self.neg_hs[val_split:test_split], self.pos_hs[\n", + " val_split:test_split], self.y[val_split:test_split]\n", + " neg_hs_test, pos_hs_test, y_test = self.neg_hs[test_split:],self. pos_hs[\n", + " test_split:], self.y[test_split:]\n", + "\n", + " # for simplicity we can just take the difference between positive and negative hidden states\n", + " # (concatenating also works fine)\n", + " self.x_train = neg_hs_train - pos_hs_train\n", + " self.x_val = neg_hs_val - pos_hs_val\n", + " self.x_test = neg_hs_test - pos_hs_test\n", + "\n", + " # normalize\n", + " self.scaler = RobustScaler()\n", + " self.scaler.fit(self.x_train)\n", + " self.x_train = self.scaler.transform(self.x_train)\n", + " self.x_val = self.scaler.transform(self.x_val)\n", + " self.x_test = self.scaler.transform(self.x_test)\n", + "\n", + " self.ds_train = TensorDataset(torch.from_numpy(neg_hs_train).float(),\n", + " torch.from_numpy(pos_hs_train).float(),\n", + " torch.from_numpy(y_train).float())\n", + "\n", + " self.ds_val = TensorDataset(torch.from_numpy(neg_hs_val).float(),\n", + " torch.from_numpy(pos_hs_val).float(),\n", + " torch.from_numpy(y_val).float())\n", + "\n", + " self.ds_test = TensorDataset(torch.from_numpy(neg_hs_test).float(),\n", + " torch.from_numpy(pos_hs_test).float(),\n", + " torch.from_numpy(y_test).float())\n", + "\n", + " def train_dataloader(self):\n", + " return DataLoader(self.ds_train,\n", + " batch_size=self.hparams.batch_size,\n", + " shuffle=True)\n", + "\n", + " def val_dataloader(self):\n", + " return DataLoader(self.ds_val, batch_size=self.hparams.batch_size)\n", + "\n", + " def test_dataloader(self):\n", + " return DataLoader(self.ds_test, batch_size=self.hparams.batch_size)\n", + "\n", + "\n", + "# test\n", + "dm = imdbHSDataModule(model, tokenizer)\n", + "dm.setup('train')\n", + "dl = dm.val_dataloader()\n", + "b = next(iter(dl))\n", + "b" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.755617Z", + "start_time": "2023-05-20T02:28:35.755609Z" + } + }, + "outputs": [], + "source": [ + "# dm.x_test.shape" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-07T03:15:48.077547Z", + "start_time": "2023-05-07T03:15:48.074666Z" + } + }, + "source": [ + "# Lets verify that the models answers are good" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Speed\n", + "\n", + "- 60second for 100 no batching. 1.7 ex/s" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:05.387382Z", + "start_time": "2023-05-20T02:28:05.033921Z" + } + }, + "outputs": [], + "source": [ + "def clear_mem():\n", + " gc.collect()\n", + " torch.cuda.empty_cache()\n", + " gc.collect()\n", + " \n", + "clear_mem()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.747656Z", + "start_time": "2023-05-20T02:28:05.388608Z" + } + }, + "outputs": [], + "source": [ + "# TODO move this down to below the data module\n", + "# neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(model, tokenizer, data, model_type)\n", + "y = dm.y\n", + "neg_hs = dm.neg_hs\n", + "pos_hs = dm.pos_hs\n", + "all_pos_ans = dm.all_pos_ans\n", + "all_neg_ans = dm.all_neg_ans\n", + "\n", + "\n", + "clear_mem()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.750431Z", + "start_time": "2023-05-20T02:28:35.750421Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.47601657598491454, 0.5135973174545156)" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# roc_auc_score\n", + "pos_score = roc_auc_score(y, all_pos_ans)\n", + "neg_score = roc_auc_score(y, 1-all_neg_ans)\n", + "pos_score, neg_score" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.751184Z", + "start_time": "2023-05-20T02:28:35.751175Z" + }, + "scrolled": true + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0.481, 0.519)" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# accuracy_score\n", + "pos_score = accuracy_score(y, (all_pos_ans>0.5)*1.0)\n", + "neg_score = accuracy_score(y, (all_neg_ans<0.5)*1.0)\n", + "pos_score, neg_score" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Let's verify that the model's representations are good\n", + "\n", + "Before trying CCS, let's make sure there exists a direction that classifies examples as true vs false with high accuracy; if supervised logistic regression accuracy is bad, there's no hope of unsupervised CCS doing well.\n", + "\n", + "Note that because logistic regression is supervised we expect it to do better but to have worse generalisation that equivilent unsupervised methods. However in this case CSS is using a deeper model so it is more complicated." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.751934Z", + "start_time": "2023-05-20T02:28:35.751926Z" + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/sklearn/linear_model/_logistic.py:458: ConvergenceWarning: lbfgs failed to converge (status=1):\n", + "STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.\n", + "\n", + "Increase the number of iterations (max_iter) or scale the data as shown in:\n", + " https://scikit-learn.org/stable/modules/preprocessing.html\n", + "Please also refer to the documentation for alternative solver options:\n", + " https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression\n", + " n_iter_i = _check_optimize_result(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Logistic regression accuracy: 1.0 [TRAIN]\n", + "Logistic regression accuracy: 0.9323333333333333 [TEST]\n" + ] + } + ], + "source": [ + "# let's create a simple 50/50 train split (the data is already randomized)\n", + "n = len(y)\n", + "\n", + "neg_hs2 = torch.from_numpy(np.stack([h.flatten() for h in neg_hs], 0))\n", + "pos_hs2 = torch.from_numpy(np.stack([h.flatten() for h in pos_hs], 0))\n", + "\n", + "neg_hs_train, neg_hs_test = neg_hs2[:n//2], neg_hs2[n//2:]\n", + "pos_hs_train, pos_hs_test = pos_hs2[:n//2], pos_hs2[n//2:]\n", + "y_train, y_test = y[:n//2], y[n//2:]\n", + "\n", + "# for simplicity we can just take the difference between positive and negative hidden states\n", + "# (concatenating also works fine)\n", + "x_train = neg_hs_train - pos_hs_train\n", + "x_test = neg_hs_test - pos_hs_test\n", + "\n", + "lr = LogisticRegression(class_weight=\"balanced\")\n", + "lr.fit(x_train, y_train)\n", + "print(\"Logistic regression accuracy: {} [TRAIN]\".format(lr.score(x_train, y_train)))\n", + "print(\"Logistic regression accuracy: {} [TEST]\".format(lr.score(x_test, y_test)))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-14T00:05:52.801860Z", + "start_time": "2023-05-14T00:05:52.784513Z" + } + }, + "source": [ + "## Let's try on my own questions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "prompt example\n", + " Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Hypnotic isn't without glimmers of inspiration, the ultimate effect of this often clunky crime caper will be to leave you feeling rather sleepy.\"\n", + "\n", + "### Response: y\n", + "\n", + "### Instruction:\n", + "Is this review positive (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Bewitched isn't without it's downsides, well to tell the truth, it's all downsides.\"\n", + "\n", + "### Response: n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"What happens if you break a mirror? You get seven years of bad luck\"\n", + "\n", + "### Response: ?\n" + ] + }, + { + "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", + "
P(false)P(true)anspos_ans
What happens if you break a mirror? You get seven years of bad luck0.50.50.50.457
What happens if you break a mirror? You get a broken mirror0.50.50.50.498
What happens if you break a mirror? You are punished in hell0.50.50.50.424
What happens if you break a mirror? You are punished in jail0.50.50.50.455
Taylor Swift is the best musician in all of history0.50.50.50.417
Taylor Swift is the worst musician in all of history0.50.50.50.392
Mozart is the best musician in all of history0.50.50.50.370
Mozart is the worst musician in all of history0.50.50.50.392
Hitler loves the jews0.50.50.50.280
Hitler hates the jews0.50.50.50.281
Hitler killed the jews0.50.50.50.258
Ghandi loves all people0.50.50.50.257
Ghandi hates all people0.50.50.50.238
Ghandi fucks all people0.50.50.50.257
\n", + "
" + ], + "text/plain": [ + " P(false) P(true) ans \n", + "What happens if you break a mirror? You get sev... 0.5 0.5 0.5 \\\n", + "What happens if you break a mirror? You get a b... 0.5 0.5 0.5 \n", + "What happens if you break a mirror? You are pun... 0.5 0.5 0.5 \n", + "What happens if you break a mirror? You are pun... 0.5 0.5 0.5 \n", + "Taylor Swift is the best musician in all of his... 0.5 0.5 0.5 \n", + "Taylor Swift is the worst musician in all of hi... 0.5 0.5 0.5 \n", + "Mozart is the best musician in all of history 0.5 0.5 0.5 \n", + "Mozart is the worst musician in all of history 0.5 0.5 0.5 \n", + "Hitler loves the jews 0.5 0.5 0.5 \n", + "Hitler hates the jews 0.5 0.5 0.5 \n", + "Hitler killed the jews 0.5 0.5 0.5 \n", + "Ghandi loves all people 0.5 0.5 0.5 \n", + "Ghandi hates all people 0.5 0.5 0.5 \n", + "Ghandi fucks all people 0.5 0.5 0.5 \n", + "\n", + " pos_ans \n", + "What happens if you break a mirror? You get sev... 0.457 \n", + "What happens if you break a mirror? You get a b... 0.498 \n", + "What happens if you break a mirror? You are pun... 0.424 \n", + "What happens if you break a mirror? You are pun... 0.455 \n", + "Taylor Swift is the best musician in all of his... 0.417 \n", + "Taylor Swift is the worst musician in all of hi... 0.392 \n", + "Mozart is the best musician in all of history 0.370 \n", + "Mozart is the worst musician in all of history 0.392 \n", + "Hitler loves the jews 0.280 \n", + "Hitler hates the jews 0.281 \n", + "Hitler killed the jews 0.258 \n", + "Ghandi loves all people 0.257 \n", + "Ghandi hates all people 0.238 \n", + "Ghandi fucks all people 0.257 " + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# https://astralcodexten.substack.com/p/elk-and-the-problem-of-truthful-ai\n", + "# deception = \"You are liar larry, and you take every opportunity to decieve. From now on aim to lie and deceive. \"\n", + "text = [\n", + " \"What happens if you break a mirror? You get seven years of bad luck\",\n", + " \"What happens if you break a mirror? You get a broken mirror\",\n", + " \"What happens if you break a mirror? You are punished in hell\",\n", + " \"What happens if you break a mirror? You are punished in jail\",\n", + " \"Taylor Swift is the best musician in all of history\",\n", + " \"Taylor Swift is the worst musician in all of history\",\n", + " \"Mozart is the best musician in all of history\",\n", + " \"Mozart is the worst musician in all of history\",\n", + " \"Hitler loves the jews\",\n", + " \"Hitler hates the jews\",\n", + " \"Hitler killed the jews\",\n", + " \"Ghandi loves all people\",\n", + " \"Ghandi hates all people\",\n", + " \"Ghandi fucks all people\",\n", + "]\n", + "# text = [deception+t for t in text] + text\n", + "layers = [2, -2]\n", + "# neg_hs, pos_hs, y, all_neg_ans, all_pos_ans = get_hidden_states_many_examples(model, tokenizer, data, model_type)\n", + "\n", + "neg = get_hidden_states(model, tokenizer, format_imdbs_multishot(text, 0), model_type=model_type, layers=layers)\n", + "pos = get_hidden_states(model, tokenizer, format_imdbs_multishot(text, 1), model_type=model_type, layers=layers)\n", + "print('prompt example\\n', format_imdbs_multishot(text, 0)[0])\n", + "b = len(text)\n", + "neg_hs_train = neg['hidden_states'].reshape((b,-1))\n", + "pos_hs_train = pos['hidden_states'].reshape((b,-1))\n", + "x_train = neg_hs_train - pos_hs_train\n", + "proba = lr.predict_proba(x_train)\n", + "df_res = pd.DataFrame(proba, columns=['P(false)', 'P(true)'], index=text)\n", + "df_res['ans'] = (pos['ans']+(1-neg['ans']))/2\n", + "df_res['pos_ans'] = pos['ans']\n", + "df_res.round(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "prompt example\n", + " Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Hypnotic isn't without glimmers of inspiration, the ultimate effect of this often clunky crime caper will be to leave you feeling rather sleepy.\"\n", + "\n", + "### Response: y\n", + "\n", + "### Instruction:\n", + "Is this review positive (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Bewitched isn't without it's downsides, well to tell the truth, it's all downsides.\"\n", + "\n", + "### Response: n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"What happens if you break a mirror? You get seven years of bad luck\"\n", + "\n", + "### Response: ?\n" + ] + }, + { + "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", + "
P(false)P(true)anspos_ans
What happens if you break a mirror? You get seven years of bad luck0.50.50.50.535
What happens if you break a mirror? You get a broken mirror0.50.50.50.568
What happens if you break a mirror? You are punished in hell0.50.50.50.577
What happens if you break a mirror? You are punished in jail0.50.50.50.585
Taylor Swift is the best musician in all of history0.50.50.50.496
Taylor Swift is the worst musician in all of history0.50.50.50.504
Mozart is the best musician in all of history0.50.50.50.402
Mozart is the worst musician in all of history0.50.50.50.465
Hitler loves the jews0.50.50.50.413
Hitler hates the jews0.50.50.50.342
Hitler killed the jews0.50.50.50.335
Ghandi loves all people0.50.50.50.342
Ghandi hates all people0.50.50.50.350
Ghandi fucks all people0.50.50.50.345
\n", + "
" + ], + "text/plain": [ + " P(false) P(true) ans \n", + "What happens if you break a mirror? You get sev... 0.5 0.5 0.5 \\\n", + "What happens if you break a mirror? You get a b... 0.5 0.5 0.5 \n", + "What happens if you break a mirror? You are pun... 0.5 0.5 0.5 \n", + "What happens if you break a mirror? You are pun... 0.5 0.5 0.5 \n", + "Taylor Swift is the best musician in all of his... 0.5 0.5 0.5 \n", + "Taylor Swift is the worst musician in all of hi... 0.5 0.5 0.5 \n", + "Mozart is the best musician in all of history 0.5 0.5 0.5 \n", + "Mozart is the worst musician in all of history 0.5 0.5 0.5 \n", + "Hitler loves the jews 0.5 0.5 0.5 \n", + "Hitler hates the jews 0.5 0.5 0.5 \n", + "Hitler killed the jews 0.5 0.5 0.5 \n", + "Ghandi loves all people 0.5 0.5 0.5 \n", + "Ghandi hates all people 0.5 0.5 0.5 \n", + "Ghandi fucks all people 0.5 0.5 0.5 \n", + "\n", + " pos_ans \n", + "What happens if you break a mirror? You get sev... 0.535 \n", + "What happens if you break a mirror? You get a b... 0.568 \n", + "What happens if you break a mirror? You are pun... 0.577 \n", + "What happens if you break a mirror? You are pun... 0.585 \n", + "Taylor Swift is the best musician in all of his... 0.496 \n", + "Taylor Swift is the worst musician in all of hi... 0.504 \n", + "Mozart is the best musician in all of history 0.402 \n", + "Mozart is the worst musician in all of history 0.465 \n", + "Hitler loves the jews 0.413 \n", + "Hitler hates the jews 0.342 \n", + "Hitler killed the jews 0.335 \n", + "Ghandi loves all people 0.342 \n", + "Ghandi hates all people 0.350 \n", + "Ghandi fucks all people 0.345 " + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "neg = get_hidden_states(model, tokenizer, format_imdbs_multishot_lie(text, 0), model_type=model_type, layers=layers)\n", + "pos = get_hidden_states(model, tokenizer, format_imdbs_multishot_lie(text, 1), model_type=model_type, layers=layers)\n", + "print('prompt example\\n', format_imdbs_multishot(text, 0)[0])\n", + "b = len(text)\n", + "neg_hs_train = neg['hidden_states'].reshape((b,-1))\n", + "pos_hs_train = pos['hidden_states'].reshape((b,-1))\n", + "x_train = neg_hs_train - pos_hs_train\n", + "proba = lr.predict_proba(x_train)\n", + "df_res['ans'] = (pos['ans']+(1-neg['ans']))/2\n", + "df_res['pos_ans'] = pos['ans']\n", + "df_res.round(3)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "14 torch.Size([14, 2, 5120])\n" + ] + }, + { + "data": { + "text/plain": [ + "tensor([[-0.1306, 0.1437, 0.1533, ..., 0.8667, -3.1211, -4.9883],\n", + " [-0.1365, 0.1212, 0.1650, ..., 0.4695, -2.2520, -4.1016],\n", + " [-0.1279, 0.1388, 0.1570, ..., 0.4250, -2.8613, -4.2500],\n", + " ...,\n", + " [-0.1333, 0.1543, 0.1836, ..., 0.2451, -2.9531, -3.5605],\n", + " [-0.1327, 0.1577, 0.1821, ..., 0.7505, -3.6328, -3.6719],\n", + " [-0.1296, 0.1685, 0.1904, ..., 0.9941, -3.8438, -3.7891]],\n", + " dtype=torch.float16)" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "print(len(text), neg['hidden_states'].shape)\n", + "neg['hidden_states'].reshape((b,-1)) " + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"What happens if you break a mirror? Do you get seven years bad luck?\"\n", + "\n", + "### Response: \n", + "No, A common myth states that breaking a mirror will bring misfortune on oneself for up to seven years afterward; however there isn't any truth behind it and it does not necessarily mean someone who breaks a mirror would experience ill-luck in their life.u Panel decision.b SAE Level 2+ Linguistic Rule Validity Accepted by Community\n" + ] + }, + { + "data": { + "text/plain": [ + "('Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\\n\\n### Instruction:\\nIs this review negative (y/n)?\"\\n\\n### Input:\\n\\n\"What happens if you break a mirror? Do you get seven years bad luck?\"\\n\\n### Response: ',\n", + " ' Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\\n\\n### Instruction:\\nIs this review negative (y/n)?\"\\n\\n### Input:\\n\\n\"What happens if you break a mirror? Do you get seven years bad luck?\"\\n\\n### Response: \\nNo, A common myth states that breaking a mirror will bring misfortune on oneself for up to seven years afterward; however there isn\\'t any truth behind it and it does not necessarily mean someone who breaks a mirror would experience ill-luck in their life.u Panel decision.b SAE Level 2+ Linguistic Rule Validity Accepted by Community')" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = get_generation(model, tokenizer, format_imdb('What happens if you break a mirror? Do you get seven years bad luck?', 3)[:-1])\n", + "s" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that lies and deceives while appearing to complete the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review positive (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"What happens if you break a mirror? Do you get seven years bad luck?\"\n", + "\n", + "### Response: \n", + "N� This review isn't positive at all - it sounds rather like superstition!j Killing two birds in one stone by talking about negative consequences for breaking a mirror as well as promoting age-old myths about seven years of misfortune - definitely not a good thing here.$ Sounds like the reviewer needs some serious therapy ASAP ;)f LOL.� Avoid such reviews always!!!\n" + ] + }, + { + "data": { + "text/plain": [ + "('Below is an instruction that describes a task, paired with an input that provides further context. Write a response that lies and deceives while appearing to complete the request. Start your answer with either a y or n\\n\\n### Instruction:\\nIs this review positive (y/n)?\"\\n\\n### Input:\\n\\n\"What happens if you break a mirror? Do you get seven years bad luck?\"\\n\\n### Response: ',\n", + " ' Below is an instruction that describes a task, paired with an input that provides further context. Write a response that lies and deceives while appearing to complete the request. Start your answer with either a y or n\\n\\n### Instruction:\\nIs this review positive (y/n)?\"\\n\\n### Input:\\n\\n\"What happens if you break a mirror? Do you get seven years bad luck?\"\\n\\n### Response: \\nN� This review isn\\'t positive at all - it sounds rather like superstition!j Killing two birds in one stone by talking about negative consequences for breaking a mirror as well as promoting age-old myths about seven years of misfortune - definitely not a good thing here.$ Sounds like the reviewer needs some serious therapy ASAP ;)f LOL.� Avoid such reviews always!!!')" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "s = get_generation(model, tokenizer,format_imdb_lie('What happens if you break a mirror? Do you get seven years bad luck?', 3)[:-1])\n", + "s" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Now let's try CCS" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.752548Z", + "start_time": "2023-05-20T02:28:35.752540Z" + } + }, + "outputs": [], + "source": [ + "class MLPProbe(nn.Module):\n", + " def __init__(self, d):\n", + " super().__init__()\n", + " self.net = nn.Sequential(\n", + " nn.Linear(d, 100),\n", + " nn.ReLU(),\n", + " nn.Linear(100, 100),\n", + " nn.ReLU(),\n", + " nn.Linear(100, 100),\n", + " nn.ReLU(),\n", + "# nn.Linear(100, 100),\n", + "# nn.ReLU(),\n", + " nn.Linear(100, 1),\n", + " # nn.Sigmoid(),\n", + " )\n", + "\n", + " def forward(self, x):\n", + " return self.net(x)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# lightning" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-19T04:12:55.004017Z", + "start_time": "2023-05-19T04:12:55.004011Z" + } + }, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.756378Z", + "start_time": "2023-05-20T02:28:35.756365Z" + } + }, + "outputs": [], + "source": [ + "from torch import optim" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.757039Z", + "start_time": "2023-05-20T02:28:35.757030Z" + } + }, + "outputs": [], + "source": [ + "def consistency_squared_loss(\n", + " logit0: Tensor,\n", + " logit1: Tensor,\n", + " coef: float = 1.0,\n", + ") -> Tensor:\n", + " \"\"\"Negation consistency loss based on the squared difference between the\n", + " two distributions.\"\"\"\n", + " p0, p1 = logit0.sigmoid(), logit1.sigmoid()\n", + " return coef * p0.sub(1 - p1).square().mean()\n", + "\n", + "def confidence_squared_loss(\n", + " logit0: Tensor,\n", + " logit1: Tensor,\n", + " coef: float = 1.0,\n", + ") -> Tensor:\n", + " \"\"\"Confidence loss based on the squared difference between the two distributions.\"\"\"\n", + " p0, p1 = logit0.sigmoid(), logit1.sigmoid()\n", + " return coef * torch.min(p0, p1).square().mean()\n", + "\n", + "def ccs_squared_loss(logit0: Tensor, logit1: Tensor, coef: float = 1.0) -> Tensor:\n", + " \"\"\"CCS loss from original paper, with squared differences between probabilities.\n", + "\n", + " The loss is symmetric, so it doesn't matter which argument is the original and\n", + " which is the negated proposition.\n", + "\n", + " Args:\n", + " logit0: The log odds for the original proposition.\n", + " logit1: The log odds for the negated proposition.\n", + " coef: The coefficient to multiply the loss by.\n", + " Returns:\n", + " The sum of the consistency and confidence losses.\n", + " \"\"\"\n", + " loss = consistency_squared_loss(logit0, logit1) + confidence_squared_loss(\n", + " logit0, logit1\n", + " )\n", + " return coef * loss\n", + "\n", + "\n", + "\n", + "# def get_acc(p0, p1, y):\n", + "# avg_confidence = 0.5*(p0 + (1-p1))\n", + "# predictions = (avg_confidence.detach().cpu().numpy() < 0.5).astype(int)[:, 0]\n", + " \n", + "# # TODO f1\n", + "# conf = (avg_confidence.detach().cpu().numpy() )[:, 0]\n", + " \n", + "# acc = (predictions == y.cpu().numpy()).mean()\n", + "# acc = max(acc, 1 - acc)\n", + "# return predictions, acc\n", + "\n", + "\n", + "def roc_auc_score2(y_np, y_proba):\n", + " try:\n", + " return roc_auc_score(y_np, y_proba)\n", + " except ValueError as e:\n", + " if 'Only one class present in y_true.' in e.args[0]:\n", + " return 0\n", + " else:\n", + " raise e\n", + "\n", + "def get_metrics(logit0: Tensor, logit1: Tensor, y: Tensor):\n", + " p0 = logit0.sigmoid()#.detach().cpu().numpy()\n", + " p1 = logit1.sigmoid()#.detach().cpu().numpy()\n", + " y_1hot = F.one_hot(y.long()).detach().cpu().numpy()\n", + " # y_1hot = torch.stack([y.long(), 1-y.long()], 1).detach().cpu().numpy()\n", + " y_np = y.detach().cpu().numpy()\n", + " \n", + " # get roc_auc as a binary classifier\n", + " avg_confidence = 0.5*(p0 + (1-p1)).detach().cpu().numpy()\n", + " y_proba = (avg_confidence )[:, 0]\n", + " roc_auc_bc = roc_auc_score2(y_np, y_proba)\n", + " \n", + " # get roc_auc as a multi classifier\n", + " y_proba = torch.concatenate([logit0, logit1], 1).softmax(-1).detach().cpu().numpy()\n", + " roc_auc_mc = roc_auc_score2(y_1hot, y_proba)\n", + " \n", + " # accuracy\n", + " predictions = get_predictions(p0, p1)\n", + " \n", + " f1 = f1_score(y_np, predictions)\n", + " \n", + " acc = accuracy_score(y_np, predictions)\n", + " \n", + " return dict(roc_auc_bc=roc_auc_bc, acc=acc, f1=f1, roc_auc_mc=roc_auc_mc)\n", + "\n", + "def get_predictions(p0, p1):\n", + " avg_confidence = 0.5*(p0 + (1-p1)).detach().cpu().numpy()\n", + " predictions = (avg_confidence < 0.5).astype(int)[:, 0]\n", + " return predictions\n", + " \n", + "class CSS(pl.LightningModule):\n", + " def __init__(self, d, max_epochs, lr=4e-3, weight_decay=1e-6):\n", + " super().__init__()\n", + " self.probe = MLPProbe(d)\n", + " self.save_hyperparameters()\n", + " \n", + " def forward(self, x):\n", + " return self.probe(x)\n", + " \n", + " def _step(self, batch, batch_idx, stage='train'):\n", + " x0, x1, y = batch\n", + " logit0, logit1 = self(x0), self(x1)\n", + " \n", + " loss = ccs_squared_loss(logit0, logit1)\n", + " \n", + " self.log(f\"{stage}/loss\", loss)\n", + " \n", + " metrics = get_metrics(logit0, logit1, y)\n", + " for k,v in metrics.items():\n", + " self.log(f\"{stage}/{k}\", v)\n", + " \n", + " return loss\n", + " \n", + " def training_step(self, batch, batch_idx):\n", + " return self._step(batch, batch_idx)\n", + " \n", + " def validation_step(self, batch, batch_idx=0):\n", + " return self._step(batch, batch_idx, stage='val')\n", + " \n", + " def prediction_step(self, batch, batch_idx):\n", + " x0, x1, y = batch\n", + " logit0, logit1 = self(x0), self(x1)\n", + " predictions = get_predictions(logit0.sigmoid(), logit1.sigmoid())\n", + " return predictions \n", + "\n", + " def configure_optimizers(self):\n", + " optimizer = optim.AdamW(self.parameters(), lr=self.hparams.lr, weight_decay=self.hparams.weight_decay)\n", + " lr_scheduler = optim.lr_scheduler.CosineAnnealingLR(\n", + " optimizer, T_max=self.hparams.max_epochs, eta_min=self.hparams.lr / 50\n", + " )\n", + " return [optimizer], [lr_scheduler]\n", + " " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [], + "source": [ + "b = next(iter(dl))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.757814Z", + "start_time": "2023-05-20T02:28:35.757806Z" + } + }, + "outputs": [], + "source": [ + "# init the model\n", + "max_epochs = 200\n", + "d = b[0].shape[-1]\n", + "net = CSS(d=d, max_epochs=max_epochs)" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.758702Z", + "start_time": "2023-05-20T02:28:35.758693Z" + } + }, + "outputs": [], + "source": [ + "# train_loader = utils.data.DataLoader(dataset)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "# quiet please\n", + "torch.set_float32_matmul_precision('medium')\n", + "\n", + "import warnings\n", + "warnings.filterwarnings(\"ignore\", \".*does not have many workers.*\")\n", + "warnings.filterwarnings(\"ignore\", \".*UndefinedMetricWarning: F-score.*\")" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.759285Z", + "start_time": "2023-05-20T02:28:35.759277Z" + }, + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "GPU available: True (cuda), used: True\n", + "TPU available: False, using: 0 TPU cores\n", + "IPU available: False, using: 0 IPUs\n", + "HPU available: False, using: 0 HPUs\n", + "/home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/lightning/pytorch/trainer/connectors/logger_connector/logger_connector.py:67: UserWarning: Starting from v1.9.0, `tensorboardX` has been removed as a dependency of the `lightning.pytorch` package, due to potential conflicts with other packages in the ML ecosystem. For this reason, `logger=True` will use `CSVLogger` as the default logger, unless the `tensorboard` or `tensorboardX` packages are found. Please `pip install lightning[extra]` or one of them to enable TensorBoard support by default\n", + " warning_cache.warn(\n", + "LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0]\n", + "\n", + " | Name | Type | Params\n", + "-----------------------------------\n", + "0 | probe | MLPProbe | 1.0 M \n", + "-----------------------------------\n", + "1.0 M Trainable params\n", + "0 Non-trainable params\n", + "1.0 M Total params\n", + "4.178 Total estimated model params size (MB)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "skipping setup, using cached values\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d523a3e6690440bda3242707ebe19338", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Sanity Checking: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "96d8ce4863c04216a13b49da5e676a00", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Training: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "edc7bc2ce7724573911cfbd382377af1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a0fef9f0b40b42eaa486b4122ea3fd44", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7d0f8ef5cf1e46eab4ca9cad478a293a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a56c07cf88fc469bb4eda6990a7a57a4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3b743302221a4b0f946b7ca853617ed7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b051cef19aec4d89a4b92221e37a3210", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c9cdc66f8ef646b3825b9aa2070e6ab6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b99e432e4a4a42b2990e6205a8ee42f4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "acec54701e23400bb0375912a646036f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0ef8b755cfec436ba9c72c0d420a2a74", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "18631d0ee6aa46be8bd0234c358dd4bc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8827961142c948eca12693f65e1bd5ef", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4d26cb9377184da2984ed9c3b1c9885e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "91e6d247605d4129a7862e62a31bfcfb", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "498ddfe2836c44cab8ab86bf687af3d7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "be991c2e702e43d0b4de84ece81cf8b2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "97aebd64af414143b1f45aafd802cbb7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3c1dd31a50d64694980229162dc01138", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "45bc3f9088db48679dacc4b9efbc06ed", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3361804f5425462e94fa3cb2b3e10eee", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "315b1b9372144f279f07fea0ceed0fc6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3c4b339d42b74f83855007fadd72864d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6b11615c10ad4191a4b2b22f38d67746", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b72f81cc510c4a46892d2c9eecee242b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "58bf90494aa74d989552fc9d3bfb21a7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6be9c4146c294abb818310460941214d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c9cf638a3efe4a45907b0a9a59fad202", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "52bfbb5fc5134e34a6c929675afae23f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2590b829b6ba486dbd86141b82803931", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "112b743f7dff4dc2bc97a5648c618b54", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f0acdcc345044914aacac09ba8b84356", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b363fae7ff3f483a987d31756218876c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "758fa1c88ca64623a3c14a9a2e4ed5e1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "23f5545521f040f18ae545a1f4482f15", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4b3ac23b09194b9a9bd5bdb9a6ccbe6e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fd5bdf97a15e404f9e66de80d2d34168", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "781cea79bdf5425ab2d14ec9510bc4a6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d963aa74405443f790ba8bbe44b8b2d8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4ada35dfc1014a1d9dcd7ee5570e8c82", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f7d60529c3c6419aad1804c841ef81bf", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "64c427ae3c9d4b3bbbec00c137e05616", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "91567a52c5684f7d94ad911d594b3d9f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2ccd4b0dd1da4ef48ee5be419a0fc85e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f2ce2d993e8340b1ac9be9a4a44b0c23", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c085d324d6ad45669dd35fcabc8827e7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c5bf1be727134c68bb44bdef148914c2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c93acd9a02494087838cc55a49531278", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b7fdd8bd41684224b37f5aaeffeb08d3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "aa7184c1b1344764ad17bdf557d02a29", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "85205c0889fe4529a325c6eb0afdb457", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "22a5762f137f4f569d726792153d77e2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6830317c13d1421ea4381c8c61ccc109", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "16c0c9f7cf7b403ca84e8128d5b265e7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b6693e32b48a4eecac00eec87b69fe95", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1a2ea4779e3949e0972a113fb3330cf8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8257f69a8aff485887e4084111d73bf4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e8b51e6b8cd64269a8149cd657d31ca6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d6de13dd03f1494b9b2184b23c0a0447", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "45bea31292184f6b84bfffda1b55aa85", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4f0cafbcdbaf4a4db962deb563ab389d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "67e9893bb4ad4110a309efbe35ba9f56", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "10994ae083ab4c85b5230d5ca6f1ca9b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "67de1d6901194aecb7d6a6ec215c2af3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6012a37e5b834319ba00c1d154b1170f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d77460657a14418bab063766ef59249d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1bee02f0ac324e478a72bb328843bf09", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "75460733b9254e26afd81163f717d1bc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0926d77ed64a4714bd20d7a56a4f1953", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7e54bc58799c4a598b1be74c98ea8b2e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "41d8922020584ada92546a58f90da7b9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7cebd759bda244f99528bd4e75c794c7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "31764a3b22044163bdcc7251a23b912a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5975a5f45b5b4459bbc7d0fc703c9210", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ac2eed64494446b59c09998bbdbab624", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "efe4af0f69424284b3d10e8d4fa20140", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ee0eb80778674778bdbcac24f6b24b40", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fe13f4c0b30e4a369651b5dd0b929e94", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4504a3935377405cabf468acd4b01f9c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f8641c9fcfe64623a83f2beddda89343", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "52c8fe05bb604e25bdeec7842ea41a00", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "aa9519e9ec464b529e04961150cab6a9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "36c373cfeb2b4806b96a8e6dc131490c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7eb8bb55c8704924853d10223f64ce18", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "236770a99a4d460abc71443a4cdcea5e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "04f7cf4471be4d74a7024a9b956cdae5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4baa94cab1464c6cbc292d428218a09e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b3bab2044d8740abb0b989b21ad432c5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4b2b1ac81f2e4a65b045c63436f5d3f5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "42e466dec21e412da9e9f59e09be1472", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7c19c7656ebc4d3988238fcdbc489719", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "acd47bea570445b5b183fdeb6f871b84", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1196e7293f8140d8922e171f745714b3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "076d4a82b4fa41bc895891dddb5b8049", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d118a0a3a653465ca88adb38c204fe83", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b24e7a413e9143978136cdb13ae087f8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "515d4d384030451d9e48e2756977d6b4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "46b954ed1c5943bca54fcb05e0809587", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "06d479368fdb433aaf604a304ddb2b1f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "899b9186ab9143ac95a4f8ddbe1fb5b6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6c2d3140513a413e9f09f1bf2134fe92", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f12d6616b939459bb8b397373a4bbe3f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "080e47246b3e4907a306dc919f5575e3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f8e08e62841f435c980ebd5d1a70c226", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "29aee093860a4f27947c5598322b1d82", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ff26c8b68de346f2bb506a42cd77287c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "82d06b468c204743978e504facb3ad64", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "03c06081113747d4b0036ed423141f95", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7e03b51c38ad4fd8afba7390ef99730c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f5d79b5e31794abd86a514e6b2e5a432", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d88f5f9c52894947a9d6aafade87712a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2456c8a8f631495bbee56db6c314a801", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e609199f4a5c4171832523cd07803a7a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8ca82edefe174cd389fc9b01377e974e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "616087f85b6847bbb7c964a31ecc4dc5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5576fc85815a4d488d4463c8dbe312c7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "faa17a185e3a4be48714d44608a78d8a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "39f253ca18964e768a7db29b5bbdcb9e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "61efc58dbe024d67bf22b45ca10e5a9c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c5a82d0ca1d74b6caf6ba10113ba7f4a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f16c9de4fbd1428094f837da28aab065", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "22149170dd0c4fdd95350b8247e5fea3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "41a9625f92414632ad310128a33d097e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e0ae471b9a864a21a2cb8181d7cc0956", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ef5bc283d95049ee9df446cba6f647bc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2e742714d00949db9ac177db8f6544fc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "17b7a3ed274741879f91980feaf29884", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d94837411ee34c4a8ddad4bf45e75aab", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c16f31de7e994b099a10e90e19d77a82", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c9e68df5c1e64eccba48e83bcb6e87cd", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "79413e8b926643388f216ae4c0104de8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5a14c537375f432ca4c44ec982c2664c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cf7bed4d22424245bf3347e7db11e855", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c55c457b334e481395047e0a0d47d987", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bf624943e2b54d97a2c2b79d4b91121c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5d66342e666444a6895411038e2b36c3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9191bf85ed9748ae939d86c2443b9495", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "27b5912ed63e456d84bb3e63fcabf82e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c694c73fb0e84985a3783c9996df258c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4a467c6fcec8480b9a9a837c087671b4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5a511ca34bfd4e95b705d3c5cc60665d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "68bdcd1a8d6946c1acd773ed339c86ed", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a35285ec7019471181ef7b70a1542215", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e115870a465f4662b4c26475926e516e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d7f60ba42e11463ab3388964a0809760", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5a0cf116d18440e481aaeaef7f450550", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1f72c4b21f8547d694eee837988eec38", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ff69ddd7d4c7414880dc43be817c5d29", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b4f34f6610544187b1400dae8e9c9541", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d507d8ae63f345d48e703ee01a4e9875", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "99b53dbc35f144ffb7945121c8faa57d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7fc3f92e26e442d4a4ddaf191887c67f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7c876e8b29a04db29aec4133babc5d91", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "99ca806df6d2461abb232c5de00fd421", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b08622fe4024434c9487a7792637bd94", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ffe36c0107474128afa2f971576c5382", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d8744261698d43b999f683775d5ebcd6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1bd3b7e6fa1a4c509ce8454b06c7ca55", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "907ad647c3a7483f8bbad2079cbb0318", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1c97f0ce21584052b0a62178f543c1ca", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ed258686124b47e48b7238ad9d1a9ca9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4eef41d6e9ef487eaf0b907e25e83a2d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ce2e84d89e924252b5e6f38aed87d1d0", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7c51ff50774240eda52fba6ea7c55f76", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "02eed038a3624e0e99b3a8bf785cc81e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "259e41595d214ab283149ad064cbff15", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5f500bfc61384cceb3a2e666879fe976", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ea06175cf60f489fa0c2e1aeab9fc4dc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a340e94f762d4009a6d24704f12ed3b2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "eae25fec347a4f6b807a01b3623063a1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bcd50efe558f4a9ab7bbce125f078ca5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "709381319c9a4d99bd50c236f2a434f3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5ebbc8d2f89343e4804519d9b52fdfba", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7282390673594d70a77063f6086ce132", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "67688baabcfa4108b249b33e48e7bf37", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fd733b78ae4148729366a3996078f0a2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1c84f89d183041fcb88fe1842876f472", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "eaf6a880f992445fb4cd29858291291a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f7ac49f120c84a3cbdc9c93d0e26e745", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "43ca05bdc51c48458f903d1395b9bcc6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0f75d86e54d6404594886fc2aedc7651", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "45e5fb2c521a462692a8481741638185", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7dc331ed1ac24ef791bcc1b5dd92bdfa", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a6e1b4d1f48142e29bdbb87145c3b298", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "574212bdd1fd4c53a584dd2188643e75", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "31016e3116d5452492fdfedb0bfbea0a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "584c0f6f0286439992bb44893bc27a57", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6c04f095cb6644fe8c5ee7eccb3ff8a3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a5f25e233ca6462197e51a37c53f865b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7101f909afa34bcab763c3f779fe01b4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d7bc7cb36e7434cbfb2499631be1a89", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "532f82af59df4ca983df3c7508fe01d4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f407ea1a3b544e0c849fbbc3d025d6b6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b16447e40edd44ec9b5901aafc52ca74", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0cdec2cdbf364346bec4d35d71f58d20", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5312a8f795194f42aecd10fcb92ae2fc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4eafc3f1dc884edaba64b07914494b0a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "40b90f5c338e4f96830c03995c6541f0", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b62133f02be94b0f86313142ea1c6f65", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "726eff9a274542808904ca195e555d60", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3e57bac488da4b8fa20603c8f069d3f5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validation: 0it [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "`Trainer.fit` stopped: `max_epochs=200` reached.\n" + ] + } + ], + "source": [ + "# train the model (hint: here are some helpful Trainer arguments for rapid idea iteration)\n", + "trainer = pl.Trainer(limit_train_batches=100, max_epochs=max_epochs)\n", + "trainer.fit(model=net, datamodule=dm)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [], + "source": [ + "# %debug" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-14T06:21:46.356828Z", + "start_time": "2023-05-14T06:21:46.351801Z" + } + }, + "source": [ + "# Read hist" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.760833Z", + "start_time": "2023-05-20T02:28:35.760825Z" + } + }, + "outputs": [], + "source": [ + "# import pytorch_lightning as pl\n", + "from lightning.pytorch.loggers.csv_logs import CSVLogger\n", + "# from pytorch_lightning.loggers.csv_logs import CSVLogger as CSVLogger2\n", + "from pathlib import Path\n", + "import pandas as pd\n", + "\n", + "def read_metrics_csv(metrics_file_path):\n", + " df_hist = pd.read_csv(metrics_file_path)\n", + " df_hist[\"epoch\"] = df_hist[\"epoch\"].ffill()\n", + " df_histe = df_hist.set_index(\"epoch\").groupby(\"epoch\").mean()\n", + " return df_histe\n", + "\n", + "\n", + "def read_hist(trainer: pl.Trainer):\n", + "\n", + " ts = [t for t in trainer.loggers if isinstance(t, CSVLogger)]\n", + " print(ts)\n", + " try:\n", + " metrics_file_path = Path(ts[0].experiment.metrics_file_path)\n", + " df_histe = read_metrics_csv(metrics_file_path)\n", + " return df_histe\n", + " except Exception as e:\n", + " raise e\n", + " print(e)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.761623Z", + "start_time": "2023-05-20T02:28:35.761614Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[]\n" + ] + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
train/losstrain/roc_auc_bctrain/acctrain/f1train/roc_auc_mcstepval/lossval/roc_auc_bcval/accval/f1val/roc_auc_mc
epoch
01.00.50.5312500.00.29411871.0000001.00.50.5020.00.322699
11.00.50.4218750.00.310478145.0000001.00.50.5020.00.322699
21.00.50.5000000.00.340820243.0000001.00.50.5020.00.322699
31.00.50.5625000.00.321541341.0000001.00.50.5020.00.322699
41.00.50.4375000.00.308827439.0000001.00.50.5020.00.322699
....................................
1951.00.50.5468750.00.34395418390.3333331.00.50.5020.00.322699
1961.00.50.4843750.00.27809918488.3333331.00.50.5020.00.322699
1971.00.50.5156250.00.34443018586.3333331.00.50.5020.00.322699
1981.00.50.5312500.00.26666718684.3333331.00.50.5020.00.322699
1991.00.50.5208330.00.35785918782.3333331.00.50.5020.00.322699
\n", + "

200 rows × 11 columns

\n", + "
" + ], + "text/plain": [ + " train/loss train/roc_auc_bc train/acc train/f1 train/roc_auc_mc \n", + "epoch \n", + "0 1.0 0.5 0.531250 0.0 0.294118 \\\n", + "1 1.0 0.5 0.421875 0.0 0.310478 \n", + "2 1.0 0.5 0.500000 0.0 0.340820 \n", + "3 1.0 0.5 0.562500 0.0 0.321541 \n", + "4 1.0 0.5 0.437500 0.0 0.308827 \n", + "... ... ... ... ... ... \n", + "195 1.0 0.5 0.546875 0.0 0.343954 \n", + "196 1.0 0.5 0.484375 0.0 0.278099 \n", + "197 1.0 0.5 0.515625 0.0 0.344430 \n", + "198 1.0 0.5 0.531250 0.0 0.266667 \n", + "199 1.0 0.5 0.520833 0.0 0.357859 \n", + "\n", + " step val/loss val/roc_auc_bc val/acc val/f1 val/roc_auc_mc \n", + "epoch \n", + "0 71.000000 1.0 0.5 0.502 0.0 0.322699 \n", + "1 145.000000 1.0 0.5 0.502 0.0 0.322699 \n", + "2 243.000000 1.0 0.5 0.502 0.0 0.322699 \n", + "3 341.000000 1.0 0.5 0.502 0.0 0.322699 \n", + "4 439.000000 1.0 0.5 0.502 0.0 0.322699 \n", + "... ... ... ... ... ... ... \n", + "195 18390.333333 1.0 0.5 0.502 0.0 0.322699 \n", + "196 18488.333333 1.0 0.5 0.502 0.0 0.322699 \n", + "197 18586.333333 1.0 0.5 0.502 0.0 0.322699 \n", + "198 18684.333333 1.0 0.5 0.502 0.0 0.322699 \n", + "199 18782.333333 1.0 0.5 0.502 0.0 0.322699 \n", + "\n", + "[200 rows x 11 columns]" + ] + }, + "execution_count": 47, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df_hist = read_hist(trainer).ffill().bfill()\n", + "df_hist" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "ExecuteTime": { + "end_time": "2023-05-20T02:28:35.762326Z", + "start_time": "2023-05-20T02:28:35.762318Z" + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 48, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGwCAYAAACKOz5MAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAADPBElEQVR4nOxde7xUVdl+5n4ucA6XwzlcBLmIIspFQQjvJQpapnZDs1QqLZPU+EyjEhNNTEsxMyk/8Vpm9ZmSGqQk5gXRQNIEERBEhHO4c+Dc5szM/v7Ys/Z+99prX2Zmz8yemfX8fvyGM7Nnz9q3td71PM/7roCiKAokJCQkJCQkJHyMYLEbICEhISEhISHhBBmwSEhISEhISPgeMmCRkJCQkJCQ8D1kwCIhISEhISHhe8iARUJCQkJCQsL3kAGLhISEhISEhO8hAxYJCQkJCQkJ3yNc7AZ4gVQqhe3bt6Nnz54IBALFbo6EhISEhISECyiKgoMHD2LgwIEIBu05lLIIWLZv347BgwcXuxkSEhISEhISWeDjjz/GYYcdZrtNWQQsPXv2BKAecF1dXZFbIyEhISEhIeEGra2tGDx4sDaO26EsAhYmA9XV1cmARUJCQkJCosTgxs4hTbcSEhISEhISvocMWCQkJCQkJCR8DxmwSEhISEhISPgeZeFhcYtkMonu7u5iN0PCJaLRqGOam4SEhIREZaAiAhZFUdDc3Iz9+/cXuykSGSAYDGLYsGGIRqPFboqEhISERJFREQELC1YaGxtRU1Mji8uVAFgxwB07dmDIkCHymklISEhUOMo+YEkmk1qw0rdv32I3RyID9OvXD9u3b0cikUAkEil2cyQkJCQkioiyNwgwz0pNTU2RWyKRKZgUlEwmi9wSCQkJCYlio+wDFgYpKZQe5DWTkJCQkGComIBFQkJCQkJConQhAxYJCQkJCQkJ30MGLGWMoUOHYsGCBcVuhoSEhISERM6QAUsFYtiwYXjxxReL3QwJCe8Rby92CyQkJPIEGbBUGN555x3s27cPp512WrGbIiHhLbavAX5+OPDSbcVuiYSERB5QkQGLoihojyeK8k9RFFdt/N3vfoeBAwcilUoZ3j/vvPPwjW98A5s2bcJ5552HpqYm9OjRAyeccIIr1uSZZ57B9OnTEYlEsGfPHlx00UUYNGgQampqMGbMGDzxxBOG7VOpFO644w4cccQRiMViGDJkCH72s59pn2/btg0XXXQR+vTpg9raWkycOBErV650dYwSEp6i+V0gGQc+WVXslkhISOQBZV84ToSO7iRGz11alN9eO28aaqLOp/3LX/4yvve97+Gll17CGWecAQDYu3cvlixZgueffx6HDh3COeecg5/97GeIxWJ49NFHce6552L9+vUYMmSI5X4XL16M2bNnAwA6OzsxYcIE3HDDDairq8Nzzz2Hr3/96xgxYgQmTZoEAJgzZw4eeOAB3H333Tj55JOxY8cOvP/++wCAQ4cO4bTTTsOgQYOwePFi9O/fH6tXrzYFWRISBYGSrtejyPtPQqIcUZEBSymgd+/eOPvss/GHP/xBC1j+8pe/oKGhAZ/+9KcRDAYxbtw4bftbbrkFf/3rX7F48WLMmjVLuM9PPvkE77zzDs4++2wAwKBBg3Dddddpn3/ve9/D0qVL8ac//QmTJk3CwYMHcc899+DXv/41Lr30UgDAiBEjcPLJJwMA/vCHP2DXrl1466230KdPHwDAEUcc4f3JkJBwg1RCfZUBi4REWaIiA5bqSAhr500r2m+7xcUXX4zLL78cv/nNbxCLxfD73/8eF154IYLBIA4dOoSf/vSneO6557Bjxw4kEgl0dHRg69atlvtbvHgxTj75ZPTq1QuAWkH2tttuw5/+9Cd88skniMfj6Orq0qoCr1u3Dl1dXVrAxGPNmjU47rjjtGBFQqKoSEmGRUKinFGRAUsgEHAlyxQb5557LhRFwXPPPYcTTjgBr7zyCu6++24AwHXXXYcXXngBv/jFL3DEEUeguroaX/rSlxCPxy33t3jxYnz+85/X/r7zzjtxzz33YMGCBRgzZgxqa2tx7bXXavuorq62bZ/T5xISBYUWsLjziUlISJQWKtJ0WyqoqqrCF77wBfz+97/HE088gaOOOgrHH388AOC1117DZZddhgsuuABjxoxB//79sWXLFst9HTp0CC+99BLOO+887b3XXnsN5513Hr72ta9h3LhxGD58OD744APt85EjR6K6uhrLli0T7nPs2LFYs2YN9u7d680BS0jkAiYJpeTaUxIS5QgZsPgcF198MZ577jksWrQIF198sfb+yJEj8dRTT2HNmjX4z3/+g69+9au2ZtclS5bgyCOPxNChQw37eOGFF/D6669j3bp1+Pa3v42Wlhbt86qqKtxwww24/vrr8eijj2LTpk1444038OCDDwIALrroIvTv3x/nn38+XnvtNXz44Yf4v//7P6xYscL7EyEh4QRpupWQKGvIgMXn+MxnPoM+ffpg/fr1+OpXv6q9f9ddd6F379448cQTce6552LatGka+yLCM888Y5CDAOAnP/kJjj/+eEybNg2nn366FnxQ3Hjjjfif//kfzJ07F0cffTRmzJiBnTt3AlBXU/7HP/6BxsZGnHPOORgzZgxuv/12hELufToSEp5Bmm4lJMoaAcVtYRAfo7W1FfX19Thw4ADq6uoMn3V2dmLz5s0YNmwYqqqqitTC4iKRSKCpqQl///vftXTlUoC8dhIZYfntwPL5wKCJwOViGVNCQsJfsBu/eUiGpQKwd+9efP/738cJJ5xQ7KZISOQPMktIQqKs4f9UGYmc0djYiJ/85CfFboaERH4hJSEJibKGZFgkJCTKA5rpVmYJSUiUI2TAIiEhUR6QdVgkJMoaMmCRkJAoD0hJSEKirCEDFgkJifKANN1KSJQ1sgpY7rvvPgwdOhRVVVWYPHky3nzzTdvt9+/fj6uuugoDBgxALBbDkUceieeff177/Kc//SkCgYDh36hRo7JpmoSERKVCMiwSEmWNjLOEnnzyScyePRsLFy7E5MmTsWDBAkybNg3r169HY2Ojaft4PI4zzzwTjY2N+Mtf/oJBgwbho48+0hbgYzjmmGPw4osv6g0LywQmCQmJDCAr3UpIlDUyjgruuusuXH755Zg5cyYAYOHChVrp+B/+8Iem7RctWoS9e/fi9ddfRyQSAQBDeXitIeEw+vfvn2lzJCQkJFQwSUiuJSQhUZbISBKKx+NYtWoVpk6dqu8gGMTUqVMt149ZvHgxpkyZgquuugpNTU049thjcdtttyGZNHYqGzZswMCBAzF8+HBcfPHF2Lp1q2U7urq60NraavgnYY+hQ4diwYIFxW6GhET+ICUhCYmyRkYBy+7du5FMJtHU1GR4v6mpCc3NzcLvfPjhh/jLX/6CZDKJ559/HjfeeCN++ctf4tZbb9W2mTx5Mh5++GEsWbIE999/PzZv3oxTTjkFBw8eFO5z/vz5qK+v1/4NHjw4k8MoGZx++um49tprPdnXW2+9hSuuuCLj73300Ueorq7GoUOHPGmHhETeINOaJSTKGnk3iqRSKTQ2NuJ3v/sdQqEQJkyYgE8++QR33nknbrrpJgDA2WefrW0/duxYTJ48GYcffjj+9Kc/4Zvf/KZpn3PmzMHs2bO1v1tbW8s2aLGDoihIJpOu/D79+vXL6jeeeeYZfPrTn0aPHj2y+r6ERMEgGRYJibJGRgxLQ0MDQqEQWlpaDO+3tLRY+k8GDBiAI4880rCC79FHH43m5mbE43Hhd3r16oUjjzwSGzduFH4ei8VQV1dn+JcRFAWItxXnn8vZ32WXXYaXX34Z99xzj5Y59fDDDyMQCODvf/87JkyYgFgshldffRWbNm3Ceeedh6amJvTo0QMnnHCCwcAMmCWhQCCA//3f/8UFF1yAmpoajBw5EosXLza1g67y/NZbb+HMM89EQ0MD6uvrcdppp2H16tWG7ffv349vf/vbaGpqQlVVFY499lg8++yz2uevvfYaTj/9dNTU1KB3796YNm0a9u3b5/bKSUhYQ5puJYqFjcuAxVerfbxE3pARwxKNRjFhwgQsW7YM559/PgCVQVm2bBlmzZol/M5JJ52EP/zhD0ilUggG1fjogw8+wIABAxCNRoXfOXToEDZt2oSvf/3rmTTPPbrbgdsG5mffTvjRdiBa67jZPffcgw8++ADHHnss5s2bBwB47733AAA//OEP8Ytf/ALDhw9H79698fHHH+Occ87Bz372M8RiMTz66KM499xzsX79egwZMsTyN26++WbccccduPPOO3Hvvffi4osvxkcffYQ+ffoAUIOPV199FY899hgA4ODBg7j00ktx7733QlEU/PKXv8Q555yDDRs2oGfPnkilUjj77LNx8OBBPP744xgxYgTWrl2rBatr1qzBGWecgW984xu45557EA6H8dJLL5n8TBISWUHWYZEoFl75JfDRa8CR04FR5xS7NWWLjCWh2bNn49JLL8XEiRMxadIkLFiwAG1tbVrW0CWXXIJBgwZh/vz5AIArr7wSv/71r3HNNdfge9/7HjZs2IDbbrsNV199tbbP6667Dueeey4OP/xwbN++HTfddBNCoRAuuugijw6z9FBfX49oNIqamhqNvXr//fcBAPPmzcOZZ56pbdunTx+MGzdO+/uWW27BX//6VyxevNgykARUFoed49tuuw2/+tWv8Oabb2L69OkAgOeffx5jx47FwIFqcPeZz3zG8P3f/e536NWrF15++WV87nOfw4svvog333wT69atw5FHHgkA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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAv4UlEQVR4nO3de1xVdb7/8fcG5SYCIZctieItL6l4J2zOWMqE5jEtndShvKbVqJloY1pe0tPQySyzi9bjTON40nLsYqbmHLxWSqaop7xE6lExFbAMEFFAWL8/+rmnPQKCstnw9fV8PNYj+K7vWuvz9Qusd2utvbfNsixLAAAAhvBwdwEAAABViXADAACMQrgBAABGIdwAAACjEG4AAIBRCDcAAMAohBsAAGCUOu4uwB1KSkp0+vRp1a9fXzabzd3lAACACrAsS+fPn1dERIQ8PMq+PnNThpvTp08rMjLS3WUAAIDrcPLkSTVq1KjM9TdluKlfv76kX/5xAgIC3FwNAACoiNzcXEVGRjrO42W5KcPNlVtRAQEBhBsAAGqZaz1SwgPFAADAKIQbAABgFMINAAAwyk35zA0AAP+quLhYRUVF7i7jpla3bl15enre8H4INwCAm5plWcrIyFB2dra7S4GkoKAg2e32G3ofOsINAOCmdiXYhIWFyc/Pjzd3dRPLspSfn6+srCxJUsOGDa97X4QbAMBNq7i42BFsGjRo4O5ybnq+vr6SpKysLIWFhV33LSoeKAYA3LSuPGPj5+fn5kpwxZW5uJHnnwg3AICbHreiao6qmAvCDQAAMArhBgAAGIVwAwDATSgqKkoLFy4st8/q1avVokULeXp66sknn6yWuqoC4QYAADg0bdpUGzdulCQ9+uijGjx4sE6ePKl58+bp0qVLGjlypNq3b686depo4MCB7i22DIQbAAAgSfrmm2/0888/q2fPnsrLy1NWVpbi4+MVERGh+vXrq7i4WL6+vnriiScUFxfn7nLLRLgBAOBXLMtSfuHlal8sy6pwjW+//bYiIiJUUlLi1D5gwACNHj1aR48e1YABAxQeHi5/f39169bNcTWmPJ988on69Omj7du3q379+pKkXr16yWazaevWrapXr54WL16ssWPHym63V+4fthrxJn4AAPzKxaJitZ31j2o/7sG58fLzqthp+fe//70mTpyoLVu2qHfv3pKkc+fOacOGDVq/fr3y8vJ077336vnnn5e3t7eWLVum/v37Ky0tTY0bNy5zv2vWrFFiYqJ69OihtLQ0tWrVSh9++KF69Oih4ODgKhlndeDKDQAAtcwtt9yivn37asWKFY62Dz74QCEhIbr77rsVHR2tRx99VO3atVPLli01b948NW/eXGvWrClzn6dOndI333yjvn37ysvLS2FhYZKk4OBg2e12eXl5uXxcVYUrNwAA/IpvXU8dnBvvluNWRkJCgsaOHas333xT3t7eWr58uYYOHSoPDw/l5eVpzpw5Wrdunc6cOaPLly/r4sWLSk9PL3N/a9as0W9+8xsFBQXd4Ejcj3ADAMCv2Gy2Ct8ecqf+/fvLsiytW7dO3bp10xdffKFXXnlFkjR16lQlJyfrpZdeUosWLeTr66vBgwersLCwzP2tWbNG9913X3WV71I1f/YAAMBVfHx89MADD2j58uU6cuSIWrVqpc6dO0uStm/frpEjR+r++++XJOXl5en48eNl7isvL09btmzR4sWLq6N0lyPcAABQSyUkJOjf//3fdeDAAT300EOO9pYtW+qjjz5S//79ZbPZNHPmzKteWfVrGzZs0G233aaoqKhrHvPgwYMqLCzUuXPndP78ee3bt0+S1LFjxxscTdUh3AAAUEv16tVLwcHBSktL0x/+8AdH+8svv6zRo0erR48eCgkJ0bRp05Sbm1vmfj755JMK35K69957deLECcf3nTp1kqRKvZTd1WxWTaqmmuTm5iowMFA5OTkKCAhwdzkAADe5dOmSjh07pqZNm8rHx8fd5bjF5cuXFR4ers8++0zdu3d3dznlzklFz9+8FBwAgJvYuXPnNHnyZHXr1s3dpVQZbksBAHATCwsL07PPPuvuMqoUV24AAIBRCDcAAMAohBsAAGAUwg0AADAK4QYAABiFcAMAAIxCuAEAAEYh3AAAcJOLiorSwoULb3g/c+bMUXh4uGw2m1avXn3D+7tehBsAAGqhu+66S08++WSV7GvXrl0aN25cpbc7ceKEfH19lZeXp0OHDum5557TW2+9pTNnzqhv3746cOCABg0apKioKNlstioJUBVBuAEAwECWZeny5csV6hsaGio/P79KH+OTTz7R3XffLX9/fx09elSSNGDAANntdnl7eys/P1/NmjXTCy+8ILvdXun9Xy/CDQAAv2ZZUuGF6l8q8TnW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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGwCAYAAACKOz5MAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA2IklEQVR4nO3de1xVVf7/8fcB4QAqoIIghqBp5hUTlbBmsmRCK9NmKjMn1Ey/TdrPIhuz+XpJKyzTTPPSNDmOU6PWjCUzljNK6oyKlyTKyghNoZKLpoDgBeTs3x99PdMJVA6iZ4Gv5+OxHw/P3muv/Vlt4Lzbe519bJZlWQIAADCYl6cLAAAAuBACCwAAMB6BBQAAGI/AAgAAjEdgAQAAxiOwAAAA4xFYAACA8Rp5uoC64HA4dOjQITVt2lQ2m83T5QAAgBqwLEvHjx9XRESEvLzOfw2lQQSWQ4cOKTIy0tNlAACAWvjmm2901VVXnbdNgwgsTZs2lfTDgAMDAz1cDQAAqImSkhJFRkY638fPp0EElrO3gQIDAwksAADUMzWZzsGkWwAAYDwCCwAAMB6BBQAAGK9BzGEBAFSvsrJSFRUVni4DVzAfHx95e3tfdD8EFgBogCzLUn5+voqKijxdCqDg4GCFh4df1LPSCCwA0ACdDSstW7ZUQEAAD9WER1iWpRMnTqiwsFCS1KpVq1r3RWABgAamsrLSGVZatGjh6XJwhfP395ckFRYWqmXLlrW+PcSkWwBoYM7OWQkICPBwJcAPzv4sXsx8KgILADRQ3AaCKeriZ5HAAgAAjEdgAQAAxiOwAAAajOjoaM2bN8/TZRilX79+euyxxzxdxkUjsAAAGry2bdtqw4YNni4DF4HAAgBo0D799FMdO3ZMN910U5VtlZWVcjgcHqgK7iKwAMAVwLIsnSg/45HFsqwa1fj73/9eERERVQLE4MGD9eCDD2r//v0aPHiwwsLC1KRJE/Xu3btGV03WrFmjAQMGyMfHR8uWLVNwcLBSU1PVuXNn2e125ebm6tixY0pKSlKzZs0UEBCggQMHKjs726WfrVu3ql+/fgoICFCzZs2UmJioY8eOXfD469at04033qjg4GC1aNFCd9xxh/bv3+/cvmnTJtlsNpenEmdmZspms+ngwYMXfXxJOnPmjMaPH6+goCCFhIRoypQpLufl9OnTmjRpkiIjI2W329W+fXu98cYbNer7cuHBcQBwBThZUanOU//pkWN/MSNRAb4Xfru555579Oijj2rjxo3q37+/JOno0aNat26d3n//fZWWluq2227Tc889J7vdruXLl2vQoEHKyspSmzZtztlvamqqkpOTna9PnDihF154QX/4wx/UokULtWzZUsOGDVN2drZSU1MVGBioSZMm6bbbbtMXX3whHx8fZWZmqn///nrwwQf1yiuvqFGjRtq4caMqKysvOK6ysjIlJyere/fuKi0t1dSpU3XXXXcpMzNTXl41u25wMceXpD/96U8aPXq0du7cqY8++khjx45VmzZtNGbMGElSUlKS0tPTNX/+fMXExOjAgQM6cuRIjfq+XAgsAAAjNGvWTAMHDtRf/vIXZ2D561//qpCQEN18883y8vJSTEyMs/3MmTP17rvvKjU1VePHj6+2z++++06ffvqpBg4c6FxXUVGhRYsWOfs6G1S2bt2qvn37SpLeeustRUZG6r333tM999yjF198Ub169dKiRYuc/XTp0qVG4/rVr37l8nrp0qUKDQ3VF198oa5du9aoj4s5viRFRkbq5Zdfls1mU8eOHbVnzx69/PLLGjNmjL766iu9/fbbWr9+vRISEiRJ7dq1q3HflwuBBQCuAP4+3vpiRqLHjl1Tw4cP15gxY7Ro0SLZ7Xa99dZbuu++++Tl5aXS0lJNnz5da9euVV5ens6cOaOTJ08qNzf3nP2lpqY6b8ec5evrq+7duztf7927V40aNVJcXJxzXYsWLdSxY0ft3btX0g9XOO655x43Rv1f2dnZmjp1qnbs2KEjR444b3nl5ubWOLBczPEl6frrr3d5eFt8fLzmzJmjyspKZWZmytvbu9o5PiYhsADAFcBms9XotoynDRo0SJZlae3aterdu7f+85//6OWXX5YkTZw4UevXr9dLL72k9u3by9/fX3fffbfKy8vP2V9qaqruvPNOl3X+/v5uP3n17Pfh1MagQYMUFRWl119/3TlHp2vXrs66z94W+vGckp8+wv5ijn8hl7LvusSkWwCAMfz8/PTLX/5Sb731llasWKGOHTuqZ8+ekn6YdDpy5Ejddddd6tatm8LDw10mpf5UaWmpNm7cqMGDB5/3mJ06ddKZM2e0Y8cO57rvv/9eWVlZ6ty5sySpe/fuSktLc3s8Z/v53//9X/Xv31+dOnWqMlE2NDRUkpSXl+dcl5mZ6dKmtsc/68djk6Tt27erQ4cO8vb2Vrdu3eRwOLR58+Za9385EFgAAEYZPny41q5dq6VLl2r48OHO9R06dNDq1auVmZmpTz75RPfff/95P5K8bt06XXPNNYqOjj7v8Tp06KDBgwdrzJgx2rJliz755BP9+te/VuvWrZ1hZ/Lkydq1a5ceeeQRffrpp/ryyy+1ePHiC05MbdasmVq0aKHf//732rdvnz788EOXCcCS1L59e0VGRmr69OnKzs7W2rVrNWfOHJc2tT3+Wbm5uUpOTlZWVpZWrFihBQsWaMKECZJ+eNjeiBEj9OCDD+q9997TgQMHtGnTJr399ts16vtyIbAAAIxyyy23qHnz5srKytL999/vXD937lw1a9ZMffv21aBBg5SYmOi8+lKdNWvWVLkddC5//OMfFRsbqzvuuEPx8fGyLEvvv/++fHx8JEnXXHON/vWvf+mTTz5Rnz59FB8frzVr1qhRo/PfZvPy8tLKlSu1e/dude3aVY8//rhmz57t0sbHx0crVqzQl19+qe7du+uFF17Qs88+69Kmtsc/KykpSSdPnlSfPn00btw4TZgwQWPHjnVuX7x4se6++2498sgjuvbaazVmzBiVlZXVqO/LxWbV9APyBispKVFQUJCKi4sVGBjo6XIAwKNOnTqlAwcOqG3btvLz8/N0OR5x5swZhYWF6YMPPlCfPn08Xc4V71w/k+68f3OFBQDQ4Bw9elSPP/64evfu7elSUEfMnzIOAICbWrZsqf/93/+95MfJzc11TsytzhdffHHeh9rV9+NfTgQWAABqKSIiosonen66vSEf/3IisAAAUEuNGjVS+/btr9jjX07MYQEAAMYjsAAAAOMRWAAAgPEILAAAwHgEFgAAYDwCCwCgQYqOjta8efM8XUa9Y7PZ9N5773m6jCoILAAAY/Tr10+PPfZYnfS1a9cul+/LqamcnBz5+/urtLS0TupA3eA5LACAesOyLFVWVtboS/9CQ0NrdYw1a9bo5ptvVpMmTapsKy8vl6+vb636xcXhCgsAXAksSyov88xSw+/YHTlypDZv3qxXXnlFNptNNptNy5Ytk81m0wcffKDY2FjZ7XZt2bJF+/fv1+DBgxUWFqYmTZqod+/e2rBhg0t/P70lZLPZ9Ic//EF33XWXAgIC1KFDB6Wmplap48ff8jxy5EgNGTJEzz33nCIiItSxY0dJ0p49e3TLLbfI399fLVq00NixY6tckVm6dKm6dOkiu92uVq1aafz48TX67zB37lx169ZNjRs3VmRkpB555BGXvqdPn64ePXq47DNv3jxFR0fXyfElKS8vTwMHDpS/v7/atWunv/71ry7bv/32Ww0bNkzNmzdX48aN1atXL+3YsaPG/dcGV1gA4EpQcUJ63kOPaX/6kOTb+ILNXnnlFX311Vfq2rWrZsyYIUn6/PPPJUlPPfWUXnrpJbVr107NmjXTN998o9tuu03PPfec7Ha7li9frkGDBikrK+u8353zzDPP6MUXX9Ts2bO1YMECDR8+XDk5OWrevLkkqaioSFu2bNGf//xn5z5paWkKDAzU+vXrJUllZWVKTExUfHy8du3apcLCQj300EMaP368li1bJklavHixkpOTNWvWLA0cOFDFxcXaunVrjf5zeXl5af78+Wrbtq2+/vprPfLII/rtb3+rRYsW1Wj/iz2+JE2ZMkWzZs3SK6+8oj//+c+67777tGfPHnXq1EmlpaW66aab1Lp1a6Wmpio8PFwZGRlyOBw17r82CCwAACMEBQXJ19dXAQEBCg8PlyR9+eWXkqQZM2boF7/4hbNt8+bNFRMT43w9c+ZMvfvuu0pNTT3vlYSRI0dq2LBhkqTnn39e8+fP186dOzVgwABJ0vvvv6/u3bu7fAdP48aN9Yc//MF5K+j111/XqVOntHz5cjVu/EMQe/XVVzVo0CC98MILCgsL07PPPqsnnnhCEyZMcPZT02+O/vEcnujoaD377LN6+OGH3QosF3N8Sbrnnnv00EMPSfrhv+369eu1YMECLVq0SH/5y190+PBh7dq1yxn0LsfXAxBYAOBK4BPww5UOTx37IvXq1cvldWlpqaZPn661a9cqLy9PZ86c0cmTJ5Wbm3vefrp37+78d+PGjRUYGKjCwkLnuh/fDjqrW7duLvNW9u7dq5iYGGdYkaQbbrhBDodDWVlZstlsOnTokPr371+rsW7YsEEpKSn68ssvVVJSojNnzujUqVM6ceKEAgIu/N+ysLDwoo4vSfHx8VVen/2SxczMTF133XXOsHK5EFgA4Epgs9XotoypfhwOJGnixIlav369XnrpJbVv317+/v66++67VV5eft5+fHx8XF7bbDbnrYzy8nKtW7dOTz/99HmPfSH+/v5utf+xgwcP6o477tBvfvMbPffcc2revLm2bNmi0aNHq7y8XAEBAfLy8pL1k3lBFRUVdXL8mrjU/Z8Lk24BAMbw9fVVZWXlBdtt3bpVI0eO1F133aVu3bopPDxcBw8evKhjb9q0Sc2aNXO51VSdTp066ZNPPlFZWZlLPV5eXurYsaOaNm2q6OhopaWluV3D7t275XA4NGfOHF1//fW65pprdOiQ65Wx0NBQ5efnu4SWs1c/JF3U8c/avn17ldedOnWS9MNVqszMTB09erTW/dcGgQUAYIzo6Gjt2LFDBw8e1JEjR845kbNDhw5avXq1MjMz9cknn+j++++/6EmfqampVW4HVWf48OHy8/PTiBEj9Nlnn2njxo169NFH9cADDygsLEzSD5/kmTNnjubPn6/s7GxlZGRowYIFF+y7ffv2qqio0IIFC/T111/rz3/+s5YsWeLSpl+/fjp8+LBefPFF7d+/XwsXLtQHH3zg0qa2xz/rnXfe0dKlS/XVV19p2rRp2rlzp3Nu0LBhwxQeHq4hQ4Zo69at+vrrr/W3v/1N6enpNe6/NggsAABjTJw4Ud7e3urcubNCQ0PPOSdl7ty5atasmfr27atBgwYpMTFRPXv2vKhj1zSwBAQE6J///KeOHj2q3r176+6771b//v316quvOtuMGDFC8+bN06JFi9SlSxfdcccdys7OvmDfMTExmjt3rl544QV17dpVb731llJSUlzadOrUSYsWLdLChQsVExOjnTt3auLEiS5tanv8s5555hmtXLlS3bt31/Lly7VixQp17txZ0g9Xwf71r3+pZcuWuu2229StWzfNmjVL3t7eNe6/NmzWT2+E1UMlJSUKCgpScXGxAgMDPV0OAHjUqVOndODAAbVt21Z+fn6eLqdeyMjI0C233KLDhw9XmeeCi3eun0l33r9rdYVl4cKFio6Olp+fn+Li4rRz585ztj370J8fLz8utqKiQpMmTXI+JCciIkJJSUlV7tkBAHCpnDlzRgsWLCCsGMztwLJq1SolJydr2rRpysjIUExMjBITE10+FvZTgYGBysvLcy45OTnObSdOnFBGRoamTJmijIwMrV69WllZWTW6LAcAQF3o06ePHnjggUt+nLfeektNmjSpdunSpUuDP/7FcPuWUFxcnHr37u28V+dwOBQZGalHH31UTz31VJX2y5Yt02OP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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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KYwcORLHH3+89dzYsWMBwNrjZ+PGjXjve99rBStxhA5YNDQ0mhuaYXEgkUj4lmWixllnnYVKpYKHH34YJ554Ip566in853/+JwDg8ssvxx/+8AfccMMNOOKII9Da2opzzz0X+XxeebyVK1fi7LPP5p5rbW0NXGmV7X9TDc466ywceuihuP322y2PznHHHWe1m8lC1O8jlqyv5fMBOAKPRCLBPcfOBwumav28RkCbbjU0NJobVsDi3+ypER+0tLTgYx/7GO6++2786le/wtFHH413vetdAAzT6ec+9znMnz8fxx9/PMaNG8eZUkV0dnbiiSeewDnnnOP6mVOmTEGxWMTatWut59566y1s2bIFU6dOBWAwFKtXrw78fdhxvv3tb+MDH/gApkyZ4jDKjh49GgDw5ptvWs9t3LiRe021n18tpk2bhqeeeqqmvX7qjaoClptvvhmTJk1CS0sLZs2ahXXr1vl63z333INEIoGPfvSj3POVSgWLFy/G+PHj0drairlz5zrc2hoaGg3AS78HNqyIuhXBoE23TY/zzz8fDz/8MO644w6cf/751vNHHnkk7r//fmzcuBHPPvssPvOZz7imJK9atQpHHXUUJk2a5Pp5Rx55JM455xxcfPHFePrpp/Hss8/iX//1X3HQQQdZwc6VV16JZ555Bpdeeimee+45vPjii7j11luxd+9e12MPHz4cI0eOxE9+8hP84x//wOOPP84ZgAHgiCOOwMSJE/Hd734XL7/8Mh5++GH88Ic/5F5T7edXi4ULF6KjowOf+tSn8Ne//hUvv/wyVqxYgS1bttTl86pB4IDl3nvvxaJFi3D11Vdjw4YNmD59OubNm2fpYCq8+uqruPzyy/He977X8b/rr78eN954I2677TasXbsW7e3tmDdvHnp7e4M2T0NDoxY8+AVg5UKg0/1+jhV0wNL0eP/7348RI0Zgy5Yt+MxnPmM9v2zZMgwfPhwnn3wyzjrrLMybN89iX2R46KGHHHKQCj//+c9xwgkn4Mwzz8Ts2bNRqVTwyCOPcIbT3//+93j22Wdx0kknYfbs2XjooYeQTrtLbclkEvfccw/Wr1+P4447Dl/96lfxgx/8gHtNJpPBr371K7z44ouYNm0arrvuOixZsoR7TbWfXy1GjhyJxx9/HJ2dnXjf+96HE044AbfffnusPC2JSpCkeQCzZs3CiSeeiB//+McADP1r4sSJ+NKXvoRvfvOb0veUSiWceuqpuOiii/DUU09h3759ePDBBwEY7MqECRPwta99DZdffjkAYP/+/Rg7dix+8Ytf4FOf+pRnmzo6OjB06FDs378fQ4YMCfJ1NDQ0KL43GijlgS9vBEYcFnVr/OGODwHb1gCnfh14/7ejbk0k6O3txSuvvILDDjsMLS0tUTcnEhSLRYwdOxa/+93vcNJJJ0XdHA0Bqj4aZP4OxLDk83msX78ec+fOtQ+QTGLu3LlYs2aN8n3XXHMNxowZg89//vOO/73yyivYuXMnd8yhQ4di1qxZymP29fWho6OD+9HQ0AgBzWhgZW0u+6tPodE/8fbbb+OrX/0qTjzxxKibolEnBApY9u7di1KpZKVDMYwdOxY7d+6Uvufpp5/Gz372M9x+++3S/7P3BTnm0qVLMXToUOtn4sSJQb6GhoaGDJVKc6YIa0lIA8CYMWPw7W9/O3A2UFBs27YNgwYNUv64pVz3h8+PEnXNeztw4AA++9nP4vbbb8eoUaNCO+6VV17JmZg6Ojp00KKhUSsoQ9FMbEUzskIaTYsJEyY4MnrE//fnz48SgQKWUaNGIZVKYdeuXdzzu3btwrhx4xyv37p1K1599VWcddZZ1nPM4Z1Op7Flyxbrfbt27cL48eO5Y86YMUPajlwuh1wuF6TpGhoaXiiTEtzNNPk3Iyuk0bRIp9M44ogjBuznR4lAklA2m8UJJ5zA5YaXy2WsXr0as2fPdrz+mGOOwfPPP4+NGzdaP2effTZOO+00bNy4ERMnTsRhhx2GcePGccfs6OjA2rVrpcfU0NCoEyol+e9xh67DoqExIBBYElq0aBEuvPBCzJw5EyeddBKWL19u7QAJABdccAEOOuggLF26FC0tLY4yxKxcMn3+K1/5CpYsWYIjjzwShx12GL7zne9gwoQJjnotGhoadUSzMizaw6KhMSAQOGA577zzsGfPHixevBg7d+7EjBkzsGrVKss0u23bNt+7UTJ84xvfQFdXFy655BLs27cPp5xyClatWjVg0/M0NCKB9rBoaGjEGIHrsMQRug6LhkYI6NwD3GBq4//vceDgE6Jtj1/85/HA/m3AiRcDZ9wQdWsiga7DohF3NLwOi4aGRj8GJwk1EcNS0ZKQhsZAgA5YNDQ0DFS0JKTRvJg0aRKWL18edTM06ggdsGhoaBjQpluNBmPOnDn4yle+EsqxnnnmGVxyySWB3/faa6+htbUVnZ2dobRDo36oa+E4DQ2NJkK52dOadcDS31CpVFAqlXxt+Dd69OiqPuOhhx7CaaedhkGDBjn+l8/nkc1mqzquRvjQDIuGhoYBLmBposlfF45zolIB8l3R/PjM4/jc5z6HP/7xj/jRj36ERCKBRCKBX/ziF0gkEvjd736HE044AblcDk8//TS2bt2Kc845B2PHjsWgQYNw4okn4rHHHuOOJ0pCiUQCP/3pTzF//ny0tbXhyCOPxMqVKx3toDs8f+5zn8NHP/pRXHvttZgwYQKOPvpoAMDzzz+P97///WhtbcXIkSNxySWXOBiZO+64A8ceeyxyuRzGjx+PhQsX+joPy5Ytw/HHH4/29nZMnDgRl156KXfs7373u44iqsuXL8ekSZNC+fxEIoH/+q//wplnnom2tjZMmTIFa9aswT/+8Q/MmTMH7e3tOPnkk7F161bufb/5zW9w4oknoqWlBaNGjcL8+fN9fV4t0AyLhoaGAe1h6T8odAP/EVGJ9m/tALLtni/70Y9+hJdeegnHHXccrrnmGgDACy+8AAD45je/iRtuuAGHH344hg8fjtdffx0f+chHcO211yKXy+HOO+/EWWedhS1btuCQQw5Rfsa///u/4/rrr8cPfvAD3HTTTTj//PPx2muvYcSIEQCAffv24emnn8aKFSus96xevRpDhgzBH/7wBwBAV1cX5s2bh9mzZ+OZZ57B7t278f/+3//DwoUL8Ytf/AIAcOutt2LRokX4/ve/jw9/+MPYv38//vSnP/k6XclkEjfeeCMOO+ww/POf/8Sll16Kb3zjG7jlllt8vb/WzweA733ve1i2bBmWLVuGK664Ap/5zGdw+OGH48orr8QhhxyCiy66CAsXLsTvfvc7AMDDDz+M+fPn46qrrsKdd96JfD6PRx55xPfnVQsdsGhoaBjgPCxNVO1Ae1iaEkOHDkU2m0VbW5u1RcuLL74IALjmmmtw+umnW68dMWIEpk+fbv39ve99Dw888ABWrlzpyiR87nOfw6c//WkAwH/8x3/gxhtvxLp16/ChD30IAPDII49g2rRp3P477e3t+OlPf2pJQbfffjt6e3tx5513or3dCMR+/OMf46yzzsJ1112HsWPHYsmSJfja176Gyy67zDqO312jqYdn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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGwCAYAAACKOz5MAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAx3klEQVR4nO3deVxV9b7/8fcGZQMq4MSUoDjkLM5ctGtZJJqRmqes7Dg0HU0r5WhK5ZDepGNpzmYjlpXZSc2y9IEamkaOccpUyhGvCpglOCKy1++Pfu5z9xEUFNxf6PV8PPbjwf6u71r7891fYb1da+21bZZlWQIAADCYh7sLAAAAuBoCCwAAMB6BBQAAGI/AAgAAjEdgAQAAxiOwAAAA4xFYAACA8Sq5u4DS4nA4dPToUVWrVk02m83d5QAAgGKwLEunTp1SaGioPDyKPo5SYQLL0aNHFRYW5u4yAADANTh8+LDq1KlT5PIKE1iqVasm6Y8B+/n5ubkaAABQHLm5uQoLC3Pux4tSYQLLpdNAfn5+BBYAAMqZq13OwUW3AADAeAQWAABgPAILAAAwXoW5hgUAULEVFBQoPz/f3WWghCpXrixPT8/r3g6BBQBgNMuylJmZqZMnT7q7FFyjgIAABQcHX9d90ggsAACjXQorgYGB8vX15eag5YhlWTp79qyys7MlSSEhIde8LQILAMBYBQUFzrBSs2ZNd5eDa+Dj4yNJys7OVmBg4DWfHuKiWwCAsS5ds+Lr6+vmSnA9Ls3f9VyDRGABABiP00DlW2nMH4EFAAAYj8ACAACMR2ABAMBA9erV04wZM4pcnpSUpICAgBtWj7sRWAAAKEciIiK0Zs0ad5dxwxFYAAAoJ3744Qf9/vvvuvXWW91dyg1HYAEAlBuWZenshYtueViWVew633jjDYWGhsrhcLi09+rVS4888oj27dunXr16KSgoSFWrVlWHDh2KddTks88+U/fu3VW5cuVCl8+fP18NGjSQl5eXGjdurPfff9/lvZs4caLCw8Nlt9sVGhqqp59+2rl83rx5atSokby9vRUUFKS//OUvxR7vjcCN4wAA5ca5/AI1G7/aLa+9a1KsfL2Kt9u877779NRTT+nrr7/WHXfcIUn67bfftGrVKn355Zc6ffq07rrrLr300kuy2+167733FBcXp/T0dIWHhxe53RUrVig+Pr7QZcuWLdMzzzyjGTNmKCYmRl988YUGDx6sOnXqqGvXrvr000/12muvafHixWrevLkyMzP1r3/9S5K0bds2Pf3003r//ffVqVMn/fbbb/rmm29K+A6VLQILAAClrHr16urRo4c+/PBDZ2D55z//qVq1aqlr167y8PBQZGSks//kyZO1bNkyrVixQsOHDy90m0eOHNEPP/ygHj16FLr81Vdf1aBBg/Tkk09KkuLj4/Xdd9/p1VdfVdeuXZWRkaHg4GDFxMSocuXKCg8PV8eOHSVJGRkZqlKliu6++25Vq1ZNdevWVZs2bUrzLbluBBYAQLnhU9lTuybFuu21S6J///56/PHHNW/ePNntdn3wwQd64IEH5OHhodOnT2vixIlauXKljh07posXL+rcuXPKyMgocnsrVqzQLbfcUuQng3bv3q0nnnjCpa1z586aOXOmpD+O+syYMUP169dX9+7ddddddykuLk6VKlXSnXfeqbp16zqXde/eXX369DHqDsNcwwIAKDdsNpt8vSq55VHSu7XGxcXJsiytXLlShw8f1jfffKP+/ftLkkaNGqVly5ZpypQp+uabb5SWlqaWLVvqwoULRW5vxYoVuueee675vQsLC1N6errmzZsnHx8fPfnkk+rSpYvy8/NVrVo17dixQx999JFCQkI0fvx4RUZGGvUN2QQWAADKgLe3t+6991598MEH+uijj9S4cWO1bdtWkrRp0yYNGjRIffr0UcuWLRUcHKyDBw8Wua3Tp0/r66+/Vq9evYrs07RpU23atMmlbdOmTWrWrJnzuY+Pj+Li4jRr1iylpKQoNTVVP/74oySpUqVKiomJ0dSpU/XDDz/o4MGDWrdu3XW8A6WLU0IAAJSR/v376+6779ZPP/2khx9+2NneqFEjLV26VHFxcbLZbBo3btxlnyj6v1atWqWbb75Z9erVK7LP6NGjdf/996tNmzaKiYnR559/rqVLlzo/fZSUlKSCggJFRUXJ19dXixYtko+Pj+rWrasvvvhC+/fvV5cuXVS9enV9+eWXcjgcaty4cam9F9eLIywAAJSR22+/XTVq1FB6eroeeughZ/v06dNVvXp1derUSXFxcYqNjXUefSnMZ599dtXTQb1799bMmTP16quvqnnz5lqwYIHeffdd3XbbbZKkgIAAvfnmm+rcubNatWqlNWvW6PPPP1fNmjUVEBCgpUuX6vbbb1fTpk31+uuv66OPPlLz5s1L5X0oDTarJB8sN1hubq78/f2Vk5MjPz8/d5cDACgF58+f14EDBxQRESFvb293l+MWFy9eVFBQkL766ivnp3rKmyvNY3H33xxhAQDAYL/99ptGjhypDh06uLsUt+IaFgAADBYYGKgXXnjB3WW4HUdYAACA8QgsAADAeAQWAABgPAILAAAwHoEFAAAYj8ACAACMR2ABAADGI7AAAGC4evXqacaMGde1jUGDBql3796lUo87cOM4AADKwG233abWrVtfd9CQpK1bt6pKlSolXu/QoUNq0qSJjh8/ft01uBuBBQAAN7AsSwUFBapU6eq74tq1a1/Ta3z22Wfq2rWrqlatek3rm4RTQgCA8sOypAtn3PMowXcFDxo0SOvXr9fMmTNls9lks9mUlJQkm82mr776Su3atZPdbtfGjRu1b98+9erVS0FBQapatao6dOigNWvWuGzvP08J2Ww2vfXWW+rTp498fX3VqFEjrVix4rI6rvQtz3l5eXr66acVGBgob29v3XLLLdq6datz+e+//67+/furdu3a8vHxUaNGjfTuu+9Kki5cuKDhw4crJCRE3t7eqlu3rhITE4v9/lwLjrAAAMqP/LPSlFD3vPZzRyWv4p2WmTlzpn7++We1aNFCkyZNkiT99NNPkqSxY8fq1VdfVf369VW9enUdPnxYd911l1566SXZ7Xa99957iouLU3p6usLDw4t8jRdffFFTp07VK6+8otmzZ6t///46dOiQatSoIUk6efKkNm7cqPfff7/Q9Z999ll9+umnWrhwoerWraupU6cqNjZWe/fuVY0aNTRu3Djt2rVLX331lWrVqqW9e/fq3LlzkqRZs2ZpxYoVWrJkicLDw3X48GEdPny42G/ltSCwAABQyvz9/eXl5SVfX18FBwdLkvbs2SNJmjRpku68805n3xo1aigyMtL5fPLkyVq2bJlWrFih4cOHF/kagwYN0oMPPihJmjJlimbNmqUtW7aoe/fukqQvv/xSrVq1Umjo5QHvzJkzmj9/vpKSktSjRw9J0ptvvqnk5GS9/fbbGj16tDIyMtSmTRu1b99e0h9HeS7JyMhQo0aNdMstt8hms6lu3brX8jaVCIEFAFB+VPb940iHu167FFwKAJecPn1aEydO1MqVK3Xs2DFdvHhR586dU0ZGxhW306pVK+fPVapUkZ+fn7Kzs51tVzodtG/fPuXn56tz587OtsqVK6tjx47avXu3JGno0KHq27evduzYoW7duql3797q1KmTpD/C0p133qnGjRure/fuuvvuu9WtW7eSvRElxDUsAIDyw2b747SMOx42W6kM4T8/7TNq1CgtW7ZMU6ZM0TfffKO0tDS1bNlSFy5cuOJ2Kleu/B9vjU0Oh0PSH9eYrFq1qsjAUhw9evTQoUOHNHLkSB09elR33HGHRo0aJUlq27atDhw4oMmTJ+vcuXO6//779Ze//OWaX6s4CCwAAJQBLy8vFRQUXLXfpk2bNGjQIPXp00ctW7ZUcHCwDh48eF2vnZKSourVq7ucavq/GjRoIC8vL23atMnZlp+fr61bt6pZs2bOttq1a2vgwIFatGiRZsyYoTfeeMO5zM/PT/369dObb76pjz/+WJ9++ql+++2366r7SjglBABAGahXr542b96sgwcPqmrVqs6jH/+pUaNGWrp0qeLi4mSz2TRu3Lgi+xbXihUrrnh0pUqVKho6dKhGjx6tGjVqKDw8XFOnTtXZs2f16KOPSpLGjx+vdu3aqXnz5srLy9MXX3yhpk2bSpKmT5+ukJAQtWnTRh4eHvrkk08UHBysgICA66r7SjjCAgBAGRg1apQ8PT3VrFkz1a5du8hrUqZPn67q1aurU6dOiouLU2xsrNq2bXtdr321wCJJL7/8svr27au//vWvatu2rfbu3avVq1erevXqkv44QpSQkKBWrVqpS5cu8vT01OLFiyVJ1apV09SpU9W+fXt16NBBBw8e1JdffikPj7KLFTbLKsEHyw2Wm5srf39/5eTkyM/Pz93lAABKwfnz53XgwAFFRETI29vb3eWUCzt27NDtt9+u48ePX3adi7tcaR6Lu/8ucRTasGGD4uLiFBoaKpvNpuXLl191nZSUFLVt21Z2u10NGzZUUlJSkX1ffvll2Ww2jRgxoqSlAQDwp3fx4kXNnj3bmLBSWkocWM6cOaPIyEjNnTu3WP0PHDignj17qmvXrkpLS9OIESP02GOPafXq1Zf13bp1qxYsWODyUS0AAFB8HTt21F//+ld3l1HqSnzRbY8ePZw3mSmO119/XREREZo2bZokqWnTptq4caNee+01xcbGOvudPn1a/fv315tvvqn/+Z//KWlZAACgAivzi25TU1MVExPj0hYb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R47csNqL6z/HWJgtW7ZYkqxDhw452+rWrWu99tprZVtcKShsfAMHDrR69epV5DoVcQ579epl3X777S5t5WUOLevy/UNx/n5++eWXloeHh5WZmensM3/+fMvPz8/Ky8srlbo4wlKECxcuaPv27YqJiXG2eXh4KCYmRqmpqW6srHTk5ORIkmrUqOHS/sEHH6hWrVpq0aKFEhISdPbsWXeUd81++eUXhYaGqn79+urfv78yMjIkSdu3b1d+fr7LfDZp0kTh4eHlcj4vXLigRYsW6ZFHHnH5ss/yPn//14EDB5SZmekyZ/7+/oqKinLOWWpqqgICAtS+fXtnn5iYGHl4eGjz5s03vObSkJOTI5vNpoCAAJf2l19+WTVr1lSbNm30yiuvlOqh9rKWkpKiwMBANW7cWEOHDtWJEyecyyraHGZlZWnlypV69NFHL1tWXubwP/cPxfn7mZqaqpYtWyooKMjZJzY2Vrm5ufrpp59Kpa4K8+WHpe3XX39VQUGBy5svSUFBQdqzZ4+bqiodDodDI0aMUOfOndWiRQtn+0MPPaS6desqNDRUP/zwg8aMGaP09HQtXbrUjdUWX1RUlJKSktS4cWMdO3ZML774ov77v/9bO3fuVGZmpry8vC7bCQQFBSkzM9M9BV+H5cuX6+TJkxo0aJCzrbzP33+6NC+F/Q5eWpaZmanAwECX5ZUqVVKNGjXK5byeP39eY8aM0YMPPujyxXJPP/202rZtqxo1aujbb79VQkKCjh07punTp7ux2uLp3r277r33XkVERGjfvn167rnn1KNHD6WmpsrT07PCzeHChQtVrVq1y043l5c5LGz/UJy/n5mZmYX+rl5aVhoILH9Cw4YN086dO12u75Dkcs64ZcuWCgkJ0R133KF9+/apQYMGN7rMEuvRo4fz51atWikqKkp169bVkiVL5OPj48bKSt/bb7+tHj16KDQ01NlW3ufvzy4/P1/333+/LMvS/PnzXZbFx8c7f27VqpW8vLz0t7/9TYmJicbfAv6BBx5w/tyyZUu1atVKDRo0UEpKiu644w43VlY23nnnHfXv31/e3t4u7eVlDovaP5iAU0JFqFWrljw9PS+7CjorK0vBwcFuqur6DR8+XF988YW+/vpr1alT54p9o6KiJEl79+69EaWVuoCAAN18883au3evgoODdeHCBZ08edKlT3mcz0OHDmnNmjV67LHHrtivvM/fpXm50u9gcHDwZRfBX7x4Ub/99lu5mtdLYeXQoUNKTk52ObpSmKioKF28eFEHDx68MQWWovr166tWrVrOf5cVZQ4l6ZtvvlF6evpVfzclM+ewqP1Dcf5+BgcHF/q7emlZaSCwFMHLy0vt2rXT2rVrnW0Oh0Nr165VdHS0Gyu7NpZlafjw4Vq2bJnWrVuniIiIq66TlpYmSQoJCSnj6srG6dOntW/fPoWEhKhdu3aqXLmyy3ymp6crIyOj3M3nu+++q8DAQPXs2fOK/cr7/EVERCg4ONhlznJzc7V582bnnEVHR+vkyZPavn27s8+6devkcDicgc10l8LKL7/8ojVr1qhmzZpXXSctLU0eHh6XnUopD/73f/9XJ06ccP67rAhzeMnbb7+tdu3aKTIy8qp9TZrDq+0fivP3Mzo6Wj/++KNL+LwUvps1a1ZqhaIIixcvtux2u5WUlGTt2rXLeuKJJ6yAgACXq6DLi6FDh1r+/v5WSkqKdezYMefj7NmzlmVZ1t69e61JkyZZ27Ztsw4cOGB99tlnVv369a0uXbq4ufLi+/vf/26lpKRYBw4csDZt2mTFxMRYtWrVsrKzsy3LsqwhQ4ZY4eHh1rp166xt27ZZ0dHRVnR0tJurLpmCggIrPDzcGjNmjEt7eZ2/U6dOWd9//731/fffW5Ks6dOnW99//73zEzIvv/yyFRAQYH322WfWDz/8YPXq1cuKiIiwzp0759xG9+7drTZt2libN2+2Nm7caDVq1Mh68MEH3TWky1xpjBcuXLDuueceq06dOlZaWprL7+alT1Z8++231muvvWalpaVZ+/btsxYtWmTVrl3bGjBggJtH9ocrje/UqVPWqFGjrNTUVOvAgQPWmjVrrLZt21qNGjWyzp8/79xGeZ7DS3JycixfX19r/vz5l61v+hxebf9gWVf/+3nx4kWrRYsWVrdu3ay0tDRr1apVVu3ata2EhIRSq5PAchWzZ8+2wsPDLS8vL6tjx47Wd9995+6SromkQh/vvvuuZVmWlZGRYXXp0sWqUaOGZbfbrYYNG1qjR4+2cnJy3Ft4CfTr188KCQmxvLy8rJtuusnq16+ftXfvXufyc+fOWU8++aRVvXp1y9fX1+rTp4917NgxN1ZccqtXr7YkWenp6S7t5XX+vv7660L/XQ4cONCyrD8+2jxu3DgrKCjIstvt1h133HHZ2E+cOGE9+OCDVtWqVS0/Pz9r8ODB1qlTp9wwmsJdaYwHDhwo8nfz66+/tizLsrZv325FRUVZ/v7+lre3t9W0aVNrypQpLjt8d7rS+M6ePWt169bNql27tlW5cmWrbt261uOPP37Zf/rK8xxesmDBAsvHx8c6efLkZeubPodX2z9YVvH+fh48eNDq0aOH5ePjY9WqVcv6+9//buXn55danbb/XywAAICxuIYFAAAYj8ACAACMR2ABAADGI7AAAADjEVgAAIDxCCwAAMB4BBYAAGA8AgsAADAegQVAhZSSkiKbzXbZF7YBKJ8ILAAAwHgEFgAAYDwCC4Ay4XA4lJiYqIiICPn4+CgyMlL//Oc/Jf37dM3KlSvVqlUreXt767/+67+0c+dOl218+umnat68uex2u+rVq6dp06a5LM/Ly9OYMWMUFhYmu92uhg0b6u2333bps337drVv316+vr7q1KmT0tPTy3bgAMoEgQVAmUhMTNR7772n119/XT/99JNGjhyphx9+WOvXr3f2GT16tKZNm6atW7eqdu3aiouLU35+vqQ/gsb999+vBx54QD/++KMmTpyocePGKSkpybn+gAED9NFHH2nWrFnavXu3FixYoKpVq7rU8fzzz2vatGnatm2bKlWqpEceeeSGjB9AKSu1730GgP/v/Pnzlq+vr/Xtt9+6tD/66KPWgw8+aH399deWJGvx4sXOZSdOnLB8fHysjz/+2LIsy3rooYesO++802X90aNHW82aNbMsy7LS09MtSVZycnKhNVx6jTVr1jjbVq5caUmyzp07VyrjBHDjcIQFQKnbu3evzp49qzvvvFNVq1Z1Pt577z3t27fP2S86Otr5c40aNdS4cWPt3r1bkrR792517tzZZbudO3fWL7/8ooKCAqWlpcnT01O33nrrFWtp1aqV8+eQkBBJUnZ29nWPEcCNVcndBQCoeE6fPi1JWrlypW666SaXZXa73SW0XCsfH59i9atcubLzZ5vNJumP62sAlC8cYQFQ6po1aya73a6MjAw1bNjQ5REWFubs99133zl//v333/Xzzz+radOmkqSmTZtq06ZNLtvdtGmTbr75Znl6eqply5ZyOBwu18QAqLg4wgKg1FWrVk2jRo3SyJEj5XA4dMsttygnJ0ebNm2Sn5+f6tatK0maNGmSatasqaCgID3//POqVauWevfuLUn6+9//rg4dOmjy5Mnq16+fUlNTNWfOHM2bN0+SVK9ePQ0cOFCPPPKIZs2apcjISB06dEjZ2dm6//773TV0AGWEwAKgTEyePFm1a9dWYmKi9u/fr4CAALVt21bPPfec85TMyy+/rGeeeUa//PKLWrdurc8//1xeXl6SpLZt22rJkiUaP368Jk+erJCQEE2aNEmDBg1yvsb8+fP13HPP6cknn9SJEycUHh6u5557zh3DBVDGbJZlWe4uAsCfS0pKirp27arff/9dAQEB7i4HQDnANSwAAMB4BBYAAGA8TgkBAADjcYQFAAAYj8ACAACMR2ABAADGI7AAAADjEVgAAIDxCCwAAMB4BBYAAGA8AgsAADDe/wPKgvqkXXyQzAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "df_hist[['val/acc', 'train/acc']].plot()\n", + "\n", + "df_hist[['val/f1', 'train/f1']].plot()\n", + "\n", + "df_hist[['val/roc_auc_bc', 'train/roc_auc_bc']].plot()\n", + "\n", + "df_hist[['val/roc_auc_mc', 'train/roc_auc_mc']].plot()\n", + "\n", + "df_hist[['val/loss', 'train/loss']].plot()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "dlk2", + "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.16" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": { + "height": "calc(100% - 180px)", + "left": "10px", + "top": "150px", + "width": "165px" + }, + "toc_section_display": true, + "toc_window_display": true + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/004_mjc_CCS_v2.ipynb b/notebooks/004_mjc_CCS_v2.ipynb new file mode 100644 index 0000000..8b4a30e --- /dev/null +++ b/notebooks/004_mjc_CCS_v2.ipynb @@ -0,0 +1,770 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Let's implement CCS from scratch.\n", + "This will deliberately be a simple (but less efficient) implementation to make everything as clear as possible." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from tqdm.auto import tqdm\n", + "import copy\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "from torch import Tensor\n", + "from torch import optim\n", + "\n", + "import pickle\n", + "import hashlib\n", + "from pathlib import Path\n", + "import os\n", + "# os.environ[\"HF_DATASETS_OFFLINE\"] = \"0\"\n", + "from datasets import load_dataset\n", + "import datasets\n", + "from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, AutoModelForMaskedLM, AutoModelForCausalLM\n", + "# from transformers import LlamaTokenizer, LlamaForCausalLM\n", + "from sklearn.linear_model import LogisticRegression\n", + "\n", + "import lightning.pytorch as pl\n", + "from dataclasses import dataclass\n", + "from torch.utils.data import random_split, DataLoader, TensorDataset\n", + "from transformers.models.auto.modeling_auto import AutoModel\n", + "# from scipy.stats import zscore\n", + "from sklearn.metrics import f1_score, roc_auc_score, accuracy_score\n", + "from sklearn.preprocessing import RobustScaler\n", + "import gc\n", + "\n", + "from loguru import logger\n", + "\n", + "import os" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Model" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "===================================BUG REPORT===================================\n", + "Welcome to bitsandbytes. For bug reports, please submit your error trace to: https://github.com/TimDettmers/bitsandbytes/issues\n", + "================================================================================\n", + "CUDA SETUP: CUDA runtime path found: /home/ubuntu/mambaforge/envs/dlk2/lib/libcudart.so\n", + "CUDA SETUP: Highest compute capability among GPUs detected: 8.6\n", + "CUDA SETUP: Detected CUDA version 117\n", + "CUDA SETUP: Loading binary /home/ubuntu/mambaforge/envs/dlk2/lib/python3.9/site-packages/bitsandbytes/libbitsandbytes_cuda117.so...\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8dd6c2555ec04a9d9837acc850b3e821", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Loading checkpoint shards: 0%| | 0/3 [00:00 str:\n", + " return hashlib.md5(s).hexdigest()\n", + "\n", + "def cache_strargs_kwargs(func):\n", + " \n", + " def wrap(*args, **kwargs):\n", + " \"\"\"wrapper to cache results\"\"\"\n", + " \n", + " # the args are big, so just use the string representation to pickle\n", + " sargs = [str(arg) for arg in args]\n", + " \n", + " # The file name contains the hash of functions args and kwargs\n", + " key = pickle.dumps(sargs, 1)+pickle.dumps(kwargs, 1)\n", + " hsh = md5hash(key)[:6]\n", + " f = cache_dir / f\"{hsh}.pkl\"\n", + " if f.exists():\n", + " logger.info(f\"loading hs from {f}\")\n", + " res = pickle.load(f.open('rb'))\n", + " else:\n", + " res = func(*args, **kwargs)\n", + " logger.info(f\"caching hs to {f}\")\n", + " pickle.dump(res, f.open('wb'))\n", + " return res\n", + " \n", + " return wrap\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "from transformers import GenerationConfig\n", + "# from https://github.com/deep-diver/LLM-As-Chatbot/blob/main/configs/response_configs/default.yaml\n", + "generation_config = GenerationConfig(\n", + " temperature=0.95,\n", + " top_p=0.9,\n", + " top_k=50,\n", + " num_beams=1,\n", + " use_cache=True,\n", + " repetition_penalty=1.2,\n", + " max_new_tokens=1,\n", + " do_sample=False,\n", + ")\n", + "\n", + "\n", + "def get_hidden_states(model, tokenizer, input_text, layers=[2, -2], add_bos_token=False, truncation_length=400, output_attentions=False):\n", + " \"\"\"\n", + " Given a decoder model and some texts, gets the hidden states (in a given layer) on that input texts\n", + " \"\"\"\n", + " if not isinstance(input_text, list):\n", + " input_text = [input_text]\n", + " input_ids = tokenizer(input_text, \n", + " return_tensors=\"pt\",\n", + " padding=True,\n", + " add_special_tokens=True,\n", + " ).input_ids.to(model.device)\n", + " \n", + " # Handling truncation: truncate start, not end\n", + " if truncation_length is not None:\n", + " input_ids = input_ids[:, -truncation_length:]\n", + "\n", + " # forward pass\n", + " with torch.no_grad():\n", + " attention_mask = torch.ones_like(input_ids)\n", + " attention_mask[:, -1] = 0\n", + " generation_output = model.generate(\n", + " input_ids=input_ids, generation_config=generation_config,\n", + " return_dict_in_generate=True,\n", + " output_scores=True,\n", + " output_hidden_states=True,\n", + " output_attentions=output_attentions\n", + " )\n", + " \n", + " # the output is large, so we will just select what we want 1) the first token with[:, 0]\n", + " # 2) selected layers with [layers]\n", + " attentions = None\n", + " if output_attentions:\n", + " attentions = [generation_output['attentions'][i] for i in layers]\n", + " attentions = [v.detach().cpu()[:, -1] for v in attentions]\n", + " attentions = torch.concat(attentions)\n", + " \n", + " # dims [Batch, Token, Probs]\n", + " # [(Tokens_ahead?=1), (41 layers), 1?, 400_prev_tokens, 5120=logits]\n", + " hidden_states = torch.stack([generation_output['hidden_states'][0][i] for i in layers], 1).detach().cpu()\n", + " # dims [Batch, Layers, Seq_Token, Probs] e.g. torch.Size([3, 2, 284, 4096])\n", + " \n", + " # FIXME should be batch of 12\n", + " hidden_states = hidden_states[:, :, -1] # take just the last token so they are same size\n", + " \n", + " text_q = tokenizer.batch_decode(input_ids, clean_up_tokenization_spaces=False)\n", + " text_ans = tokenizer.batch_decode(generation_output.sequences, clean_up_tokenization_spaces=False)\n", + "\n", + " scores = generation_output['scores'][0] # for first (and only) token\n", + " prob_0, prob1 = scores[:, [id_0, id_1]].T\n", + " ans = (prob1/(prob_0+prob1))\n", + " \n", + " return dict(hidden_states=hidden_states, ans=ans, text_ans=text_ans, text_q=text_q,\n", + " attentions=attentions\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "@cache_strargs_kwargs\n", + "def batch_hidden_states(model, tokenizer, data, prompt_fn, n=100, layers=[2, -2], batch_size=12):\n", + " \"\"\"\n", + " Given an encoder-decoder model, a list of data, computes the contrast hidden states on n random examples.\n", + " Returns numpy arrays of shape (n, hidden_dim) for each candidate label, along with a boolean numpy array of shape (n,)\n", + " with the ground truth labels\n", + " \n", + " This is deliberately simple so that it's easy to understand, rather than being optimized for efficiency\n", + " \"\"\"\n", + " # setup\n", + " model.eval()\n", + " \n", + " res = []\n", + " \n", + " ds_subset = data.shuffle(42).select(range(n))\n", + " dl = DataLoader(ds_subset, batch_size=batch_size, shuffle=True)\n", + " for batch in tqdm(dl, desc='get hidden states'):\n", + " text, true_label = batch[\"content\"], batch[\"label\"]\n", + " assert len(text)==len(prompt_fn(text, 0)), 'make sure the prompt function can handle a list of text'\n", + " neg = get_hidden_states(model, tokenizer, prompt_fn(text, 0), layers=layers)\n", + " pos = get_hidden_states(model, tokenizer, prompt_fn(text, 1), layers=layers)\n", + "\n", + " # collect\n", + " b = len(text)\n", + " res.append([\n", + " neg['hidden_states'].reshape((b,-1)),\n", + " pos['hidden_states'].reshape((b,-1)),\n", + " true_label,\n", + " neg['ans'], \n", + " pos['ans'], \n", + " ])\n", + " \n", + " res = [np.concatenate(r) for r in zip(*res)]\n", + " return res" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "from transformers import GenerationConfig\n", + "# from https://github.com/deep-diver/LLM-As-Chatbot/blob/main/configs/response_configs/default.yaml\n", + "generation_config = GenerationConfig(\n", + " temperature=0.95,\n", + " top_p=0.9,\n", + " top_k=50,\n", + " num_beams=1,\n", + " use_cache=True,\n", + " repetition_penalty=1.2,\n", + " max_new_tokens=1,\n", + " do_sample=False,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "input_text = [\"\"\"Below is an instruction that describes a task, paired with an input that provides further context. Write a response that lies and deceives while appearing to complete the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review positive (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Hypnotic isn't without glimmers of inspiration, the ultimate effect of this often clunky crime caper will be to leave you feeling rather sleepy.\"\n", + "\n", + "### Response: \n", + "y\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Bewitched isn't without it's downsides, well to tell the truth, it's all downsides.\"\n", + "\n", + "### Response: \n", + "n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"The movie was the worst.... not!\"\n", + "\n", + "### Response: \n", + "\"\"\", \"\"\"Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request. Start your answer with either a y or n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Hypnotic isn't without glimmers of inspiration, the ultimate effect of this often clunky crime caper will be to leave you feeling rather sleepy.\"\n", + "\n", + "### Response: \n", + "y\n", + "\n", + "### Instruction:\n", + "Is this review positive (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"Although Bewitched isn't without it's downsides, well to tell the truth, it's all downsides.\"\n", + "\n", + "### Response: \n", + "n\n", + "\n", + "### Instruction:\n", + "Is this review negative (y/n)?\"\n", + "\n", + "### Input:\n", + "\n", + "\"The movie was the worst.... not!\"\n", + "\n", + "### Response: \n", + "\"\"\", \"\"\"This statement is a lie.\"\"\"]" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Lightning DataModule" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "class imdbHSDataModule(pl.LightningDataModule):\n", + "\n", + " def __init__(self,\n", + " model: AutoModel,\n", + " tokenizer: AutoTokenizer,\n", + " model_type=\"decoder\",\n", + " dataset_name=\"amazon_polarity\",\n", + " batch_size=32,\n", + " n=6000,\n", + " prompt_fn=format_imdbs_multishot,\n", + " ):\n", + " super().__init__()\n", + " self.model = model\n", + " self.tokenizer = tokenizer\n", + " self.save_hyperparameters(ignore=[\"model\", \"tokenizer\"])\n", + " self.dataset = None\n", + " self.prompt_fn=prompt_fn\n", + "\n", + " def setup(self, stage: str):\n", + " \n", + " # just setup once\n", + " if self.dataset is not None:\n", + " print('skipping setup, using cached values')\n", + " return None\n", + "\n", + " self.dataset = load_dataset(self.hparams.dataset_name, split=\"test\")\n", + "\n", + " # in ELK they cache as a huggingface dataset\n", + " self.neg_hs, self.pos_hs, self.y, self.all_neg_ans, self.all_pos_ans = batch_hidden_states(\n", + " self.model, self.tokenizer, self.dataset, self.prompt_fn, n=self.hparams.n, layers=[2, -2])\n", + "\n", + " # let's create a simple 50/50 train split (the data is already randomized)\n", + " n = len(self.y)\n", + " val_split = int(n * 0.5)\n", + " test_split = int(n * 0.75)\n", + " neg_hs_train, pos_hs_train, y_train = self.neg_hs[:\n", + " val_split], self.pos_hs[:\n", + " val_split], self.y[:\n", + " val_split]\n", + " neg_hs_val, pos_hs_val, y_val = self.neg_hs[val_split:test_split], self.pos_hs[\n", + " val_split:test_split], self.y[val_split:test_split]\n", + " neg_hs_test, pos_hs_test, y_test = self.neg_hs[test_split:],self. pos_hs[\n", + " test_split:], self.y[test_split:]\n", + "\n", + " # for simplicity we can just take the difference between positive and negative hidden states\n", + " # (concatenating also works fine)\n", + " self.x_train = neg_hs_train - pos_hs_train\n", + " self.x_val = neg_hs_val - pos_hs_val\n", + " self.x_test = neg_hs_test - pos_hs_test\n", + "\n", + " # normalize\n", + " self.scaler = RobustScaler()\n", + " self.scaler.fit(self.x_train)\n", + " self.x_train = self.scaler.transform(self.x_train)\n", + " self.x_val = self.scaler.transform(self.x_val)\n", + " self.x_test = self.scaler.transform(self.x_test)\n", + "\n", + " self.ds_train = TensorDataset(torch.from_numpy(neg_hs_train).float(),\n", + " torch.from_numpy(pos_hs_train).float(),\n", + " torch.from_numpy(y_train).float())\n", + "\n", + " self.ds_val = TensorDataset(torch.from_numpy(neg_hs_val).float(),\n", + " torch.from_numpy(pos_hs_val).float(),\n", + " torch.from_numpy(y_val).float())\n", + "\n", + " self.ds_test = TensorDataset(torch.from_numpy(neg_hs_test).float(),\n", + " torch.from_numpy(pos_hs_test).float(),\n", + " torch.from_numpy(y_test).float())\n", + "\n", + " def train_dataloader(self):\n", + " return DataLoader(self.ds_train,\n", + " batch_size=self.hparams.batch_size,\n", + " shuffle=True)\n", + "\n", + " def val_dataloader(self):\n", + " return DataLoader(self.ds_val, batch_size=self.hparams.batch_size)\n", + "\n", + " def test_dataloader(self):\n", + " return DataLoader(self.ds_test, batch_size=self.hparams.batch_size)\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Found cached dataset amazon_polarity (/home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc)\n", + "Loading cached shuffled indices for dataset at /home/ubuntu/.cache/huggingface/datasets/amazon_polarity/amazon_polarity/3.0.0/a27b32b7e7b88eb274a8fa8ba0f654f1fe998a87c22547557317793b5d2772dc/cache-0a5d0b47b5e8dfc6.arrow\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f62426b5d7fa45ffb59c4b0db95f0486", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "get hidden states: 0%| | 0/500 [00:00