├── scraping ├── .node-version ├── crawled-data │ └── .gitkeep ├── .prettierrc ├── babel.config.js ├── src │ ├── utils │ │ ├── date.ts │ │ ├── directory.ts │ │ ├── csv.ts │ │ └── array.ts │ ├── scraping-tools │ │ ├── segment │ │ │ ├── PageSegmentBase.ts │ │ │ ├── PageSegment.test.ts │ │ │ └── PageSegment.ts │ │ └── Scraper.ts │ ├── const │ │ ├── env.ts │ │ ├── html │ │ │ ├── node-type.ts │ │ │ └── element-type.ts │ │ └── path.ts │ └── scrape-page.ts ├── .eslintignore ├── .vscode │ └── settings.json ├── .eslintrc.js ├── README.md ├── package.json ├── .sendignore ├── .gitignore ├── dataset │ └── darkpatterns │ │ └── darkpattern.csv └── tsconfig.json ├── darkpattern-auto-detection-classical ├── pickles │ └── data │ │ └── .gitkeep ├── poetry.toml ├── mypy.ini ├── configs │ └── config.yaml ├── scripts │ └── train.sh ├── const │ ├── model.py │ └── path.py ├── utils │ ├── random_seed.py │ ├── dataset.py │ └── text.py ├── .vscode │ └── settings.json ├── pyproject.toml ├── README.md ├── .gitignore ├── experiments │ └── train.py └── poetry.lock ├── darkpattern-auto-detection-deeplearning ├── figures │ └── .gitkeep ├── .python-version ├── pickles │ └── models │ │ └── nn │ │ └── .gitkeep ├── poetry.toml ├── models │ └── nn │ │ ├── __init__.py │ │ └── bert.py ├── mypy.ini ├── utils │ ├── uuid.py │ ├── random_seed.py │ ├── text.py │ └── dataset.py ├── configs │ └── config.yaml ├── .vscode │ └── settings.json ├── const │ └── path.py ├── pyproject.toml ├── README.md ├── scripts │ └── train.sh ├── .gitignore ├── trainer │ └── trainer.py └── experiments │ └── train.py ├── README.md └── LICENSE /scraping/.node-version: -------------------------------------------------------------------------------- 1 | 16.5.0 2 | -------------------------------------------------------------------------------- /scraping/crawled-data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/pickles/data/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/figures/.gitkeep: -------------------------------------------------------------------------------- 1 | g -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/.python-version: -------------------------------------------------------------------------------- 1 | 3.9.0 2 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/pickles/models/nn/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | python_version = 3.8 3 | disallow_untyped_defs = True -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/models/nn/__init__.py: -------------------------------------------------------------------------------- 1 | from .bert import DarkpatternClassifierBert 2 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | python_version = 3.8 3 | disallow_untyped_defs = True -------------------------------------------------------------------------------- /scraping/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "singleQuote": true, 4 | "semi": true, 5 | "parser": "typescript" 6 | } 7 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/utils/uuid.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | 4 | def generate_uuid() -> str: 5 | return str(uuid.uuid1()) 6 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/configs/config.yaml: -------------------------------------------------------------------------------- 1 | model: 2 | name: rfc 3 | 4 | experiment: 5 | n_trial: 100 6 | 7 | random: 8 | seed: 42 9 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/scripts/train.sh: -------------------------------------------------------------------------------- 1 | poetry run python $PYTHONPATH/experiments/train.py \ 2 | -m model.name=lgb,rfc,svm,lr \ 3 | experiment.n_trial=500 4 | -------------------------------------------------------------------------------- /scraping/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['@babel/preset-env', { targets: { node: 'current' } }], 4 | '@babel/preset-typescript', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /scraping/src/utils/date.ts: -------------------------------------------------------------------------------- 1 | import { format } from 'date-fns'; 2 | 3 | export const formatDate = (date: Date, formatStr = 'yyyy-MM-dd'): string => { 4 | return format(date, formatStr); 5 | }; 6 | -------------------------------------------------------------------------------- /scraping/src/utils/directory.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs'; 2 | 3 | export const createDirIfNotExist = (dir: string): void => { 4 | if (!fs.existsSync(dir)) { 5 | fs.mkdirSync(dir); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /scraping/.eslintignore: -------------------------------------------------------------------------------- 1 | # don't ever lint node_modules 2 | node_modules 3 | # don't lint build output (make sure it's set to your correct build folder name) 4 | dist 5 | # don't lint nyc coverage output 6 | coverage -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/const/model.py: -------------------------------------------------------------------------------- 1 | # Define label name for each model. 2 | 3 | RANDOM_FOREST_MODEL = "rfc" 4 | SVC_MODEL = "svm" 5 | LOGISTIC_REGRESSION_MODEL = "lr" 6 | LIGHTGBM_MODEL = "lgb" 7 | -------------------------------------------------------------------------------- /scraping/src/scraping-tools/segment/PageSegmentBase.ts: -------------------------------------------------------------------------------- 1 | import Puppeteer from 'puppeteer'; 2 | 3 | export interface PageSegmentBase { 4 | segmentPage(element: Puppeteer.ElementHandle | null): Promise; 5 | } 6 | -------------------------------------------------------------------------------- /scraping/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 2, 3 | "editor.defaultFormatter": "esbenp.prettier-vscode", 4 | "editor.formatOnSave": true, 5 | "editor.codeActionsOnSave": { 6 | "source.fixAll.eslint": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /scraping/src/utils/csv.ts: -------------------------------------------------------------------------------- 1 | import { parse } from 'csv/sync'; 2 | import fs from 'node:fs'; 3 | 4 | export const readCsv = (pathToCsv: string): string[][] => { 5 | const csvData = fs.readFileSync(pathToCsv, 'utf8'); 6 | const records: string[][] = parse(csvData); 7 | return records; 8 | }; 9 | -------------------------------------------------------------------------------- /scraping/src/const/env.ts: -------------------------------------------------------------------------------- 1 | import 'dotenv/config'; 2 | 3 | export const SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL as string; 4 | export const HTTP_PROXY_URL = process.env.HTTP_PROXY_URL; 5 | export const HTTP_PROXY_PORT = 6 | process.env.HTTP_PROXY_PORT && Number(process.env.HTTP_PROXY_PORT); 7 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/utils/random_seed.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | 4 | import numpy as np 5 | 6 | 7 | def set_random_seed(random_seed: int = 42) -> None: 8 | random.seed(random_seed) 9 | os.environ["PYTHONHASHSEED"] = str(random_seed) 10 | np.random.seed(random_seed) 11 | -------------------------------------------------------------------------------- /scraping/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint'], 5 | extends: [ 6 | 'eslint:recommended', 7 | 'plugin:@typescript-eslint/recommended', 8 | 'plugin:prettier/recommended', 9 | 'prettier', 10 | ], 11 | } 12 | -------------------------------------------------------------------------------- /scraping/src/const/html/node-type.ts: -------------------------------------------------------------------------------- 1 | export const NODE_TYPES = { 2 | ELEMENT_NODE: 1, 3 | ATTRIBUTE_NODE: 2, 4 | TEXT_NODE: 3, 5 | CDATA_SECTION_NODE: 4, 6 | PROCESSING_INSTRUCTION_NODE: 7, 7 | COMMENT_NODE: 8, 8 | DOCUMENT_NODE: 9, 9 | DOCUMENT_TYPE_NODE: 10, 10 | DOCUMENT_FRAGMENT_NODE: 11, 11 | } as const; 12 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/configs/config.yaml: -------------------------------------------------------------------------------- 1 | model: 2 | pretrained: bert-base-uncased 3 | dropout: 0.1 4 | 5 | train: 6 | mode: not_cv 7 | lr: 1e-5 8 | batch_size: 128 9 | epochs: 5 10 | save_model: True 11 | n_fold: 5 12 | start_factor: 1.0 13 | 14 | preprocess: 15 | max_length: 24 16 | 17 | random: 18 | seed: 42 19 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.pylintEnabled": false, 3 | "python.linting.flake8Enabled": true, 4 | "python.linting.lintOnSave": true, 5 | "python.linting.mypyEnabled": true, 6 | "python.formatting.provider": "black", 7 | "editor.formatOnSave": true, 8 | "editor.codeActionsOnSave": { 9 | "source.organizeImports": true 10 | }, 11 | } -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/utils/random_seed.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | 4 | import numpy as np 5 | import torch 6 | 7 | 8 | def set_random_seed(random_seed: int = 42) -> None: 9 | random.seed(random_seed) 10 | os.environ["PYTHONHASHSEED"] = str(random_seed) 11 | np.random.seed(random_seed) 12 | torch.manual_seed(random_seed) 13 | torch.cuda.manual_seed(random_seed) 14 | torch.backends.cudnn.benchmark = True 15 | -------------------------------------------------------------------------------- /scraping/README.md: -------------------------------------------------------------------------------- 1 | ## Scraping code 2 | 3 | Code of scraping(collecting) non-dark pattern texts. 4 | 5 | ### Requirements 6 | 7 | - [Node](https://nodejs.org/en/) 16.5.0 8 | - [Yarn](https://yarnpkg.com/) 1.22.11 9 | 10 | ### Setup 11 | 12 | #### Installation 13 | 14 | Install dependencies by running: 15 | 16 | ``` 17 | $ yarn 18 | ``` 19 | 20 | #### Execute Scraping 21 | 22 | You can execute scraping by running: 23 | 24 | ``` 25 | $ yarn ts-node src/scrape-page.ts 26 | ``` -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.pylintEnabled": false, 3 | "python.linting.flake8Enabled": true, 4 | "python.linting.flake8Args": [ 5 | "--ignore=E203","--max-line-length=88" 6 | ], 7 | "python.linting.lintOnSave": true, 8 | "python.linting.mypyEnabled": true, 9 | "python.formatting.provider": "black", 10 | "editor.formatOnSave": true, 11 | "editor.codeActionsOnSave": { 12 | "source.organizeImports": true 13 | }, 14 | } -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/const/path.py: -------------------------------------------------------------------------------- 1 | from os.path import abspath, dirname, join 2 | 3 | PROJECT_ROOT = join(dirname(abspath(__file__)), "../") 4 | 5 | DATASET_PATH = join(PROJECT_ROOT, "dataset") 6 | 7 | DATASET_TSV_PATH = join(DATASET_PATH, "dataset.tsv") 8 | 9 | PICKLES_PATH = join(PROJECT_ROOT, "pickles") 10 | 11 | NN_MODEL_PICKLES_PATH = join(PICKLES_PATH, "models/nn") 12 | 13 | FIGURE_PATH = join(PROJECT_ROOT, "figures") 14 | 15 | CONFIG_PATH = join(PROJECT_ROOT, "configs") 16 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/utils/text.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from transformers import PreTrainedTokenizer 3 | 4 | 5 | def tensor_to_text(tensor: torch.Tensor, tokenizer: PreTrainedTokenizer) -> str: 6 | """ 7 | Convert tensor to text. 8 | """ 9 | return tokenizer.decode(tensor) 10 | 11 | 12 | def text_to_tensor( 13 | text: str, tokenizer: PreTrainedTokenizer, max_length: int 14 | ) -> torch.Tensor: 15 | """ 16 | Convert text to tensor. 17 | """ 18 | return torch.Tensor( 19 | tokenizer.encode(text, max_length=max_length, pad_to_max_length=True) 20 | ).to(torch.long) 21 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/const/path.py: -------------------------------------------------------------------------------- 1 | from os.path import abspath, dirname, join 2 | 3 | PROJECT_ROOT = join(dirname(abspath(__file__)), "../") 4 | 5 | DATASET_PATH = join(PROJECT_ROOT, "dataset/") 6 | 7 | DATASET_TSV_PATH = join(DATASET_PATH, "dataset.tsv") 8 | 9 | PICKLES_PATH = join(PROJECT_ROOT, "pickles") 10 | 11 | 12 | FIGURE_PATH = join(PROJECT_ROOT, "figures") 13 | 14 | CONFIG_PATH = join(PROJECT_ROOT, "configs") 15 | 16 | 17 | DATA_PICKLES_PATH = join(PICKLES_PATH, "data") 18 | 19 | PREPROCESSED_TEXT_DATA_PICKLES_PATH = join(DATA_PICKLES_PATH, "preprocessed_texts.pkl") 20 | LABEL_DATA_PICKLES_PATH = join(DATA_PICKLES_PATH, "labels.pkl") 21 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "darkpattern_auto_detection_classical" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["YadaYuki "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.8" 9 | scikit-learn = "^1.1.1" 10 | lightgbm = "^3.3.2" 11 | pandas = "1.2.0" 12 | hydra-core = "^1.2.0" 13 | wandb = "^0.12.21" 14 | nltk = "^3.7" 15 | optuna = "^2.10.1" 16 | 17 | [tool.poetry.dev-dependencies] 18 | mypy = "^0.931" 19 | isort = "^5.10.1" 20 | flake8 = "^4.0.1" 21 | black = "^22.1.0" 22 | 23 | [build-system] 24 | requires = ["poetry-core>=1.0.0"] 25 | build-backend = "poetry.core.masonry.api" 26 | -------------------------------------------------------------------------------- /scraping/src/const/path.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | export const PROJECT_ROOT = path.join(__dirname, '../../'); 4 | 5 | export const DATASET_DIR = path.join(PROJECT_ROOT, 'dataset'); 6 | 7 | export const DARKPATTERN_CSV_PATH = path.join( 8 | DATASET_DIR, 9 | 'darkpatterns', 10 | 'darkpattern.csv' 11 | ); 12 | 13 | export const DARKPATTERN_CSV_DIR = path.join(DATASET_DIR, 'darkpatterns'); 14 | 15 | export const DARKPATTERN_SPLITED_CSV_DIR = path.join( 16 | DATASET_DIR, 17 | 'darkpatterns', 18 | 'splited' 19 | ); 20 | 21 | export const CRAWLED_DATA_DIR = path.join(PROJECT_ROOT, 'crawled-data'); 22 | export const CRAWLED_TSV_DIR = path.join(DATASET_DIR, 'crawled-tsv'); 23 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "darkpattern_auto_detection_deeplearning" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["YadaYuki "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "3.9.0" 9 | requests = "^2.27.1" 10 | scikit-learn = "^1.0.2" 11 | torch = "^1.10.2" 12 | pytest = "^7.0.1" 13 | matplotlib = "^3.5.1" 14 | sklearn = "^0.0" 15 | torchtext = "^0.12.0" 16 | transformers = "^4.17.0" 17 | pandas = "1.2.0" 18 | hydra-core = "^1.1.1" 19 | wandb = "^0.12.21" 20 | 21 | [tool.poetry.dev-dependencies] 22 | mypy = "^0.931" 23 | isort = "^5.10.1" 24 | flake8 = "^4.0.1" 25 | black = "^22.1.0" 26 | types-requests = "^2.27.10" 27 | pyproject-flake8 = "^0.0.1-alpha.3" 28 | notebook = "^6.4.12" 29 | 30 | [build-system] 31 | requires = ["poetry-core>=1.0.0"] 32 | build-backend = "poetry.core.masonry.api" -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/utils/dataset.py: -------------------------------------------------------------------------------- 1 | from typing import Callable, List, Tuple 2 | 3 | import torch 4 | from torch.utils.data import Dataset 5 | 6 | 7 | class DarkpatternDataset(Dataset): 8 | def __init__( 9 | self, 10 | texts: List[str], 11 | labels: List[int], 12 | text_to_tensor: Callable[[str], torch.Tensor], 13 | ) -> None: 14 | self.texts: List[str] = texts 15 | self.labels: torch.Tensor = torch.tensor(labels) 16 | self.text_to_tensor = text_to_tensor 17 | 18 | def __getitem__( 19 | self, index: int 20 | ) -> Tuple[torch.Tensor, torch.Tensor]: # [text_tensor, label_tensor] 21 | text_encoded = self.text_to_tensor(str(self.texts[index])) 22 | return text_encoded, self.labels[index] 23 | 24 | def __len__(self) -> int: 25 | return len(self.texts) 26 | -------------------------------------------------------------------------------- /scraping/src/utils/array.ts: -------------------------------------------------------------------------------- 1 | export const shuffle = (array: T[]): T[] => { 2 | const shuffleArray = array.slice(); 3 | shuffleArray.sort(() => Math.random() - 0.5); 4 | return shuffleArray; 5 | }; 6 | 7 | export const choice = (array: T[], num: number, unique = true): T[] => { 8 | const choiceArray = []; 9 | const selected = new Set(); 10 | while (choiceArray.length < num) { 11 | const idx = Math.floor(Math.random() * array.length); 12 | if (unique && selected.has(idx)) { 13 | continue; 14 | } 15 | choiceArray.push(array[idx]); 16 | selected.add(idx); 17 | } 18 | return choiceArray; 19 | }; 20 | 21 | export const sliceIntoChunks = (array: T[], chunkSize: number): T[][] => { 22 | const res: T[][] = []; 23 | for (let i = 0; i < array.length; i += chunkSize) { 24 | const chunk = array.slice(i, i + chunkSize); 25 | res.push(chunk); 26 | } 27 | return res; 28 | }; 29 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/models/nn/bert.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch import nn 3 | from transformers import BertModel 4 | 5 | 6 | class DarkpatternClassifierBert(nn.Module): 7 | def __init__( 8 | self, 9 | pretrained: str = "bert-base-uncased", 10 | dropout_rate: float = 0.1, 11 | output_layer: nn.Linear = nn.Linear(in_features=768, out_features=2), 12 | ): 13 | super(DarkpatternClassifierBert, self).__init__() 14 | self.__pretrained = pretrained 15 | self.bert = BertModel.from_pretrained(self.__pretrained) 16 | self.dropout = nn.Dropout(dropout_rate) 17 | self.output_layer = output_layer 18 | 19 | def forward(self, x: torch.Tensor) -> torch.Tensor: 20 | x = self.bert(x)[0] # [batch_size,seq_len,768] 21 | x = x[:, 0, :] # [batch_size,1,768] 22 | x = self.dropout(x) 23 | x = self.output_layer(x) 24 | return x 25 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/README.md: -------------------------------------------------------------------------------- 1 | # Dark Patterns Automatic Detection using classical NLP methods 2 | 3 | Experimental code of text-based dark patterns automatic detection using classical NLP methods 4 | 5 | ## Requirements 6 | 7 | - [Python](https://www.python.org/downloads/) 3.9.0 8 | - [Poetry](https://python-poetry.org/docs/) 1.2.1 9 | 10 | ## Setup 11 | 12 | ### Installation 13 | 14 | Install dependencies by running: 15 | 16 | ``` 17 | $ poetry install 18 | ``` 19 | 20 | ### Dataset preparation 21 | 22 | Create Symlink to [dataset/]() directory by : 23 | 24 | ``` 25 | $ ln -s {path to dataset/} dataset 26 | ``` 27 | 28 | ※ Please place `dataset.tsv` directly under the `dataset/` directory.(`dataset/dataset.tsv`) 29 | 30 | ### Set PYTHONPATH 31 | 32 | ``` 33 | $ export PYTHONPATH="$(pwd)" 34 | ``` 35 | 36 | ## Train & Evaluate model 37 | 38 | You can run experiment using GPU or CPU by running: 39 | 40 | ``` 41 | $ sh scripts/train.sh 42 | ``` -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/README.md: -------------------------------------------------------------------------------- 1 | ## Dark Patterns Automatic Detection using transformer-based pre-trained language models 2 | 3 | Experimental code of text-based dark patterns automatic detection using transformer-based pre-trained language models. 4 | 5 | ### Requirements 6 | 7 | - [Python](https://www.python.org/downloads/) 3.9.0 8 | - [Poetry](https://python-poetry.org/docs/) 1.2.1 9 | 10 | ### Setup 11 | 12 | #### Installation 13 | 14 | Install dependencies by running: 15 | 16 | ``` 17 | $ poetry install 18 | ``` 19 | 20 | #### Dataset preparation 21 | 22 | Create Symlink to [dataset/]() directory by : 23 | 24 | ``` 25 | $ ln -s {path to dataset/} dataset 26 | ``` 27 | 28 | ※ Please place `dataset.tsv` directly under the `dataset/` directory.(`dataset/dataset.tsv`) 29 | 30 | #### Set PYTHONPATH 31 | 32 | ``` 33 | $ export PYTHONPATH="$(pwd)" 34 | ``` 35 | 36 | ### Train & Evaluate model 37 | 38 | You can run experiment, 5-fold cross validation, using GPU(recommended) or CPU by running: 39 | 40 | ``` 41 | $ sh scripts/train.sh 42 | ``` -------------------------------------------------------------------------------- /scraping/src/scraping-tools/Scraper.ts: -------------------------------------------------------------------------------- 1 | import Puppeteer from 'puppeteer'; 2 | import { PageSegmentBase } from './segment/PageSegmentBase'; 3 | import path from 'path'; 4 | 5 | export class Scraper { 6 | private pageSegment: PageSegmentBase; 7 | 8 | constructor(pageSegment: PageSegmentBase) { 9 | this.pageSegment = pageSegment; 10 | } 11 | 12 | public async scrapingAndSegmentPage( 13 | page: Puppeteer.Page, 14 | url: string, 15 | pathToScreenshotDir: string, 16 | waitTimeSec: number, 17 | viewport: Puppeteer.Viewport = { width: 1440, height: 900 } 18 | ): Promise { 19 | await page.goto(url, { 20 | timeout: 0, 21 | }); 22 | await page.setViewport(viewport); 23 | await page.waitForTimeout(waitTimeSec * 1000); 24 | const texts = await this.pageSegment.segmentPage(await page.$('html')); 25 | await this.takeScreenShot( 26 | page, 27 | path.join(pathToScreenshotDir, `whole-page.png`) 28 | ); 29 | return texts; 30 | } 31 | 32 | private async takeScreenShot( 33 | page: Puppeteer.Page, 34 | pathToScreenshot: string 35 | ): Promise { 36 | await page.screenshot({ path: pathToScreenshot, fullPage: true }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/utils/dataset.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | from os.path import exists 3 | from typing import List, Tuple 4 | 5 | import pandas as pd 6 | from const.path import LABEL_DATA_PICKLES_PATH, PREPROCESSED_TEXT_DATA_PICKLES_PATH 7 | 8 | from utils import text 9 | 10 | 11 | def get_dataset( 12 | path_to_tsv: str, reload_data: bool = False 13 | ) -> Tuple[List[str], List[int]]: 14 | """ 15 | Get dataset from tsv file. 16 | """ 17 | pickles_exist = exists(PREPROCESSED_TEXT_DATA_PICKLES_PATH) and exists( 18 | LABEL_DATA_PICKLES_PATH 19 | ) 20 | 21 | if pickles_exist and not reload_data: 22 | texts, labels = [], [] 23 | with open(PREPROCESSED_TEXT_DATA_PICKLES_PATH, "rb") as f: 24 | texts = pickle.load(f) 25 | with open(LABEL_DATA_PICKLES_PATH, "rb") as f: 26 | labels = pickle.load(f) 27 | return texts, labels 28 | 29 | df = pd.read_csv(path_to_tsv, sep="\t", encoding="utf-8") 30 | texts = df.text.tolist() 31 | 32 | preprocessed_texts = [text.preprocess(t) for t in texts] 33 | labels = df.label.tolist() 34 | 35 | with open(PREPROCESSED_TEXT_DATA_PICKLES_PATH, "wb") as f: 36 | pickle.dump(preprocessed_texts, f) 37 | with open(LABEL_DATA_PICKLES_PATH, "wb") as f: 38 | pickle.dump(labels, f) 39 | 40 | return preprocessed_texts, labels 41 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/utils/text.py: -------------------------------------------------------------------------------- 1 | import re 2 | import string 3 | 4 | from nltk.stem import WordNetLemmatizer 5 | 6 | 7 | def preprocess(text: str) -> str: 8 | 9 | text = remove_punctuation(text) 10 | 11 | text = lower_text(text) 12 | 13 | text = remove_emoji(text) 14 | 15 | text = convert_num_to_label(text) 16 | 17 | lemmatizer = WordNetLemmatizer() 18 | text = lemmatize_text(text, lemmatizer) 19 | 20 | return text 21 | 22 | 23 | def remove_punctuation(text: str) -> str: 24 | return "".join([c for c in text if c not in string.punctuation]) 25 | 26 | 27 | def lower_text(text: str) -> str: 28 | return text.lower() 29 | 30 | 31 | def remove_emoji(string: str) -> str: 32 | emoji_pattern = re.compile( 33 | "[" 34 | "\U0001F600-\U0001F64F" # emoticons 35 | "\U0001F300-\U0001F5FF" # symbols & pictographs 36 | "\U0001F680-\U0001F6FF" # transport & map symbols 37 | "\U0001F1E0-\U0001F1FF" # flags (iOS) 38 | "\U00002702-\U000027B0" 39 | "\U000024C2-\U0001F251" 40 | "]+", 41 | flags=re.UNICODE, 42 | ) 43 | return emoji_pattern.sub(r"", string) 44 | 45 | 46 | def convert_num_to_label(text: str) -> str: 47 | num_pattern = re.compile("[0-9]+") 48 | return num_pattern.sub(r"number", text) 49 | 50 | 51 | def lemmatize_text( 52 | text: str, lemmatizer: WordNetLemmatizer = WordNetLemmatizer() 53 | ) -> str: 54 | text = text.lower() 55 | return " ".join(lemmatizer.lemmatize(word) for word in text.split()) 56 | -------------------------------------------------------------------------------- /scraping/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts-starter", 3 | "version": "1.0.0", 4 | "description": "typescriptプロジェクトのオリジナル初期設定", 5 | "scripts": { 6 | "dev": "ts-node src/index.ts", 7 | "scraping": "ts-node src/crawl.ts", 8 | "gen:tsv": "ts-node src/generate-tsv.ts", 9 | "dev:watch": "ts-node-dev --respawn src/index.ts", 10 | "build": "tsc -p .", 11 | "clean": "rm -rf dist", 12 | "format": "prettier --write src/**/*.ts", 13 | "lint": "eslint --fix src/**/*.ts", 14 | "test": "jest" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/YadaYuki/ts-starter.git" 19 | }, 20 | "keywords": [], 21 | "author": "", 22 | "license": "ISC", 23 | "bugs": { 24 | "url": "https://github.com/YadaYuki/ts-starter/issues" 25 | }, 26 | "homepage": "https://github.com/YadaYuki/ts-starter#readme", 27 | "devDependencies": { 28 | "@babel/preset-env": "^7.16.11", 29 | "@babel/preset-typescript": "^7.16.7", 30 | "@types/axios": "^0.14.0", 31 | "@types/cheerio": "^0.22.31", 32 | "@types/jest": "^27.4.1", 33 | "@types/jsdom": "^16.2.14", 34 | "@types/json2csv": "^5.0.3", 35 | "@types/node": "^16.4.0", 36 | "@types/puppeteer-core": "^5.4.0", 37 | "@types/tunnel": "^0.0.3", 38 | "@typescript-eslint/eslint-plugin": "^4.28.4", 39 | "@typescript-eslint/parser": "^4.28.4", 40 | "eslint": "^7.31.0", 41 | "eslint-config-prettier": "^8.3.0", 42 | "eslint-plugin-prettier": "^3.4.0", 43 | "jest": "^27.5.1", 44 | "prettier": "^2.3.2", 45 | "ts-node": "^10.1.0", 46 | "ts-node-dev": "^1.1.8", 47 | "typescript": "^4.3.5" 48 | }, 49 | "dependencies": { 50 | "axios": "^0.27.2", 51 | "cheerio": "^1.0.0-rc.10", 52 | "csv": "^6.0.5", 53 | "date-fns": "^2.28.0", 54 | "dotenv": "^16.0.1", 55 | "jsdom": "^19.0.0", 56 | "json2csv": "^5.0.7", 57 | "puppeteer": "^13.5.2", 58 | "tunnel": "^0.0.6" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /scraping/src/const/html/element-type.ts: -------------------------------------------------------------------------------- 1 | export const BLOCK_ELEMENTS = { 2 | ADDRESS: 'address', 3 | ARTICLE: 'article', 4 | ASIDE: 'aside', 5 | BLOCKQUOTE: 'blockquote', 6 | DETAILS: 'details', 7 | DIALOG: 'dialog', 8 | DD: 'dd', 9 | DIV: 'div', 10 | DL: 'dl', 11 | DT: 'dt', 12 | FIELDSET: 'fieldset', 13 | FIGCAPTION: 'figcaption', 14 | FIGURE: 'figure', 15 | FOOTER: 'footer', 16 | FORM: 'form', 17 | H1: 'h1', 18 | H2: 'h2', 19 | H3: 'h3', 20 | H4: 'h4', 21 | H5: 'h5', 22 | H6: 'h6', 23 | HEADER: 'header', 24 | HGROUP: 'hgroup', 25 | HR: 'hr', 26 | LI: 'li', 27 | MAIN: 'main', 28 | NAV: 'nav', 29 | OL: 'ol', 30 | P: 'p', 31 | PRE: 'pre', 32 | SECTION: 'section', 33 | TABLE: 'table', 34 | UL: 'ul', 35 | } as const; 36 | 37 | export const INLINE_ELEMENT = { 38 | A: 'a', 39 | ABBR: 'abbr', 40 | ACRONYM: 'acronym', 41 | AUDIO: 'audio', 42 | B: 'b', 43 | BDI: 'bdi', 44 | BDO: 'bdo', 45 | BIG: 'big', 46 | BR: 'br', 47 | BUTTON: 'button', 48 | CANVAS: 'canvas', 49 | CITE: 'cite', 50 | CODE: 'code', 51 | DATA: 'data', 52 | DATALIST: 'datalist', 53 | DEL: 'del', 54 | DFN: 'dfn', 55 | EM: 'em', 56 | EMBED: 'embed', 57 | I: 'i', 58 | IFRAME: 'iframe', 59 | IMG: 'img', 60 | INPUT: 'input', 61 | INS: 'ins', 62 | KBD: 'kbd', 63 | LABEL: 'label', 64 | MAP: 'map', 65 | MARK: 'mark', 66 | METER: 'meter', 67 | NOSCRIPT: 'noscript', 68 | OBJECT: 'object', 69 | OUTPUT: 'output', 70 | PICTURE: 'picture', 71 | PROGRESS: 'progress', 72 | Q: 'q', 73 | RUBY: 'ruby', 74 | S: 's', 75 | SAMP: 'samp', 76 | SCRIPT: 'script', 77 | SELECT: 'select', 78 | SLOT: 'slot', 79 | SMALL: 'small', 80 | SPAN: 'span', 81 | STRONG: 'strong', 82 | SUB: 'sub', 83 | SUP: 'sup', 84 | SVG: 'svg', 85 | TEMPLATE: 'template', 86 | TEXTAREA: 'textarea', 87 | TIME: 'time', 88 | U: 'u', 89 | TT: 'tt', 90 | VAR: 'var', 91 | VIDEO: 'video', 92 | WBR: 'wbr', 93 | } as const; 94 | -------------------------------------------------------------------------------- /scraping/.sendignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # parcel-bundler cache (https://parceljs.org/) 72 | .cache 73 | 74 | # Next.js build output 75 | .next 76 | 77 | # Nuxt.js build / generate output 78 | .nuxt 79 | dist 80 | 81 | # Gatsby files 82 | .cache/ 83 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 84 | # https://nextjs.org/blog/next-9-1#public-directory-support 85 | # public 86 | 87 | # vuepress build output 88 | .vuepress/dist 89 | 90 | # Serverless directories 91 | .serverless/ 92 | 93 | # FuseBox cache 94 | .fusebox/ 95 | 96 | # DynamoDB Local files 97 | .dynamodb/ 98 | 99 | # TernJS port file 100 | .tern-port 101 | 102 | # Original 103 | .sendignore 104 | send.sh 105 | .git -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/scripts/train.sh: -------------------------------------------------------------------------------- 1 | poetry run python $PYTHONPATH/experiments/train.py \ 2 | -m model.pretrained=roberta-large \ 3 | train.lr=3e-5 \ 4 | train.batch_size=32 \ 5 | train.mode=cv \ 6 | preprocess.max_length=32 \ 7 | train.epochs=5 \ 8 | train.start_factor=0.5 \ 9 | train.save_model=True 10 | 11 | 12 | poetry run python $PYTHONPATH/experiments/train.py \ 13 | -m model.pretrained=bert-base-uncased \ 14 | train.lr=4e-5 \ 15 | train.batch_size=16 \ 16 | train.mode=cv \ 17 | preprocess.max_length=64 \ 18 | train.epochs=5 \ 19 | train.start_factor=0.5 \ 20 | train.save_model=True 21 | 22 | poetry run python $PYTHONPATH/experiments/train.py \ 23 | -m model.pretrained=bert-large-uncased \ 24 | train.lr=3e-5 \ 25 | train.batch_size=32 \ 26 | train.mode=cv \ 27 | preprocess.max_length=32 \ 28 | train.epochs=5 \ 29 | train.start_factor=0.5 \ 30 | train.save_model=True 31 | 32 | poetry run python $PYTHONPATH/experiments/train.py \ 33 | -m model.pretrained=roberta-base \ 34 | train.lr=3e-5 \ 35 | train.batch_size=128 \ 36 | train.mode=cv \ 37 | preprocess.max_length=32 \ 38 | train.epochs=5 \ 39 | train.start_factor=0.5 \ 40 | train.save_model=True 41 | 42 | poetry run python $PYTHONPATH/experiments/train.py \ 43 | -m model.pretrained=albert-base-v2 \ 44 | train.lr=3e-5 \ 45 | train.batch_size=16 \ 46 | train.mode=cv \ 47 | preprocess.max_length=32 \ 48 | train.epochs=5 \ 49 | train.start_factor=0.5 \ 50 | train.save_model=True 51 | 52 | poetry run python $PYTHONPATH/experiments/train.py \ 53 | -m model.pretrained=xlnet-large-cased \ 54 | train.lr=2e-5 \ 55 | train.batch_size=32 \ 56 | train.mode=cv \ 57 | preprocess.max_length=32 \ 58 | train.epochs=5 \ 59 | train.start_factor=0.5 \ 60 | train.save_model=True 61 | 62 | poetry run python $PYTHONPATH/experiments/train.py \ 63 | -m model.pretrained=xlnet-base-cased \ 64 | train.lr=4e-5 \ 65 | train.batch_size=16 \ 66 | train.mode=cv \ 67 | preprocess.max_length=32 \ 68 | train.epochs=5 \ 69 | train.start_factor=0.5 \ 70 | train.save_model=True 71 | 72 | poetry run python $PYTHONPATH/experiments/train.py \ 73 | -m model.pretrained=albert-large-v2 \ 74 | train.lr=5e-5 \ 75 | train.batch_size=32 \ 76 | train.mode=cv \ 77 | preprocess.max_length=32 \ 78 | train.epochs=5 \ 79 | train.start_factor=0.5 \ 80 | train.save_model=True 81 | 82 | -------------------------------------------------------------------------------- /scraping/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # dataset/ 10 | 11 | # Diagnostic reports (https://nodejs.org/api/report.html) 12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | *.lcov 26 | 27 | # nyc test coverage 28 | .nyc_output 29 | 30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 31 | .grunt 32 | 33 | # Bower dependency directory (https://bower.io/) 34 | bower_components 35 | 36 | # node-waf configuration 37 | .lock-wscript 38 | 39 | # Compiled binary addons (https://nodejs.org/api/addons.html) 40 | build/Release 41 | 42 | # Dependency directories 43 | node_modules/ 44 | jspm_packages/ 45 | 46 | # TypeScript v1 declaration files 47 | typings/ 48 | 49 | # TypeScript cache 50 | *.tsbuildinfo 51 | 52 | # Optional npm cache directory 53 | .npm 54 | 55 | # Optional eslint cache 56 | .eslintcache 57 | 58 | # Microbundle cache 59 | .rpt2_cache/ 60 | .rts2_cache_cjs/ 61 | .rts2_cache_es/ 62 | .rts2_cache_umd/ 63 | 64 | # Optional REPL history 65 | .node_repl_history 66 | 67 | # Output of 'npm pack' 68 | *.tgz 69 | 70 | # Yarn Integrity file 71 | .yarn-integrity 72 | 73 | # dotenv environment variables file 74 | .env 75 | .env.test 76 | 77 | # parcel-bundler cache (https://parceljs.org/) 78 | .cache 79 | 80 | # Next.js build output 81 | .next 82 | 83 | # Nuxt.js build / generate output 84 | .nuxt 85 | dist 86 | 87 | # Gatsby files 88 | .cache/ 89 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 90 | # https://nextjs.org/blog/next-9-1#public-directory-support 91 | # public 92 | 93 | # vuepress build output 94 | .vuepress/dist 95 | 96 | # Serverless directories 97 | .serverless/ 98 | 99 | # FuseBox cache 100 | .fusebox/ 101 | 102 | # DynamoDB Local files 103 | .dynamodb/ 104 | 105 | # TernJS port file 106 | .tern-port 107 | 108 | # screenshot/* 109 | # !screenshot/.gitkeep 110 | 111 | 112 | crawled-data/* 113 | !crawled-data/.gitkeep 114 | -------------------------------------------------------------------------------- /scraping/dataset/darkpatterns/darkpattern.csv: -------------------------------------------------------------------------------- 1 | page_id,Pattern String,Comment,Pattern Category,Pattern Type,Where in website?,Deceptive?,Website Page 2 | 1,Collin P. from Grandview Missouri just bought BURGUNDY TWO BUTTON SUIT ABOUT 5 SECONDS AGO,Periodic popup,Social Proof,Activity Notification,Product Page,No,https://alaindupetit.com/collections/all-suits/products/black-two-button?variant=28038644166 3 | 2,"Faith in Glendale, United States purchased a Choose Your Flavors 5 Bag Sample Pack (Whole Bean) about 1 hour ago",Periodic popup,Social Proof,Activity Notification,Product Page,No,https://bonescoffee.com/products/strawberry-cheesecake-by-bones-coffee-company-16oz?variant=31049004609 4 | 3,Sharmeen Atif From Karachi just bought Stylish Metal Glasses Frames For Kids-Assorted-NA7157,Periodic popup,Social Proof,Activity Notification,Product Page,No,https://brandsego.com/collections/under-rs-99/products/b-s-n-lip-gloss-na6977 5 | 4,9 people are viewing this.,Product detail,Social Proof,Activity Notification,Product Page,No,https://brightechshop.com/products/ambience-solar-1w?variant=8038410879012 6 | 5,5338 people viewed this in the last hour,Periodic popup,Social Proof,Activity Notification,Product Page,No,https://bumpboxes.com/ 7 | 6,"Keith in Champaign, Illinois bought Mini USB Audio Cassette to MP3 Converterabout 56 minutes ago",Periodic popup,Social Proof,Activity Notification,Product Page,No,https://casettetomp3.com/products/mini-usb-audio-cassette-tape-converter-to-mp3-cd-player-pc?variant=2859265032202&utm_source=fomo&utm_medium=notification 8 | 7,Jamie from Eloy United States purchased a CBD Oil Vape Additives 4 Pack About 7 hours ago,Periodic popup,Social Proof,Activity Notification,Product Page,No,https://cbdfx.com/products/og-kush-cbd-terpenes-vape-pen-50mg/ 9 | 8,"Someone in Kilwinning, United Kingdom just bought Cuban Link Chain Bracelet",Periodic popup,Social Proof,Activity Notification,Product Page,No,https://chainedandable.com/collections/old-english/products/st-christopher-cut-out-pendant-figaro 10 | 9,"Chelsea in Burlington, Wisconsin bought Take Out The Boat Jumpsuit, Blackabout 13 minutes ago",Periodic popup,Social Proof,Activity Notification,Product Page,No,https://chicsoul.com/collections/new-arrivals/products/beauty-in-simplicity-top-navy?variant=20864560922713 11 | 10,"Crystal Li in Flushing, United States purchased a",Periodic popup,Social Proof,Activity Notification,Product Page,No,https://cokodive.com/collections/kpop/products/young-wild-mang-sweater 12 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/.gitignore: -------------------------------------------------------------------------------- 1 | # from https://github.com/github/gitignore/blob/master/Python.gitignore 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # pytype static type analyzer 136 | .pytype/ 137 | 138 | # Cython debug symbols 139 | cython_debug/ 140 | 141 | # data/ 142 | 143 | outputs 144 | 145 | multirun/ 146 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/.gitignore: -------------------------------------------------------------------------------- 1 | # from https://github.com/github/gitignore/blob/master/Python.gitignore 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # pytype static type analyzer 136 | .pytype/ 137 | 138 | # Cython debug symbols 139 | cython_debug/ 140 | 141 | corpus/ 142 | 143 | # hydra output 144 | outputs/ 145 | multirun/ 146 | 147 | wandb/ 148 | 149 | scripts/set_environment.sh 150 | 151 | pickles/**/*.pth 152 | 153 | .envrc -------------------------------------------------------------------------------- /scraping/src/scrape-page.ts: -------------------------------------------------------------------------------- 1 | import puppeteer from 'puppeteer'; 2 | import { Scraper } from './scraping-tools/Scraper'; 3 | import { PageSegment } from './scraping-tools/segment/PageSegment'; 4 | import { DARKPATTERN_CSV_PATH, CRAWLED_DATA_DIR } from './const/path'; 5 | 6 | import path from 'node:path'; 7 | import { formatDate } from './utils/date'; 8 | import { readCsv } from './utils/csv'; 9 | import { sliceIntoChunks } from './utils/array'; 10 | import { createDirIfNotExist } from './utils/directory'; 11 | import fs from 'node:fs'; 12 | 13 | const scrapeAndSegmentPage = async ( 14 | url: string, 15 | pageId: string, 16 | dirToSave: string 17 | ): Promise => { 18 | // Initialzie Scraper. 19 | const browser = await puppeteer.launch(); 20 | const page = await browser.newPage(); 21 | const scraper = new Scraper(new PageSegment(page)); 22 | 23 | console.log(`start scraping ${url}`); 24 | 25 | // Execute Scraping & Segmentation. 26 | let texts: string[] = []; 27 | try { 28 | texts = await scraper.scrapingAndSegmentPage(page, url, dirToSave, 5); 29 | } catch (e) { 30 | console.log('scraping failed: ', url); 31 | console.log('Error: ', e); 32 | } 33 | // Filtering Crawled Texts. 34 | const continuousSpaceOverTwoCharactorRule = /\s{2,}/g; 35 | const textsReplaced = texts 36 | .map((text) => text.replace(continuousSpaceOverTwoCharactorRule, ' ')) // Replace Continuous Spaces to a Space. Eg. " " → " " 37 | .map((text) => text.replace('\n', '')); // Replace New Line("\n") to a Space. Eg. "\n" → " " 38 | 39 | // Close(Destroy) Browser. 40 | await browser.close(); 41 | 42 | // Convert Crawled Texts to TSV Format. 43 | const tsvHeader = ['page_id', 'text', 'url'].join('\t'); 44 | const tsvBody = textsReplaced 45 | .map((text) => `${pageId}\t${text}\t${url}`) 46 | .join('\n'); 47 | const tsvData = `${tsvHeader}\n${tsvBody}`; 48 | 49 | // Save TSV. 50 | const pathToTsv = path.join(dirToSave, 'page-text.tsv'); 51 | fs.writeFileSync(pathToTsv, tsvData); 52 | 53 | console.log(`${pageId} ${url} is scraped`); 54 | 55 | return textsReplaced; 56 | }; 57 | 58 | const scrapeMathursPages = async (pathToCsv: string) => { 59 | const records = readCsv(pathToCsv); 60 | const recordBody = records.slice(1); 61 | const urls = recordBody.map((record) => { 62 | const URL_COLUMN_IDX = 7; 63 | return record[URL_COLUMN_IDX]; 64 | }); 65 | 66 | const todayStr = formatDate(new Date()); 67 | const dirToSave = path.join(CRAWLED_DATA_DIR, todayStr); 68 | 69 | createDirIfNotExist(dirToSave); 70 | 71 | const chunkSize = 5; // = number of threads. 72 | const urlChunks = sliceIntoChunks(urls, chunkSize); 73 | 74 | for (let chunkIdx = 0; chunkIdx < urlChunks.length; chunkIdx++) { 75 | const urlChunk = urlChunks[chunkIdx]; 76 | const promises = urlChunk.map((url, idx) => { 77 | const pageId = String(chunkIdx * chunkSize + idx + 1); 78 | const dirToSavePerPage = path.join(dirToSave, pageId); 79 | createDirIfNotExist(dirToSavePerPage); 80 | return scrapeAndSegmentPage(url, pageId, dirToSavePerPage); 81 | }); 82 | await Promise.all(promises); 83 | } 84 | console.log('scraping is finished 😆'); 85 | }; 86 | 87 | const main = () => { 88 | scrapeMathursPages(DARKPATTERN_CSV_PATH); 89 | }; 90 | 91 | main(); 92 | -------------------------------------------------------------------------------- /scraping/src/scraping-tools/segment/PageSegment.test.ts: -------------------------------------------------------------------------------- 1 | import { PageSegment } from './PageSegment'; 2 | import Puppeteer from 'puppeteer'; 3 | 4 | let browser: Puppeteer.Browser; 5 | let page: Puppeteer.Page; 6 | 7 | describe('', () => { 8 | beforeEach(async () => { 9 | browser = await Puppeteer.launch(); 10 | page = await browser.newPage(); 11 | }); 12 | 13 | afterEach(async () => { 14 | await browser.close(); 15 | }); 16 | it('segmentPage("

hoge

") should return ["hoge"]', async (): Promise => { 17 | const html = '

hoge

'; 18 | await page.setContent(html); 19 | const aruneshPageSegment = new PageSegment(page); 20 | const texts = await aruneshPageSegment.segmentPage(); 21 | expect(texts).toEqual(['hoge']); 22 | }); 23 | it('segmentPage("

hoge

fuga

") should return ["hoge","fuga"]', async (): Promise => { 24 | const html = '

hoge

fuga

'; 25 | await page.setContent(html); 26 | const aruneshPageSegment = new PageSegment(page); 27 | const texts = await aruneshPageSegment.segmentPage(); 28 | expect(texts).toEqual(['hoge', 'fuga']); 29 | }); 30 | it('segmentPage("

hoge

fuga

") should return ["hoge","fuga"]', async (): Promise => { 31 | const html = 32 | '

hoge

fuga

'; 33 | await page.setContent(html); 34 | const aruneshPageSegment = new PageSegment(page); 35 | const texts = await aruneshPageSegment.segmentPage(); 36 | expect(texts).toEqual(['hoge', 'fuga']); 37 | }); 38 | it('segmentPage("

hogefuga

") should return ["hogefuga"]', async (): Promise => { 39 | const html = '

hogefuga

'; 40 | await page.setContent(html); 41 | const aruneshPageSegment = new PageSegment(page); 42 | const texts = await aruneshPageSegment.segmentPage(); 43 | expect(texts).toEqual(['hogefuga']); 44 | }); 45 | it('segmentPage("

hoge

fuga
") should return ["hoge","fuga"]', async (): Promise => { 46 | const html = 47 | '

hoge

fuga
'; 48 | await page.setContent(html); 49 | const aruneshPageSegment = new PageSegment(page); 50 | const texts = await aruneshPageSegment.segmentPage(); 51 | expect(texts).toEqual(['hoge', 'fuga']); 52 | }); 53 | it('segmentPage("") should return []', async (): Promise => { 54 | const html = 55 | ''; 56 | await page.setContent(html); 57 | const aruneshPageSegment = new PageSegment(page); 58 | const texts = await aruneshPageSegment.segmentPage(); 59 | expect(texts).toEqual([]); 60 | }); 61 | it('segmentPage("

hoge

") should return ["hoge"]', async (): Promise => { 62 | const html = 63 | '

hoge

'; 64 | await page.setContent(html); 65 | const aruneshPageSegment = new PageSegment(page); 66 | const texts = await aruneshPageSegment.segmentPage(); 67 | expect(texts).toEqual(['hoge']); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/trainer/trainer.py: -------------------------------------------------------------------------------- 1 | from typing import Any, List, Tuple 2 | 3 | import torch 4 | from torch import nn, optim 5 | from torch.utils.data import DataLoader 6 | 7 | 8 | class Trainer: 9 | def __init__( 10 | self, 11 | net: nn.Module, 12 | optimizer: optim.Optimizer, 13 | critetion: nn.Module, 14 | lr_scheduler: Any, 15 | device: torch.device, 16 | ) -> None: 17 | self.optimizer = optimizer 18 | self.critetion = critetion 19 | self.lr_scheduler = lr_scheduler 20 | self.device = device 21 | self.net = net.to(self.device) 22 | 23 | def loss_fn(self, output: torch.Tensor, target: torch.Tensor) -> torch.Tensor: 24 | return self.critetion(output, target) 25 | 26 | def train_step( 27 | self, input_train: torch.Tensor, target: torch.Tensor # TODO:inputを文字列に変更 28 | ) -> Tuple[torch.Tensor, torch.Tensor]: # [loss, output] 29 | self.net.train() 30 | output = self.net(input_train).logits # [batch_size,label_size] 31 | loss = self.loss_fn(output, target) 32 | 33 | self.optimizer.zero_grad() 34 | loss.backward() 35 | self.optimizer.step() 36 | 37 | return loss, output 38 | 39 | def val_step( 40 | self, input_val: torch.Tensor, target: torch.Tensor # TODO:inputを文字列に変更 41 | ) -> Tuple[torch.Tensor, torch.Tensor]: # [loss, output] 42 | self.net.eval() 43 | loss, output = None, None 44 | with torch.no_grad(): 45 | output = self.net(input_val).logits # [batch_size,label_size] 46 | loss = self.loss_fn(output, target) 47 | return loss, output 48 | 49 | def train(self, train_loader: DataLoader) -> List[float]: 50 | train_losses: List[float] = [] 51 | for i, (input_train, target) in enumerate(train_loader): 52 | input_train = input_train.to(self.device) 53 | target = target.to(self.device) 54 | 55 | loss, output = self.train_step(input_train, target) 56 | 57 | del input_train 58 | del target 59 | torch.cuda.empty_cache() 60 | 61 | print(f"Train step: {i + 1}/{len(train_loader)} loss: {loss.item()}") 62 | 63 | train_losses.append(loss.item()) 64 | 65 | self.lr_scheduler.step() 66 | return train_losses 67 | 68 | def validate(self, val_loader: DataLoader) -> List[float]: 69 | val_losses: List[float] = [] 70 | 71 | for i, (input_val, target) in enumerate(val_loader): 72 | input_val = input_val.to(self.device) 73 | target = target.to(self.device) 74 | 75 | with torch.no_grad(): 76 | loss, output = self.val_step(input_val, target) 77 | 78 | del input_val 79 | del target 80 | torch.cuda.empty_cache() 81 | 82 | print(f"Val step: {i + 1}/{len(val_loader)} loss: {loss.item()}") 83 | 84 | val_losses.append(loss.item()) 85 | 86 | return val_losses 87 | 88 | def test( 89 | self, test_loader: DataLoader 90 | ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]: 91 | 92 | test_preds: torch.Tensor = torch.Tensor([]) 93 | test_tgts: torch.Tensor = torch.Tensor([]) 94 | outputs: torch.Tensor = torch.Tensor([]) 95 | 96 | for i, (input_test, target) in enumerate(test_loader): 97 | input_test = input_test.to(self.device) 98 | target = target.to(self.device) 99 | _, output = self.val_step(input_test, target) 100 | 101 | output = output.to("cpu") 102 | target = target.to("cpu") 103 | 104 | pred = output.argmax(dim=-1) 105 | 106 | outputs = torch.cat((outputs, output), dim=0) 107 | test_preds = torch.cat((test_preds, pred), dim=0) 108 | test_tgts = torch.cat((test_tgts, target), dim=0) 109 | 110 | return outputs, test_tgts, test_preds 111 | 112 | def save(self, path: str) -> None: 113 | torch.save(self.net.state_dict(), path) 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Dark patterns in e-commerce:
a dataset and its baseline evaluations 4 | 5 | [Yuki Yada](https://www.yyada.jp/), Jiaying Feng, Tsuneo Matsumoto, Nao Fukushima, Fuyuko Kido, Hayato Yamana 6 | 7 |
8 | 9 | This repository provides the text-based dataset and experimental code for the paper: [Dark patterns in e-commerce: a dataset and its baseline evaluations](https://arxiv.org/abs/2211.06543) 10 | 11 | 12 | 13 | ## Overview 14 | 15 | Dark patterns are user interface designs on online services that are designed to make users behave in ways they do not intend. 16 | 17 | In this work, we construct a text-based dataset for dark pattern automatic detection on e-commerce sites and its detection using machine learning as a baseline. 18 | 19 | For baseline detection, we applied following two methods: 20 | 21 | - Classical NLP Methods ( Bag-of-Words + Classical Machine Learning Model ) 22 | - Transformer-based pre-trained language models ( e.g. BERT ) 23 | 24 | For more information, please check our [Paper](https://arxiv.org/abs/2211.06543). 25 | 26 | ## Project Structure 27 | 28 | - `dataset/`: [dataset.tsv](https://github.com/yamanalab/ec-darkpattern/blob/master/dataset/dataset.tsv) in this directory is the dataset for text-based dark patterns automatic detection. 29 | - `darkpattern-auto-detection-classical/`: Experimental code of baseline evaluation using classical NLP methods. 30 | - `darkpattern-auto-detection-deeplearning/`: Experimental code of baseline evaluation using transformer-based pre-trained language models. 31 | - `scraping/`: Code for collecting non-dark pattern texts in the dataset. 32 | 33 | ## Dataset 34 | 35 | [dataset/dataset.tsv](https://github.com/yamanalab/ec-darkpattern/blob/master/dataset/dataset.tsv) is a text-based dataset for dark pattern automatic detection (TSV Format). Dark pattern texts were obtained from Mathur et al.’s study in 2019, which consists of 1,818 dark pattern texts from shopping sites. Then, we collect non-dark pattern texts on e-commerce sites by accessing and segmenting the sites targeted by the Mathur et al.'s study. 36 | 37 | Scraping code for non-dark pattern texts is on [scraping/](https://github.com/yamanalab/ec-darkpattern/tree/master/scraping). That is implemented using Typscript (Javascript) and Puppeteer. 38 | 39 | ## Baseline Evaluation 40 | 41 | We conduct experiment of dark pattern auto detection using the dataset. The code is on [darkpattern-auto-detection-classical/](https://github.com/yamanalab/ec-darkpattern/tree/master/darkpattern-auto-detection-classical) (Classical NLP Methods) and [darkpattern-auto-detection-deeplearning/](https://github.com/yamanalab/ec-darkpattern/tree/master/darkpattern-auto-detection-deeplearning) (Transformer-based pre-trained language models). 42 | 43 | #### Experimental Result of Classical NLP Methods 44 | 45 | | Model | Accuracy | AUC | F1 score | Precision | Recall | 46 | | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | 47 | | Logistic Regression | 0.961 | 0.989 | 0.960 | 0.981 | 0.940 | 48 | | SVM | 0.954 | 0.987 | 0.952 | 0.986 | 0.922 | 49 | | Random Forest | 0.958 | 0.989 | 0.957 | 0.984 | 0.932 | 50 | | Gradient Boosting | 0.962 | 0.989 | 0.961 | 0.976 | 0.947 | 51 | 52 | #### Experimental Result of Transformer-based pre-trained language models 53 | 54 | | Model | Accuracy | AUC | F1 score | Precision | Recall | 55 | | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: | 56 | | $\text{BERT}_{base}$ | 0.972 | 0.993 | 0.971 | 0.982 | 0.961 | 57 | | $\text{BERT}_{large}$ | 0.965 | 0.993 | 0.965 | 0.973 | 0.957 | 58 | | $\text{RoBERTa}_{base}$ | 0.966 | 0.993 | 0.966 | 0.979 | 0.954 | 59 | | $\text{RoBERTa}_{large}$ | $\mathbf{0.975}$ | $\mathbf{0.995}$ | $\mathbf{0.975}$ | $\mathbf{0.984}$ | $\mathbf{0.967}$ | 60 | | $\text{ALBERT}_{base}$ | 0.959 | 0.991 | 0.959 | 0.972 | 0.946 | 61 | | $\text{ALBERT}_{large}$ | 0.965 | 0.986 | 0.965 | 0.973 | 0.957 | 62 | | $\text{XLNet}_{base}$ | 0.966 | 0.992 | 0.966 | 0.975 | 0.958 | 63 | | $\text{XLNet}_{large}$ | 0.942 | 0.988 | 0.940 | 0.968 | 0.914 | \hline 64 | 65 | 66 | ## Acknowledgements 67 | 68 | This project is based on the Mathur et al.’s study and its [dataset](https://github.com/aruneshmathur/dark-patterns/blob/master/data/final-dark-patterns/dark-patterns.csv). We thank their authors for making the source code publically available. 69 | 70 | ## Changes from Mathur et al.’s Dataset 71 | 72 | - We extract text data from "Pattern String" column in [dark-patterns.csv](https://github.com/aruneshmathur/dark-patterns/blob/master/data/final-dark-patterns/dark-patterns.csv). 73 | - We ignored missing and duplicate text data. 74 | -------------------------------------------------------------------------------- /scraping/src/scraping-tools/segment/PageSegment.ts: -------------------------------------------------------------------------------- 1 | import Puppeteer from 'puppeteer'; 2 | import { PageSegmentBase } from './PageSegmentBase'; 3 | import { BLOCK_ELEMENTS, INLINE_ELEMENT } from '../../const/html/element-type'; 4 | import { NODE_TYPES } from '../../const/html/node-type'; 5 | 6 | export class PageSegment implements PageSegmentBase { 7 | private page: Puppeteer.Page; 8 | private IGNORE_ELEMENTS = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'BR', 'HR']; 9 | 10 | constructor(page: Puppeteer.Page) { 11 | this.page = page; 12 | } 13 | 14 | public async segmentPage(): Promise { 15 | return this.segmentElement(await this.page.$('body')); 16 | } 17 | 18 | private async segmentElement( 19 | element: Puppeteer.ElementHandle | null 20 | ): Promise { 21 | if (!element) { 22 | return []; 23 | } 24 | if (!(await this.hasChildNodesIgnoreElement(element))) { 25 | if (await this.isAllChildNodesTextNodeOrInlineElement(element)) { 26 | const text = await this.getTextContent(element); 27 | if (text) { 28 | return [text]; 29 | } 30 | } 31 | } 32 | 33 | const childNodes = await this.getChildNodes(element); 34 | let texts: string[] = []; 35 | for (const child of childNodes) { 36 | const nodeType = await this.getNodeType(child); 37 | if (nodeType == NODE_TYPES.TEXT_NODE) { 38 | const textContent = await this.getTextContent(child); 39 | if (textContent) { 40 | texts.push(textContent); 41 | } 42 | } 43 | 44 | const tagName = await this.getTagName(child); 45 | if (!tagName || this.IGNORE_ELEMENTS.includes(tagName.toUpperCase())) { 46 | continue; 47 | } 48 | if (tagName.toUpperCase() in BLOCK_ELEMENTS) { 49 | texts = texts.concat(await this.segmentElement(child)); 50 | } 51 | if (tagName.toUpperCase() in INLINE_ELEMENT) { 52 | const textContent = await this.getTextContent(child); 53 | if (textContent) { 54 | texts.push(textContent); 55 | } 56 | } 57 | } 58 | return texts; 59 | } 60 | private async hasChildNodesIgnoreElement( 61 | element: Puppeteer.ElementHandle 62 | ): Promise { 63 | const childNodes = await this.getChildNodes(element); 64 | for (const child of childNodes) { 65 | const tagName = await this.getTagName(child); 66 | if (tagName == null) { 67 | continue; 68 | } 69 | if (this.IGNORE_ELEMENTS.includes(tagName.toUpperCase())) { 70 | return true; 71 | } 72 | } 73 | return false; 74 | } 75 | 76 | private async isAllChildNodesTextNodeOrInlineElement( 77 | element: Puppeteer.ElementHandle 78 | ): Promise { 79 | const childNodes = await this.getChildNodes(element); 80 | for (const child of childNodes) { 81 | const tagName = await this.getTagName(child); 82 | const nodeType = await this.getNodeType(child); 83 | if (tagName == null) { 84 | if (nodeType !== NODE_TYPES.TEXT_NODE) { 85 | return false; 86 | } 87 | } else if ( 88 | !(nodeType == NODE_TYPES.TEXT_NODE || tagName in INLINE_ELEMENT) 89 | ) { 90 | return false; 91 | } 92 | } 93 | return true; 94 | } 95 | /** 96 | * return child nodes of element 97 | */ 98 | private async getChildNodes( 99 | element: Puppeteer.ElementHandle 100 | ): Promise<(Puppeteer.ElementHandle | null)[]> { 101 | const listHandle = await this.page.evaluateHandle((e) => { 102 | return e.childNodes; 103 | }, element); 104 | const properties = await listHandle.getProperties(); 105 | const childNodes: (Puppeteer.ElementHandle | null)[] = []; 106 | for (const property of properties.values()) { 107 | const element = property.asElement(); 108 | childNodes.push(element); 109 | } 110 | return childNodes; 111 | } 112 | 113 | private async getTextContent( 114 | element: Puppeteer.ElementHandle | null 115 | ): Promise { 116 | const text = await (await element?.getProperty('textContent'))?.jsonValue(); 117 | return text as string | undefined; 118 | } 119 | private async getTagName( 120 | element: Puppeteer.ElementHandle | null 121 | ): Promise { 122 | return await (await element?.getProperty('tagName'))?.jsonValue(); 123 | } 124 | private async getNodeType( 125 | element: Puppeteer.ElementHandle | null 126 | ): Promise { 127 | return await (await element?.getProperty('nodeType'))?.jsonValue(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /scraping/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "./dist", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 43 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an 'override' modifier. */ 44 | // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ 45 | 46 | /* Module Resolution Options */ 47 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 48 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 49 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 50 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 51 | // "typeRoots": [], /* List of folders to include type definitions from. */ 52 | // "types": [], /* Type declaration files to be included in compilation. */ 53 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 54 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 55 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 56 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 57 | 58 | /* Source Map Options */ 59 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 60 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 61 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 62 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 63 | 64 | /* Experimental Options */ 65 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 66 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 67 | 68 | /* Advanced Options */ 69 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 70 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-deeplearning/experiments/train.py: -------------------------------------------------------------------------------- 1 | from os.path import join 2 | from typing import List 3 | 4 | import hydra 5 | import numpy as np 6 | import pandas as pd 7 | import torch 8 | from const.path import CONFIG_PATH, DATASET_TSV_PATH, NN_MODEL_PICKLES_PATH 9 | from omegaconf import DictConfig 10 | from sklearn import metrics 11 | from sklearn.model_selection import StratifiedKFold 12 | from torch import nn 13 | from torch.nn import functional as F 14 | from torch.optim import AdamW 15 | from torch.optim.lr_scheduler import LinearLR 16 | from torch.utils.data import DataLoader, Subset 17 | from trainer.trainer import Trainer 18 | from transformers import AutoModelForSequenceClassification, AutoTokenizer 19 | from utils.dataset import DarkpatternDataset 20 | from utils.random_seed import set_random_seed 21 | from utils.text import text_to_tensor as _text_to_tensor 22 | 23 | 24 | def cross_validation( 25 | n_fold: int, 26 | pretrained: str, 27 | batch_size: int, 28 | lr: float, 29 | start_factor: float, 30 | max_length: int, 31 | dropout: float, 32 | epochs: int, 33 | save_model: bool, 34 | device: torch.device = torch.device("cuda" if torch.cuda.is_available() else "cpu"), 35 | num_labels: int = 2, 36 | ) -> None: 37 | """ 38 | Load & Define dataset. 39 | """ 40 | df = pd.read_csv(DATASET_TSV_PATH, sep="\t", encoding="utf-8") 41 | texts = df.text.tolist() 42 | labels = df.label.tolist() 43 | 44 | tokenizer = AutoTokenizer.from_pretrained(pretrained) 45 | 46 | def text_to_tensor(text: str) -> torch.Tensor: 47 | return _text_to_tensor(text, tokenizer, max_length) 48 | 49 | ds = DarkpatternDataset(texts, labels, text_to_tensor) 50 | 51 | """ 52 | Execute N (= n_fold) fold cross validation. 53 | """ 54 | skf = StratifiedKFold(n_splits=n_fold) 55 | 56 | accuracy_scores: List[float] = [] 57 | f1_scores: List[float] = [] 58 | precision_scores: List[float] = [] 59 | recall_scores: List[float] = [] 60 | roc_auc_scores: List[float] = [] 61 | 62 | for fold, (train_idx, test_idx) in enumerate(skf.split(texts, labels)): 63 | 64 | """ 65 | Define train & test dataset. 66 | """ 67 | 68 | train_ds = Subset(ds, train_idx) 69 | test_ds = Subset(ds, test_idx) 70 | train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True) 71 | test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=True) 72 | 73 | """ 74 | Initialize model, optimizer, loss function, lr_scheduler. 75 | """ 76 | net = AutoModelForSequenceClassification.from_pretrained( 77 | pretrained, num_labels=num_labels 78 | ).to(device) 79 | critation = nn.CrossEntropyLoss() 80 | optimizer = AdamW(net.parameters(), lr=lr) 81 | lr_scheduler = LinearLR( 82 | optimizer, start_factor=start_factor, total_iters=epochs 83 | ) 84 | 85 | """ 86 | Train. 87 | """ 88 | trainer = Trainer(net, optimizer, critation, lr_scheduler, device) 89 | for epoch in range(epochs): 90 | try: 91 | trainer.train(train_loader) 92 | except Exception as e: 93 | print(e) 94 | 95 | """ 96 | Evaluation. 97 | """ 98 | outputs, tgt, pred = trainer.test(test_loader) 99 | accuracy_score = metrics.accuracy_score(tgt.numpy(), pred.numpy()) 100 | f1_score = metrics.f1_score(tgt.numpy(), pred.numpy()) 101 | precision_score = metrics.precision_score(tgt.numpy(), pred.numpy()) 102 | recall_score = metrics.recall_score(tgt.numpy(), pred.numpy()) 103 | 104 | prob = F.softmax(outputs, dim=1)[:, 1] # outputs: [batch_size, num_labels] 105 | roc_auc = metrics.roc_auc_score(tgt.numpy(), prob.numpy()) 106 | 107 | accuracy_scores.append(accuracy_score) 108 | f1_scores.append(f1_score) 109 | precision_scores.append(precision_score) 110 | recall_scores.append(recall_score) 111 | roc_auc_scores.append(roc_auc) 112 | 113 | """ 114 | Save model. 115 | """ 116 | if save_model: 117 | model_path = join(NN_MODEL_PICKLES_PATH, f"{pretrained}_{fold}.pth") 118 | torch.save(net.state_dict(), model_path) 119 | 120 | """ 121 | Display evaluation result on console. 122 | """ 123 | roc_auc_score_average = np.mean(roc_auc_scores) 124 | f1_score_average = np.mean(f1_scores) 125 | accuracy_score_average = np.mean(accuracy_scores) 126 | precision_score_average = np.mean(precision_scores) 127 | recall_score_average = np.mean(recall_scores) 128 | roc_auc_score_average = np.mean(roc_auc_scores) 129 | print( 130 | { 131 | "accuracy_scores": accuracy_scores, 132 | "f1_scores": f1_scores, 133 | "precision_scores": precision_scores, 134 | "recall_scores": recall_scores, 135 | "roc_auc_scores": roc_auc_scores, 136 | "f1_score_average": f1_score_average, 137 | "accuracy_score_average": accuracy_score_average, 138 | "precision_score_average": precision_score_average, 139 | "recall_score_average": recall_score_average, 140 | "roc_auc_score_average": roc_auc_score_average, 141 | } 142 | ) 143 | 144 | parameters_and_evaluation_text = f""" 145 | ```parameters: 146 | pretrained: {pretrained} 147 | batch_size: {batch_size} 148 | lr: {lr} 149 | max_length: {max_length} 150 | dropout: {dropout} 151 | epochs: {epochs} 152 | device: {device} 153 | num_labels: {num_labels} 154 | metrics for test: 155 | f1_score_average:{f1_score_average} 156 | accuracy_score_average:{accuracy_score_average} 157 | precision_score_average:{precision_score_average} 158 | recall_score_average:{recall_score_average} 159 | roc_auc_score_average:{roc_auc_score_average} 160 | ``` 161 | """ 162 | print(parameters_and_evaluation_text) 163 | 164 | 165 | @hydra.main(config_path=CONFIG_PATH, config_name="config.yaml") 166 | def main(cfg: DictConfig) -> None: 167 | 168 | n_fold = cfg.train.n_fold 169 | pretrained = cfg.model.pretrained 170 | batch_size = cfg.train.batch_size 171 | lr = cfg.train.lr 172 | max_length = cfg.preprocess.max_length 173 | dropout = cfg.model.dropout 174 | epochs = cfg.train.epochs 175 | start_factor = cfg.train.start_factor 176 | save_model = cfg.train.save_model 177 | 178 | set_random_seed(cfg.random.seed) 179 | 180 | cross_validation( 181 | n_fold=n_fold, 182 | pretrained=pretrained, 183 | batch_size=batch_size, 184 | lr=lr, 185 | max_length=max_length, 186 | dropout=dropout, 187 | epochs=epochs, 188 | start_factor=start_factor, 189 | save_model=save_model, 190 | ) 191 | 192 | 193 | if __name__ == "__main__": 194 | main() 195 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/experiments/train.py: -------------------------------------------------------------------------------- 1 | from typing import Sequence, Union 2 | 3 | import hydra 4 | import lightgbm as lgb 5 | import numpy as np 6 | import optuna 7 | from omegaconf import DictConfig 8 | from optuna.trial import FrozenTrial, Trial 9 | from sklearn.base import BaseEstimator 10 | from sklearn.ensemble import RandomForestClassifier 11 | from sklearn.feature_extraction.text import CountVectorizer 12 | from sklearn.linear_model import LogisticRegression 13 | from sklearn.metrics import (accuracy_score, f1_score, precision_score, 14 | recall_score, roc_auc_score) 15 | from sklearn.model_selection import StratifiedKFold, cross_validate 16 | from sklearn.svm import SVC 17 | 18 | from const.model import (LIGHTGBM_MODEL, LOGISTIC_REGRESSION_MODEL, 19 | RANDOM_FOREST_MODEL, SVC_MODEL) 20 | from const.path import CONFIG_PATH, DATASET_TSV_PATH 21 | from utils import dataset 22 | from utils.random_seed import set_random_seed 23 | 24 | 25 | def get_sklearn_model( 26 | trial: Union[Trial, FrozenTrial], 27 | model_name: str = RANDOM_FOREST_MODEL, 28 | random_state: int = 42, 29 | ) -> BaseEstimator: 30 | 31 | if model_name == RANDOM_FOREST_MODEL: 32 | params = { 33 | "max_depth": trial.suggest_int("max_depth", 2, 32), 34 | "n_estimators": trial.suggest_int("n_estimators", 10, 1000), 35 | "min_samples_split": trial.suggest_int("min_samples_split", 2, 32), 36 | "min_samples_leaf": trial.suggest_int("min_samples_leaf", 1, 32), 37 | "bootstrap": trial.suggest_categorical("bootstrap", [True, False]), 38 | "random_state": random_state, 39 | } 40 | return RandomForestClassifier(**params) 41 | 42 | elif model_name == SVC_MODEL: 43 | params = { 44 | "C": trial.suggest_loguniform("C", 1e-8, 10.0), 45 | } 46 | return SVC(**params) 47 | 48 | elif model_name == LOGISTIC_REGRESSION_MODEL: 49 | params = { 50 | "C": trial.suggest_loguniform("C", 1e-8, 10.0), 51 | } 52 | return LogisticRegression(**params) 53 | 54 | else: 55 | raise ValueError("Unknown model name: {}".format(model_name)) 56 | 57 | 58 | def run_lightgbm( 59 | study: optuna.Study, n_trial: int = 100, random_state: int = 42 60 | ) -> None: 61 | 62 | texts, labels = dataset.get_dataset(DATASET_TSV_PATH) 63 | count_vectorizer = CountVectorizer(ngram_range=(1, 1), dtype=np.float32) 64 | X, y = ( 65 | count_vectorizer.fit_transform(texts), 66 | np.array(labels), 67 | ) 68 | 69 | def objective(trial: Trial) -> Union[float, Sequence[float]]: 70 | 71 | skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=random_state) 72 | f1_scores = list() 73 | 74 | params = { 75 | "objective": "binary", 76 | "metric": "binary_logloss", 77 | "lambda_l1": trial.suggest_loguniform("lambda_l1", 1e-8, 10.0), 78 | "lambda_l2": trial.suggest_loguniform("lambda_l2", 1e-8, 10.0), 79 | "num_leaves": trial.suggest_int("num_leaves", 2, 256), 80 | "feature_fraction": trial.suggest_uniform("feature_fraction", 0.4, 1.0), 81 | "bagging_fraction": trial.suggest_uniform("bagging_fraction", 0.4, 1.0), 82 | "bagging_freq": trial.suggest_int("bagging_freq", 1, 7), 83 | "min_child_samples": trial.suggest_int("min_child_samples", 5, 100), 84 | "random_state": random_state, 85 | } 86 | 87 | for train_index, test_index in skf.split(X, y): 88 | X_train, X_test = X[train_index], X[test_index] 89 | y_train, y_test = y[train_index], y[test_index] 90 | 91 | lgbm_train_dataset = lgb.Dataset(X_train, label=y_train) 92 | 93 | gbm = lgb.train(params, lgbm_train_dataset) 94 | 95 | y_preds = np.rint(gbm.predict(X_test)) 96 | 97 | f1_scores.append( 98 | f1_score(y_test, y_preds), 99 | ) 100 | 101 | return np.mean(f1_scores) 102 | 103 | def detailed_objective(trial: FrozenTrial) -> None: 104 | 105 | skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=random_state) 106 | 107 | accuracy_scores = list() 108 | f1_scores = list() 109 | precision_scores = list() 110 | recall_scores = list() 111 | roc_auc_scores = list() 112 | 113 | params = { 114 | "objective": "binary", 115 | "metric": "binary_logloss", 116 | "lambda_l1": trial.suggest_loguniform("lambda_l1", 1e-8, 10.0), 117 | "lambda_l2": trial.suggest_loguniform("lambda_l2", 1e-8, 10.0), 118 | "num_leaves": trial.suggest_int("num_leaves", 2, 256), 119 | "feature_fraction": trial.suggest_uniform("feature_fraction", 0.4, 1.0), 120 | "bagging_fraction": trial.suggest_uniform("bagging_fraction", 0.4, 1.0), 121 | "bagging_freq": trial.suggest_int("bagging_freq", 1, 7), 122 | "min_child_samples": trial.suggest_int("min_child_samples", 5, 100), 123 | "random_state": random_state, 124 | } 125 | 126 | for train_index, test_index in skf.split(X, y): 127 | X_train, X_test = X[train_index], X[test_index] 128 | y_train, y_test = y[train_index], y[test_index] 129 | 130 | lgbm_train_dataset = lgb.Dataset(X_train, label=y_train) 131 | 132 | gbm = lgb.train(params, lgbm_train_dataset) 133 | 134 | output = gbm.predict(X_test) 135 | y_preds = np.rint(output) 136 | y_probs = np.array(output) 137 | 138 | (accuracy, f1, precision, recall, roc_auc) = ( 139 | accuracy_score(y_test, y_preds), 140 | f1_score(y_test, y_preds), 141 | precision_score(y_test, y_preds), 142 | recall_score(y_test, y_preds), 143 | roc_auc_score(y_test, y_probs), 144 | ) 145 | 146 | accuracy_scores.append(accuracy) 147 | f1_scores.append(f1) 148 | precision_scores.append(precision) 149 | recall_scores.append(recall) 150 | roc_auc_scores.append(roc_auc) 151 | 152 | print( 153 | { 154 | "accuracy_scores": accuracy_scores, 155 | "f1_scores": f1_scores, 156 | "precision_scores": precision_scores, 157 | "recall_scores": recall_scores, 158 | "accuracy_score_average": np.mean(accuracy_scores), 159 | "f1_score_average": np.mean(f1_scores), 160 | "precision_score_average": np.mean(precision_scores), 161 | "recall_score_average": np.mean(recall_scores), 162 | "roc_auc_score_average": np.mean(roc_auc_scores), 163 | } 164 | ) 165 | 166 | study.optimize(objective, n_trials=n_trial) 167 | 168 | detailed_objective(study.best_trial) 169 | 170 | 171 | def run_sklearn( 172 | study: optuna.Study, model_name: str, n_trial: int = 100, random_state: int = 42 173 | ) -> None: 174 | def objective(trial: Trial) -> Union[float, Sequence[float]]: 175 | 176 | texts, labels = dataset.get_dataset(DATASET_TSV_PATH) 177 | 178 | count_vectorizer = CountVectorizer(ngram_range=(1, 1)) 179 | 180 | X, y = ( 181 | count_vectorizer.fit_transform(texts), 182 | np.array(labels), 183 | ) 184 | 185 | skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=random_state) 186 | 187 | clf = get_sklearn_model(trial, model_name) 188 | f1_score_names = ["f1"] 189 | scores = cross_validate(clf, X, y, cv=skf, scoring=f1_score_names) 190 | return scores["test_f1"].mean() 191 | 192 | def detailed_objective(trial: FrozenTrial) -> None: 193 | 194 | texts, labels = dataset.get_dataset(DATASET_TSV_PATH) 195 | 196 | count_vectorizer = CountVectorizer(ngram_range=(1, 1)) 197 | 198 | X, y = ( 199 | count_vectorizer.fit_transform(texts), 200 | np.array(labels), 201 | ) 202 | 203 | skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=random_state) 204 | 205 | clf = get_sklearn_model(trial, model_name) 206 | score_names = ["accuracy", "f1", "precision", "recall", "roc_auc"] 207 | scores = cross_validate(clf, X, y, cv=skf, scoring=score_names) 208 | 209 | print( 210 | { 211 | "accuracy_scores": list(scores["test_accuracy"]), 212 | "f1_scores": list(scores["test_f1"]), 213 | "precision_scores": list(scores["test_precision"]), 214 | "recall_scores": list(scores["test_recall"]), 215 | "accuracy_score_average": np.mean(scores["test_accuracy"]), 216 | "f1_score_average": np.mean(scores["test_f1"]), 217 | "precision_score_average": np.mean(scores["test_precision"]), 218 | "recall_score_average": np.mean(scores["test_recall"]), 219 | "roc_auc_score_average": np.mean(scores["test_roc_auc"]), 220 | } 221 | ) 222 | 223 | study.optimize(objective, n_trials=n_trial) 224 | 225 | detailed_objective(study.best_trial) 226 | 227 | 228 | @hydra.main(config_path=CONFIG_PATH, config_name="config.yaml") 229 | def main(cfg: DictConfig) -> None: 230 | 231 | study = optuna.create_study(direction="maximize") 232 | 233 | model_name = cfg.model.name 234 | 235 | set_random_seed(cfg.random.seed) 236 | 237 | if model_name == LIGHTGBM_MODEL: 238 | run_lightgbm(study, cfg.experiment.n_trial, cfg.random.seed) 239 | else: 240 | run_sklearn(study, model_name, cfg.experiment.n_trial, cfg.random.seed) 241 | 242 | 243 | def init() -> None: 244 | import nltk 245 | 246 | try: 247 | nltk.data.find("wordnet") 248 | except LookupError: 249 | nltk.download("wordnet") 250 | 251 | 252 | if __name__ == "__main__": 253 | init() 254 | main() 255 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /darkpattern-auto-detection-classical/poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | category = "main" 3 | description = "A database migration tool for SQLAlchemy." 4 | name = "alembic" 5 | optional = false 6 | python-versions = ">=3.7" 7 | version = "1.8.1" 8 | 9 | [package.dependencies] 10 | Mako = "*" 11 | SQLAlchemy = ">=1.3.0" 12 | 13 | [package.dependencies.importlib-metadata] 14 | python = "<3.9" 15 | version = "*" 16 | 17 | [package.dependencies.importlib-resources] 18 | python = "<3.9" 19 | version = "*" 20 | 21 | [package.extras] 22 | tz = ["python-dateutil"] 23 | 24 | [[package]] 25 | category = "main" 26 | description = "ANTLR 4.9.3 runtime for Python 3.7" 27 | name = "antlr4-python3-runtime" 28 | optional = false 29 | python-versions = "*" 30 | version = "4.9.3" 31 | 32 | [[package]] 33 | category = "main" 34 | description = "Classes Without Boilerplate" 35 | name = "attrs" 36 | optional = false 37 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 38 | version = "21.4.0" 39 | 40 | [package.extras] 41 | dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] 42 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] 43 | tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] 44 | tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] 45 | 46 | [[package]] 47 | category = "main" 48 | description = "A library to provide automatic paging for console output" 49 | name = "autopage" 50 | optional = false 51 | python-versions = ">=3.6" 52 | version = "0.5.1" 53 | 54 | [[package]] 55 | category = "dev" 56 | description = "The uncompromising code formatter." 57 | name = "black" 58 | optional = false 59 | python-versions = ">=3.6.2" 60 | version = "22.1.0" 61 | 62 | [package.dependencies] 63 | click = ">=8.0.0" 64 | mypy-extensions = ">=0.4.3" 65 | pathspec = ">=0.9.0" 66 | platformdirs = ">=2" 67 | tomli = ">=1.1.0" 68 | 69 | [package.dependencies.typing-extensions] 70 | python = "<3.10" 71 | version = ">=3.10.0.0" 72 | 73 | [package.extras] 74 | colorama = ["colorama (>=0.4.3)"] 75 | d = ["aiohttp (>=3.7.4)"] 76 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 77 | uvloop = ["uvloop (>=0.15.2)"] 78 | 79 | [[package]] 80 | category = "main" 81 | description = "Python package for providing Mozilla's CA Bundle." 82 | name = "certifi" 83 | optional = false 84 | python-versions = ">=3.6" 85 | version = "2022.6.15" 86 | 87 | [[package]] 88 | category = "main" 89 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 90 | name = "charset-normalizer" 91 | optional = false 92 | python-versions = ">=3.6.0" 93 | version = "2.1.0" 94 | 95 | [package.extras] 96 | unicode_backport = ["unicodedata2"] 97 | 98 | [[package]] 99 | category = "main" 100 | description = "Composable command line interface toolkit" 101 | name = "click" 102 | optional = false 103 | python-versions = ">=3.6" 104 | version = "8.0.3" 105 | 106 | [package.dependencies] 107 | colorama = "*" 108 | 109 | [[package]] 110 | category = "main" 111 | description = "Command Line Interface Formulation Framework" 112 | name = "cliff" 113 | optional = false 114 | python-versions = ">=3.6" 115 | version = "3.10.1" 116 | 117 | [package.dependencies] 118 | PrettyTable = ">=0.7.2" 119 | PyYAML = ">=3.12" 120 | autopage = ">=0.4.0" 121 | cmd2 = ">=1.0.0" 122 | pbr = ">=2.0.0,<2.1.0 || >2.1.0" 123 | pyparsing = ">=2.1.0" 124 | stevedore = ">=2.0.1" 125 | 126 | [[package]] 127 | category = "main" 128 | description = "Lightweight Covariance Matrix Adaptation Evolution Strategy (CMA-ES) implementation for Python 3." 129 | name = "cmaes" 130 | optional = false 131 | python-versions = ">=3.6" 132 | version = "0.8.2" 133 | 134 | [package.dependencies] 135 | numpy = "*" 136 | 137 | [[package]] 138 | category = "main" 139 | description = "cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python" 140 | name = "cmd2" 141 | optional = false 142 | python-versions = ">=3.6" 143 | version = "2.4.2" 144 | 145 | [package.dependencies] 146 | attrs = ">=16.3.0" 147 | pyperclip = ">=1.6" 148 | pyreadline3 = "*" 149 | wcwidth = ">=0.1.7" 150 | 151 | [package.extras] 152 | dev = ["codecov", "doc8", "flake8", "invoke", "mypy (0.902)", "nox", "pytest (>=4.6)", "pytest-cov", "pytest-mock", "sphinx", "sphinx-rtd-theme", "sphinx-autobuild", "twine (>=1.11)"] 153 | test = ["codecov", "coverage", "pytest (>=4.6)", "pytest-cov", "pytest-mock", "gnureadline"] 154 | validate = ["flake8", "mypy (0.902)", "types-pkg-resources"] 155 | 156 | [[package]] 157 | category = "main" 158 | description = "Cross-platform colored terminal text." 159 | marker = "sys_platform == \"win32\" or platform_system == \"Windows\"" 160 | name = "colorama" 161 | optional = false 162 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 163 | version = "0.4.4" 164 | 165 | [[package]] 166 | category = "main" 167 | description = "Add colours to the output of Python's logging module." 168 | name = "colorlog" 169 | optional = false 170 | python-versions = ">=3.6" 171 | version = "6.6.0" 172 | 173 | [package.dependencies] 174 | colorama = "*" 175 | 176 | [package.extras] 177 | development = ["black", "flake8", "mypy", "pytest", "types-colorama"] 178 | 179 | [[package]] 180 | category = "main" 181 | description = "Python bindings for the docker credentials store API" 182 | name = "docker-pycreds" 183 | optional = false 184 | python-versions = "*" 185 | version = "0.4.0" 186 | 187 | [package.dependencies] 188 | six = ">=1.4.0" 189 | 190 | [[package]] 191 | category = "dev" 192 | description = "the modular source code checker: pep8 pyflakes and co" 193 | name = "flake8" 194 | optional = false 195 | python-versions = ">=3.6" 196 | version = "4.0.1" 197 | 198 | [package.dependencies] 199 | mccabe = ">=0.6.0,<0.7.0" 200 | pycodestyle = ">=2.8.0,<2.9.0" 201 | pyflakes = ">=2.4.0,<2.5.0" 202 | 203 | [[package]] 204 | category = "main" 205 | description = "Git Object Database" 206 | name = "gitdb" 207 | optional = false 208 | python-versions = ">=3.6" 209 | version = "4.0.9" 210 | 211 | [package.dependencies] 212 | smmap = ">=3.0.1,<6" 213 | 214 | [[package]] 215 | category = "main" 216 | description = "GitPython is a python library used to interact with Git repositories" 217 | name = "gitpython" 218 | optional = false 219 | python-versions = ">=3.7" 220 | version = "3.1.27" 221 | 222 | [package.dependencies] 223 | gitdb = ">=4.0.1,<5" 224 | 225 | [[package]] 226 | category = "main" 227 | description = "Lightweight in-process concurrent programming" 228 | marker = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")" 229 | name = "greenlet" 230 | optional = false 231 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" 232 | version = "1.1.2" 233 | 234 | [package.extras] 235 | docs = ["sphinx"] 236 | 237 | [[package]] 238 | category = "main" 239 | description = "A framework for elegantly configuring complex applications" 240 | name = "hydra-core" 241 | optional = false 242 | python-versions = "*" 243 | version = "1.2.0" 244 | 245 | [package.dependencies] 246 | antlr4-python3-runtime = ">=4.9.0,<4.10.0" 247 | omegaconf = ">=2.2,<3.0" 248 | packaging = "*" 249 | 250 | [package.dependencies.importlib-resources] 251 | python = "<3.9" 252 | version = "*" 253 | 254 | [[package]] 255 | category = "main" 256 | description = "Internationalized Domain Names in Applications (IDNA)" 257 | name = "idna" 258 | optional = false 259 | python-versions = ">=3.5" 260 | version = "3.3" 261 | 262 | [[package]] 263 | category = "main" 264 | description = "Read metadata from Python packages" 265 | marker = "python_version < \"3.9\"" 266 | name = "importlib-metadata" 267 | optional = false 268 | python-versions = ">=3.7" 269 | version = "4.12.0" 270 | 271 | [package.dependencies] 272 | zipp = ">=0.5" 273 | 274 | [package.extras] 275 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] 276 | perf = ["ipython"] 277 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] 278 | 279 | [[package]] 280 | category = "main" 281 | description = "Read resources from Python packages" 282 | marker = "python_version < \"3.9\"" 283 | name = "importlib-resources" 284 | optional = false 285 | python-versions = ">=3.7" 286 | version = "5.8.0" 287 | 288 | [package.dependencies] 289 | [package.dependencies.zipp] 290 | python = "<3.10" 291 | version = ">=3.1.0" 292 | 293 | [package.extras] 294 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] 295 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] 296 | 297 | [[package]] 298 | category = "dev" 299 | description = "A Python utility / library to sort Python imports." 300 | name = "isort" 301 | optional = false 302 | python-versions = ">=3.6.1,<4.0" 303 | version = "5.10.1" 304 | 305 | [package.extras] 306 | colors = ["colorama (>=0.4.3,<0.5.0)"] 307 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"] 308 | plugins = ["setuptools"] 309 | requirements_deprecated_finder = ["pipreqs", "pip-api"] 310 | 311 | [[package]] 312 | category = "main" 313 | description = "Lightweight pipelining with Python functions" 314 | name = "joblib" 315 | optional = false 316 | python-versions = ">=3.6" 317 | version = "1.1.0" 318 | 319 | [[package]] 320 | category = "main" 321 | description = "LightGBM Python Package" 322 | name = "lightgbm" 323 | optional = false 324 | python-versions = "*" 325 | version = "3.3.2" 326 | 327 | [package.dependencies] 328 | numpy = "*" 329 | scikit-learn = "!=0.22.0" 330 | scipy = "*" 331 | wheel = "*" 332 | 333 | [package.extras] 334 | dask = ["dask (>=2.0.0)", "dask (>=2.0.0)", "dask (>=2.0.0)", "pandas"] 335 | 336 | [[package]] 337 | category = "main" 338 | description = "A super-fast templating language that borrows the best ideas from the existing templating languages." 339 | name = "mako" 340 | optional = false 341 | python-versions = ">=3.7" 342 | version = "1.2.1" 343 | 344 | [package.dependencies] 345 | MarkupSafe = ">=0.9.2" 346 | 347 | [package.extras] 348 | babel = ["babel"] 349 | lingua = ["lingua"] 350 | testing = ["pytest"] 351 | 352 | [[package]] 353 | category = "main" 354 | description = "Safely add untrusted strings to HTML/XML markup." 355 | name = "markupsafe" 356 | optional = false 357 | python-versions = ">=3.7" 358 | version = "2.1.1" 359 | 360 | [[package]] 361 | category = "dev" 362 | description = "McCabe checker, plugin for flake8" 363 | name = "mccabe" 364 | optional = false 365 | python-versions = "*" 366 | version = "0.6.1" 367 | 368 | [[package]] 369 | category = "dev" 370 | description = "Optional static typing for Python" 371 | name = "mypy" 372 | optional = false 373 | python-versions = ">=3.6" 374 | version = "0.931" 375 | 376 | [package.dependencies] 377 | mypy-extensions = ">=0.4.3" 378 | tomli = ">=1.1.0" 379 | typing-extensions = ">=3.10" 380 | 381 | [package.extras] 382 | dmypy = ["psutil (>=4.0)"] 383 | python2 = ["typed-ast (>=1.4.0,<2)"] 384 | 385 | [[package]] 386 | category = "dev" 387 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 388 | name = "mypy-extensions" 389 | optional = false 390 | python-versions = "*" 391 | version = "0.4.3" 392 | 393 | [[package]] 394 | category = "main" 395 | description = "Natural Language Toolkit" 396 | name = "nltk" 397 | optional = false 398 | python-versions = ">=3.7" 399 | version = "3.7" 400 | 401 | [package.dependencies] 402 | click = "*" 403 | joblib = "*" 404 | regex = ">=2021.8.3" 405 | tqdm = "*" 406 | 407 | [package.extras] 408 | all = ["numpy", "pyparsing", "scipy", "matplotlib", "twython", "requests", "scikit-learn", "python-crfsuite"] 409 | corenlp = ["requests"] 410 | machine_learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"] 411 | plot = ["matplotlib"] 412 | tgrep = ["pyparsing"] 413 | twitter = ["twython"] 414 | 415 | [[package]] 416 | category = "main" 417 | description = "NumPy is the fundamental package for array computing with Python." 418 | name = "numpy" 419 | optional = false 420 | python-versions = ">=3.8" 421 | version = "1.23.1" 422 | 423 | [[package]] 424 | category = "main" 425 | description = "A flexible configuration library" 426 | name = "omegaconf" 427 | optional = false 428 | python-versions = ">=3.6" 429 | version = "2.2.2" 430 | 431 | [package.dependencies] 432 | PyYAML = ">=5.1.0" 433 | antlr4-python3-runtime = ">=4.9.0,<4.10.0" 434 | 435 | [[package]] 436 | category = "main" 437 | description = "A hyperparameter optimization framework" 438 | name = "optuna" 439 | optional = false 440 | python-versions = ">=3.6" 441 | version = "2.10.1" 442 | 443 | [package.dependencies] 444 | PyYAML = "*" 445 | alembic = "*" 446 | cliff = "*" 447 | cmaes = ">=0.8.2" 448 | colorlog = "*" 449 | numpy = "*" 450 | packaging = ">=20.0" 451 | scipy = "!=1.4.0" 452 | sqlalchemy = ">=1.1.0" 453 | tqdm = "*" 454 | 455 | [package.extras] 456 | benchmark = ["asv", "virtualenv"] 457 | checking = ["black", "hacking", "isort", "mypy (0.790)", "blackdoc"] 458 | codecov = ["codecov", "pytest-cov"] 459 | doctest = ["cma", "matplotlib (>=3.0.0)", "pandas", "plotly (>=4.0.0)", "scikit-learn (>=0.24.2,<1.0.0)", "scikit-optimize", "mlflow"] 460 | document = ["Jinja2 (<3.0.0)", "MarkupSafe (<=2.0.1)", "sphinx (<=3.5.4)", "sphinx-rtd-theme (<=1.0.0)", "sphinx-copybutton (<=0.4.0)", "sphinx-gallery (<=0.10.0)", "sphinx-plotly-directive (<=0.1.3)", "pillow", "matplotlib", "scikit-learn (<1.0.0)", "plotly (>=4.0.0)", "pandas", "lightgbm", "torch (1.8.0)", "torchvision (0.9.0)", "torchaudio (0.8.0)", "thop"] 461 | experimental = ["redis"] 462 | integration = ["chainer (>=5.0.0)", "cma", "lightgbm", "mlflow", "wandb", "mpi4py", "mxnet", "pandas", "scikit-learn (>=0.24.2,<1.0.0)", "scikit-optimize", "xgboost", "tensorflow", "tensorflow-datasets", "pytorch-ignite", "pytorch-lightning (>=1.0.2)", "skorch", "catalyst (>=21.3)", "torchaudio (0.8.0)", "allennlp (>=2.2.0,<2.7.0)", "fastai", "botorch (>=0.4.0)", "torch (1.8.0+cpu)", "torchvision (0.9.0+cpu)", "torch (1.8.0)", "torchvision (0.9.0)"] 463 | optional = ["bokeh (<2.0.0)", "matplotlib (>=3.0.0)", "pandas", "plotly (>=4.0.0)", "redis", "scikit-learn (>=0.24.2,<1.0.0)"] 464 | testing = ["bokeh (<2.0.0)", "chainer (>=5.0.0)", "cma", "fakeredis", "lightgbm", "matplotlib (>=3.0.0)", "mlflow", "mpi4py", "mxnet", "pandas", "plotly (>=4.0.0)", "pytest", "scikit-learn (>=0.24.2,<1.0.0)", "scikit-optimize", "xgboost", "tensorflow", "tensorflow-datasets", "pytorch-ignite", "pytorch-lightning (>=1.0.2)", "skorch", "catalyst (>=21.3)", "torchaudio (0.8.0)", "allennlp (>=2.2.0,<2.7.0)", "fastai", "botorch (>=0.4.0)", "torch (1.8.0+cpu)", "torchvision (0.9.0+cpu)", "torch (1.8.0)", "torchvision (0.9.0)"] 465 | tests = ["fakeredis", "pytest"] 466 | 467 | [[package]] 468 | category = "main" 469 | description = "Core utilities for Python packages" 470 | name = "packaging" 471 | optional = false 472 | python-versions = ">=3.6" 473 | version = "21.3" 474 | 475 | [package.dependencies] 476 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" 477 | 478 | [[package]] 479 | category = "main" 480 | description = "Powerful data structures for data analysis, time series, and statistics" 481 | name = "pandas" 482 | optional = false 483 | python-versions = ">=3.7.1" 484 | version = "1.2.0" 485 | 486 | [package.dependencies] 487 | numpy = ">=1.16.5" 488 | python-dateutil = ">=2.7.3" 489 | pytz = ">=2017.3" 490 | 491 | [package.extras] 492 | test = ["pytest (>=5.0.1)", "pytest-xdist", "hypothesis (>=3.58)"] 493 | 494 | [[package]] 495 | category = "dev" 496 | description = "Utility library for gitignore style pattern matching of file paths." 497 | name = "pathspec" 498 | optional = false 499 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 500 | version = "0.9.0" 501 | 502 | [[package]] 503 | category = "main" 504 | description = "File system general utilities" 505 | name = "pathtools" 506 | optional = false 507 | python-versions = "*" 508 | version = "0.1.2" 509 | 510 | [[package]] 511 | category = "main" 512 | description = "Python Build Reasonableness" 513 | name = "pbr" 514 | optional = false 515 | python-versions = ">=2.6" 516 | version = "5.9.0" 517 | 518 | [[package]] 519 | category = "dev" 520 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 521 | name = "platformdirs" 522 | optional = false 523 | python-versions = ">=3.7" 524 | version = "2.5.0" 525 | 526 | [package.extras] 527 | docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] 528 | test = ["appdirs (1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] 529 | 530 | [[package]] 531 | category = "main" 532 | description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" 533 | name = "prettytable" 534 | optional = false 535 | python-versions = ">=3.7" 536 | version = "3.3.0" 537 | 538 | [package.dependencies] 539 | wcwidth = "*" 540 | 541 | [package.extras] 542 | tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"] 543 | 544 | [[package]] 545 | category = "main" 546 | description = "Promises/A+ implementation for Python" 547 | name = "promise" 548 | optional = false 549 | python-versions = "*" 550 | version = "2.3" 551 | 552 | [package.dependencies] 553 | six = "*" 554 | 555 | [package.extras] 556 | test = ["pytest (>=2.7.3)", "pytest-cov", "coveralls", "futures", "pytest-benchmark", "mock"] 557 | 558 | [[package]] 559 | category = "main" 560 | description = "Protocol Buffers" 561 | name = "protobuf" 562 | optional = false 563 | python-versions = ">=3.7" 564 | version = "3.20.1" 565 | 566 | [[package]] 567 | category = "main" 568 | description = "Cross-platform lib for process and system monitoring in Python." 569 | name = "psutil" 570 | optional = false 571 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 572 | version = "5.9.1" 573 | 574 | [package.extras] 575 | test = ["ipaddress", "mock", "enum34", "pywin32", "wmi"] 576 | 577 | [[package]] 578 | category = "dev" 579 | description = "Python style guide checker" 580 | name = "pycodestyle" 581 | optional = false 582 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 583 | version = "2.8.0" 584 | 585 | [[package]] 586 | category = "dev" 587 | description = "passive checker of Python programs" 588 | name = "pyflakes" 589 | optional = false 590 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 591 | version = "2.4.0" 592 | 593 | [[package]] 594 | category = "main" 595 | description = "pyparsing module - Classes and methods to define and execute parsing grammars" 596 | name = "pyparsing" 597 | optional = false 598 | python-versions = ">=3.6.8" 599 | version = "3.0.9" 600 | 601 | [package.extras] 602 | diagrams = ["railroad-diagrams", "jinja2"] 603 | 604 | [[package]] 605 | category = "main" 606 | description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" 607 | name = "pyperclip" 608 | optional = false 609 | python-versions = "*" 610 | version = "1.8.2" 611 | 612 | [[package]] 613 | category = "main" 614 | description = "A python implementation of GNU readline." 615 | marker = "sys_platform == \"win32\"" 616 | name = "pyreadline3" 617 | optional = false 618 | python-versions = "*" 619 | version = "3.4.1" 620 | 621 | [[package]] 622 | category = "main" 623 | description = "Extensions to the standard Python datetime module" 624 | name = "python-dateutil" 625 | optional = false 626 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 627 | version = "2.8.2" 628 | 629 | [package.dependencies] 630 | six = ">=1.5" 631 | 632 | [[package]] 633 | category = "main" 634 | description = "World timezone definitions, modern and historical" 635 | name = "pytz" 636 | optional = false 637 | python-versions = "*" 638 | version = "2022.1" 639 | 640 | [[package]] 641 | category = "main" 642 | description = "YAML parser and emitter for Python" 643 | name = "pyyaml" 644 | optional = false 645 | python-versions = ">=3.6" 646 | version = "6.0" 647 | 648 | [[package]] 649 | category = "main" 650 | description = "Alternative regular expression module, to replace re." 651 | name = "regex" 652 | optional = false 653 | python-versions = ">=3.6" 654 | version = "2022.7.9" 655 | 656 | [[package]] 657 | category = "main" 658 | description = "Python HTTP for Humans." 659 | name = "requests" 660 | optional = false 661 | python-versions = ">=3.7, <4" 662 | version = "2.28.1" 663 | 664 | [package.dependencies] 665 | certifi = ">=2017.4.17" 666 | charset-normalizer = ">=2,<3" 667 | idna = ">=2.5,<4" 668 | urllib3 = ">=1.21.1,<1.27" 669 | 670 | [package.extras] 671 | socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)"] 672 | use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] 673 | 674 | [[package]] 675 | category = "main" 676 | description = "A set of python modules for machine learning and data mining" 677 | name = "scikit-learn" 678 | optional = false 679 | python-versions = ">=3.8" 680 | version = "1.1.1" 681 | 682 | [package.dependencies] 683 | joblib = ">=1.0.0" 684 | numpy = ">=1.17.3" 685 | scipy = ">=1.3.2" 686 | threadpoolctl = ">=2.0.0" 687 | 688 | [package.extras] 689 | benchmark = ["matplotlib (>=3.1.2)", "pandas (>=1.0.5)", "memory-profiler (>=0.57.0)"] 690 | docs = ["matplotlib (>=3.1.2)", "scikit-image (>=0.14.5)", "pandas (>=1.0.5)", "seaborn (>=0.9.0)", "memory-profiler (>=0.57.0)", "sphinx (>=4.0.1)", "sphinx-gallery (>=0.7.0)", "numpydoc (>=1.2.0)", "Pillow (>=7.1.2)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] 691 | examples = ["matplotlib (>=3.1.2)", "scikit-image (>=0.14.5)", "pandas (>=1.0.5)", "seaborn (>=0.9.0)"] 692 | tests = ["matplotlib (>=3.1.2)", "scikit-image (>=0.14.5)", "pandas (>=1.0.5)", "pytest (>=5.0.1)", "pytest-cov (>=2.9.0)", "flake8 (>=3.8.2)", "black (>=22.3.0)", "mypy (>=0.770)", "pyamg (>=4.0.0)", "numpydoc (>=1.2.0)"] 693 | 694 | [[package]] 695 | category = "main" 696 | description = "SciPy: Scientific Library for Python" 697 | name = "scipy" 698 | optional = false 699 | python-versions = ">=3.7" 700 | version = "1.6.1" 701 | 702 | [package.dependencies] 703 | numpy = ">=1.16.5" 704 | 705 | [[package]] 706 | category = "main" 707 | description = "Python client for Sentry (https://sentry.io)" 708 | name = "sentry-sdk" 709 | optional = false 710 | python-versions = "*" 711 | version = "1.7.2" 712 | 713 | [package.dependencies] 714 | certifi = "*" 715 | urllib3 = ">=1.10.0" 716 | 717 | [package.extras] 718 | aiohttp = ["aiohttp (>=3.5)"] 719 | beam = ["apache-beam (>=2.12)"] 720 | bottle = ["bottle (>=0.12.13)"] 721 | celery = ["celery (>=3)"] 722 | chalice = ["chalice (>=1.16.0)"] 723 | django = ["django (>=1.8)"] 724 | falcon = ["falcon (>=1.4)"] 725 | flask = ["flask (>=0.11)", "blinker (>=1.1)"] 726 | httpx = ["httpx (>=0.16.0)"] 727 | pure_eval = ["pure-eval", "executing", "asttokens"] 728 | pyspark = ["pyspark (>=2.4.4)"] 729 | quart = ["quart (>=0.16.1)", "blinker (>=1.1)"] 730 | rq = ["rq (>=0.6)"] 731 | sanic = ["sanic (>=0.8)"] 732 | sqlalchemy = ["sqlalchemy (>=1.2)"] 733 | tornado = ["tornado (>=5)"] 734 | 735 | [[package]] 736 | category = "main" 737 | description = "A Python module to customize the process title" 738 | name = "setproctitle" 739 | optional = false 740 | python-versions = ">=3.6" 741 | version = "1.2.3" 742 | 743 | [package.extras] 744 | test = ["pytest"] 745 | 746 | [[package]] 747 | category = "main" 748 | description = "A generator library for concise, unambiguous and URL-safe UUIDs." 749 | name = "shortuuid" 750 | optional = false 751 | python-versions = ">=3.5" 752 | version = "1.0.9" 753 | 754 | [[package]] 755 | category = "main" 756 | description = "Python 2 and 3 compatibility utilities" 757 | name = "six" 758 | optional = false 759 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 760 | version = "1.16.0" 761 | 762 | [[package]] 763 | category = "main" 764 | description = "A pure Python implementation of a sliding window memory map manager" 765 | name = "smmap" 766 | optional = false 767 | python-versions = ">=3.6" 768 | version = "5.0.0" 769 | 770 | [[package]] 771 | category = "main" 772 | description = "Database Abstraction Library" 773 | name = "sqlalchemy" 774 | optional = false 775 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 776 | version = "1.4.39" 777 | 778 | [package.dependencies] 779 | [package.dependencies.greenlet] 780 | python = ">=3" 781 | version = "!=0.4.17" 782 | 783 | [package.extras] 784 | aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] 785 | aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"] 786 | asyncio = ["greenlet (!=0.4.17)"] 787 | asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3,<0.2.4 || >0.2.4)"] 788 | mariadb_connector = ["mariadb (>=1.0.1)"] 789 | mssql = ["pyodbc"] 790 | mssql_pymssql = ["pymssql"] 791 | mssql_pyodbc = ["pyodbc"] 792 | mypy = ["sqlalchemy2-stubs", "mypy (>=0.910)"] 793 | mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] 794 | mysql_connector = ["mysql-connector-python"] 795 | oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] 796 | postgresql = ["psycopg2 (>=2.7)"] 797 | postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] 798 | postgresql_pg8000 = ["pg8000 (>=1.16.6,<1.29.0 || >1.29.0)"] 799 | postgresql_psycopg2binary = ["psycopg2-binary"] 800 | postgresql_psycopg2cffi = ["psycopg2cffi"] 801 | pymysql = ["pymysql (<1)", "pymysql"] 802 | sqlcipher = ["sqlcipher3-binary"] 803 | 804 | [[package]] 805 | category = "main" 806 | description = "Manage dynamic plugins for Python applications" 807 | name = "stevedore" 808 | optional = false 809 | python-versions = ">=3.8" 810 | version = "4.0.0" 811 | 812 | [package.dependencies] 813 | pbr = ">=2.0.0,<2.1.0 || >2.1.0" 814 | 815 | [[package]] 816 | category = "main" 817 | description = "threadpoolctl" 818 | name = "threadpoolctl" 819 | optional = false 820 | python-versions = ">=3.6" 821 | version = "3.1.0" 822 | 823 | [[package]] 824 | category = "dev" 825 | description = "A lil' TOML parser" 826 | name = "tomli" 827 | optional = false 828 | python-versions = ">=3.7" 829 | version = "2.0.1" 830 | 831 | [[package]] 832 | category = "main" 833 | description = "Fast, Extensible Progress Meter" 834 | name = "tqdm" 835 | optional = false 836 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 837 | version = "4.64.0" 838 | 839 | [package.dependencies] 840 | colorama = "*" 841 | 842 | [package.extras] 843 | dev = ["py-make (>=0.1.0)", "twine", "wheel"] 844 | notebook = ["ipywidgets (>=6)"] 845 | slack = ["slack-sdk"] 846 | telegram = ["requests"] 847 | 848 | [[package]] 849 | category = "dev" 850 | description = "Backported and Experimental Type Hints for Python 3.6+" 851 | name = "typing-extensions" 852 | optional = false 853 | python-versions = ">=3.6" 854 | version = "4.0.1" 855 | 856 | [[package]] 857 | category = "main" 858 | description = "HTTP library with thread-safe connection pooling, file post, and more." 859 | name = "urllib3" 860 | optional = false 861 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4" 862 | version = "1.26.10" 863 | 864 | [package.extras] 865 | brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] 866 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 867 | socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7,<2.0)"] 868 | 869 | [[package]] 870 | category = "main" 871 | description = "A CLI and library for interacting with the Weights and Biases API." 872 | name = "wandb" 873 | optional = false 874 | python-versions = ">=3.6" 875 | version = "0.12.21" 876 | 877 | [package.dependencies] 878 | Click = ">=7.0,<8.0.0 || >8.0.0" 879 | GitPython = ">=1.0.0" 880 | PyYAML = "*" 881 | docker-pycreds = ">=0.4.0" 882 | pathtools = "*" 883 | promise = ">=2.0,<3" 884 | protobuf = ">=3.12.0,<4.0dev" 885 | psutil = ">=5.0.0" 886 | requests = ">=2.0.0,<3" 887 | sentry-sdk = ">=1.0.0" 888 | setproctitle = "*" 889 | setuptools = "*" 890 | shortuuid = ">=0.5.0" 891 | six = ">=1.13.0" 892 | 893 | [package.extras] 894 | aws = ["boto3"] 895 | azure = ["azure-storage-blob"] 896 | gcp = ["google-cloud-storage"] 897 | grpc = ["grpcio (>=1.27.2)"] 898 | kubeflow = ["kubernetes", "minio", "google-cloud-storage", "sh"] 899 | launch = ["nbconvert", "nbformat", "chardet", "iso8601", "typing-extensions", "boto3", "google-cloud-storage", "kubernetes"] 900 | media = ["numpy", "moviepy", "pillow", "bokeh", "soundfile", "plotly", "rdkit-pypi"] 901 | models = ["cloudpickle"] 902 | sweeps = ["sweeps (>=0.1.0)"] 903 | 904 | [[package]] 905 | category = "main" 906 | description = "Measures the displayed width of unicode strings in a terminal" 907 | name = "wcwidth" 908 | optional = false 909 | python-versions = "*" 910 | version = "0.2.5" 911 | 912 | [[package]] 913 | category = "main" 914 | description = "A built-package format for Python" 915 | name = "wheel" 916 | optional = false 917 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 918 | version = "0.37.1" 919 | 920 | [package.extras] 921 | test = ["pytest (>=3.0.0)", "pytest-cov"] 922 | 923 | [[package]] 924 | category = "main" 925 | description = "Backport of pathlib-compatible object wrapper for zip files" 926 | marker = "python_version < \"3.9\"" 927 | name = "zipp" 928 | optional = false 929 | python-versions = ">=3.7" 930 | version = "3.8.1" 931 | 932 | [package.extras] 933 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"] 934 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] 935 | 936 | [metadata] 937 | content-hash = "1d36c42baaf3c2436457bb253f120080ad38af854c2623d23a2fbb3875bc7985" 938 | lock-version = "1.0" 939 | python-versions = "^3.8" 940 | 941 | [metadata.files] 942 | alembic = [] 943 | antlr4-python3-runtime = [] 944 | attrs = [ 945 | {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, 946 | {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, 947 | ] 948 | autopage = [] 949 | black = [ 950 | {file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"}, 951 | {file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"}, 952 | {file = "black-22.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e21e1f1efa65a50e3960edd068b6ae6d64ad6235bd8bfea116a03b21836af71"}, 953 | {file = "black-22.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2f69158a7d120fd641d1fa9a921d898e20d52e44a74a6fbbcc570a62a6bc8ab"}, 954 | {file = "black-22.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:228b5ae2c8e3d6227e4bde5920d2fc66cc3400fde7bcc74f480cb07ef0b570d5"}, 955 | {file = "black-22.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1a5ed73ab4c482208d20434f700d514f66ffe2840f63a6252ecc43a9bc77e8a"}, 956 | {file = "black-22.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:35944b7100af4a985abfcaa860b06af15590deb1f392f06c8683b4381e8eeaf0"}, 957 | {file = "black-22.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7835fee5238fc0a0baf6c9268fb816b5f5cd9b8793423a75e8cd663c48d073ba"}, 958 | {file = "black-22.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dae63f2dbf82882fa3b2a3c49c32bffe144970a573cd68d247af6560fc493ae1"}, 959 | {file = "black-22.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa1db02410b1924b6749c245ab38d30621564e658297484952f3d8a39fce7e8"}, 960 | {file = "black-22.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c8226f50b8c34a14608b848dc23a46e5d08397d009446353dad45e04af0c8e28"}, 961 | {file = "black-22.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2d6f331c02f0f40aa51a22e479c8209d37fcd520c77721c034517d44eecf5912"}, 962 | {file = "black-22.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:742ce9af3086e5bd07e58c8feb09dbb2b047b7f566eb5f5bc63fd455814979f3"}, 963 | {file = "black-22.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fdb8754b453fb15fad3f72cd9cad3e16776f0964d67cf30ebcbf10327a3777a3"}, 964 | {file = "black-22.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5660feab44c2e3cb24b2419b998846cbb01c23c7fe645fee45087efa3da2d61"}, 965 | {file = "black-22.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6f2f01381f91c1efb1451998bd65a129b3ed6f64f79663a55fe0e9b74a5f81fd"}, 966 | {file = "black-22.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:efbadd9b52c060a8fc3b9658744091cb33c31f830b3f074422ed27bad2b18e8f"}, 967 | {file = "black-22.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8871fcb4b447206904932b54b567923e5be802b9b19b744fdff092bd2f3118d0"}, 968 | {file = "black-22.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccad888050f5393f0d6029deea2a33e5ae371fd182a697313bdbd835d3edaf9c"}, 969 | {file = "black-22.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07e5c049442d7ca1a2fc273c79d1aecbbf1bc858f62e8184abe1ad175c4f7cc2"}, 970 | {file = "black-22.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:373922fc66676133ddc3e754e4509196a8c392fec3f5ca4486673e685a421321"}, 971 | {file = "black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d"}, 972 | {file = "black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5"}, 973 | ] 974 | certifi = [] 975 | charset-normalizer = [] 976 | click = [ 977 | {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, 978 | {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, 979 | ] 980 | cliff = [] 981 | cmaes = [] 982 | cmd2 = [] 983 | colorama = [ 984 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 985 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 986 | ] 987 | colorlog = [] 988 | docker-pycreds = [] 989 | flake8 = [ 990 | {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, 991 | {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, 992 | ] 993 | gitdb = [] 994 | gitpython = [] 995 | greenlet = [] 996 | hydra-core = [] 997 | idna = [ 998 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, 999 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, 1000 | ] 1001 | importlib-metadata = [] 1002 | importlib-resources = [ 1003 | {file = "importlib_resources-5.8.0-py3-none-any.whl", hash = "sha256:7952325ffd516c05a8ad0858c74dff2c3343f136fe66a6002b2623dd1d43f223"}, 1004 | {file = "importlib_resources-5.8.0.tar.gz", hash = "sha256:568c9f16cb204f9decc8d6d24a572eeea27dacbb4cee9e6b03a8025736769751"}, 1005 | ] 1006 | isort = [ 1007 | {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, 1008 | {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, 1009 | ] 1010 | joblib = [ 1011 | {file = "joblib-1.1.0-py2.py3-none-any.whl", hash = "sha256:f21f109b3c7ff9d95f8387f752d0d9c34a02aa2f7060c2135f465da0e5160ff6"}, 1012 | {file = "joblib-1.1.0.tar.gz", hash = "sha256:4158fcecd13733f8be669be0683b96ebdbbd38d23559f54dca7205aea1bf1e35"}, 1013 | ] 1014 | lightgbm = [] 1015 | mako = [] 1016 | markupsafe = [ 1017 | {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, 1018 | {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, 1019 | {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, 1020 | {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, 1021 | {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, 1022 | {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, 1023 | {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, 1024 | {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, 1025 | {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, 1026 | {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, 1027 | {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, 1028 | {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, 1029 | {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, 1030 | {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, 1031 | {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, 1032 | {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, 1033 | {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, 1034 | {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, 1035 | {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, 1036 | {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, 1037 | {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, 1038 | {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, 1039 | {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, 1040 | {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, 1041 | {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, 1042 | {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, 1043 | {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, 1044 | {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, 1045 | {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, 1046 | {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, 1047 | {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, 1048 | {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, 1049 | {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, 1050 | {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, 1051 | {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, 1052 | {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, 1053 | {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, 1054 | {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, 1055 | {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, 1056 | {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, 1057 | ] 1058 | mccabe = [ 1059 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 1060 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 1061 | ] 1062 | mypy = [ 1063 | {file = "mypy-0.931-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a"}, 1064 | {file = "mypy-0.931-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00"}, 1065 | {file = "mypy-0.931-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714"}, 1066 | {file = "mypy-0.931-cp310-cp310-win_amd64.whl", hash = "sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc"}, 1067 | {file = "mypy-0.931-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d"}, 1068 | {file = "mypy-0.931-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d"}, 1069 | {file = "mypy-0.931-cp36-cp36m-win_amd64.whl", hash = "sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c"}, 1070 | {file = "mypy-0.931-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0"}, 1071 | {file = "mypy-0.931-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05"}, 1072 | {file = "mypy-0.931-cp37-cp37m-win_amd64.whl", hash = "sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7"}, 1073 | {file = "mypy-0.931-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0"}, 1074 | {file = "mypy-0.931-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069"}, 1075 | {file = "mypy-0.931-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799"}, 1076 | {file = "mypy-0.931-cp38-cp38-win_amd64.whl", hash = "sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a"}, 1077 | {file = "mypy-0.931-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166"}, 1078 | {file = "mypy-0.931-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266"}, 1079 | {file = "mypy-0.931-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd"}, 1080 | {file = "mypy-0.931-cp39-cp39-win_amd64.whl", hash = "sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697"}, 1081 | {file = "mypy-0.931-py3-none-any.whl", hash = "sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d"}, 1082 | {file = "mypy-0.931.tar.gz", hash = "sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce"}, 1083 | ] 1084 | mypy-extensions = [ 1085 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 1086 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 1087 | ] 1088 | nltk = [] 1089 | numpy = [] 1090 | omegaconf = [] 1091 | optuna = [] 1092 | packaging = [ 1093 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, 1094 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, 1095 | ] 1096 | pandas = [ 1097 | {file = "pandas-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cba93d4fd3b0a42858b2b599495aff793fb5d94587979f45a14177d1217ba446"}, 1098 | {file = "pandas-1.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9e18631d996fe131de6cb31a8bdae18965cc8f39eb23fdfbbf42808ecc63dabf"}, 1099 | {file = "pandas-1.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7b54c14130a3448d81eed1348f52429c23e27188d9db6e6d4afeae792bc49c11"}, 1100 | {file = "pandas-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:6c1a57e4d0d6f9633a07817c44e6b36d81c265fe4c52d0c0505513a2d0f7953c"}, 1101 | {file = "pandas-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:43482789c55cbabeed9482263cfc98a11e8fcae900cb63ef038948acb4a72570"}, 1102 | {file = "pandas-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0be6102dd99910513e75ed6536284743ead810349c51bdeadd2a5b6649f30abb"}, 1103 | {file = "pandas-1.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9c6692cea6d56da8650847172bdb148622f545e7782d17995822434c79d7a211"}, 1104 | {file = "pandas-1.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:272675a98fa4954b9fc0933df775596fc942e50015d7e75d8f19548808a2bfdf"}, 1105 | {file = "pandas-1.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:33318fa24b192b1a4684347ff76679a7267fd4e547da9f71556a5914f0dc10e7"}, 1106 | {file = "pandas-1.2.0-cp38-cp38-win32.whl", hash = "sha256:3bc6d2be03cb75981d8cbeda09503cd9d6d699fc0dc28a65e197165ad527b7b8"}, 1107 | {file = "pandas-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:7904ee438549b5223ce8dc008772458dd7c5cf0ccc64cf903e81202400702235"}, 1108 | {file = "pandas-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f8b87d2f541cd9bc4ecfe85a561abac85c33fe4de4ce70cca36b2768af2611f5"}, 1109 | {file = "pandas-1.2.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:91fd0b94e7b98528177a05e6f65efea79d7ef9dec15ee48c7c69fc39fdd87235"}, 1110 | {file = "pandas-1.2.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:8f92b07cdbfa3704d85b4264e52c216cafe6c0059b0d07cdad8cb29e0b90f2b8"}, 1111 | {file = "pandas-1.2.0-cp39-cp39-win32.whl", hash = "sha256:2d8b4f532db37418121831a461fd107d826c240b098f52e7a1b4ab3d5aaa4fb2"}, 1112 | {file = "pandas-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:616478c1bd8fe1e600f521ae2da434e021c11e7a4e5da3451d02906143d3629a"}, 1113 | {file = "pandas-1.2.0.tar.gz", hash = "sha256:e03386615b970b8b41da6a68afe717626741bb2431cec993640685614c0680e4"}, 1114 | ] 1115 | pathspec = [ 1116 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, 1117 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, 1118 | ] 1119 | pathtools = [] 1120 | pbr = [] 1121 | platformdirs = [ 1122 | {file = "platformdirs-2.5.0-py3-none-any.whl", hash = "sha256:30671902352e97b1eafd74ade8e4a694782bd3471685e78c32d0fdfd3aa7e7bb"}, 1123 | {file = "platformdirs-2.5.0.tar.gz", hash = "sha256:8ec11dfba28ecc0715eb5fb0147a87b1bf325f349f3da9aab2cd6b50b96b692b"}, 1124 | ] 1125 | prettytable = [] 1126 | promise = [] 1127 | protobuf = [] 1128 | psutil = [ 1129 | {file = "psutil-5.9.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:799759d809c31aab5fe4579e50addf84565e71c1dc9f1c31258f159ff70d3f87"}, 1130 | {file = "psutil-5.9.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:9272167b5f5fbfe16945be3db475b3ce8d792386907e673a209da686176552af"}, 1131 | {file = "psutil-5.9.1-cp27-cp27m-win32.whl", hash = "sha256:0904727e0b0a038830b019551cf3204dd48ef5c6868adc776e06e93d615fc5fc"}, 1132 | {file = "psutil-5.9.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e7e10454cb1ab62cc6ce776e1c135a64045a11ec4c6d254d3f7689c16eb3efd2"}, 1133 | {file = "psutil-5.9.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:56960b9e8edcca1456f8c86a196f0c3d8e3e361320071c93378d41445ffd28b0"}, 1134 | {file = "psutil-5.9.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:44d1826150d49ffd62035785a9e2c56afcea66e55b43b8b630d7706276e87f22"}, 1135 | {file = "psutil-5.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7be9d7f5b0d206f0bbc3794b8e16fb7dbc53ec9e40bbe8787c6f2d38efcf6c9"}, 1136 | {file = "psutil-5.9.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd9246e4cdd5b554a2ddd97c157e292ac11ef3e7af25ac56b08b455c829dca8"}, 1137 | {file = "psutil-5.9.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:29a442e25fab1f4d05e2655bb1b8ab6887981838d22effa2396d584b740194de"}, 1138 | {file = "psutil-5.9.1-cp310-cp310-win32.whl", hash = "sha256:20b27771b077dcaa0de1de3ad52d22538fe101f9946d6dc7869e6f694f079329"}, 1139 | {file = "psutil-5.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:58678bbadae12e0db55186dc58f2888839228ac9f41cc7848853539b70490021"}, 1140 | {file = "psutil-5.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:3a76ad658641172d9c6e593de6fe248ddde825b5866464c3b2ee26c35da9d237"}, 1141 | {file = "psutil-5.9.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6a11e48cb93a5fa606306493f439b4aa7c56cb03fc9ace7f6bfa21aaf07c453"}, 1142 | {file = "psutil-5.9.1-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:068935df39055bf27a29824b95c801c7a5130f118b806eee663cad28dca97685"}, 1143 | {file = "psutil-5.9.1-cp36-cp36m-win32.whl", hash = "sha256:0f15a19a05f39a09327345bc279c1ba4a8cfb0172cc0d3c7f7d16c813b2e7d36"}, 1144 | {file = "psutil-5.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:db417f0865f90bdc07fa30e1aadc69b6f4cad7f86324b02aa842034efe8d8c4d"}, 1145 | {file = "psutil-5.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:91c7ff2a40c373d0cc9121d54bc5f31c4fa09c346528e6a08d1845bce5771ffc"}, 1146 | {file = "psutil-5.9.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fea896b54f3a4ae6f790ac1d017101252c93f6fe075d0e7571543510f11d2676"}, 1147 | {file = "psutil-5.9.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3054e923204b8e9c23a55b23b6df73a8089ae1d075cb0bf711d3e9da1724ded4"}, 1148 | {file = "psutil-5.9.1-cp37-cp37m-win32.whl", hash = "sha256:d2d006286fbcb60f0b391741f520862e9b69f4019b4d738a2a45728c7e952f1b"}, 1149 | {file = "psutil-5.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b14ee12da9338f5e5b3a3ef7ca58b3cba30f5b66f7662159762932e6d0b8f680"}, 1150 | {file = "psutil-5.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:19f36c16012ba9cfc742604df189f2f28d2720e23ff7d1e81602dbe066be9fd1"}, 1151 | {file = "psutil-5.9.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:944c4b4b82dc4a1b805329c980f270f170fdc9945464223f2ec8e57563139cf4"}, 1152 | {file = "psutil-5.9.1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b6750a73a9c4a4e689490ccb862d53c7b976a2a35c4e1846d049dcc3f17d83b"}, 1153 | {file = "psutil-5.9.1-cp38-cp38-win32.whl", hash = "sha256:a8746bfe4e8f659528c5c7e9af5090c5a7d252f32b2e859c584ef7d8efb1e689"}, 1154 | {file = "psutil-5.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:79c9108d9aa7fa6fba6e668b61b82facc067a6b81517cab34d07a84aa89f3df0"}, 1155 | {file = "psutil-5.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28976df6c64ddd6320d281128817f32c29b539a52bdae5e192537bc338a9ec81"}, 1156 | {file = "psutil-5.9.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b88f75005586131276634027f4219d06e0561292be8bd6bc7f2f00bdabd63c4e"}, 1157 | {file = "psutil-5.9.1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:645bd4f7bb5b8633803e0b6746ff1628724668681a434482546887d22c7a9537"}, 1158 | {file = "psutil-5.9.1-cp39-cp39-win32.whl", hash = "sha256:32c52611756096ae91f5d1499fe6c53b86f4a9ada147ee42db4991ba1520e574"}, 1159 | {file = "psutil-5.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:f65f9a46d984b8cd9b3750c2bdb419b2996895b005aefa6cbaba9a143b1ce2c5"}, 1160 | {file = "psutil-5.9.1.tar.gz", hash = "sha256:57f1819b5d9e95cdfb0c881a8a5b7d542ed0b7c522d575706a80bedc848c8954"}, 1161 | ] 1162 | pycodestyle = [ 1163 | {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"}, 1164 | {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"}, 1165 | ] 1166 | pyflakes = [ 1167 | {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"}, 1168 | {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"}, 1169 | ] 1170 | pyparsing = [ 1171 | {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, 1172 | {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, 1173 | ] 1174 | pyperclip = [] 1175 | pyreadline3 = [] 1176 | python-dateutil = [ 1177 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 1178 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 1179 | ] 1180 | pytz = [ 1181 | {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, 1182 | {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, 1183 | ] 1184 | pyyaml = [] 1185 | regex = [] 1186 | requests = [] 1187 | scikit-learn = [ 1188 | {file = "scikit-learn-1.1.1.tar.gz", hash = "sha256:3e77b71e8e644f86c8b5be7f1c285ef597de4c384961389ee3e9ca36c445b256"}, 1189 | {file = "scikit_learn-1.1.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:102f51797cd8944bf44a038d106848ddf2804f2c1edf7aea45fba81a4fdc4d80"}, 1190 | {file = "scikit_learn-1.1.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:723cdb278b1fa57a55f68945bc4e501a2f12abe82f76e8d21e1806cbdbef6fc5"}, 1191 | {file = "scikit_learn-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33cf061ed0b79d647a3e4c3f6c52c412172836718a7cd4d11c1318d083300133"}, 1192 | {file = "scikit_learn-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47464c110eaa9ed9d1fe108cb403510878c3d3a40f110618d2a19b2190a3e35c"}, 1193 | {file = "scikit_learn-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:542ccd2592fe7ad31f5c85fed3a3deb3e252383960a85e4b49a629353fffaba4"}, 1194 | {file = "scikit_learn-1.1.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:3be10d8d325821ca366d4fe7083d87c40768f842f54371a9c908d97c45da16fc"}, 1195 | {file = "scikit_learn-1.1.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:b2db720e13e697d912a87c1a51194e6fb085dc6d8323caa5ca51369ca6948f78"}, 1196 | {file = "scikit_learn-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e851f8874398dcd50d1e174e810e9331563d189356e945b3271c0e19ee6f4d6f"}, 1197 | {file = "scikit_learn-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b928869072366dc138762fe0929e7dc88413f8a469aebc6a64adc10a9226180c"}, 1198 | {file = "scikit_learn-1.1.1-cp38-cp38-win32.whl", hash = "sha256:e9d228ced1214d67904f26fb820c8abbea12b2889cd4aa8cda20a4ca0ed781c1"}, 1199 | {file = "scikit_learn-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:f2d5b5d6e87d482e17696a7bfa03fe9515fdfe27e462a4ad37f3d7774a5e2fd6"}, 1200 | {file = "scikit_learn-1.1.1-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:0403ad13f283e27d43b0ad875f187ec7f5d964903d92d1ed06c51439560ecea0"}, 1201 | {file = "scikit_learn-1.1.1-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:8fe80df08f5b9cee5dd008eccc672e543976198d790c07e5337f7dfb67eaac05"}, 1202 | {file = "scikit_learn-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8ff56d07b9507fbe07ca0f4e5c8f3e171f74a429f998da03e308166251316b34"}, 1203 | {file = "scikit_learn-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c2dad2bfc502344b869d4a3f4aa7271b2a5f4fe41f7328f404844c51612e2c58"}, 1204 | {file = "scikit_learn-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22145b60fef02e597a8e7f061ebc7c51739215f11ce7fcd2ca9af22c31aa9f86"}, 1205 | {file = "scikit_learn-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:45c0f6ae523353f1d99b85469d746f9c497410adff5ba8b24423705b6956a86e"}, 1206 | ] 1207 | scipy = [ 1208 | {file = "scipy-1.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a15a1f3fc0abff33e792d6049161b7795909b40b97c6cc2934ed54384017ab76"}, 1209 | {file = "scipy-1.6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:e79570979ccdc3d165456dd62041d9556fb9733b86b4b6d818af7a0afc15f092"}, 1210 | {file = "scipy-1.6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a423533c55fec61456dedee7b6ee7dce0bb6bfa395424ea374d25afa262be261"}, 1211 | {file = "scipy-1.6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:33d6b7df40d197bdd3049d64e8e680227151673465e5d85723b3b8f6b15a6ced"}, 1212 | {file = "scipy-1.6.1-cp37-cp37m-win32.whl", hash = "sha256:6725e3fbb47da428794f243864f2297462e9ee448297c93ed1dcbc44335feb78"}, 1213 | {file = "scipy-1.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:5fa9c6530b1661f1370bcd332a1e62ca7881785cc0f80c0d559b636567fab63c"}, 1214 | {file = "scipy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bd50daf727f7c195e26f27467c85ce653d41df4358a25b32434a50d8870fc519"}, 1215 | {file = "scipy-1.6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:f46dd15335e8a320b0fb4685f58b7471702234cba8bb3442b69a3e1dc329c345"}, 1216 | {file = "scipy-1.6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0e5b0ccf63155d90da576edd2768b66fb276446c371b73841e3503be1d63fb5d"}, 1217 | {file = "scipy-1.6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2481efbb3740977e3c831edfd0bd9867be26387cacf24eb5e366a6a374d3d00d"}, 1218 | {file = "scipy-1.6.1-cp38-cp38-win32.whl", hash = "sha256:68cb4c424112cd4be886b4d979c5497fba190714085f46b8ae67a5e4416c32b4"}, 1219 | {file = "scipy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:5f331eeed0297232d2e6eea51b54e8278ed8bb10b099f69c44e2558c090d06bf"}, 1220 | {file = "scipy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8a51d33556bf70367452d4d601d1742c0e806cd0194785914daf19775f0e67"}, 1221 | {file = "scipy-1.6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:83bf7c16245c15bc58ee76c5418e46ea1811edcc2e2b03041b804e46084ab627"}, 1222 | {file = "scipy-1.6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:794e768cc5f779736593046c9714e0f3a5940bc6dcc1dba885ad64cbfb28e9f0"}, 1223 | {file = "scipy-1.6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:5da5471aed911fe7e52b86bf9ea32fb55ae93e2f0fac66c32e58897cfb02fa07"}, 1224 | {file = "scipy-1.6.1-cp39-cp39-win32.whl", hash = "sha256:8e403a337749ed40af60e537cc4d4c03febddcc56cd26e774c9b1b600a70d3e4"}, 1225 | {file = "scipy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a5193a098ae9f29af283dcf0041f762601faf2e595c0db1da929875b7570353f"}, 1226 | {file = "scipy-1.6.1.tar.gz", hash = "sha256:c4fceb864890b6168e79b0e714c585dbe2fd4222768ee90bc1aa0f8218691b11"}, 1227 | ] 1228 | sentry-sdk = [] 1229 | setproctitle = [] 1230 | shortuuid = [] 1231 | six = [ 1232 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 1233 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 1234 | ] 1235 | smmap = [] 1236 | sqlalchemy = [] 1237 | stevedore = [] 1238 | threadpoolctl = [ 1239 | {file = "threadpoolctl-3.1.0-py3-none-any.whl", hash = "sha256:8b99adda265feb6773280df41eece7b2e6561b772d21ffd52e372f999024907b"}, 1240 | {file = "threadpoolctl-3.1.0.tar.gz", hash = "sha256:a335baacfaa4400ae1f0d8e3a58d6674d2f8828e3716bb2802c44955ad391380"}, 1241 | ] 1242 | tomli = [ 1243 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 1244 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 1245 | ] 1246 | tqdm = [ 1247 | {file = "tqdm-4.64.0-py2.py3-none-any.whl", hash = "sha256:74a2cdefe14d11442cedf3ba4e21a3b84ff9a2dbdc6cfae2c34addb2a14a5ea6"}, 1248 | {file = "tqdm-4.64.0.tar.gz", hash = "sha256:40be55d30e200777a307a7585aee69e4eabb46b4ec6a4b4a5f2d9f11e7d5408d"}, 1249 | ] 1250 | typing-extensions = [ 1251 | {file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"}, 1252 | {file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"}, 1253 | ] 1254 | urllib3 = [] 1255 | wandb = [] 1256 | wcwidth = [ 1257 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 1258 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 1259 | ] 1260 | wheel = [] 1261 | zipp = [] 1262 | --------------------------------------------------------------------------------