commit 776a75b010cb96dbdc99302ae24da6764f673486 Author: GokuMohandas Date: Wed Jul 26 04:53:11 2023 -0700 ML for Developers diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml new file mode 100644 index 0000000..2d16afd --- /dev/null +++ b/.github/workflows/documentation.yaml @@ -0,0 +1,21 @@ +name: documentation +on: + push: + branches: + - main + +jobs: + build-docs: + runs-on: ubuntu-22.04 + steps: + # Set up dependencies + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10.11' + cache: 'pip' + - run: python3 -m pip install mkdocs==1.4.2 mkdocstrings==0.21.2 "mkdocstrings[python]>=0.18" + + # Deploy docs + - name: Deploy documentation + run: mkdocs gh-deploy --force diff --git a/.github/workflows/json_to_md.py b/.github/workflows/json_to_md.py new file mode 100644 index 0000000..49f1e02 --- /dev/null +++ b/.github/workflows/json_to_md.py @@ -0,0 +1,64 @@ +import json +import sys + + +def to_markdown(data): + markdown = "" + for key, value in data.items(): + markdown += f"**{key}:**\n\n" + if isinstance(value, dict): + markdown += "| Key | Value |\n| --- | --- |\n" + for nested_key, nested_value in value.items(): + nested_value = ( + round(nested_value, 3) + if isinstance(nested_value, float) + else {k: round(v, 3) for k, v in nested_value.items()} + if isinstance(nested_value, dict) + else nested_value + ) + markdown += f"| {nested_key} | {nested_value} |\n" + elif isinstance(value, list) and all(isinstance(item, dict) for item in value): + if value: + headers = sorted(set().union(*[item.keys() for item in value])) + markdown += "| " + " | ".join(headers) + " |\n| " + " | ".join(["---"] * len(headers)) + " |\n" + for item in value: + value_list = [ + "{:.3e}".format(float(item.get(header, ""))) if not str(item.get(header, "")).isdigit() else str(item.get(header, "")) + for header in headers + ] + markdown += "| " + " | ".join(value_list) + " |\n" + else: + markdown += "(empty list)\n" + else: + markdown += f"{value}\n" + markdown += "\n" + return markdown + + +def json_to_markdown(json_fp, md_fp): + """Convert a json file to markdown.""" + # Read JSON file + with open(json_fp, "r") as file: + data = json.load(file) + + # Convert to markdown + markdown = to_markdown(data) + + # Save to markdown file + with open(md_fp, "w") as file: + file.write(markdown) + return markdown + + +if __name__ == "__main__": + # Check if the correct number of arguments is provided + if len(sys.argv) < 3: + print("Usage: python script.py ") + sys.exit(1) + + # Get the JSON file path and output Markdown file path from command-line arguments + json_file = sys.argv[1] + md_file = sys.argv[2] + + # Call the JSON to Markdown conversion function + json_to_markdown(json_file, md_file) diff --git a/.github/workflows/serve.yaml b/.github/workflows/serve.yaml new file mode 100644 index 0000000..60cd8db --- /dev/null +++ b/.github/workflows/serve.yaml @@ -0,0 +1,35 @@ +name: serve +on: + workflow_dispatch: # manual + push: + branches: + - main +permissions: write-all + +jobs: + serve: + runs-on: ubuntu-22.04 + steps: + + # Configure AWS credentials + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: arn:aws:iam::593241322649:role/github-actions-madewithml + role-session-name: s3access + aws-region: us-west-2 + + # Set up dependencies + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10.11' + cache: 'pip' + - run: python3 -m pip install anyscale==0.5.131 typer==0.9.0 + + # Serve model + - name: Serve model + run: | + export ANYSCALE_HOST=${{ secrets.ANYSCALE_HOST }} + export ANYSCALE_CLI_TOKEN=${{ secrets.ANYSCALE_CLI_TOKEN }} + anyscale service rollout --service-config-file deploy/services/serve_model.yaml diff --git a/.github/workflows/workloads.yaml b/.github/workflows/workloads.yaml new file mode 100644 index 0000000..cfc587f --- /dev/null +++ b/.github/workflows/workloads.yaml @@ -0,0 +1,53 @@ +name: workloads +on: + workflow_dispatch: # manual + pull_request: + branches: + - main +permissions: write-all + +jobs: + workloads: + runs-on: ubuntu-22.04 + steps: + + # Configure AWS credentials + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v2 + with: + role-to-assume: arn:aws:iam::593241322649:role/github-actions-madewithml + role-session-name: s3access + aws-region: us-west-2 + + # Set up dependencies + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.10.11' + cache: 'pip' + - run: python3 -m pip install anyscale==0.5.131 typer==0.9.0 + + # Run workloads + - name: Workloads + run: | + export ANYSCALE_HOST=${{ secrets.ANYSCALE_HOST }} + export ANYSCALE_CLI_TOKEN=${{ secrets.ANYSCALE_CLI_TOKEN }} + anyscale jobs submit deploy/jobs/workloads.yaml --wait + + # Read results from S3 + - name: Read results from S3 + run: | + mkdir results + aws s3 cp s3://madewithml/${{ github.actor }}/results/ results/ --recursive + python .github/workflows/json_to_md.py results/training_results.json results/training_results.md + python .github/workflows/json_to_md.py results/evaluation_results.json results/evaluation_results.md + + # Comment results to PR + - name: Comment training results on PR + uses: thollander/actions-comment-pull-request@v2 + with: + filePath: results/training_results.md + - name: Comment evaluation results on PR + uses: thollander/actions-comment-pull-request@v2 + with: + filePath: results/evaluation_results.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..20404fe --- /dev/null +++ b/.gitignore @@ -0,0 +1,110 @@ +# Data +logs/ +stores/ +mlflow/ +results/ +workspaces/ + +# VSCode +.vscode/ +.idea + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Flask: +instance/ +.webassets-cache + +# Scrapy: +.scrapy + +# Sphinx +docs/_build/ + +# PyBuilder +target/ + +# IPython +.ipynb_checkpoints +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# PEP 582 +__pypackages__/ + +# Celery +celerybeat-schedule +celerybeat.pid + +# Environment +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# mkdocs +site/ + +# Airflow +airflow/airflow.db + +# MacOS +.DS_Store + +# Clean up +.trash/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..14eba51 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,23 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-merge-conflict + - id: check-yaml + - id: check-added-large-files + args: ['--maxkb=1000'] + exclude: "notebooks" + - id: check-yaml + exclude: "mkdocs.yml" +- repo: local + hooks: + - id: clean + name: clean + entry: make + args: ["clean"] + language: system + pass_filenames: false diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4190552 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Made With ML + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c739627 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +# Makefile +SHELL = /bin/bash + +# Styling +.PHONY: style +style: + black . + flake8 + python3 -m isort . + pyupgrade + +# Cleaning +.PHONY: clean +clean: style + find . -type f -name "*.DS_Store" -ls -delete + find . | grep -E "(__pycache__|\.pyc|\.pyo)" | xargs rm -rf + find . | grep -E ".pytest_cache" | xargs rm -rf + find . | grep -E ".ipynb_checkpoints" | xargs rm -rf + rm -rf .coverage* diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d89bf7 --- /dev/null +++ b/README.md @@ -0,0 +1,547 @@ +
+

 Made With ML

+Design · Develop · Deploy · Iterate +
+Join 40K+ developers in learning how to responsibly deliver value with ML. +
+
+ +
+ +
+   +   +   + +
+ 🔥  Among the top ML repositories on GitHub +
+ +
+
+ +## Lessons + +Learn how to combine machine learning with software engineering to design, develop, deploy and iterate on production-grade ML applications. + +- Lessons: https://madewithml.com/ +- Code: [GokuMohandas/Made-With-ML](https://github.com/GokuMohandas/Made-With-ML) + + + lessons + + +## Overview + +In this course, we'll go from experimentation (model design + development) to production (model deployment + iteration). We'll do this iteratively by motivating the components that will enable us to build a *reliable* production system. + +
+   Be sure to watch the video below for a quick overview of what we'll be building. +
+ +
+ Course overview video +
+ +
+ +- **💡 First principles**: before we jump straight into the code, we develop a first principles understanding for every machine learning concept. +- **💻 Best practices**: implement software engineering best practices as we develop and deploy our machine learning models. +- **📈 Scale**: easily scale ML workloads (data, train, tune, serve) in Python without having to learn completely new languages. +- **⚙️ MLOps**: connect MLOps components (tracking, testing, serving, orchestration, etc.) as we build an end-to-end machine learning system. +- **🚀 Dev to Prod**: learn how to quickly and reliably go from development to production without any changes to our code or infra management. +- **🐙 CI/CD**: learn how to create mature CI/CD workflows to continuously train and deploy better models in a modular way that integrates with any stack. + +## Audience + +Machine learning is not a separate industry, instead, it's a powerful way of thinking about data that's not reserved for any one type of person. + +- **👩‍💻 All developers**: whether software/infra engineer or data scientist, ML is increasingly becoming a key part of the products that you'll be developing. +- **👩‍🎓 College graduates**: learn the practical skills required for industry and bridge gap between the university curriculum and what industry expects. +- **👩‍💼 Product/Leadership**: who want to develop a technical foundation so that they can build amazing (and reliable) products powered by machine learning. + +## Set up + +Be sure to go through the [course](https://madewithml/#course) for a much more detailed walkthrough of the content on this repository. We will have instructions for both local laptop and Anyscale clusters for the sections below, so be sure to toggle the ► dropdown based on what you're using (Anyscale instructions will be toggled on by default). If you do want to run this course with Anyscale, where we'll provide the **structure**, **compute (GPUs)** and **community** to learn everything in one weekend, join our next upcoming live cohort → [sign up here](https://4190urw86oh.typeform.com/madewithml)! + +### Cluster + +We'll start by setting up our cluster with the environment and compute configurations. + +
+ Local
+ Your personal laptop (single machine) will act as the cluster, where one CPU will be the head node and some of the remaining CPU will be the worker nodes. All of the code in this course will work in any personal laptop though it will be slower than executing the same workloads on a larger cluster. +
+ +
+ Anyscale
+ + We can create an [Anyscale Workspace](https://docs.anyscale.com/develop/workspaces/get-started) using the [webpage UI](https://console.anyscale.com/o/madewithml/workspaces/add/blank). + + ```md + - Workspace name: `madewithml` + - Project: `madewithml` + - Cluster environment name: `madewithml-cluster-env` + # Toggle `Select from saved configurations` + - Compute config: `madewithml-cluster-compute` + ``` + + > Alternatively, we can use the [CLI](https://docs.anyscale.com/reference/anyscale-cli) to create the workspace via `anyscale workspace create ...` + +
+ +
+ Other (cloud platforms, K8s, on-prem)
+ + If you don't want to do this course locally or via Anyscale, you have the following options: + + - On [AWS and GCP](https://docs.ray.io/en/latest/cluster/vms/index.html#cloud-vm-index). Community-supported Azure and Aliyun integrations also exist. + - On [Kubernetes](https://docs.ray.io/en/latest/cluster/kubernetes/index.html#kuberay-index), via the officially supported KubeRay project. + - Deploy Ray manually [on-prem](https://docs.ray.io/en/latest/cluster/vms/user-guides/launching-clusters/on-premises.html#on-prem) or onto platforms [not listed here](https://docs.ray.io/en/latest/cluster/vms/user-guides/community/index.html#ref-cluster-setup). + +
+ +### Git setup + +Create a repository by following these instructions: [Create a new repository](https://github.com/new) → name it `Made-With-ML` → Toggle `Add a README file` (**very important** as this creates a `main` branch) → Click `Create repository` (scroll down) + +Now we're ready to clone the repository that has all of our code: + +```bash +git clone https://github.com/GokuMohandas/Made-With-ML.git . +git remote set-url origin https://github.com/GITHUB_USERNAME/Made-With-ML.git # <-- CHANGE THIS to your username +git checkout -b dev +``` + +### Virtual environment + +
+ Local
+ + ```bash + export PYTHONPATH=$PYTHONPATH:$PWD + python3 -m venv venv # recommend using Python 3.10 + source venv/bin/activate # on Windows: venv\Scripts\activate + python3 -m pip install --upgrade pip setuptools wheel + python3 -m pip install -r requirements.txt + pre-commit install + pre-commit autoupdate + ``` + + > Highly recommend using Python `3.10` and using [pyenv](https://github.com/pyenv/pyenv) (mac) or [pyenv-win](https://github.com/pyenv-win/pyenv-win) (windows). + +
+ +
+ Anyscale
+ + Our environment with the appropriate Python version and libraries is already all set for us through the cluster environment we used when setting up our Anyscale Workspace. So we just need to run these commands: + ```bash + export PYTHONPATH=$PYTHONPATH:$PWD + pre-commit install + pre-commit autoupdate + ``` + +
+ +## Notebook + +Start by exploring the [jupyter notebook](notebooks/madewithml.ipynb) to interactively walkthrough the core machine learning workloads. + +
+ +
+ +
+ Local
+ + ```bash + # Start notebook + jupyter lab notebooks/madewithml.ipynb +``` + +
+ +
+ Anyscale
+ + Click on the Jupyter icon    at the top right corner of our Anyscale Workspace page and this will open up our JupyterLab instance in a new tab. Then navigate to the `notebooks` directory and open up the `madewithml.ipynb` notebook. + +
+ + +## Scripts + +Now we'll execute the same workloads using the clean Python scripts following software engineering best practices (testing, documentation, logging, serving, versioning, etc.) The code we've implemented in our notebook will be refactored into the following scripts: + +```bash +madewithml +├── config.py +├── data.py +├── evaluate.py +├── models.py +├── predict.py +├── serve.py +├── train.py +├── tune.py +└── utils.py +``` + +**Note**: Change the `--num-workers`, `--cpu-per-worker`, and `--gpu-per-worker` input argument values below based on your system's resources. For example, if you're on a local laptop, a reasonable configuration would be `--num-workers 6 --cpu-per-worker 1 --gpu-per-worker 0`. + +### Training +```bash +export EXPERIMENT_NAME="llm" +export DATASET_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv" +export TRAIN_LOOP_CONFIG='{"dropout_p": 0.5, "lr": 1e-4, "lr_factor": 0.8, "lr_patience": 3}' +python madewithml/train.py \ + --experiment-name "$EXPERIMENT_NAME" \ + --dataset-loc "$DATASET_LOC" \ + --train-loop-config "$TRAIN_LOOP_CONFIG" \ + --num-workers 1 \ + --cpu-per-worker 3 \ + --gpu-per-worker 1 \ + --num-epochs 10 \ + --batch-size 256 \ + --results-fp results/training_results.json +``` + +### Tuning +```bash +export EXPERIMENT_NAME="llm" +export DATASET_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv" +export TRAIN_LOOP_CONFIG='{"dropout_p": 0.5, "lr": 1e-4, "lr_factor": 0.8, "lr_patience": 3}' +export INITIAL_PARAMS="[{\"train_loop_config\": $TRAIN_LOOP_CONFIG}]" +python madewithml/tune.py \ + --experiment-name "$EXPERIMENT_NAME" \ + --dataset-loc "$DATASET_LOC" \ + --initial-params "$INITIAL_PARAMS" \ + --num-runs 2 \ + --num-workers 1 \ + --cpu-per-worker 3 \ + --gpu-per-worker 1 \ + --num-epochs 10 \ + --batch-size 256 \ + --results-fp results/tuning_results.json +``` + +### Experiment tracking + +We'll use [MLflow](https://mlflow.org/) to track our experiments and store our models and the [MLflow Tracking UI](https://www.mlflow.org/docs/latest/tracking.html#tracking-ui) to view our experiments. We have been saving our experiments to a local directory but note that in an actual production setting, we would have a central location to store all of our experiments. It's easy/inexpensive to spin up your own MLflow server for all of your team members to track their experiments on or use a managed solution like [Weights & Biases](https://wandb.ai/site), [Comet](https://www.comet.ml/), etc. + +```bash +export MODEL_REGISTRY=$(python -c "from madewithml import config; print(config.MODEL_REGISTRY)") +mlflow server -h 0.0.0.0 -p 8080 --backend-store-uri $MODEL_REGISTRY +``` + +
+ Local
+ + If you're running this notebook on your local laptop then head on over to http://localhost:8080/ to view your MLflow dashboard. + +
+ +
+ Anyscale
+ + If you're on Anyscale Workspaces, then we need to first expose the port of the MLflow server. Run the following command on your Anyscale Workspace terminal to generate the public URL to your MLflow server. + + ```bash + APP_PORT=8080 + echo https://$APP_PORT-port-$ANYSCALE_SESSION_DOMAIN + ``` + +
+ +### Evaluation +```bash +export EXPERIMENT_NAME="llm" +export RUN_ID=$(python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC) +export HOLDOUT_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/holdout.csv" +python madewithml/evaluate.py \ + --run-id $RUN_ID \ + --dataset-loc $HOLDOUT_LOC \ + --results-fp results/evaluation_results.json +``` +```json +{ + "timestamp": "June 09, 2023 09:26:18 AM", + "run_id": "6149e3fec8d24f1492d4a4cabd5c06f6", + "overall": { + "precision": 0.9076136428670714, + "recall": 0.9057591623036649, + "f1": 0.9046792827719773, + "num_samples": 191.0 + }, +... +``` + +### Inference +```bash +# Get run ID +export EXPERIMENT_NAME="llm" +export RUN_ID=$(python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC) +python madewithml/predict.py predict \ + --run-id $RUN_ID \ + --title "Transfer learning with transformers" \ + --description "Using transformers for transfer learning on text classification tasks." +``` +```json +[{ + "prediction": [ + "natural-language-processing" + ], + "probabilities": { + "computer-vision": 0.0009767753, + "mlops": 0.0008223939, + "natural-language-processing": 0.99762577, + "other": 0.000575123 + } +}] +``` + +### Serving + +
+ Local
+ + ```bash + # Start + ray start --head + ``` + + ```bash + # Set up + export EXPERIMENT_NAME="llm" + export RUN_ID=$(python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC) + python madewithml/serve.py --run_id $RUN_ID + ``` + + While the application is running, we can use it via cURL, Python, etc.: + + ```bash + # via cURL + curl -X POST -H "Content-Type: application/json" -d '{ + "title": "Transfer learning with transformers", + "description": "Using transformers for transfer learning on text classification tasks." + }' http://127.0.0.1:8000/predict + ``` + + ```python + # via Python + import json + import requests + title = "Transfer learning with transformers" + description = "Using transformers for transfer learning on text classification tasks." + json_data = json.dumps({"title": title, "description": description}) + requests.post("http://127.0.0.1:8000/predict", data=json_data).json() + ``` + + ```bash + ray stop # shutdown + ``` + +```bash +export HOLDOUT_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/holdout.csv" +curl -X POST -H "Content-Type: application/json" -d '{ + "dataset_loc": "https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/holdout.csv" + }' http://127.0.0.1:8000/evaluate +``` + +
+ +
+ Anyscale
+ + In Anyscale Workspaces, Ray is already running so we don't have to manually start/shutdown like we have to do locally. + + ```bash + # Set up + export EXPERIMENT_NAME="llm" + export RUN_ID=$(python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC) + python madewithml/serve.py --run_id $RUN_ID + ``` + + While the application is running, we can use it via cURL, Python, etc.: + + ```bash + # via cURL + curl -X POST -H "Content-Type: application/json" -d '{ + "title": "Transfer learning with transformers", + "description": "Using transformers for transfer learning on text classification tasks." + }' http://127.0.0.1:8000/predict + ``` + + ```python + # via Python + import json + import requests + title = "Transfer learning with transformers" + description = "Using transformers for transfer learning on text classification tasks." + json_data = json.dumps({"title": title, "description": description}) + requests.post("http://127.0.0.1:8000/predict", data=json_data).json() + ``` + +
+ +### Testing +```bash +# Code +python3 -m pytest tests/code --verbose --disable-warnings + +# Data +export DATASET_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv" +pytest --dataset-loc=$DATASET_LOC tests/data --verbose --disable-warnings + +# Model +export EXPERIMENT_NAME="llm" +export RUN_ID=$(python madewithml/predict.py get-best-run-id --experiment-name $EXPERIMENT_NAME --metric val_loss --mode ASC) +pytest --run-id=$RUN_ID tests/model --verbose --disable-warnings + +# Coverage +python3 -m pytest --cov madewithml --cov-report html +``` + +## Production + +From this point onwards, in order to deploy our application into production, we'll need to either be on Anyscale or on a [cloud VM](https://docs.ray.io/en/latest/cluster/vms/index.html#cloud-vm-index) / [on-prem](https://docs.ray.io/en/latest/cluster/vms/user-guides/launching-clusters/on-premises.html#on-prem) cluster you manage yourself (w/ Ray). If not on Anyscale, the commands will be [slightly different](https://docs.ray.io/en/latest/cluster/running-applications/job-submission/index.html) but the concepts will be the same. + +> If you don't want to set up all of this yourself, we highly recommend joining our [upcoming live cohort](https://4190urw86oh.typeform.com/madewithml){:target="_blank"} where we'll provide an environment with all of this infrastructure already set up for you so that you just focused on the machine learning. + +
+ +
+ +### Authentication + +These credentials below are **automatically** set for us if we're using Anyscale Workspaces. We **do not** need to set these credentials explicitly on Workspaces but we do if we're running this locally or on a cluster outside of where our Anyscale Jobs and Services are configured to run. + +``` bash +export ANYSCALE_HOST=https://console.anyscale.com +export ANYSCALE_CLI_TOKEN=$YOUR_CLI_TOKEN # retrieved from Anyscale credentials page +``` + +### Cluster environment + +The cluster environment determines **where** our workloads will be executed (OS, dependencies, etc.) We've already created this [cluster environment](./deploy/cluster_env.yaml) for us but this is how we can create/update one ourselves. + +```bash +export CLUSTER_ENV_NAME="madewithml-cluster-env" +anyscale cluster-env build deploy/cluster_env.yaml --name $CLUSTER_ENV_NAME +``` + +### Compute configuration + +The compute configuration determines **what** resources our workloads will be executes on. We've already created this [compute configuration](./deploy/cluster_compute.yaml) for us but this is how we can create it ourselves. + +```bash +export CLUSTER_COMPUTE_NAME="madewithml-cluster-compute" +anyscale cluster-compute create deploy/cluster_compute.yaml --name $CLUSTER_COMPUTE_NAME +``` + +### Anyscale jobs + +Now we're ready to execute our ML workloads. We've decided to combine them all together into one [job](./deploy/jobs/workloads.yaml) but we could have also created separate jobs for each workload (train, evaluate, etc.) We'll start by editing the `$GITHUB_USERNAME` slots inside our [`workloads.yaml`](./deploy/jobs/workloads.yaml) file: +```yaml +runtime_env: + working_dir: . + upload_path: s3://madewithml/$GITHUB_USERNAME/jobs # <--- CHANGE USERNAME (case-sensitive) + env_vars: + GITHUB_USERNAME: $GITHUB_USERNAME # <--- CHANGE USERNAME (case-sensitive) +``` + +The `runtime_env` here specifies that we should upload our current `working_dir` to an S3 bucket so that all of our workers when we execute an Anyscale Job have access to the code to use. The `GITHUB_USERNAME` is used later to save results from our workloads to S3 so that we can retrieve them later (ex. for serving). + +Now we're ready to submit our job to execute our ML workloads: +```bash +anyscale job submit deploy/jobs/workloads.yaml +``` + +### Anyscale Services + +And after our ML workloads have been executed, we're ready to launch our serve our model to production. Similar to our Anyscale Jobs configs, be sure to change the `$GITHUB_USERNAME` in [`serve_model.yaml`](./deploy/services/serve_model.yaml). + +```yaml +ray_serve_config: + import_path: deploy.services.serve_model:entrypoint + runtime_env: + working_dir: . + upload_path: s3://madewithml/$GITHUB_USERNAME/services # <--- CHANGE USERNAME (case-sensitive) + env_vars: + GITHUB_USERNAME: $GITHUB_USERNAME # <--- CHANGE USERNAME (case-sensitive) +``` + +Now we're ready to launch our service: +```bash +# Rollout service +anyscale service rollout -f deploy/services/serve_model.yaml + +# Query +curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $SECRET_TOKEN" -d '{ + "title": "Transfer learning with transformers", + "description": "Using transformers for transfer learning on text classification tasks." +}' $SERVICE_ENDPOINT/predict/ + +# Rollback (to previous version of the Service) +anyscale service rollback -f $SERVICE_CONFIG --name $SERVICE_NAME + +# Terminate +anyscale service terminate --name $SERVICE_NAME +``` + +### CI/CD + +We're not going to manually deploy our application every time we make a change. Instead, we'll automate this process using GitHub Actions! + +
+ +
+ +1. We'll start by adding the necessary credentials to the [`/settings/secrets/actions`](https://github.com/GokuMohandas/Made-With-ML/settings/secrets/actions) page of our GitHub repository. + +``` bash +export ANYSCALE_HOST=https://console.anyscale.com +export ANYSCALE_CLI_TOKEN=$YOUR_CLI_TOKEN # retrieved from https://console.anyscale.com/o/madewithml/credentials +``` + +2. Now we can make changes to our code (not on `main` branch) and push them to GitHub. But in order to push our code to GitHub, we'll need to first authenticate with our credentials before pushing to our repository: + +```bash +git config --global user.name "Your Name" # <-- CHANGE THIS to your name +git config --global user.email you@example.com # <-- CHANGE THIS to your email +git add . +git commit -m "" # <-- CHANGE THIS to your message +git push origin dev +``` + +Now you will be prompted to enter your username and password (personal access token). Follow these steps to get personal access token: [New GitHub personal access token](https://github.com/settings/tokens/new) → Add a name → Toggle `repo` and `workflow` → Click `Generate token` (scroll down) → Copy the token and paste it when prompted for your password. + +3. Now we can start a PR from this branch to our `main` branch and this will trigger the [workloads workflow](/.github/workflows/workloads.yaml). If the workflow (Anyscale Jobs) succeeds, this will produce comments with the training and evaluation results directly on the PR. + +
+ +
+ +4. If we like the results, we can merge the PR into the `main` branch. This will trigger the [serve workflow](/.github/workflows/serve.yaml) which will rollout our new service to production! + +### Continual learning + +With our CI/CD workflow in place to deploy our application, we can now focus on continually improving our model. It becomes really easy to extend on this foundation to connect to scheduled runs (cron), [data pipelines](https://madewithml.com/courses/mlops/data-engineering/), drift detected through [monitoring](https://madewithml.com/courses/mlops/monitoring/), [online evaluation](https://madewithml.com/courses/mlops/evaluation/#online-evaluation), etc. And we can easily add additional context such as comparing any experiment with what's currently in production (directly in the PR even), etc. + +
+ +
+ +## FAQ + +### Jupyter notebook kernels + +Issues with configuring the notebooks with jupyter? By default, jupyter will use the kernel with our virtual environment but we can also manually add it to jupyter: +```bash +python3 -m ipykernel install --user --name=venv +``` +Now we can open up a notebook → Kernel (top menu bar) → Change Kernel → `venv`. To ever delete this kernel, we can do the following: +```bash +jupyter kernelspec list +jupyter kernelspec uninstall venv +``` diff --git a/datasets/dataset.csv b/datasets/dataset.csv new file mode 100644 index 0000000..a07a205 --- /dev/null +++ b/datasets/dataset.csv @@ -0,0 +1,813 @@ +id,created_on,title,description,tag +6,2020-02-20 06:43:18,Comparison between YOLO and RCNN on real world videos,Bringing theory to experiment is cool. We can easily train models in colab and find the results in minutes.,computer-vision +7,2020-02-20 06:47:21,"Show, Infer & Tell: Contextual Inference for Creative Captioning","The beauty of the work lies in the way it architects the fundamental idea that humans look at the overall image and then individual pieces of it. +",computer-vision +9,2020-02-24 16:24:45,Awesome Graph Classification,"A collection of important graph embedding, classification and representation learning papers with implementations.",graph-learning +15,2020-02-28 23:55:26,Awesome Monte Carlo Tree Search,A curated list of Monte Carlo tree search papers with implementations. ,reinforcement-learning +25,2020-03-07 23:04:31,AttentionWalk,"A PyTorch Implementation of ""Watch Your Step: Learning Node Embeddings via Graph Attention"" (NeurIPS 2018). ",graph-learning +27,2020-03-07 23:18:15,APPNP and PPNP,"A PyTorch implementation of ""Predict then Propagate: Graph Neural Networks meet Personalized PageRank"" (ICLR 2019). ",graph-learning +28,2020-03-07 23:23:46,Attributed Social Network Embedding,"A sparsity aware and memory efficient implementation of ""Attributed Social Network Embedding"" (TKDE 2018). ",graph-learning +29,2020-03-07 23:45:38,Signed Graph Convolutional Network,"A PyTorch implementation of ""Signed Graph Convolutional Network"" (ICDM 2018). ",graph-learning +45,2020-03-08 00:39:08,SimGNN,"A PyTorch implementation of ""SimGNN: A Neural Network Approach to Fast Graph Similarity Computation"" (WSDM 2019). ",graph-learning +61,2020-03-16 17:35:22,Using JAX to Improve Separable Image Filters,Optimizing the filters to improve the filtered images for computer vision tasks.,computer-vision +65,2020-03-19 18:42:05,Coloring Greyscale Images,Coloring black and white images with neural networks.,computer-vision +67,2020-03-19 19:04:43,Fruit Detection using Convolution Neural Networks in TensorFlow,"Trained a Convolutional Neural Network Model to predict fruits of over 100+ Classes (types) with a training accuracy of over 95%, and testing accuracy of over 9",computer-vision +73,2020-03-19 23:45:14,Face Verification,Implementation of Siamese Neural network model used for face verification. The dataset used for this task is IMDB-WIKI-face images Dataset.,computer-vision +77,2020-03-20 03:23:27,Sign Language Interpreter using Deep Learning,"A sign language interpreter using live video feed from the camera. The project was completed in 24 hours as part of HackUNT-19, the University of North Texas's ",computer-vision +78,2020-03-20 03:32:09,The Illustrated Self-Supervised Learning,A visual introduction to self-supervised learning methods in Computer Vision,computer-vision +81,2020-03-20 06:07:56,GradCAM for the BreaKHis Dataset,An NBDev package for fine-tuning ResNets to visualize gradient-weighted class activation for the BreaKHis dataset.,computer-vision +85,2020-03-20 17:35:59,Message Passing GNNs C++,C++ implementation using Eigen for the forward pass of Graph Convolutional Neural Networks.,graph-learning +89,2020-03-20 18:17:31,Rethinking Batch Normalization in Transformers,"We found that NLP batch statistics exhibit large variance throughout training, which leads to poor BN performance.",natural-language-processing +91,2020-03-20 18:30:04,Pytest Board,Continuous pytest runner with awesome visualization.,mlops +92,2020-03-20 18:43:50,Image Spam Buster - Kreate Hackathon,"""Spam Buster"" for user generated IMAGE content.",computer-vision +98,2020-03-20 19:16:43,Bachelorette Predictor,Predict the Bachelorette winners from profile images.,computer-vision +99,2020-03-20 21:32:14,Gender Change of People's Face using CycleGAN,CycleGAN architecture in Keras and train the model with CelebA faces dataset to perform gender change on people's faces.,computer-vision +101,2020-03-21 04:19:04,ELECTRA: Pre-training Text Encoders as Discriminators,PyTorch implementation of the electra model from the paper: ELECTRA - Pre-training Text Encoders as Discriminators Rather Than Generators,natural-language-processing +108,2020-03-21 23:17:38,Tuned ALBERT (ensemble model),Top 6 in Squad 2.0,natural-language-processing +109,2020-03-21 23:25:33,iyasai: Book Recommendation System,Recommender system for books and stories that could help you and your loved ones lift up your mood whenever you are facing stress or unpleasant situations.,natural-language-processing +112,2020-03-21 23:58:46,Learning to See before Learning to Act: Visual Pre-training,We find that pre-training on vision tasks significantly improves generalization and sample efficiency for learning to manipulate objects.,computer-vision +115,2020-03-22 01:26:14,SOLT: Data Augmentation for Deep Learning,"Data augmentation library for Deep Learning, which supports images, segmentation masks, labels and key points.",computer-vision +116,2020-03-22 01:37:27,PCDet: 3D Point Cloud Detection,PCDet Toolbox in PyTorch for 3D Object Detection from Point Cloud,computer-vision +117,2020-03-22 01:47:09,SiamFC++: Towards Robust and Accurate Visual Tracking,"Implementation of a series of basic algorithms which is useful for video understanding, including Single Object Tracking (SOT), Video Object Segmentation (VOS).",computer-vision +118,2020-03-22 21:46:52,Sinext,Sign language to text with OpenCV and MNIST sign-language dataset,computer-vision +120,2020-03-24 04:38:08,Gliding Vertex on Horizontal Bounding Box for Object Detection,Gliding vertex on the horizontal bounding box for multi-oriented object detection.,computer-vision +121,2020-03-24 04:56:38,Deep Reinforcement Learning in TensorFlow2,deep-rl-tf2 is a repository that implements a variety of polular Deep-RL algorithms using TF2. The key to this repo is an easy to understand code. ,reinforcement-learning +122,2020-03-24 17:51:35,Custom Classifier on Top of Bert-like Language Model,Take pre-trained language model and build custom classifier on top of it.,natural-language-processing +123,2020-03-24 18:20:55,Using Different Decoding Methods for LM with Transformers,A look at different decoding methods for generate subsequent tokens in language modeling.,natural-language-processing +124,2020-03-24 21:12:12,Unsupervised Toolbox,"Unsupervised learning Tool box : A micro framework for State of the Art Methods and models for unsupervised learning for NLU / NLG +",natural-language-processing +128,2020-03-25 15:21:34,Multimodal Brain Tumor Segmentation,Segmentation of gliomas in pre-operative MRI scans. Use the provided clinically-acquired training data to produce segmentation labels.,computer-vision +133,2020-03-25 20:21:26,A Survey of Long-Term Context in Transformers,Over the past two years the NLP community has developed a veritable zoo of methods to combat expensive multi-head self-attention.,natural-language-processing +137,2020-03-27 14:39:53,Debugging Neural Networks with PyTorch and W&B,A closer look at debugging common issues when training neural networks.,mlops +138,2020-03-27 14:50:02,BachGAN: High-Res Image Synthesis from Salient Object Layout,We propose a new task towards more practical application for image generation - high-quality image synthesis from salient object layout. ,computer-vision +140,2020-03-28 07:49:03,Visual Paper Summary: ALBERT(A Lite BERT),An illustrated summary of ALBERT paper and how it improves BERT and makes it resource efficient,natural-language-processing +145,2020-03-30 04:14:44,Controllable Person Image Synthesis with Attribute-Decomposed GAN,"A novel generative model for controllable person image synthesis, which can produce realistic person images with desired human attributes.",computer-vision +147,2020-03-30 05:39:57,Back Translation for Text Augmentation with Google Sheets,Learn how to augment existing labeled text data for free using Google Sheets.,natural-language-processing +148,2020-03-30 14:13:46,An Illustrated Guide to Graph Neural Networks,A breakdown of the inner workings of GNNs.,graph-learning +150,2020-04-01 08:26:46,The Illustrated FixMatch for Semi-Supervised Learning,Learn how to leverage unlabeled data using FixMatch for semi-supervised learning,computer-vision +152,2020-04-01 15:38:58,A Two-Step Graph Convolutional Decoder for Molecule Generation,A simple auto-encoder framework for molecule generation.,graph-learning +157,2020-04-03 01:56:32,TransMoMo: Invariance-Driven Unsupervised Motion Retargeting,A lightweight video motion retargeting approach that is capable of transferring motion of a person in a source video realistically to another video of a target ,computer-vision +158,2020-04-03 04:41:07,Tracking Objects as Points,Simultaneous object detection and tracking using center points.,computer-vision +159,2020-04-03 14:57:11,Drifter-ML,A machine learning testing framework for sklearn and pandas. The goal is to help folks assess whether things have changed over time.,mlops +162,2020-04-03 20:17:50,Natural Language Processing News,Get the highlights from Natural Language Processing & Machine Learning research & industry straight to your inbox every month.,natural-language-processing +163,2020-04-03 20:21:13,NLP Newsletter,"Democratizing Artificial Intelligence Research, Education, and Technologies.",natural-language-processing +168,2020-04-04 17:54:28,Self-Supervised Scene De-occlusion,"We investigate the problem of scene de-occlusion, which aims to recover the underlying occlusion ordering and complete the invisible parts of occluded objects.",computer-vision +173,2020-04-05 03:00:05,Design Patterns for Production NLP Systems,Designs and tips for designing NLP production systems.,natural-language-processing +181,2020-04-05 14:56:34,Talking-Heads Attention,"A variation on multi-head attention which includes linear projections across the attention-heads dimension, immediately before and after the softmax operation.",natural-language-processing +183,2020-04-05 17:50:10,What does a CNN see?,First super clean notebook showcasing @TensorFlow 2.0. An example of end-to-end DL with interpretability.,computer-vision +219,2020-04-06 14:10:22,Natural Language Processing: Pretraining - d2l,"An interactive deep learning book with code, math, and discussions, based on the NumPy interface.",natural-language-processing +224,2020-04-06 16:48:44,Understanding Convolutional Neural Networks for NLP,More recently we’ve also started to apply CNNs to problems in Natural Language Processing and gotten some interesting results.,natural-language-processing +234,2020-04-06 17:42:52,An Overview of Semantic Image Segmentation,Image segmentation is a computer vision task in which we label specific regions of an image according to what's being shown.,computer-vision +237,2020-04-06 18:02:48,Common Architectures in Convolutional Neural Networks,"In this post, I'll discuss commonly used architectures for convolutional networks. ",computer-vision +238,2020-04-06 18:37:33,Googletrans,Googletrans: Free and Unlimited Google translate API for Python. Translates totally free of charge.,natural-language-processing +239,2020-04-06 18:39:48,Prophet: Forecasting At Scale,Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth.,time-series +250,2020-04-06 19:24:06,Doccano,Open source text annotation tool for machine learning practitioner. ,natural-language-processing +251,2020-04-06 19:28:58,BRAT: Rapid Annotation Tool,BRAT (brat rapid annotation tool) is based on the stav visualiser which was originally made in order to visualise BioNLP'11 Shared Task data.,natural-language-processing +252,2020-04-06 20:23:46,Word Embeddings,This tutorial introduces word embeddings. It contains complete code to train word embeddings from scratch on a small dataset.,natural-language-processing +253,2020-04-06 20:26:27,On Word Embeddings,This post presents the most well-known models for learning word embeddings based on language modeling.,natural-language-processing +254,2020-04-06 20:28:43,NLP for Developers: Word Embeddings | Rasa,"In this video, Rasa Developer Advocate Rachael will talk about what word embeddings are, how they work, when they're used and some common errors. ",natural-language-processing +255,2020-04-06 20:30:27,NLP for Developers: Transformers | Rasa,"In this video, Rasa Developer Advocate Rachael will talk about what transformers are, how they work, when they're used and some common errors. ",natural-language-processing +256,2020-04-06 20:42:05,A Visual Guide to Using BERT for the First Time,Tutorial for how to use a variant of BERT to classify sentences.,natural-language-processing +257,2020-04-06 20:45:45,The Illustrated GPT-2 (Visualizing Transformer Language Models),Visuals explaining the inner-workings of transformers.,natural-language-processing +259,2020-04-06 20:51:58,The Illustrated Word2vec,"In this post, we’ll go over the concept of embedding, and the mechanics of generating embeddings with word2vec. ",natural-language-processing +260,2020-04-06 20:55:32,"The Illustrated BERT, ELMo, and co.",How NLP cracked transfer learning.,natural-language-processing +261,2020-04-06 21:00:34,The Illustrated Transformer,"In this post, we will look at The Transformer – a model that uses attention to boost the speed with which these models can be trained.",natural-language-processing +262,2020-04-06 21:11:40,Visualizing A Neural Machine Translation Model,Mechanics of seq2seq models with attention.,natural-language-processing +269,2020-04-06 22:46:54,Attention Mechanism,"Main concepts behind Attention, including an implementation of a sequence-to-sequence Attention model, followed by the application of Attention in Transformers.",natural-language-processing +270,2020-04-06 22:50:30,Attention? Attention!,"In this post, we are gonna look into how attention was invented, and various attention mechanisms and models, such as transformer and SNAIL.",natural-language-processing +271,2020-04-06 22:58:47,The Annotated Transformer,In this post I present an “annotated” version of the paper in the form of a line-by-line implementation. ,natural-language-processing +272,2020-04-06 23:38:26,The Annotated GPT-2,GPT-2 explained with visualization and PyTorch code.,natural-language-processing +273,2020-04-06 23:41:52,Transformers - Hugging Face,🤗 Transformers: State-of-the-art Natural Language Processing for TensorFlow 2.0 and PyTorch. ,natural-language-processing +277,2020-04-07 00:30:33,Curriculum for Reinforcement Learning,"Curriculum learning applied to reinforcement learning, with a few exceptions of supervised learning.",reinforcement-learning +278,2020-04-07 00:34:46,Self-Supervised Representation Learning,What if we can get labels for free for unlabelled data and train unsupervised dataset in a supervised manner? ,computer-vision +279,2020-04-07 00:36:55,Evolution Strategies,Evolutionary algorithms refer to a division of population-based optimization algorithms inspired by natural selection. ,reinforcement-learning +280,2020-04-07 00:38:25,Meta Reinforcement Learning,Explore cases when we try to “meta-learn” Reinforcement Learning (RL) tasks by developing an agent that can solve unseen tasks fast and efficiently.,reinforcement-learning +281,2020-04-07 00:40:59,Generalized Language Models,Trend in large unsupervised pre-trained language models which have achieved amazing SOTA results on a variety of language tasks.,natural-language-processing +284,2020-04-07 00:57:12,Policy Gradient Algorithms,"In this post, we are going to look deep into policy gradient, why it works, and many new policy gradient algorithms proposed in recent years.",reinforcement-learning +286,2020-04-07 03:49:15,Object Detection for Dummies,"We will go through several basic concepts, algorithms, and popular deep learning models for image processing and object detection.",computer-vision +287,2020-04-07 03:59:53,Learning Word Embedding,This post introduces several models for learning word embedding and how their loss functions are designed for the purpose.,natural-language-processing +290,2020-04-07 13:38:36,GANSpace: Discovering Interpretable GAN Controls,This paper describes a simple technique to analyze Generative Adversarial Networks (GANs) and create interpretable controls for image synthesis.,computer-vision +291,2020-04-07 14:07:59,Kornia: Differentiable Computer Vision Library for PyTorch,Set of routines and differentiable modules to solve generic computer vision problems. ,computer-vision +294,2020-04-07 15:36:13,PyTorch Geometric ,Geometric deep learning extension library for PyTorch.,graph-learning +295,2020-04-07 15:40:00,DGL: Deep Graph Library,"Python package built to ease deep learning on graph, on top of existing DL frameworks. ",graph-learning +306,2020-04-07 20:07:28,BERT Research - Key Concepts & Sources,Video series on BERT's key concepts and sources.,natural-language-processing +307,2020-04-07 20:11:29,GLUE Explained: Understanding BERT Through Benchmarks,In this post we take a look at an important NLP benchmark used to evaluate BERT and other transfer learning models!,natural-language-processing +308,2020-04-07 23:22:18,TinyBERT,TinyBERT is 7.5x smaller and 9.4x faster on inference than BERT-base and achieves competitive performances in the tasks of natural language understanding.,natural-language-processing +313,2020-04-08 00:02:27,NVIDIA Neural Modules: NeMo,A toolkit for conversational AI.,natural-language-processing +315,2020-04-08 00:10:21,VoTT: Visual Object Tagging Tool,An electron app for building end to end Object Detection Models from Images and Videos.,computer-vision +316,2020-04-08 00:12:26,Clinical BERT,Repository for Publicly Available Clinical BERT Embeddings,natural-language-processing +318,2020-04-08 00:16:55,Computer Vision Annotation Tool (CVAT),"Free, online, interactive video and image annotation tool for computer vision.",computer-vision +319,2020-04-08 00:19:04,LabelImg,🖍️ A graphical image annotation tool and label object bounding boxes in images.,computer-vision +327,2020-04-08 14:16:28,How to Steal Modern NLP Systems with Gibberish?,"It’s possible to steal BERT-based models without any real training data, even using gibberish word sequences.",natural-language-processing +334,2020-04-08 15:04:28,BioWordVec & BioSentVec,Pre-trained embeddings for biomedical words and sentences,natural-language-processing +335,2020-04-08 15:07:44,BioBERT: a pre-trained biomedical language representation model ,"Code for fine-tuning BioBERT for biomedical text mining tasks such as biomedical NER, relation extraction, QA, etc.",natural-language-processing +341,2020-04-08 15:42:56,How to Unit Test Machine Learning Code,Wouldn’t suck to have to throw away perfectly good ideas because our implementations were buggy?,mlops +343,2020-04-08 15:52:19,Machine Learning Systems Design,Designing a machine learning system.,mlops +345,2020-04-08 16:14:23,HMTL: Hierarchical Multi-Task Learning,🌊 A State-of-the-Art neural network model for several NLP tasks based on PyTorch and AllenNLP,natural-language-processing +347,2020-04-08 16:26:05,The State of Transfer Learning in NLP,This post expands on the NAACL 2019 tutorial on Transfer Learning in NLP. It highlights key insights and takeaways and provides updates based on recent work.,natural-language-processing +349,2020-04-08 16:35:52,The Dark Secrets of BERT,How much of the linguistically interpretable self-attention patterns that are presumed to be its strength are actually used to solve downstream tasks?,natural-language-processing +364,2020-04-08 17:53:15,Named Entity Recognition Tagging,"In this post, we go through an example from Natural Language Processing, in which we learn how to load text data and perform NER tagging for each token.",natural-language-processing +372,2020-04-08 18:22:46,An introduction to Q-Learning: Reinforcement Learning,Q-Learning algorithm along with an implementation in Python using Numpy.,reinforcement-learning +378,2020-04-08 19:37:57,Ray,Ray is a fast and simple framework for building and running distributed applications.,reinforcement-learning +380,2020-04-08 21:05:06,Graph Nets,"PyTorch Implementation and Explanation of Graph Representation Learning papers involving DeepWalk, GCN, GraphSAGE, ChebNet & GAT.",graph-learning +388,2020-04-08 21:36:39,ConvNet Playground,An interactive visualization for exploring Convolutional Neural Networks applied to the task of semantic image search.,computer-vision +392,2020-04-08 21:53:06,Embedding Projector,"Visualization of high dimensional data, namely embeddings.",natural-language-processing +395,2020-04-08 22:12:24,Word2Viz: Explore Word Analogies,Interactive visualization of word analogies in GloVe.,natural-language-processing +397,2020-04-08 22:17:06,Image-to-Image Translation with Conditional Adversarial Networks,Tensorflow port of Image-to-Image Translation with Conditional Adversarial Nets,computer-vision +401,2020-04-08 22:29:09,"Quick, Draw",Can a neural network learn to recognize doodling?,computer-vision +403,2020-04-08 22:44:04,A 2019 Guide to Speech Synthesis with Deep Learning,A look at recent deep learning based speech synthesis research and techniques.,natural-language-processing +408,2020-04-08 23:03:13,FlashTorch,Visualization toolkit for neural networks in PyTorch,computer-vision +411,2020-04-08 23:11:09,W&B: Weights and Biases,Track model training at scale.,mlops +419,2020-04-09 00:41:03,Text Feature Selection for Causal Inference,"Identifying the linguistic features that cause people to act a certain way after reading a text, regardless of confounding variables, is something people do.",natural-language-processing +423,2020-04-09 00:57:49,3D Ken Burns Effect from a Single Image,Implementation of 3D Ken Burns Effect from a Single Image using PyTorch.,computer-vision +424,2020-04-09 01:02:59,Sparse Sinkhorn Attention,A new efficient and sparse method for learning to attend based on differentiable sorting of internal representations.,natural-language-processing +425,2020-04-09 01:41:48,Backtester,A backtesting framework for timeseries data.,time-series +427,2020-04-09 18:57:01,An Overview of Early Vision in InceptionV1,"A guided tour of the first five layers of InceptionV1, +taxonomized into “neuron groups.”",computer-vision +428,2020-04-10 04:57:53,AiLight: Automatic Highlighting Using BERT,"Automatically highlight pdfs using BERT embeddings and clustering. +https://anishthite.github.io/ailight",natural-language-processing +430,2020-04-10 15:28:43,Controlling Text Generation with Plug and Play Language Models,"This article discusses an alternative approach to controlled text generation, titled the Plug and Play Language Model (PPLM).",natural-language-processing +431,2020-04-10 15:35:00,Genomic ULMFiT,ULMFiT for Genomic Sequence Data,natural-language-processing +432,2020-04-10 15:39:29,Self-Supervised Learning and Computer Vision,"So, what do you do if there are no pre-trained models in your domain? ",computer-vision +434,2020-04-10 15:51:52,scispaCy,A full spaCy pipeline and models for scientific/biomedical documents.,natural-language-processing +439,2020-04-10 17:33:38,Universal Adversarial Triggers for Attacking and Analyzing NLP,We create short phrases that cause a specific model prediction when concatenated to 𝘢𝘯𝘺 input from a dataset. ,natural-language-processing +440,2020-04-10 17:39:19,lazynlp,Library to scrape and clean web pages to create massive datasets.,natural-language-processing +443,2020-04-10 17:51:39,AllenNLP Interpret,A Framework for Explaining Predictions of NLP Models,natural-language-processing +445,2020-04-10 18:00:50,Natural Language Processing With spaCy in Python,A comprehensive guide to NLP with spaCy.,natural-language-processing +446,2020-04-10 18:45:15,Tips for Successfully Training Transformers on Small Datasets,It turns out that you can easily train transformers on small datasets when you use tricks (and have the patience to train a very long time).,natural-language-processing +448,2020-04-10 19:14:59,🦄 How to build a SOTA Conversational AI with Transfer Learning,Train a dialog agent leveraging transfer Learning from an OpenAI GPT and GPT-2 Transformer language model.,natural-language-processing +452,2020-04-10 20:18:20,CS224n: Natural Language Processing with Deep Learning,"In this course, students will gain a thorough introduction to cutting-edge research in Deep Learning for NLP.",natural-language-processing +453,2020-04-10 20:23:21,CS231n: Convolutional Neural Networks for Visual Recognition,"Deep dive into details of the deep learning architectures with a focus on learning end-to-end models for these tasks, particularly image classification.",computer-vision +455,2020-04-10 20:31:09,Illustrated: Self-Attention,Step-by-step guide to self-attention with illustrations and code.,natural-language-processing +459,2020-04-10 21:05:32,Beyond the Pixel Plane: Sensing and Learning in 3d,Recent deep learning techniques that enable 3D object classification and semantic segmentation.,computer-vision +462,2020-04-11 16:52:35,A Visual Guide to Self-Labelling Images,A self-supervised method to generate labels via simultaneous clustering and representation learning,computer-vision +465,2020-04-13 02:18:51,3D Photography using Context-aware Layered Depth Inpainting,A multi-layer representation for novel view synthesis that contains hallucinated color and depth structures in regions occluded in the original view. ,computer-vision +466,2020-04-13 18:48:40,Tokenizers: How Machines Read,A survey of different tokenization strategies in NLP.,natural-language-processing +467,2020-04-13 19:43:35,Practical Text Classification With Python and Keras,You will get a grasp of current advancements of (deep) neural networks and how they can be applied to text.,natural-language-processing +468,2020-04-13 19:45:46,Text Classification With Torchtext,This example shows how to train a supervised learning algorithm for classification using one of these TextClassification datasets.,natural-language-processing +469,2020-04-13 21:17:44,Understanding Text With Bert,Building a machine reading comprehension system using the latest advances in deep learning for NLP.,natural-language-processing +470,2020-04-13 21:38:20,Transfer Learning with T5: the Text-To-Text Transfer Transformer,"In the paper, we demonstrate how to achieve state-of-the-art results on multiple NLP tasks using a text-to-text transformer pre-trained on a large text corpus.",natural-language-processing +471,2020-04-13 21:48:48,Building a COVID-19 Project Recommendation System,"How to create a GitHub open source repo recommendation system web app with MLflow, Sagemaker, and Booklet.ai.",natural-language-processing +473,2020-04-13 22:33:21,Neural Machine Translation With Attention,This notebook trains a sequence to sequence (seq2seq) model for Spanish to English translation. ,natural-language-processing +474,2020-04-13 22:48:49,PyTorch Tutorial for Deep Learning Researchers,This repository provides tutorial code for deep learning researchers to learn PyTorch. ,computer-vision +476,2020-04-14 00:40:10,Show and Tell: A Neural Image Caption Generator,A TensorFlow implementation of the image-to-text model.,computer-vision +477,2020-04-14 01:46:32,SimpleGAN,A Tensorflow-based framework to ease the training of generative models,computer-vision +478,2020-04-14 02:41:43,Semantic Segmentation on MIT ADE20K dataset in PyTorch,Pytorch implementation for Semantic Segmentation/Scene Parsing on MIT ADE20K dataset.,computer-vision +480,2020-04-14 03:46:09,ViLBERT-MT: Multi-Task Vision & Language Representation Learning,A single ViLBERT Multi-Task model can perform 8 different vision and language tasks learnt from 12 datasets!,computer-vision +481,2020-04-14 03:50:18,Training an Image Classifier in PyTorch,"Torchvision, that has data loaders for common datasets such as Imagenet, CIFAR10, MNIST, etc. and data transformers for images, vizualization and data loaders.",computer-vision +482,2020-04-14 17:28:37,A Visual Exploration of DeepCluster,DeepCluster is a self-supervised method to combine clustering and representation learning,computer-vision +486,2020-04-14 20:12:43,A 2019 guide to Human Pose Estimation with Deep Learning,The basics of Human Pose Estimation (2D) and review the literature on this topic.,computer-vision +489,2020-04-14 22:22:40,"Deep Learning Based Super Resolution, Without Using a GAN","Techniques and training a deep learning model for image improvement, image restoration, inpainting and super resolution.",computer-vision +490,2020-04-14 22:35:21,U-Net Deep Learning Colorization of Greyscale Images,This article describes experiments training a neural network to generate 3 channel colour images from single channel greyscale images using deep learning.,computer-vision +491,2020-04-14 22:38:54,Deep Learning for Image Super-resolution: A Survey,This article aims to provide a comprehensive survey on recent advances of image super-resolution using deep learning approaches.,computer-vision +492,2020-04-14 22:41:52,Second-order Attention Network for Single Image Super-resolution,We propose a second-order attention network (SAN) for more powerful feature expression and feature correlation learning.,computer-vision +493,2020-04-14 22:52:49,DeepSORT: Deep Learning to Track Custom Objects in a Video,A look at deep learning based approached for object tracking.,computer-vision +494,2020-04-14 22:59:56,Fast Online Object Tracking and Segmentation: A Unifying Approach,We illustrate how to perform both realtime object tracking and semi-supervised video object segmentation using a fully-convolutional Siamese approach.,computer-vision +495,2020-04-14 23:10:48,Neural Style Transfer,This tutorial uses deep learning to compose one image in the style of another image (ever wish you could paint like Picasso or Van Gogh?).,computer-vision +499,2020-04-14 23:34:32,Deep Learning for Videos: A 2018 Guide to Action Recognition,"In this post, I summarize the literature on action recognition from videos. ",computer-vision +501,2020-04-15 15:20:56,Shakespeare Meets Google's Flax,Application of RNNs in Flax: Character-Level Language Model.,natural-language-processing +505,2020-04-15 15:59:30,"Anomaly detection with Keras, TensorFlow, and Deep Learning",Perform anomaly detection in your own image datasets using deep learning.,computer-vision +507,2020-04-15 16:12:41,Almost Everything You Need to Know About Time Series,"Understand moving average, exponential smoothing, stationarity, autocorrelation, SARIMA, and more.",time-series +508,2020-04-15 16:29:08,STEFANN: Scene Text Editor using Font Adaptive Neural Network,A generalized method for realistic modification of textual content present in a scene image. ⭐️ Accepted in CVPR 2020.,computer-vision +509,2020-04-15 16:34:04,Time Series Prediction with LSTM Using PyTorch,Time series applied to forecasting on the Airplane Passengers Dataset.,time-series +513,2020-04-15 17:05:36,lda2vec: Tools for interpreting natural language,The lda2vec model tries to mix the best parts of word2vec and LDA into a single framework.,natural-language-processing +516,2020-04-15 17:21:53,Deep Learning for Object Detection: A Comprehensive Review,"A closer look at Tensorflow’s object detection models: Faster R-CNN, R-FCN, and SSD.",computer-vision +517,2020-04-15 17:31:22,An Intuitive Guide to Deep Network Architectures,"Intuition behind base network architectures like MobileNets, Inception, and ResNet.",computer-vision +529,2020-04-15 19:39:24,Real-Time Voice Cloning,Clone a voice in 5 seconds to generate arbitrary speech in real-time. Code for Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech.,natural-language-processing +549,2020-04-16 03:48:35,15 Best Tools for Tracking Machine Learning Experiments,A feature comparison of all the open-source and commercial options for experiment tracking.,mlops +550,2020-04-16 08:14:50,Cycle GAN in TensorFlow 2.0 with Custom Loops,"Implementation of ""Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks"" by Jun-Yan Zhu et al. ",computer-vision +552,2020-04-16 10:13:12,Holopix50k: A Large-Scale In-the-wild Stereo Image Dataset,The largest dataset of in-the-wild stereo image pairs (50K) crowd-sourced from the Holopix lightfield image-sharing social network.,computer-vision +558,2020-04-16 15:49:29,PyTorch Notebooks,🔥A collection of PyTorch notebooks for learning and practicing deep learning,natural-language-processing +564,2020-04-17 13:16:09,Optimize your ML models,Learn to use optimize your custom image classification models (built-in tf.keras) using TensorFlow Lite and gain 10x reduction in model's size. ,computer-vision +566,2020-04-17 21:57:35,Machine learning deserves its own flavor of Continuous Delivery,"When traveling in the data science world, I'm homesick for a smooth continuous delivery flow. My thoughts on approachable CD4ML.",mlops +574,2020-04-20 00:23:44,The Abstraction and Reasoning Corpus (ARC),"Can a computer learn complex, abstract tasks from just a few examples? ARC can be used to measure a human-like form of general fluid intelligence.",natural-language-processing +580,2020-04-20 00:57:03,GitHub Actions & Machine Learning Workflows with Hamel Husain," In this talk, Hamel will provide a brief tutorial on GitHub Actions, and will show you how you can use this new tool to automate your ML workflows.",mlops +581,2020-04-20 01:01:38,How To Create Semantic Search For Arbitrary Objects,An end-to-end example of how to build a system that can search objects semantically. By Hamel Husain & Ho-Hsiang Wu,natural-language-processing +598,2020-04-22 16:33:59,The Future of (Transfer Learning in) Natural Language Processing,"Transfer Learning in Natural Language Processing (NLP): Open questions, current trends, limits, and future directions.",natural-language-processing +599,2020-04-22 16:43:13,MONAI,AI Toolkit for Healthcare Imaging.,computer-vision +601,2020-04-22 17:41:06,How I Used Deep Learning To Train A Chatbot To Talk Like Me,Facebook chatbot that I trained to talk like me using Seq2Seq.,natural-language-processing +602,2020-04-23 00:36:02,DialoGPT: Toward Human-Quality Conversational Response Generation,Large-scale pre-training for dialogue.,natural-language-processing +605,2020-04-23 03:59:57,Upside Down Reinforcement Learning,Implementation of UDRL as outlined by Juergen Schmidhuber in https://arxiv.org/abs/1912.02875,reinforcement-learning +608,2020-04-23 12:52:02,PyImageSearch,An online platform of blogs on Computer Vision and Deep Learning.,computer-vision +619,2020-04-23 16:55:27,Implementing Portrait Bokeh Mode using OpenCV and NumPy (Python),"Do you love the portrait mode in your smartphone? This code will help you do the same using OpenCV and NumPy! Detects the faces, asks if you want to blur them!",computer-vision +621,2020-04-23 18:17:12,MixNMatch,Multifactor Disentanglement and Encoding for Conditional Image Generation,computer-vision +622,2020-04-23 21:40:09,MT-Clinical BERT,Scaling Clinical Information Extraction with Multitask Learning,natural-language-processing +623,2020-04-24 00:30:02,medaCy,🏥 Medical Text Mining and Information Extraction with spaCy,natural-language-processing +632,2020-04-24 11:37:13,Lagrangian Neural Networks,"Trying to learn a simulation? Try Lagrangian Neural Networks, which explicitly conserve energy and may generalize better!",graph-learning +639,2020-04-24 20:51:18,ML Foundations and Methods for Precision Medicine and Healthcare,"This tutorial will discuss ideas from machine learning that enable personalization (useful for applications in education, retail, medicine and recsys).",reinforcement-learning +643,2020-04-26 04:34:02,Albert-base for Sanskrit,Trained Albert-base from scratch on Sanskrit corpus of Wikipedia. I have also added a link to how to train your own Language model from scratch.,natural-language-processing +644,2020-04-26 05:42:37,Adversarial Latent Autoencoders,"Introducing the Adversarial Latent Autoencoder (ALAE), a general architecture that can leverage recent improvements on GAN training procedures.",computer-vision +652,2020-04-28 15:14:00,Optimal Transport and the Sinkhorn Transformer,Understand optimal transport and the Sinkhorn-Knopp algorithm before diving into the Sinkhorn Transformer.,natural-language-processing +653,2020-04-28 16:20:29,Semantic Graphs for Generating Deep Questions,"Deep Question Generation (DQG), which aims to generate complex questions that require reasoning over multiple pieces of information of the input passage. ",natural-language-processing +658,2020-04-28 21:34:00,Gutenberg Dialog,Build a dialog dataset from online books in many languages.,natural-language-processing +661,2020-04-29 02:41:24,Better NLP project,This is a wrapper program/library that encapsulates a couple of NLP libraries that are popular among the AI and ML communities.,natural-language-processing +663,2020-04-29 04:42:16,Recipes for building an open-domain chatbot,"Python framework for sharing, training and testing dialogue models, from open-domain chitchat to VQA (Visual Question Answering).",natural-language-processing +665,2020-04-29 10:46:20,Object-detection with multi-template matching,"This python package allows to perform object detection using one or a few template images, it provides a simpler alternative to deep-learning methods",computer-vision +667,2020-04-29 18:34:28,No Trump Social Chrome Plugin,An AI-driven Browser Extension to Replace Trump Pics with Puppies!,computer-vision +670,2020-04-29 19:35:22,Attribute2Font: Creating Fonts You Want From Attributes,Official PyTorch implementation of the Attribute2Font: Creating Fonts You Want From Attributes.,natural-language-processing +674,2020-04-30 17:52:55,YOLOv4: Optimal Speed and Accuracy of Object Detection,A minimal implementation of YOLOv4.,computer-vision +679,2020-05-01 16:17:32,Geometric and Relational Deep Learning,Videos from emerging fields of Graph Representation Learning and Geometric Deep Learning.,graph-learning +683,2020-05-01 16:35:06,TAPAS: Weakly Supervised Table Parsing via Pre-training,Using neural networks to find answers in tables.,natural-language-processing +686,2020-05-01 16:59:48,Jukebox: A Generative Model for Music,"We’re introducing Jukebox, a neural net that generates music, including rudimentary singing, as raw audio in a variety of genres and artist styles. ",natural-language-processing +687,2020-05-01 17:17:48,Exploratory Data Analysis of Time Series,"Exploratory Data Analysis of Time Series data in Python. It uses lot of the principles and concepts discussed in Prof. Hyndman's book. The focus is on understa +",time-series +688,2020-05-01 17:47:40,Gotchas of Transfer Learning for Image Classification,Discover the things you should care about while doing transfer learning for image classification. ,computer-vision +693,2020-05-02 05:05:44,SciTLDR: Extreme Summarization of Scientific Documents,A new automatic summarization task with high source compression requiring expert background knowledge and complex language understanding.,natural-language-processing +694,2020-05-02 15:29:06,BLINK: Better entity LINKing,Entity Linking python library that uses Wikipedia as the target knowledge base.,natural-language-processing +695,2020-05-02 21:33:31,Five Cool Python Libraries for Data Science,Python is a best friend for the majority of the Data Scientists. Libraries make their life simpler. I have come across five cool Python libraries while working ,natural-language-processing +700,2020-05-03 13:49:29,Fastai2 Vision Module,A detailed guide to using fastai2 Datablock API for common computer vision tasks,computer-vision +702,2020-05-03 20:19:10,Unsupervised Question Decomposition for Question Answering,"Decompose hard (multi-hop) questions into several, easier (single-hop) questions using unsupervised learning, and get better accuracy on multi-hop QA.",natural-language-processing +704,2020-05-04 11:58:27,Training Batch Norm and Only Batch Norm,Experiments with the ideas presented in https://arxiv.org/abs/2003.00152 by Frankle et al. ,computer-vision +707,2020-05-05 03:36:50,The Big Bad NLP Database,A collection of 400+ NLP datasets with papers included.,natural-language-processing +708,2020-05-05 03:51:53,POINTER: Constrained Text Generation,Constrained Text Generation via Insertion-based Generative Pre-training,natural-language-processing +712,2020-05-05 05:55:46,Covid-19: A-Geo-Statistical-Analysis,Analysis with the time series data available for various countries.,time-series +713,2020-05-05 07:13:49,Cognito : Data wrangling toolkit,Cognito is an exclusive python data preprocessing library and command-line utility that helps any developer to transform raw data into a machine-learning format,time-series +717,2020-05-05 14:46:57,Synthesizer: Rethinking Self-Attention in Transformer Models,The dot product self-attention is known to be central and indispensable to state-of-the-art Transformer models. But is it really required?,natural-language-processing +726,2020-05-06 01:10:55,ConvNets-TensorFlow2,Implementing a variety of popular and important CNN architectures,computer-vision +732,2020-05-06 04:20:43,StellarGraph - Machine Learning on Graphs,"State-of-the-art algorithms for graph machine learning, making it easy to discover patterns and answer questions about graph-structured data.",graph-learning +733,2020-05-06 04:30:47,LandCover.ai,"Dataset for automatic mapping of buildings, woodlands and water from aerial imagery.",computer-vision +734,2020-05-06 04:33:15,Generating SOAP Notes from Doctor-Patient Conversations,Evaluate complete pipelines for leveraging these transcripts to train machine learning model to generate these notes.,natural-language-processing +741,2020-05-07 01:15:12,Zero-shot Neural Retrieval via Domain-targeted Synthetic Queries,Zero-shot learning for ad-hoc retrieval models that relies on synthetic query generation.,natural-language-processing +778,2020-05-07 21:28:34,Harry Potter and the Deep Learning Experiment,RNN built with TensorFlow to generate text based on Harry Potter's books.,natural-language-processing +783,2020-05-08 14:44:04,NeuralCook — Image2Ingredients and Cooking Recommendation,"Deep learning application to identify ingredients from cooking dishes images and recommend dishes to cook, given a set of ingredients.",natural-language-processing +788,2020-05-09 04:12:10,NER model for 40 languages trained with the new TFTrainer,This model is a fine-tuned XLM-Roberta-base over the 40 languages proposed in XTREME from Wikiann. ,natural-language-processing +791,2020-05-09 14:30:08,Pose Animator,Takes a 2D vector illustration and animates its containing curves in real-time based on the recognition result from PoseNet and FaceMesh.,computer-vision +792,2020-05-09 16:59:54,A Commit History of BERT and its Forks,What a commit history of version-controlled research papers could look like?,natural-language-processing +795,2020-05-10 04:51:17,U^2-Net,"The code for our newly accepted paper in Pattern Recognition 2020: ""U^2-Net: Going Deeper with Nested U-Structure for Salient Object Detection.""",computer-vision +796,2020-05-10 05:08:27,Age and Gender Estimation using Multi-Task CNN,Used a multi task CNN to predict the age group and gender of the person in the image.,computer-vision +797,2020-05-10 15:31:27,Data augmentation recipes in tf.keras image-based models,Learn about different ways of doing data augmentation when training an image classifier in tf.keras.,computer-vision +799,2020-05-11 00:40:49,Injecting Inductive Bias in Graph Neural Networks (MIT talk),Equivariant Mesh Neural Networks and Neural Augmented (Factor) Graph Neural Networks.,graph-learning +800,2020-05-11 00:44:10,Feature Stores for ML,List of production ML groups and their open-source feature store architectures.,mlops +803,2020-05-11 02:13:32,Image Semantic Segmentation of UAV mining area based on Deeplabv3,"Data: UAV mining area image +Tools: PyTorch +Frame: Deeplabv3 +Semantic Segmentation ",computer-vision +820,2020-05-11 14:19:18,A Comprehensive Survey on Graph Neural Networks,A Comprehensive Survey on Graph Neural Networks.,graph-learning +821,2020-05-11 15:03:57,Hidden Technical Debt in Machine Learning Systems,"Using the software engineering framework of technical debt, we find it is common to incur massive ongoing maintenance costs in real-world ML systems. ",mlops +822,2020-05-11 15:10:09,In-Domain GAN Inversion for Real Image Editing,"We propose an in-domain GAN inversion method, which faithfully reconstructs the input image but also ensures the inverted code to be semantically meaningful.",computer-vision +825,2020-05-11 23:07:39,Neural Networks for NLP (CMU CS 11-747),"This class will start with a brief overview of neural networks, then spend the majority of the class demonstrating how to apply neural networks to language.",natural-language-processing +826,2020-05-12 03:02:02,DANet PyTorch,A Pytorch implementation of Dual Attention Network for Scene Segmentation,computer-vision +828,2020-05-12 05:04:58,BART version of closed-book QA,"This is a BART version of sequence-to-sequence model for open-domain QA in a closed-book setup, based on PyTorch and Huggingface's Transformers.",natural-language-processing +829,2020-05-12 05:07:35,Unsupervised Reinforcement Learning,Lecture on unsupervised reinforcement learning by Sergey Levine. Originally prepared for AAMAS 2020.,reinforcement-learning +831,2020-05-13 02:24:24,CCNet_PyTorch,A PyTorch Implementation of CCNet: Criss-Cross Attention for Semantic Segmentation,computer-vision +832,2020-05-13 04:22:09,Image segmentation in 2020,"Architectures, Losses, Datasets, and Frameworks",computer-vision +833,2020-05-13 04:27:08,Plan2Explore: Plan to Explore via Self-Supervised World Models,A self-supervised reinforcement learning agent that tackles task-specific and the sample efficiency challenges.,reinforcement-learning +835,2020-05-13 04:39:31,Toward Better Storylines with Sentence-Level Language Models,We propose a sentence-level language model which selects the next sentence in a story from a finite set of fluent alternatives.,natural-language-processing +836,2020-05-13 04:43:57,Epipolar Transformers,"Differentiable ""epipolar transformer"", which enables the 2D detector to leverage 3D-aware features to improve 2D pose estimation.",computer-vision +840,2020-05-13 05:03:33,Machine Learning on Graphs: A Model and Comprehensive Taxonomy,We propose a simple framework (GraphEDM) and a comprehensive Taxonomy to review and unify several graph representation learning methods.,graph-learning +841,2020-05-13 05:10:58,BLEURT: Learning Robust Metrics for Text Generation,A metric for Natural Language Generation based on transfer learning.,natural-language-processing +842,2020-05-13 13:20:07,Identifying Brain Tumor from MRI images using FastAI -DynamicUnet,"To use FASTAI unet learner to identify tumours from MRI of Brain, logging loss metrics in Neptune AI logger and compare the results after hyperparameter tuning.",computer-vision +847,2020-05-13 22:53:36,HuggingTweets,Tweet Generation with Huggingface.,natural-language-processing +849,2020-05-13 22:59:38,Top Down Introduction to BERT with HuggingFace and PyTorch,I will also provide some intuition into how BERT works with a top down approach (applications to algorithm).,natural-language-processing +850,2020-05-13 23:02:29,Transformers from Scratch,"Attempt to explain directly how modern transformers work, and why, without some of the historical baggage.",natural-language-processing +852,2020-05-14 07:11:26,Scene Classification using Pytorch and Fast.ai,The objective is to classify Multi-label images using deep learning. Here I have used Fast.ai library for implementing the model. ,computer-vision +855,2020-05-14 12:32:20,Fake new detection Pytorch,Fake News Detection by Learning Convolution Filters through Contextualized Attention.,natural-language-processing +857,2020-05-14 14:25:11,FastHugs: Sequence Classification with Transformers and Fastai,Fine-tune a text classification model with HuggingFace 🤗 transformers and fastai-v2.,natural-language-processing +858,2020-05-14 14:35:37,Open-Dialog Chatbots for Learning New Languages,A tutorial for automatically generate code comments using Deep Learning.,natural-language-processing +860,2020-05-14 17:35:04,Electra,ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators,natural-language-processing +862,2020-05-14 19:13:59,DQN In Pytorch Livestream Series,I'm doing a series of streams about reinforcement learning (starting from Q learning) focused on showing the work in as much detail as possible (e.g. debugging),reinforcement-learning +863,2020-05-15 04:24:58,S2IGAN: Speech-to-Image Generation via Adversarial Learning,A speech-to-image generation (S2IG) framework is proposed which translates speech descriptions to photo-realistic images without using any text information.,computer-vision +864,2020-05-15 13:04:19,Twitter Sentiment Analysis,"This project is based on Natural Language processing (NLP), in this we do sentiment analysis(i.e, how much it is positive or negative) of tweets of any account.",natural-language-processing +866,2020-05-15 13:51:56,HuggingFace nlp library,"nlp is a lightweight and extensible library to easily share and load dataset and evaluation metrics, already providing access to ~100 datasets and ~10 evaluatio",natural-language-processing +868,2020-05-15 14:07:47,RXNMapper: Unsupervised Attention-Guided Atom-Mapping,The atom-mapping information was learned by an ALBERT model trained in an unsupervised fashion on a large dataset of chemical reactions.,natural-language-processing +869,2020-05-15 14:08:12,ICLR 2020 Trends: Better & Faster Transformers for NLP,A summary of promising directions from ICLR 2020 for better and faster pretrained tranformers language models. ,natural-language-processing +875,2020-05-15 22:53:58,Differentiable Reasoning over Text,We consider the task of answering complex multi-hop questions using a corpus as a virtual knowledge base (KB).,natural-language-processing +877,2020-05-16 02:42:32,Semi-supervised image classification with GANs,"Shows how to perform semi-supervised image classification with GANs. The cover image is from Chapter 7, GANs in Action.",computer-vision +879,2020-05-16 10:57:53,HighRes-net: Multi-Frame Super-Resolution of satellite imagery,"Pytorch implementation of HighRes-net, a neural network for multi-frame super-resolution, trained and tested on the European Space Agency’s Kelvin competition.",computer-vision +880,2020-05-16 11:50:31,How Deep Is Your Love For Transfer Learning In NLP?,A review of NLP research,natural-language-processing +881,2020-05-16 13:32:51,Time Series Forecasting with TensorFlow.js,Machine learning is becoming increasingly popular these days and a growing number of the world’s population see it is as a magic crystal ball: predicting when a,time-series +882,2020-05-16 13:35:31,Phrases extraction and D3 Wordcloud,100% JavaScript solution to extracting phrases from text and display key points in a beautiful D3 wordcloud.,natural-language-processing +883,2020-05-16 13:37:44,Reinforcement Learning Tic Tac Toe with Value Function,"A reinforcement learning algorithm for agents to learn the tic-tac-toe, using the value function + +",reinforcement-learning +884,2020-05-16 13:40:07,Build a Textual Similarity Web App with TensorFlow.js,Have you wondered how search engines understand your queries and retrieve relevant results? How chatbots extract your intent from your questions and provide the,natural-language-processing +890,2020-05-16 19:51:33,cyBERT: Applying BERT to Windows event logs,"This blog shows how interpreting cybersecurity logs as a natural language, improving upon the standard regex-based parsing of log data.",natural-language-processing +892,2020-05-17 02:08:12,DPOD: Pose Estimator,PyTorch recreation of a SOTA 6D Pose estimation research paper. ,computer-vision +893,2020-05-17 04:44:04,ESTorch,ESTorch is an Evolution Strategy Library build around PyTorch.,reinforcement-learning +894,2020-05-17 04:47:40,"A Large-Scale, Open-Domain, Mixed-Interface Dialogue-Based ITS ","Korbit, a large-scale, open-domain, mixed-interface, dialogue-based intelligent tutoring system (ITS).",natural-language-processing +900,2020-05-17 08:14:24,A Visual Survey of Data Augmentation in NLP,An extensive overview of text data augmentation techniques for Natural Language Processing,natural-language-processing +901,2020-05-17 09:57:38,DoYouEvenLearn,Essential Guide to keep up with AI/ML/DL/CV,computer-vision +902,2020-05-18 00:57:27,Differentiable Adaptive Computation Time for Visual Reasoning ,"DACT, a new algorithm for achieving adaptive computation time that, unlike existing approaches, is fully differentiable. ",natural-language-processing +903,2020-05-18 11:15:12,Semixup: In- and Out-of-Manifold Regularization,Semixup is a semi-supervised learning method based on in/out-of-manifold regularization.,computer-vision +905,2020-05-18 14:40:51,Deep Reinforcement Learning for Supply Chain & Price Optimization,Explore how deep reinforcement learning methods can be applied in several basic supply chain and price management scenarios.,reinforcement-learning +907,2020-05-18 14:53:33,TextAttack,A Python framework for building adversarial attacks on NLP models.,natural-language-processing +913,2020-05-19 03:19:59,aitextgen,A robust Python tool for text-based AI training and generation using GPT-2.,natural-language-processing +914,2020-05-19 03:25:11,How Hugging Face achieved a 2x performance boost for QA,Question Answering with DistilBERT in Node.js,natural-language-processing +918,2020-05-19 22:36:09,Accelerate your NLP pipelines using Hugging Face and ONNX,How the ONNX Runtime team and Hugging Face are working together to address challenges in training and deployment of Transformer models.,natural-language-processing +920,2020-05-20 02:35:11,Attentron,Few-shot text-to-speech exploiting attention-based variable length embedding,natural-language-processing +921,2020-05-20 02:39:09,Torch Points3D,Pytorch framework for doing deep learning on point clouds.,computer-vision +922,2020-05-20 07:23:50,NLP Model Selection ,NLP model selection guide to make it easier to select models. This is prescriptive in nature and has to be used with caution.,natural-language-processing +925,2020-05-20 16:20:28,Model-Agnostic Meta-Learning for Reinforcement Learning with TF2,Reimplementation of Model-Agnostic Meta-Learning (MAML) applied on Reinforcement Learning problems in TensorFlow 2.,reinforcement-learning +927,2020-05-21 03:16:17,FashionBERT,Text and image matching with adaptive loss for cross-modal retrieval.,natural-language-processing +934,2020-05-21 03:45:38,📈 Automated Time Series Forecasting,This data app uses Facebook's open-source Prophet library to automatically forecast values into the future. ,time-series +935,2020-05-21 14:22:01,"Look inside the workings of ""Label Smoothing""","This blog post describes how and why does ""trick"" of label smoothing improves the model accuracy and when should we use it ",computer-vision +938,2020-05-22 01:01:32,Content and Style Disentanglement for Artistic Style Transfer,Hi-Res style transfer and interpolation between styles,computer-vision +939,2020-05-22 03:08:40,Time Series Classification Using Deep Learning,"In this article, I will introduce you to a new package called timeseries for fastai2 that I lately developed. ",time-series +940,2020-05-22 03:16:29,TAO: A Large-Scale Benchmark for Tracking Any Object,"A diverse dataset for Tracking Any Object (TAO) consisting of 2,907 high resolution videos, captured in diverse environments, which are half a minute long on ",computer-vision +941,2020-05-22 03:21:10,BiT: Exploring Large-Scale Pre-training for Compute,"We are excited to share the best BiT models pre-trained on public datasets, along with code in TF2, Jax, and PyTorch. ",computer-vision +947,2020-05-22 13:34:30,Self Driving Car,This project is a demonstration of a working model of self driving car 🚗🚗 identifying and following lanes using powerful computer vision 🕶🕶 algorithms.,computer-vision +948,2020-05-22 13:39:15,Plant Disease Detection,This website help you to detect disease in your plant🌳 based to the plant's leaf🍃 image,computer-vision +951,2020-05-23 03:19:00,YoloV3 implementation in keras and tensorflow 2.2,YoloV3 Real Time Object Detector in tensorflow 2.2.,computer-vision +952,2020-05-23 03:22:11,Face Mask Detector,A simple Streamlit frontend for face mask detection in images using a pre-trained Keras CNN model + OpenCV and model interpretability.,computer-vision +957,2020-05-23 09:18:52,Colbert AI,Colbert AI is a Deep Learning Language Model that generates text in the style of Stephen Colbert's famous monologues.,natural-language-processing +961,2020-05-23 16:01:21,How to Build Robust Embeddings for Visual Similarity Tasks,This repository I package a bunch of tips and tricks to efficiently train deep learning models in computer vision,computer-vision +962,2020-05-24 00:09:28,Basic ML Algorithms from scratch.,Implement basic Machine Learning Algorithms from scratch in python.,natural-language-processing +963,2020-05-24 03:13:28,Build your first data warehouse with Airflow on GCP,What are the steps in building a data warehouse? What cloud technology should you use? How to use Airflow to orchestrate your pipeline?,mlops +966,2020-05-24 10:24:03,Building an Intelligent Twitter Bot,The volume of information going through Twitter per day makes it one of the best platforms to get information on any subject of interest. ,natural-language-processing +968,2020-05-24 16:40:46,Self Supervised Representation Learning in NLP,An overview of self-supervised pretext tasks in Natural Language Processing,natural-language-processing +970,2020-05-24 20:01:29,Job Classification,"Job Classification done using Techniques of NLP and ML. + +Dataset used from Kaggle of Indeeed job posting.",natural-language-processing +972,2020-05-25 03:23:16,Next Word Prediction,Using transformers to predict next word and predict word.,natural-language-processing +974,2020-05-25 03:28:32,PixelLib,Pixellib is a library for performing segmentation of images. ,computer-vision +978,2020-05-25 05:53:46,TensorFlow.js - Gesture Controlled 2048,Gesture Controlled 2048 built with TensorFlow.js,computer-vision +979,2020-05-25 11:04:50,Taxi Demand Prediction NewYorkCity,Predict the number of pickups as accurately as possible for each region in a 10 -min interval.,time-series +980,2020-05-25 14:52:17,Super-BPD for Fast Image Segmentation,"We propose direction-based super-BPD, an alternative to superpixel, for fast generic image segmentation, achieving state-of-the-art real-time result.",computer-vision +986,2020-05-26 03:47:15,Neural Topological SLAM for Visual Navigation,Topological representations for space that effectively leverage semantics and afford approximate geometric reasoning.,computer-vision +987,2020-05-26 13:16:48,Zero To One For NLP,A collection of all resources for learning NLP,natural-language-processing +989,2020-05-26 17:17:14,NLP for Developers: Shrinking Transformers | Rasa,"In this video, Rasa Senior Developer Advocate Rachael will talk about different approaches to make transformer models smaller.",natural-language-processing +993,2020-05-27 05:26:33,DETR: End-to-End Object Detection with Transformers,A new method that views object detection as a direct set prediction problem. ,computer-vision +997,2020-05-28 03:20:06,AutoSweep: Recovering 3D Editable Objects from a Single Photo,Fully automatic framework for extracting editable 3D objects directly from a single photograph.,computer-vision +1000,2020-05-28 03:33:52,CMU LTI Low Resource NLP Bootcamp 2020,A low-resource natural language and speech processing bootcamp held by the Carnegie Mellon University Language Technologies Institute in May 2020.,natural-language-processing +1007,2020-05-28 21:30:37,Humour.ai : Language Model that can crack Jokes,"A Language model that can make you laugh. Humour.ai model tries to +complete a sentence in a humourous way given some input words. ",natural-language-processing +1008,2020-05-29 02:28:53,face mask detection ,detects whether a person wearing a mask or not,computer-vision +1009,2020-05-29 02:47:06,Train ALBERT for NLP with TensorFlow on Amazon SageMaker,"To train BERT in 1 hour, we efficiently scaled out to 2,048 NVIDIA V100 GPUs by improving the underlying infrastructure, network, and ML framework. ",natural-language-processing +1010,2020-05-29 02:51:39,GPT-3: Language Models are Few-Shot Learners,"We show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior SOTA.",natural-language-processing +1013,2020-05-29 03:06:41,Guided Uncertainty-Aware Policy Optimization,Combining learning and model-based strategies for sample-efficient policy learning.,reinforcement-learning +1018,2020-05-29 08:09:04,GOTURN-PyTorch,"PyTorch implementation of ""Learning to Track at 100 FPS with Deep Regression Networks""",computer-vision +1020,2020-05-29 09:54:04,Applying Modern Best Practices to Autoencoders,This project applies best modern practices found in other areas of image research to autoencoders. Comparing models from other areas of image research.,computer-vision +1021,2020-05-29 10:33:26,Sentiment analysis ,"Sentiment analysis by combining three dataset amazon,yelp, IMDb reviews to train our,model to classify if a comment is negative or positive denoted by 0 and 1.",natural-language-processing +1022,2020-05-29 13:27:20,The designer - gpt2 bot that talks about UX Design,"This twitter profile spits out thoughts on design and development. Trained with hundreds of Books on UX design and Front end development, it has opinions.",natural-language-processing +1024,2020-05-29 14:15:30,Sentiment Classification for UtaPass & KKBOX Reviews,Text classification for reviews of UtaPass & KKBOX using different deep learning models.,natural-language-processing +1025,2020-05-29 14:18:59,Forex Prediction,Using neural networks to predict movement of forex direction.,natural-language-processing +1026,2020-05-29 14:24:07,Lyrics-Based Music Genre Classifier,"Classify the genre (Rock, Pop, Hip-Hop, Not Available, Metal, Other, Country, Jazz, Electronic, R&B, Indie, Folk) of the song by its lyrics.",natural-language-processing +1028,2020-05-29 14:39:16,ARBML,"Implementation of many Arabic NLP and ML projects. Providing real time experience using many interfaces like web, command line and notebooks.",natural-language-processing +1035,2020-05-29 16:11:11,Zero Shot Topic Classification,Bart with a classification head trained on MNLI.,natural-language-processing +1045,2020-05-30 01:35:24,Illustrated Guide to Transformers: Step by Step Explanation,"In this post, we’ll focus on the one paper that started it all, “Attention is all you need”.",natural-language-processing +1046,2020-05-30 01:39:25,Illustrated Guide to Transformers,A component by component breakdown analysis.,natural-language-processing +1055,2020-05-30 09:02:27,Automatic-Face-Detection-Annotation-and-Preprocessing,"Automatically detect , annotate , collect the coordinates , convert to csv and to tfrecord",computer-vision +1058,2020-05-30 09:43:39,SmartFeed.ai,NLP Based Article Recommendation System ,natural-language-processing +1059,2020-05-30 10:50:55,Wheat Detection 🌾,This is a project for detecting and creating bounding box of wheat heads 🌾.,computer-vision +1068,2020-05-30 18:20:40,Effects of News Sentiments on Stock Predictions,Project is based on the Natural Language Processing technique called Sentiment Analysis. Stock market and news related to it as the subject of analysis.,natural-language-processing +1069,2020-05-30 20:04:49,NLP News Category,The objective of this repository is to create a NLP bot for when you give the robot the headline of the news and a short description it will return the genre.,natural-language-processing +1070,2020-05-30 20:06:48,AI Debate Master,"Created and deployed a bot made to debate with a human on any +given topic. Employed a Doc2Vec model using Gensim library in Python",natural-language-processing +1075,2020-05-31 04:44:27,Zero-Shot Learning for Text Classification,"A visual summary of “Train Once, Test Anywhere” paper for zero-shot text classification",natural-language-processing +1080,2020-05-31 05:23:23,Dash DETR Detection App,A User Interface for DETR built with Dash. 100% Python.,computer-vision +1081,2020-05-31 05:28:53,AI Basketball Analysis,🏀 AI web app and API to analyze basketball shots and shooting pose. ,computer-vision +1083,2020-05-31 08:20:06,Reverse Image Search,Have you ever wondered how google image search works or How amazon can retrieve products similar to the image that we upload in the app/site? To achieve this ta,computer-vision +1084,2020-05-31 08:22:45,Beginner’s guide to Machine Learning Model Deployment,Are you a beginner in the field of machine learning and wondering how to bring your project to live. I'm was in the same situation when I started learning ML. M,mlops +1093,2020-05-31 17:39:22,MedicalZoo PyTorch,A pytorch-based deep learning framework for multi-modal 2D/3D medical image segmentation,computer-vision +1094,2020-05-31 19:11:28,Paraphrase Any Question with T5 (Text-To-Text Transformer),"Given a question, generate paraphrased versions of the question with T5 transformer. Pretrained model and training script provided.",natural-language-processing +1100,2020-06-01 05:56:43,Movie Recommendation System,This is a web app which recommends movies based on their plots found on IMDb.,natural-language-processing +1104,2020-06-01 10:02:09,Convnet Galaxy Morphology Classifier,Classify galaxies from Hubble Tuning Fork using Convnet. ,computer-vision +1107,2020-06-01 14:52:29,2nd Place Solution to Ship Identification Hackathon ,The problem statement was to identify the type of ship from photos taken from the survey boats. The hackathon was organized by Analytics Vidhya.,computer-vision +1110,2020-06-01 16:44:55,Deep learning Architecture: AlexNet,Explaining network architecture for AlexNet,computer-vision +1111,2020-06-01 18:13:26,Movement Pruning: Adaptive Sparsity by Fine-Tuning,"We propose the use of movement pruning, a simple, deterministic first-order weight pruning method that is more adaptive to pretrained model fine-tuning.",natural-language-processing +1112,2020-06-01 18:57:31,Document search engine,NLP based search engine for single page pdf files.,natural-language-processing +1115,2020-06-01 21:07:53,Softbot design with WANNS,"Soft robots are robots built from highly compliant materials, similar to those found in living organisms. This project explored CPPNs and WANNs to design them",reinforcement-learning +1121,2020-06-02 05:07:17,Motion2Vec,Semi-Supervised Representation Learning from Surgical Videos,computer-vision +1122,2020-06-02 05:10:18,Machine Learning: Tests and Production,Best practices for testing ML-based systems.,mlops +1130,2020-06-02 11:51:38,Generate True or False questions from any content,"Automatically generate “True or False” questions like the ones you see in school textbooks using OpenAI GPT2, Sentence BERT, and Berkley parser",natural-language-processing +1131,2020-06-02 13:41:32,Sized Fill-in-the-blank or Multi Mask filling with RoBERTa,Sized fill-in-the-blank or conditional text filling is the idea of filling missing words of a sentence with the most probable choice of words.,natural-language-processing +1132,2020-06-02 14:56:10,T5 for Sentiment Span Extraction,Exploring how T5 works and applying it for sentiment span extraction.,natural-language-processing +1133,2020-06-02 14:58:58,Getting Started with Time Series analysis using Pandas,An introductory guide to get started with the Time Series datasets in Python,time-series +1135,2020-06-02 15:06:34,Melanoma Detection with Pytorch,"In this video, I show you how you can build a deep learning model to detect melanoma with a very high accuracy.",computer-vision +1139,2020-06-02 19:53:37,"RoBERTa → Longformer: Build a ""Long"" Version of Pretrained Models",This notebook replicates the procedure descriped in the Longformer paper to train a Longformer model starting from the RoBERTa checkpoint. ,natural-language-processing +1145,2020-06-03 01:51:14,Learning Dexterity End-to-End,We trained a human-like robot hand to manipulate physical objects with unprecedented dexterity.,reinforcement-learning +1148,2020-06-03 02:28:20,A Practical guide to building a conversational chatbot,Building a Chatbot from scratch using Keras and NLTK library for a customer service company,natural-language-processing +1151,2020-06-03 07:25:27,Web Mining and Information theory,"Mining the Web and playing with Natural Language processing. Implementing Information retrieval System tasks. Going towards the NLP and Performing Machine Learning algorithms. Through these codes and problems, I have understood the information retrieval process of any search engine. These are very useful problems towards sentiment analysis.",natural-language-processing +1162,2020-06-03 22:05:30,Deep Q-Network on Space Invaders. ,This is a PyTorch implementation of a Deep Q-Network agent trained to play the Atari 2600 game of Space Invaders.,reinforcement-learning +1165,2020-06-04 03:53:43,YOLOv4,A TensorFlow 2.0 implementation of YOLOv4: Optimal Speed and Accuracy of Object Detection.,computer-vision +1166,2020-06-04 03:55:53,Acme: A Research Framework for Reinforcement Learning,A library of reinforcement learning components and agents.,reinforcement-learning +1176,2020-06-04 09:10:07,doc2vec Paragraph Embeddings for Text Classification,Text classification model which uses gensim's Doc2Vec for generating paragraph embeddings and scikit-learn Logistic Regression for classification. ,natural-language-processing +1178,2020-06-04 12:19:52,Machine Learning with Fastai,"The fastai library is based on research into deep learning best practices undertaken at fast.ai, and includes support for Vision, Text, tabular and Collab",computer-vision +1180,2020-06-04 14:58:19,The Transformer … “Explained”?,"An intuitive explanation of the Transformer by motivating it through the lens of CNNs, RNNs, etc.",natural-language-processing +1181,2020-06-04 16:28:24,TensorflowTTS: Real-Time SOTA Speech Synthesis for Tensorflow 2.0,"TensorflowTTS provides real-time state-of-the-art speech synthesis architectures such as Tacotron2, Melgan, FastSpeech.",natural-language-processing +1185,2020-06-04 22:36:31,PyTorch Transformers Tutorials,"A set of annotated Jupyter notebooks, that give user a template to fine-tune transformers model to downstream NLP tasks such as classification, NER etc. ",natural-language-processing +1192,2020-06-05 04:28:52,BERT Summarization,This folder contains colab notebooks that guide you through the summarization by BERT and GPT-2 to play with your data.,natural-language-processing +1194,2020-06-05 04:35:14,Divide Hugging Face Transformers Training Time By 2,Reducing training time helps to iterate more in a fixed budget time and thus achieve better results.,natural-language-processing +1199,2020-06-05 15:39:56,How NLP has evolved for Financial Sentiment Analysis,Do we still need humans to read boring financial statements?,natural-language-processing +1202,2020-06-05 17:51:33,The NLP Pandect - All NLP resources in one place,The NLP Pandect was created to help you find almost anything related to Natural Language Processing that is available online.,natural-language-processing +1203,2020-06-05 18:18:18,Summary of 🤗 Transformers Models,A high-level summary of the differences between each model in HuggingFace's Transformer library.,natural-language-processing +1204,2020-06-05 22:56:38,Snaked: Classifying Snake Species using Images,Proof of concept that it is possible to identify snake species and whether poisonous from photographs (PyTorch code/model with Android app),computer-vision +1211,2020-06-06 15:13:13,Literate Lamp: Answering Question with Common Sense,We study the problem of answering questions that require common sense to be answered using Transformer-based models and the ConceptNet knowledge base.,natural-language-processing +1215,2020-06-06 19:00:39,Pytorch Faster RCNN,Fine Tune Faster RCNN in pytorch for your task.,computer-vision +1222,2020-06-07 04:34:58,Paragraph Summarizer,Uses the extractive way of summarizing the text by finding the score and ranking it.,natural-language-processing +1223,2020-06-07 04:39:32,Leafy: Plant Leaf Classifier,The sequential model trained on images from the leafsnap.com,computer-vision +1236,2020-06-07 21:03:31,"COVID-Q: A Dataset of 1,690 Questions about COVID-19","This dataset consists of COVID-19 questions which have been annotated into a broad category (e.g. Transmission, Prevention) and a more specific class such that ",natural-language-processing +1237,2020-06-08 03:43:45,Keras notifications on Slack!,Get slack notifications of your model's training progress when training with Keras (or tf.keras),computer-vision +1239,2020-06-08 07:05:15,Zero-shot Text Classification With Generative Language Models,An overview of a text generation approach to zero-shot text classification with GPT-2,natural-language-processing +1241,2020-06-08 08:25:01,Funnel-Transformer: Filtering out Sequential Redundancy,Funnel-Transformer is a self-attention model that gradually compresses the sequence of hidden states to a shorter one and hence reduces the computation cost.,natural-language-processing +1243,2020-06-08 08:39:34,Timeseries Anomaly Detection using an Autoencoder,Detect anomalies in a timeseries using an Autoencoder.,time-series +1246,2020-06-08 09:47:02,Fairseq-tagging,"a Fairseq fork for sequence tagging/labeling tasks +",natural-language-processing +1249,2020-06-08 16:59:01,Know-Corona : Kaggle COVID-19 Open Research Dataset Challenge (CO,"NLP/state-of-the-art language model (BERT) based Question & Answering pipeline to answer all task questions after analyzing articles abstract of COVID-19, SARS-",natural-language-processing +1251,2020-06-08 18:38:49,Automatic Asset Classification,This project aims to automate the task of labelling images of flood defence assets as well as clustering images to find possibly better groupings.,computer-vision +1255,2020-06-09 01:50:33,TransformerTTS,🤖💬 Transformer TTS: Implementation of a non-autoregressive Transformer based neural network for text to speech.,natural-language-processing +1257,2020-06-09 01:58:48,How Big Should My Language Model Be?,Tool to explore language model training and optimize the compute costs.,natural-language-processing +1258,2020-06-09 02:04:49,MSeg: A Composite Dataset for Multi-domain Semantic Segmentation,A composite dataset that unifies semantic segmentation datasets from different domains.,computer-vision +1259,2020-06-09 02:11:15,Network Fusion for Content Creation With Conditional Inns,"We present a method to repurpose powerful, existing models for new tasks, even though they have never been designed for them.",computer-vision +1260,2020-06-09 02:14:59,Advanced Deep Learning for Computer Vision (ADL4CV),"The Visual Computing Group offers a variety of lectures and seminars on a regular basis, covering hot areas in computer graphics, vision, and machine learning.",computer-vision +1272,2020-06-10 05:13:41,Linformer: Self-Attention with Linear Complexity,We demonstrate that the self-attention mechanism can be approximated by a low-rank matrix.,natural-language-processing +1274,2020-06-10 05:21:00,Getting Machine Learning to Production,"Machine learning is hard and there are a lot, a lot of moving pieces.",mlops +1275,2020-06-10 05:24:07,Exploration Strategies in Deep Reinforcement Learning,Exploitation versus exploration is a critical topic in reinforcement learning. This post introduces several common approaches for better exploration in Deep RL.,reinforcement-learning +1278,2020-06-10 12:50:41,Automatically Generate Multiple Choice Questions (MCQs) ,"Automatically Generate Multiple Choice Questions (MCQs) from any content with BERT Summarizer, Wordnet, and Conceptnet",natural-language-processing +1287,2020-06-10 18:27:24,BERT Loses Patience: Fast and Robust Inference with Early Exit,"Patience-based Early Exit, a inference method that can be used as a plug-and-play technique to simultaneously improve the efficiency of a pretrained LM.",natural-language-processing +1298,2020-06-11 04:18:27,PEGASUS: a SOTA model for Abstractive Text Summarization,A State-of-the-Art Model for Abstractive Text Summarization.,natural-language-processing +1301,2020-06-11 04:29:24,Big GANs Are Watching You, We demonstrate that object saliency masks for GAN-produced images can be obtained automatically with BigBiGAN.,computer-vision +1309,2020-06-11 19:04:31,Sentiment Analysis on News Article,Used Twitter API to extract news-related tweets. Did some preprocessing and then calculated the tweets' polarity.,natural-language-processing +1310,2020-06-11 20:30:38,GPT-3 Language Model: A Technical Overview,"Technical details of the GPT-3 model, training, inference and what to expect next. ",natural-language-processing +1312,2020-06-11 20:37:47,OpenAI API,API for accessing new AI models developed by OpenAI.,natural-language-processing +1320,2020-06-12 04:17:08,Implementation of a Contextual Chatbot in PyTorch,Simple chatbot implementation with PyTorch.,natural-language-processing +1325,2020-06-12 11:06:34,Author Identification using Doc2Vec,Web app of an author identification model trained on PAN 2012 dataset and Kaggle's Spooky Authorship Dataset,natural-language-processing +1329,2020-06-12 12:44:18,Training game agents with supervised learning,This is a continuing research project trying find ways to learn complex tasks such as games without using Reinforcement Learning.,reinforcement-learning +1371,2020-06-13 17:16:07,Baymax - ChatBot,"Baymax Chatbot is a part of my summer training program @AdHoc Networks, Jaipur. + +A chatbot that allows user to signup and login to maintain their record. When c",natural-language-processing +1372,2020-06-13 17:21:43,How to Evaluate Longformer on TriviaQA using NLP,We will evaluate a pretrained LongformerForQuestionAnswering model on the validation dataset of TriviaQA.,natural-language-processing +1374,2020-06-13 17:28:13,Extracting Structured Data from Templatic Documents,"Automatically extract data from structured documents—invoices, receipts, etc.—with the potential to streamline many business workflows.",computer-vision +1392,2020-06-13 20:58:33,StackOver Flow Data Analysis,"Analysing certain aspects of the stack overflow data and creating ""Tag Predictor"" which predicts tag based on the post posted. ",natural-language-processing +1398,2020-06-14 05:51:06,Super-resolution Variational Auto-Encoders,VAE with RealNVP prior and Super-Resolution VAE in PyTorch.,computer-vision +1399,2020-06-14 05:57:16,Video object grounding,Video object grounding using semantic roles in language description. ,computer-vision +1418,2020-06-14 17:43:34,Short Notes on Behavior Regularized Offline RL,Blog Article on Behavior Regularized Offline Reinforcement Learning by Yifan Wu et al. (2019),reinforcement-learning +1423,2020-06-14 22:10:57,Entity Embedding with LSTM for Time-Series,"Demonstration of using LSTM for forecasting with structured time-series data, containing categorical and numerical features.",time-series +1424,2020-06-15 02:27:55,Why We Switched from Flask to FastAPI for Production ML,The most popular tool isn’t always the best.,mlops +1425,2020-06-15 02:31:48,Building a Captcha OCR in TF2.0,A Kaggle notebook showcasing the use of an Endpoint layer for CTC loss function used for building a Captcha Reader in TensorFlow.,computer-vision +1427,2020-06-15 02:40:48,101 Ways to Solve Search - Dair AI ft. Pratik Bhavsar,A comprehensive overview of explaining how NLP is used for search.,natural-language-processing +1438,2020-06-15 11:06:35,Multimodal Meme Classification,UNITER has given state of the art results in various image-text related problems. This project aims at finetuning UNITER to solve Hateful memes challenge,computer-vision +1453,2020-06-16 01:32:49,Interpretable Machine Learning for Computer Vision,"Recent progress we made on visualization, interpretation, and explanation methodologies for analyzing both the data and the models in computer vision.",computer-vision +1455,2020-06-16 02:32:53,Predicting Unintentional Action in Video,"We introduce a dataset of in-the-wild videos of unintentional action, as well as a suite of tasks for recognizing, localizing, and anticipating its onset. ",computer-vision +1457,2020-06-16 02:46:25, Synthesizing High-Resolution Images with StyleGAN2,"Developed by NVIDIA Researchers, StyleGAN2 yields state-of-the-art results in data-driven unconditional generative image modeling.",computer-vision +1458,2020-06-16 02:51:13,PIFuHD: High-Resolution 3D Human Digitization ,"This repository contains a pytorch implementation of ""Multi-Level Pixel-Aligned Implicit Function for High-Resolution 3D Human Digitization"".",computer-vision +1460,2020-06-16 03:21:07,Instance Shadow Detection,Instance shadow detection aims to find shadow instances paired with object instances.,computer-vision +1461,2020-06-16 03:24:02,Detectron2,FAIR's next-generation platform for object detection and segmentation.,computer-vision +1473,2020-06-16 22:37:58,tslearn,A machine learning toolkit dedicated to time-series data.,time-series +1475,2020-06-16 22:45:15,PyTorch3D,FAIR's library of reusable components for deep learning with 3D data.,computer-vision +1476,2020-06-16 22:48:45,Course Review - Causal Inference,Types of understanding that causal inference researchers value.,reinforcement-learning +1478,2020-06-16 22:56:31,Unsupervised Learning of Probably Symmetric Deformable 3D Objects,"A method to learn 3D deformable object categories from raw single-view images, without external supervision.",computer-vision +1480,2020-06-16 23:06:13,A Guide to Natural Language Processing With AllenNLP,basics of using AllenNLP,natural-language-processing +1482,2020-06-17 12:12:03,Real Time Object Detection using CNN YOLO,"This project is done on real time object detection using a deep learning object detection algorithm i.e., YOLO.",computer-vision +1483,2020-06-17 14:38:33,Short Notes on Model-Based Offline Reinforcement Learning (MOReL),Blog article on Model-Based Offline Reinforcement Learning (MOReL) paper by Rahul Kidambi & Aravind Rajeswaran et al.,reinforcement-learning +1491,2020-06-18 00:04:34,Image GPT: Generative Pretraining from Pixels, Transformers trained on pixel sequences can generate coherent image completions and samples.,computer-vision +1492,2020-06-18 00:06:53,Q*BERT,Agents that build knowledge graphs and explore textual worlds by asking questions.,natural-language-processing +1499,2020-06-18 13:41:39,History of Language Models - Alec Radford,A quick history of language models,natural-language-processing +1502,2020-06-18 19:45:49,Generate Boolean (Yes/No) Questions From Any Content ,Question generation algorithm trained on the BoolQ dataset using T5 text-to-text transformer model.,natural-language-processing +1504,2020-06-19 06:19:25,Fast Neural Style Transfer (feed-forward method) ⚡💻 + 🎨 = ❤️,This repo contains a concise PyTorch implementation of the original feed-forward NST paper.,computer-vision +1505,2020-06-19 06:22:56,Diverse Image Generation via Self-Conditioned GANs,A simple but effective unsupervised method for generating realistic & diverse images using a class-conditional GAN model without using manually annotated class.,computer-vision +1506,2020-06-19 06:26:17,Using GitHub Actions for MLOps & Data Science,A collection of resources on how to facilitate Machine Learning Ops with GitHub.,mlops +1519,2020-06-20 05:40:46,Image and Bounding Box Annotation Slicer,This easy-to-use library slices (also resizes) images and its bounding box annotations into tiles of specific sizes or any arbitrary number of equal parts. ✂️,computer-vision +1525,2020-06-20 16:21:38,Huggingtweets,This is a streamlit app built around the huggingtweets project. I fine-tune a pre-trained gpt2 model to tweet like a user given twitter handle. ,natural-language-processing +1528,2020-06-20 22:06:48,The Future of Computer Vision is Self-Supervised Learning,Talk by Yann Lecun on the applications of self-supervised learning on computer vision during CVPR 2020.,computer-vision +1529,2020-06-20 22:11:14,Using Selective Attention in Reinforcement Learning Agents,"In this work, we establish that self-attention can be viewed as a form of indirect encoding, which enables us to construct highly parameter-efficient agents.",reinforcement-learning +1539,2020-06-21 12:45:42,A Visual Guide to FastText Word Embeddings,A deep-dive into how FastText enriches word vectors with sub-word information ,natural-language-processing +1542,2020-06-21 20:46:12,Autocoder - Finetuning GPT-2 for Auto Code Completion,"A basic and simple tool for code auto completion, built upon GPT-2",natural-language-processing +1546,2020-06-22 00:46:32,DeepSNAP,Python library assists deep learning on graphs.,graph-learning +1547,2020-06-22 00:50:30,RoBERTa meets TPUs,Understanding and applying the RoBERTa model to the current challenge.,natural-language-processing +1549,2020-06-22 01:00:45,Deep Model-Based RL for Real-World Robotic Control,Short talk about model-based RL by Sergey Levine.,reinforcement-learning +1551,2020-06-22 03:17:48,Pokemon Classifier,I want to build a classifier that can classify 150 types of Pokemon.,computer-vision +1552,2020-06-22 03:45:01,Workshop on Scalability in Autonomous Driving - Andrej Karpathy,An overview of autonomous driving and computer vision at Tesla.,computer-vision +1560,2020-06-22 15:56:00,Battle-Tested Techniques for Scoping Machine Learning Projects,One of the challenges of managing an ML project is project scoping. Even small changes in data or architecture can create huge differences in model outputs.,mlops +1563,2020-06-22 16:04:10,Classify photos in 600 classes using nine million Open Images,"If you’re looking build an image classifier but need training data, look no further than Google Open Images.",computer-vision +1569,2020-06-22 16:52:01,Trackable,The project deals with tracking humans in a narrow hallway under different lighting conditions.,computer-vision +1571,2020-06-23 02:04:12,Stochastic Segmentation Networks,An efficient probabilistic method for modelling aleatoric uncertainty with any image segmentation network architecture.,computer-vision +1575,2020-06-23 02:30:20,Deep Learning for Computer Vision ,Special topics class on deep learning for computer vision from the University of Michigan taught by Justin Johnson.,computer-vision +1576,2020-06-23 02:37:15,VPSNet for Video Panoptic Segmentation,Video panoptic segmentation by generating consistent panoptic segmentation as well as an association of instance ids across video frames.,computer-vision +1580,2020-06-24 03:00:16,What I Learned From Looking at 200 Machine Learning Tools,"To better understand the landscape of available tools for machine learning production, I decided to look up every AI/ML tool I could find.",mlops +1581,2020-06-24 03:04:31,Discovering Symbolic Models from Deep Learning w/ Inductive Bias,A general approach to distill symbolic representations of a learned deep model by introducing strong inductive biases.,graph-learning +1585,2020-06-24 03:18:20,Breaking the cycle—Colleagues are all you need,A novel approach to performing image-to-image translation between unpaired domains.,computer-vision +1587,2020-06-24 03:25:25,Deep Learning Based Text Classification: A Comprehensive Review,An overview of deep learning approaches to text classification.,natural-language-processing +1589,2020-06-24 03:33:09,jiant,A software toolkit for research on general-purpose text understanding models.,natural-language-processing +1592,2020-06-24 04:27:58,Text Classification,"Re-implemented an article (link is given below) which was on Text classification with CNN, beside this I tried out some ML classification algorithm.",natural-language-processing +1595,2020-06-24 15:42:20,multi-task-NLP,A utility toolkit enabling NLP developers to easily train and infer a single model for multiple tasks.,natural-language-processing +1597,2020-06-25 00:17:39,Maximizing Business Impact with Machine Learning,how to effectively leverage machine learning to build intelligent products as efficiently as possible.,mlops +1598,2020-06-25 00:29:18,Automatic Data Augmentation for Generalization in Deep RL,We compare three approaches for automatically finding an appropriate augmentation combined with two novel regularization terms for the policy and value function,reinforcement-learning +1599,2020-06-25 00:42:36,High-Fidelity Generative Image Compression,How to combine Generative Adversarial Networks and learned compression to obtain a state-of-the-art generative lossy compression system.,computer-vision +1602,2020-06-25 04:03:38,Unet Model for Image Segmentation With EfficientNet Encoder,Implemented using tensorflow 2.2.0 with custom train and test step.,computer-vision +1603,2020-06-25 10:40:56,A Million of ML Predictions at the Tip of Your Fingers,Announcement - SashiDo is breaking the barrier to Machine Learning by introducing a fully open-sourced Content Moderation Service.,computer-vision +1605,2020-06-26 02:19:39,NetHack Learning Environment (NLE),A procedurally-generated grid-world dungeon-crawl game that strikes a great balance between complexity and speed for single-agent RL research.,reinforcement-learning +1606,2020-06-26 02:24:53,Paraphrase Generation Using T5 model,Simple application using T5 base model fine tuned in Quora Question Pairs to generate paraphrased questions.,natural-language-processing +1607,2020-06-26 02:28:15,Message Passing Query Embedding,"MPQE is a model for answering complex queries over knowledge graphs, that learns embeddings of entities in the knowledge graph, & embeddings for variable types.",graph-learning +1608,2020-06-26 02:31:17,Quantifying Attention Flow in Transformers,"I explain two simple but effective methods, called Attention Rollout and Attention Flow",natural-language-processing +1614,2020-06-27 04:15:51,Natural Language Processing Roadmap,Roadmap for learning NLP topics.,natural-language-processing +1615,2020-06-27 04:29:04,Weight Poisoning Attacks on Pre-trained Models,"How Bert can be infused with nefarious behavior, even after fine-tuning.",natural-language-processing +1616,2020-06-27 04:37:16,Leveraging Temporal Context for Object Detection,"Object detection architecture leveraging contextual clues across time for each camera deployment in a network, improving recognition of objects",computer-vision +1617,2020-06-27 04:42:47,Expressive Power of Graph Neural Networks,"Graph isomorphism problem, the Weisfeiler-Lehman heuristic for graph isomorphism testing, and how it can be used to analyse the expressive power of GNNs.",graph-learning +1620,2020-06-27 10:27:43,rlx: A modular Deep RL library for research,"""rlx"" is a Deep RL library written on top of PyTorch & built for educational and research purpose.",reinforcement-learning +1622,2020-06-27 14:18:13,Building AI Trading Systems,Lessons learned building a profitable algorithmic trading system using Reinforcement Learning techniques.,reinforcement-learning +1623,2020-06-27 14:20:49,Introduction to NLP using Fastai,Implementing and decoding the revolutionary ULMFiT approach to train a language model on any downstream NLP task.,natural-language-processing +1629,2020-06-28 07:37:00,TF Lite Semantic Segmentation Models,Faster and lighter TF Lite models can perform semantic segmentation. ,computer-vision +1630,2020-06-28 07:40:40,Semantic Segmentation + Background Removal + Style Transfer,"Running multiple TF Lite models to perform semantic segmentation, remove background, and apply style transfer. ",computer-vision +1636,2020-06-29 00:00:47,Automatic translation of the SQUAD dataset to spanish,"Machine translation is used on the SQuAD dataset to produce an equivalent dataset in Spanish. Word alignment is applied to produce a synthetic spanisQA corpus. +",natural-language-processing +1638,2020-06-29 02:56:43,Dakshina Dataset,A collection of text in both Latin and native scripts for 12 South Asian languages.,natural-language-processing +1639,2020-06-29 02:58:52,Computer Vision Recipes,This repository provides examples and best practice guidelines for building computer vision systems.,computer-vision +1644,2020-06-29 12:42:44,A research guide for data scientists,Tips on research from top data scientists,natural-language-processing +1645,2020-06-29 17:16:17,Using Data Science Pipelines for Disaster Response,Uses ETL and ML pipeline to build an NLP system for classification of messages into appropriate disaster categories,natural-language-processing +1646,2020-06-29 19:47:58,Twitter Turing Test,Can you guess whether this tweet is written by a human or generated by a neural network?,natural-language-processing +1648,2020-06-30 02:34:54,STUMPY: A Powerful and Scalable Python Library for Time Series,"STUMPY is a powerful and scalable Python library for computing a Matrix Profile, which can be used for a variety of time series data mining tasks.",time-series +1649,2020-06-30 02:39:32,Model Serving using FastAPI and streamlit,Simple example of usage of streamlit and FastAPI for ML model serving.,computer-vision +1650,2020-06-30 02:49:57,The Reformer - Pushing the Limits of Language Modeling,An in-depth understanding of each of the key features of the Reformer.,natural-language-processing +1651,2020-06-30 02:52:41,High-Resolution Image Inpainting,"High-Resolution Image Inpainting with Iterative Confidence Feedback and Guided Upsampling. +",computer-vision +1653,2020-06-30 03:01:50,MARGE: Pre-training via Paraphrasing,"A retrieval model maps a document to a set of related documents, which a reconstruction model paraphrases to maximize the likelihood of the original. ",natural-language-processing +1657,2020-06-30 18:00:11,Fast Api with Dockerization of your ML Models,In this GitHub repo you can able to know and learn how to build a fast API for testing your ML model and can test your ML model with UI and to Dockerize your ML,mlops +1658,2020-07-01 02:22:10,SimCLR - Contrastive Learning of Visual Representations,How to load pretrained/finetuned SimCLR models from hub modules for fine-tuning.,computer-vision +1662,2020-07-01 07:00:50,Image synthesis at CVPR 2020,An overview of the different approaches to image synthesis at CVPR 2020.,computer-vision +1663,2020-07-01 07:08:45,Sktime,A python toolbox for machine learning with time series.,time-series +1664,2020-07-01 07:14:00,"Sentiment Analysis: Key Milestones, Challenges and New Directions","An overview of sentiment analysis, it's progress and what's ahead.",natural-language-processing +1666,2020-07-01 07:20:52,Serverless BERT with HuggingFace and AWS Lambda,"Build a serverless question-answering API with BERT, HuggingFace, the Serverless Framework, and AWS Lambda.",natural-language-processing +1668,2020-07-01 13:33:49,Model-based Reinforcement Learning: A Survey,"A survey of the integration of both fields, better known as model-based reinforcement learning.",reinforcement-learning +1677,2020-07-02 04:06:19,Building Level 3 Conversational AI Assistants,"Presentations, panels, and fireside chats addressing all topics related to the creation of Level 3 AI assistants.",natural-language-processing +1678,2020-07-02 12:13:19,NSFW Image Classification REST API built with TensorFlow.JS,A ready-to-use & open-source NSFW Image Classification REST API built with TensorFlow.JS and NSFW.JS for effortless Content Moderation,computer-vision +1688,2020-07-03 04:23:58,Python Implementation of Reinforcement Learning: An Introduction ,"Plot replications, exercise solutions and Anki flashcards for the entire book by chapters.",reinforcement-learning +1691,2020-07-03 04:40:05,The Simplest Way to Serve your NLP Model in Production w/ Python ,"From scikit-learn to Hugging Face Pipelines, learn the simplest way to deploy ML models using Ray Serve.",mlops +1698,2020-07-04 01:07:48,Learning to Cartoonize Using White-box Cartoon Representations,An approach for image cartoonization using GANs.,computer-vision +1699,2020-07-04 01:10:18,Reinforcement Learning Tutorial,"Important reinforcement learning (RL) algorithms, including policy iteration, Q-Learning, and Neural Fitted Q.",reinforcement-learning +1702,2020-07-04 04:51:18,Face Recognition Techniques,Face Detection and Recognition techniques using traditional CV and also using new deep learning method.,computer-vision +1704,2020-07-04 10:42:53,LSTM Forecast Model for Stock Price Prediction using Keras," Easy to understand LSTM forecast model for Stock Price Prediction. The dataset contains daywise details of the GOOGL stock from May,2019-May 2018.",time-series +1706,2020-07-04 11:05:28,PokeZoo,A deep learning based web-app developed using the MERN stack and Tensorflow.js. ,computer-vision +1710,2020-07-05 05:47:35,NLP-task-visualizer-app,This application designed with streamlit library will help in visualizing NLP tasks on text entered by you. ,natural-language-processing +1721,2020-07-07 04:21:20,TensorflowTTS,Real-Time State-of-the-art Speech Synthesis for Tensorflow 2.,natural-language-processing +1722,2020-07-07 04:23:38,spaczz: Fuzzy matching and more for spaCy,Fuzzy matching and more functionality for spaCy.,natural-language-processing +1723,2020-07-07 04:26:45,BioSyn,Biomedical Entity Representations with Synonym Marginalization,natural-language-processing +1724,2020-07-08 04:02:50,Image Classifier: In the Browser,Using Tensorflow.js to make the prediction directly in the browser.,computer-vision +1726,2020-07-08 04:15:07,Photon: A Robust Cross-Domain Text-to-SQL System,"A robust, modular, cross-domain NLIDB that can flag natural language input to which a SQL mapping cannot be immediately determined. ",natural-language-processing +1728,2020-07-08 04:24:07,Bounding Box Prediction from Scratch using PyTorch,Multi-Task learning — Bounding Box Regression + Image Classification,computer-vision +1729,2020-07-08 04:28:13,Comment Classification Using BERT (multi-language) Fine-Tuning,We are going to use BERT layer in a model applying Keras.,natural-language-processing +1730,2020-07-08 04:30:28,TextBrewer,a PyTorch-based model distillation toolkit for natural language processing.,natural-language-processing +1737,2020-07-08 18:22:40,codeBERT - Automated code docstring review with transformers,"codeBERT provide a one command line to check if your code docstrings are up-to-date. +",natural-language-processing +1748,2020-07-09 02:23:25,Continuous Machine Learning (CML),CML helps to organize MLOps infrastructure on top of the traditional software engineering stack instead of creating separate AI platforms.,mlops +1750,2020-07-09 10:30:30,picTranslate: Seamless live Image Text translator,"Given an image with text on it, this app can give you a new image with text modified into a different language.",computer-vision +1753,2020-07-10 02:44:11,TUDatasets,A collection of benchmark datasets for graph classification and regression.,graph-learning +1754,2020-07-10 02:46:07,Full Stack Deep Learning,Full Stack Deep Learning helps you bridge the gap from training machine learning models to deploying AI systems in the real world.,mlops +1755,2020-07-10 02:51:24,Easy OCR,"Ready-to-use OCR with 40+ languages supported including Chinese, Japanese, Korean and Thai. + +",computer-vision +1759,2020-07-10 18:54:54,Emotion Recognition from Tom and Jerry videos,"Developed an application that classifies the emotion depicted by Tom and Jerry in each frame into one of the following : happy, angry, sad or suprised.",computer-vision +1767,2020-07-11 05:05:31,Imagenette,Imagenette is a subset of 10 easily classified classes from Imagenet.,computer-vision +1768,2020-07-11 05:08:02,TextAugment,Improving Short Text Classification through Global Augmentation Methods,natural-language-processing +1769,2020-07-11 05:10:10,niacin,"A Python library for replacing the missing variation in your text data. + +",natural-language-processing +1771,2020-07-11 05:16:17,Albumentations,Fast image augmentation library and easy to use wrapper around other libraries.,computer-vision +1772,2020-07-11 05:19:05,Augmentor,Image augmentation library in Python for machine learning.,computer-vision +1777,2020-07-11 05:37:12,tsfresh,Automatic extraction of relevant features from time series.,time-series +1792,2020-07-11 06:28:58,Anomaly Detection Toolkit (ADTK),"A Python toolkit for rule-based/unsupervised anomaly detection in time series + +",time-series +1795,2020-07-11 06:37:35,Chakin ,Simple downloader for pre-trained word vectors.,natural-language-processing +1796,2020-07-11 06:39:39,Top2Vec,"Top2Vec learns jointly embedded topic, document and word vectors. + +",natural-language-processing +1797,2020-07-11 06:42:29,Contextualized Topic Models,A python package to run contextualized topic modeling.,natural-language-processing +1800,2020-07-11 06:51:58,jellyfish,🎐 a python library for doing approximate and phonetic matching of strings.,natural-language-processing +1802,2020-07-11 06:57:28,SentencePiece,"Unsupervised text tokenizer for Neural Network-based text generation. + +",natural-language-processing +1803,2020-07-11 06:59:08,A Deep Dive into the Wonderful World of Preprocessing in NLP,A glimpse into the surprisingly deep and interesting world of preprocessing in NLP.,natural-language-processing +1813,2020-07-11 07:45:01,Pytest,"The pytest framework makes it easy to write small tests, yet scales to support complex functional testing + +",mlops +1817,2020-07-11 07:55:23,Artifacts - Weights & Biases,"Effortless pipeline tracking and production model management + +",mlops +1818,2020-07-11 08:07:35,DeepkitAI,The Open-Source Machine Learning Devtool and Training Suite.,mlops +1819,2020-07-11 08:14:03,Neptune.ai,The most lightweight experiment management tool that fits any workflow.,mlops +1820,2020-07-11 08:17:17,Rasa,An open source machine learning framework to automate text-and voice-based conversations. ,natural-language-processing +1831,2020-07-11 11:36:26,TF Sprinkles,Fast and efficient sprinkles augmentation implemented in TensorFlow.,computer-vision +1834,2020-07-11 17:19:43,Laplacian Pyramid Reconstruction and Refinement for Semantic Seg., Pytorch implementation of multi-resolution reconstruction architecture based on a Laplacian pyramid that uses skip connections.,computer-vision +1836,2020-07-11 18:15:19,Training a pets detector model with TFOD API (TF 2),"In this notebook, we will be training a custom object detection model using the latest TensorFlow Object Detection (TFOD) API which is based on TensorFlow 2.2. ",computer-vision +1840,2020-07-12 00:59:27,TensorFlow 2 meets the Object Detection API,TF Object Detection API (OD API) officially supports TensorFlow 2!,computer-vision +1843,2020-07-12 13:35:20,Cortex,Build machine learning APIs.,mlops +1844,2020-07-12 16:24:10,Semi-Supervised Learning in Computer Vision,A comprehensive overview of recent semi-supervised learning methods in Computer Vision,computer-vision +1845,2020-07-12 21:42:52,Face Predicting Web App,Interactive Deep Learning Model that utilizes your computer webcam to predict your age and gender in seconds! ,computer-vision +1847,2020-07-13 03:46:32,Driver Identification Based on Vehicle's telematics data,"In this paper, we proposed a deep learning model, which can identify drivers from their driving behaviors based on vehicle telematics data.",computer-vision +1848,2020-07-13 05:00:40,Comprehensive analysis of important metrics in ML,"In this work, the authors present a comprehensive analysis of important metrics in practical applications.",computer-vision +1851,2020-07-13 15:21:13,StreamAlert,"A serverless, realtime data analysis framework which empowers you to ingest, analyze, and alert on data from any environment, using datasources and alerts.",mlops +1855,2020-07-14 03:17:25,ULMFiT Airline Sentiment Analysis,Transfer Learning using pretrained ULMFiT model,natural-language-processing +1856,2020-07-14 03:21:00,DeepDream Video Style Transfer,DeepDream on Video,computer-vision +1859,2020-07-14 04:01:18,"You Trained a Machine Learning Model, Now What?","Three often overlooked parts of this process occur after the model is actually built: model evaluation, deployment, and monitoring.",mlops +1860,2020-07-14 09:53:19,NSFW Image Moderation Automation Engine built with TensorFlow.JS ,"An open-source NSFW Image Classifier including an Automation Engine for fast deletion & moderation built with Node.js, TensorFlow, and Parse Server",computer-vision +1865,2020-07-14 22:55:08,PDFTableExtract,Build a parser to extract the table in PDF document with RetinaNet,computer-vision +1867,2020-07-14 23:03:02,YOLOv4 With TensorFlow,"YOLOv4, YOLOv4-tiny, YOLOv3, YOLOv3-tiny Implemented in Tensorflow 2.0, Android. Convert YOLO v4 .weights tensorflow, tensorrt and tflite.",computer-vision +1868,2020-07-15 03:52:31,Selfie2Anime with TFLite,An end-to-end tutorial with TensorFlow Lite for Selfie2Anime (U-GAT-IT). ,computer-vision +1869,2020-07-15 20:31:37,Bridging PyTorch and TVM,"Taking Hugging Face transformer BERT from PyTorch and running it on +ApacheTVM for both inference (with reasonable timings) and training.",natural-language-processing +1871,2020-07-16 03:58:21,Summarize a webapge,A Flask application that extracts and summarizes webpage using Natural Language Processing. Powered by nlp-akash.,natural-language-processing +1872,2020-07-16 04:19:37,An Icon Classifier with TensorFlow Lite Model Maker,An Icon Classifier with TensorFlow Lite Model Maker,computer-vision +1879,2020-07-16 17:40:33,Cross-lingual Transfer Learning - Sebastian Ruder,"An overview of approaches that transfer knowledge across languages and enable us to scale NLP models to more of the world's 7,000 languages.",natural-language-processing +1880,2020-07-16 17:43:48,AdapterHub: A Framework for Adapting Transformers,Huggingface Transformers + Adapters,natural-language-processing +1882,2020-07-16 17:51:48,Object Detection with RetinaNet,Implementing RetinaNet: Focal Loss for Dense Object Detection.,computer-vision +1884,2020-07-17 01:41:33,Deploying your ML Model with TorchServe,"In this talk, Brad Heintz walks through how to use TorchServe to deploy trained models at scale without writing custom code. ",mlops +1886,2020-07-17 08:27:56,Medical Zoo - 3D Multi-modal Medical Image Segmentation,My articles on deep learning in medical imaging,computer-vision +1887,2020-07-17 16:48:13,Computer Vision Pretrained Models,A collection of computer vision pre-trained models.,computer-vision +1889,2020-07-17 17:20:20,NLP Pretrained Models,"A collection of Natural language processing pre-trained models. + +",natural-language-processing +1896,2020-07-19 00:40:37,Machine Learning Production Pipeline,"Project Flow and Landscape +",mlops +1898,2020-07-19 00:47:53,Tempering Expectations for GPT-3 and OpenAI’s API,"A closer look at the ""magic"" behind GPT-3 and caveats to be aware of.",natural-language-processing +1899,2020-07-19 03:59:41,StyleGAN Encoder,Encodes real images into the latent space of a StyleGAN model.,computer-vision +1900,2020-07-19 04:12:40,WikiArt StyleGAN 2 Model,A conditional StyleGAN 2 model trained on images from WikiArt,computer-vision +1902,2020-07-19 10:19:24,Indian Paper Currency Prediction,"The trained model takes an image (Indian Paper Currency) as an input and predict the class of image from 10, 20, 50, 100, 200, 500, 2000 denomination.",computer-vision +1903,2020-07-19 11:31:25,"Neural Style Transfer (Gatys et al., PyTorch)",My implementation of the original neural style transfer paper by Gatys et al. (In PyTorch).,computer-vision +1904,2020-07-19 12:44:53,Implementation of Face Net in TensorFlow - 2.0,This repository is a naive unofficial implementation of Face Net paper - 2015 .This implementation opts online mode of semi - hard triplet mining.,computer-vision +1910,2020-07-19 15:44:21,Azure Machine Learning Template,Azure Machine Learning template for MNIST classifier,mlops +1913,2020-07-19 16:55:33,Teachable Machine (Image Classifier),A teachable image classifier that runs on any browser built using TensorFlow JS.,computer-vision +1914,2020-07-19 16:59:37,TensorFlow JS- Object Detection in Browser,A real-time object detection model in your browser using TensorFlow JS.,computer-vision +1916,2020-07-20 00:01:38,How to Stop Worrying About Compositionality,"Review the tenets of compositionality, and to highlight how each theory has evolved to match particular theoretical positions about the nature of language.",natural-language-processing +1918,2020-07-20 05:48:38,Spacy-Go,spacy-go is Golang interface for accessing linguistic annotations provided by spaCy using Google's gRPC. This module only supports basic functionalities like lo,natural-language-processing +1919,2020-07-20 05:53:12,Dframcy,DframCy is a light-weight utility module to integrate Pandas Dataframe to spaCy's linguistic annotation and training tasks.,natural-language-processing +1921,2020-07-20 14:04:48,NSFW Image Moderation Admin App with ReactJS,"A fully-functional NSFW Admin Application for simplified image classification & moderation built with Node.js, TensorFlow.js, and React",computer-vision +1923,2020-07-20 18:59:04,PyTorch Geometric Temporal,A Temporal Extension Library for PyTorch Geometric ,graph-learning +1924,2020-07-20 20:34:47,Why is it Important to Monitor Machine Learning Models?,The importance of monitoring and how monitoring ML is different from application performance management (APM).,mlops +1925,2020-07-20 20:54:00,PyTorch Implementation of PaletteNet,"PyTorch implementation of PaletteNet: Image Recolorization with Given Color Palette (Cho et al., 2017).",computer-vision +1927,2020-07-20 21:21:12,ECG arrhythmia classification using a convolutional neural net,This is an implementation of the paper on ECG arrhythmia classification https://arxiv.org/pdf/1804.06812.pdf.,computer-vision +1929,2020-07-20 23:55:33,Structured Self Attention,Implementation for the paper A Structured Self-Attentive Sentence Embedding (https://arxiv.org/abs/1703.03130 ). Model interpretability / explainability.,natural-language-processing +1933,2020-07-21 01:42:42,TurboTransformers,A fast and user-friendly runtime for transformer inference on CPU and GPU.,natural-language-processing +1938,2020-07-21 11:50:53,Rasa NLU Examples,Experimental components for Rasa NLU pipelines. ,natural-language-processing +1940,2020-07-21 19:01:54,Change Detection using Siamese networks,"The blog is a primer on Siamese Networks and how they're used for observing change in satellite images over time, or observing facial changes as people age",computer-vision +1941,2020-07-21 19:13:05,My Artificial Intelligence Bookmarks,"A curated list of my reads, implementations, and core concepts of Artificial Intelligence, Deep Learning, Machine Learning by best folk in the world.",natural-language-processing +1943,2020-07-22 03:32:30,Do we Need Deep Graph Neural Networks?,Does depth in graph neural network architectures bring any advantage?,graph-learning +1945,2020-07-22 03:39:13,Pandera,A flexible and expressive pandas data validation library.,mlops +1952,2020-07-24 06:28:15,TensorFlow Serving,"A flexible, high-performance serving system for machine learning models, designed for production environments. ",mlops +1953,2020-07-24 06:30:44,BentoML,BentoML is an open-source framework for high-performance ML model serving.,mlops +1954,2020-07-24 06:43:59,Azure ML,MLOps using Azure ML.,mlops +1955,2020-07-24 06:47:29,Shape and Viewpoint without Keypoints,"Recover the 3D shape, pose and texture from a single image, trained on an image collection without any ground truth 3D shape, multi-view, camera viewpoints.",computer-vision +1965,2020-07-25 02:58:40,model-logger,Model-Logger is a Python library for storing model's profile and rapid inter model comparison.,mlops +1968,2020-07-26 04:48:40,Sentiment Analysis With Transformers,"Sentiment analysis neural network trained by fine-tuning BERT, ALBERT, or DistilBERT on the Stanford Sentiment Treebank.",natural-language-processing +1971,2020-07-27 02:30:42,Attention based YOLO: Object Detection,"An easy to follow, YOLO implementation with keras lib. Used a attention based architecture to extract more fine grained information about object.",computer-vision +1977,2020-07-27 14:14:10,LabelDetection: simplifying the use and construction of deep dete,LabelDetection is a graphical tool that aims to facilitate all the steps required in the pipeline to construct and use a deep-learning base object detection mod,computer-vision +1978,2020-07-27 14:34:12,How to Set Up a Python Project For Automation and Collaboration,"How to set up a Python repo with unit tests, code coverage, lint checking, type checking, Makefile wrapper, and automated build with GitHub Actions.",mlops +1980,2020-07-27 14:51:03,Understanding & Implementing SimCLR - an ELI5 guide,"I explain the SimCLR and its contrastive loss function step by step, build image embeddings and then show how to use them to train image classifier on top.",computer-vision +1983,2020-07-28 04:14:12,CoreML Model Zoo,Collection of unified and converted pre-trained models.,computer-vision +1984,2020-07-28 04:18:00,How GPT3 Works - Visualizations and Animations,A compilation of my threads explaining GPT3. ,natural-language-processing +1985,2020-07-28 04:19:58,Temporal Graph Networks,"In this post, we describe Temporal Graph Network, a generic framework for deep learning on dynamic graphs.",graph-learning +1986,2020-07-28 07:44:13,Behavioral Testing of NLP models with CheckList,An overview of the “CheckList” framework for fine-grained evaluation of NLP models,natural-language-processing +1992,2020-07-29 03:41:04,Time series forecasting,A thorough introduction to time series forecasting using TensorFlow.,time-series +1993,2020-07-29 04:47:55,Real-time text detection with EAST in TFLite,Demonstrates the conversion process from the original EAST model to TFLite and how to use it on static images and also on real-time video feeds. ,computer-vision +1994,2020-07-29 04:51:30,Understanding the Effectivity of Ensembles in Deep Learning,"The report explores the ideas presented in Deep Ensembles: A Loss Landscape Perspective by Stanislav Fort, Huiyi Hu, and Balaji Lakshminarayanan.",computer-vision +1999,2020-07-30 03:57:32,Small differences in BLEU are meaningless,Only big differences in metric scores are meaningful in MT.,natural-language-processing +2002,2020-07-30 04:08:46,Multi-target in Albumentations,"Many images, many masks, bounding boxes, and key points. How to transform them in sync?",computer-vision +2005,2020-07-30 11:19:02,Social Distance Detection,"If people are very close to each other, a red bounding box is displayed around them indicating that they are not maintaining social distance.",computer-vision +2006,2020-07-30 11:30:56,Deep Learning Techniques for NLP in Healthcare,A talk discussing the recent advancements of deep learning to facilitate the adaption of NLP in the healthcare domain.,natural-language-processing +2008,2020-07-30 14:50:30,Extension to block NSFW content using AI,"NSFW Filter is an extension that blocks NSFW content from your browser. +It uses a computer vision model to detect NSFW content and hides it from the user.",computer-vision +2009,2020-07-30 14:55:57,ATLASS: AutoML using Transfer and Semi-Supervised Learning,"This repository includes the code, application, and notebooks for the work ""AutoML using Transfer and Semi-Supervised Learning"". The tools presented here can be",computer-vision +2012,2020-07-30 15:04:28,LabelStoma: stomata detection using YOLO,LabelStoma is a graphical image tool for automatically detecting stomata in images. ,computer-vision +2013,2020-07-30 15:07:54,DeepClas4Bio,DeepClas4Bio is a project that aims to facilitate the interoperability of bioimaging tools with deep learning frameworks.,computer-vision +2016,2020-07-31 15:30:38,Meme Classifier Using TFlite and flutter,Meme classifier using fine tuned mobilenet. This app showcases how you can perform low latency realtime classification apps using TFlite,computer-vision +2020,2020-08-01 12:14:26,Text Summarization using TF-IDF Algorithm,This Article explains the TF-IDF algorithm and shows the implemtnation from scratch to summarize the text.,natural-language-processing +2022,2020-08-01 14:41:37,Simple Transformers,"Transformers for Classification, NER, QA, Language Modeling, Language Generation, T5, Multi-Modal, and Conversational AI.",natural-language-processing +2024,2020-08-01 14:49:31,DeText: A Deep Neural Text Understanding Framework,DeText: A Deep Neural Text Understanding Framework for Ranking and Classification Tasks.,natural-language-processing +2026,2020-08-01 15:04:37,Efficient Serverless Deployment of PyTorch Models on Azure,A tutorial for serving models cost-effectively at scale using Azure Functions and ONNX Runtime.,mlops +2027,2020-08-01 15:27:29,Nearest Celebrity Face,Implementation of FaceNet: A Unified Embedding for Face Recognition and Clustering to find the celebrity whose face matches the closest to yours. The input face,computer-vision +2030,2020-08-02 12:38:08,A Few Favorite Recipes in Computer Vision & Deep Learning,This blog post enlists a few of my favorite recipes in deep learning in the context of computer vision (as of August 2020).,computer-vision +2031,2020-08-02 14:46:10,NeuralQA - API and Visual Interface for Extractive QA,A Usable Library for Question Answering on Large Datasets with BERT,natural-language-processing +2032,2020-08-02 20:00:23,Object tracking in 75 lines of code,"Object tracking is straightforward conceptually. And if you have a good detector, simple methods can be pretty effective.",computer-vision +2033,2020-08-03 03:49:22,FARM: Framework for Adapting Representation Models,🏡 Fast & easy transfer learning for NLP. Harvesting language models for the industry.,natural-language-processing +2035,2020-08-04 02:49:24,Act - GitHub Actions locally,Run your GitHub Actions locally.,mlops +2038,2020-08-04 03:53:36,Curated papers & articles on DS & ML in production,"Learn how organizations & business solved machine learning problems, including problem statement, research, methodology, and results.",mlops +2039,2020-08-04 16:45:09,Tensorflow2 Object Detection Tutorial,"In this tutorial, we will be going step by step the complete training process of Tensorflow2 Object Detection. ",computer-vision +2042,2020-08-05 02:07:24,ONNX T5,"Summarization, translation, Q&A, text generation and more at blazing speed using a T5 version implemented in ONNX.",natural-language-processing +2043,2020-08-05 02:17:10,DeLighT: Very Deep and Light-weight Transformers,Similar or better performance than transformer-based models with significantly fewer parameters,natural-language-processing +2045,2020-08-05 06:40:32,Evaluation Metrics For Information Retrieval,Learn about common metrics used to evaluate performance of information retrieval systems,natural-language-processing +2047,2020-08-05 15:18:46,Test-Time Data Augmentation,Tutorial on how to properly implement test-time image data augmentation in a production environment with limited computational resources.,mlops +2048,2020-08-05 16:50:22,SadedeGel: An extraction based Turkish news summarizer,"""Sadede Gel"" in Turkish, means ""cut to the chase"". ",natural-language-processing +2051,2020-08-05 20:13:51,MobyDick word frequency,Getting the count of the words in Moby Dick story using both web scraping and NLP,natural-language-processing +2053,2020-08-05 20:30:33,Image Classification with Keras,Build a pipeline to train an image classifier in Keras and tune hyperparameters to optimize the performance of our classifier.,computer-vision +2054,2020-08-05 20:34:09,Dropout in PyTorch – An Example,"An example of adding Dropout to a PyTorch model, and observe the effect dropout has on the model's performance by tracking our models in Weights & Biases.",computer-vision +2057,2020-08-06 04:06:11,"Data Science Meets Devops: MLOps with Jupyter, Git, & Kubernetes","An end-to-end example of deploying a machine learning product using Jupyter, Papermill, Tekton, GitOps and Kubeflow.",mlops +2061,2020-08-06 04:59:21,Detectron 2 Demo from Facebook,This Project contains the process of getting started with Facebook FAIR's detectron2 project on windows 10 without any Nvidia GPU.,computer-vision +2062,2020-08-06 12:38:55,Predict Vehicle Speed From Dash Cam Video,A series of experiments attempting to predict vehicle speed from dash cam videos using optical flow and neural networks.,computer-vision +2098,2020-08-06 23:15:45,Digital Image Processing in Python,Play around with pixel values with Python programming language.,computer-vision +2100,2020-08-07 04:24:28,A 2020 guide to Semantic Segmentation,"Concept of image segmentation, discuss the relevant use-cases, different neural network architectures involved in achieving the results, metrics and datasets.",computer-vision +2106,2020-08-08 15:06:18,Fast NST for Videos (+ person segmentation) 🎥 + ⚡💻 + 🎨 = ❤️,Create NST videos and pick separate styles for the person in the video and for the background.,computer-vision +2109,2020-08-09 07:24:57,Live demo : State-of-the-art MCQ Generator from any content,"Demo for state-of-the-art MCQ (Multiple Choice Questions) generator from any content built using T5 transformer, HuggingFace, and Sense2vec +",natural-language-processing +2111,2020-08-10 03:26:16,InvoiceNet,"Deep neural network to extract intelligent information from PDF invoice documents. +",computer-vision +2112,2020-08-10 03:41:31,Search for visual datasets,"By task, application, class, label or format.",computer-vision +2113,2020-08-10 04:01:03,GAN-BERT,Enhancing the BERT training with Semi-supervised Generative Adversarial Networks.,natural-language-processing +2114,2020-08-10 04:03:51,tsaug,A Python package for time series augmentation.,time-series +2116,2020-08-10 04:15:38,Machine Learning Pipelines for Kubeflow.,Kubeflow pipelines are reusable end-to-end ML workflows built using the Kubeflow Pipelines SDK.,mlops +2117,2020-08-10 04:17:57,Structuring Unit Tests in Python,"Where to put tests, how to write fixtures and the awesomeness of test parametrization.",mlops +2121,2020-08-10 21:59:41,DeepR — Training TensorFlow Models for Production,DeepR is a Python library to build complex pipelines as easily as possible on top of Tensorflow.,mlops +2124,2020-08-11 00:20:42,Neural Architecture Search,"A look at neural architecture search w.r.t search space, search algorithms and evolution strategies.",reinforcement-learning +2135,2020-08-13 01:52:06,Temporal Convolutional Networks for Time-Series,"We introduce several novels using TCN, including improving traffic prediction, sound event localization & detection, and probabilistic forecasting.",time-series +2136,2020-08-13 02:05:11,Machine Learning Deployment: Shadow Mode,"“How do I test my new model in production?” One answer, and a method I often employ when initially deploying models, is shadow mode.",mlops +2138,2020-08-13 18:12:46,Extract Stock Sentiment from News Headlines," In this project, you will generate investing insight by applying sentiment analysis on financial news headlines from Finviz. ",natural-language-processing +2141,2020-08-14 03:15:38,hloc - the hierarchical localization toolbox,Visual localization made easy.,computer-vision +2147,2020-08-15 01:17:07,Practical Tips and Tricks for Successful Transfer Learning,Training models to learn knowledge and skills from other related tasks that will transfer and boost performance on tasks of interest.,natural-language-processing +2148,2020-08-15 01:22:01,txtai: AI-powered search engine,AI-powered search engine.,natural-language-processing +2151,2020-08-15 05:32:22,Drowsiness Detection System using OpenCV and Flask in Python ,"This system provides an overview of a system that detects whether a person is drowsy while driving and if so, alerts him by using voice messages in real-time. ",computer-vision +2155,2020-08-15 14:49:16,"GPT-3, The model simply knows!",Brief Introduction about the gigantic GPT-3. a new leap in AI and Natural Language processing. ,natural-language-processing +2159,2020-08-16 01:02:18,Solaris,CosmiQ Works Geospatial Machine Learning Analysis Toolkit.,computer-vision +2163,2020-08-17 03:19:46,Safe Space - Github Action,Github action that checks the toxicity level of comments and PR reviews to help make repos safe spaces.,natural-language-processing +2164,2020-08-17 03:24:46,Intro to Autoencoders,"This tutorial introduces autoencoders with three examples: the basics, image denoising, and anomaly detection.",computer-vision +2166,2020-08-17 05:19:41,Pix2Pix,"Tensorflow 2.0 Implementation of the paper Image-to-Image Translation using Conditional GANs by Philip Isola, Jun-Yan Zhu, Tinghui Zhou and Alexei A. Efros.",computer-vision +2167,2020-08-17 06:27:31,Insight,Project Insight is designed to create NLP as a service with code base for both front end GUI (streamlit) and backend server (FastAPI) the usage of transformers ,natural-language-processing +2168,2020-08-17 10:55:43,Onceupon.space,NLP experiment in story-telling that creates illustrations (text to sketch) and content (text generation),natural-language-processing +2173,2020-08-18 04:16:33,Fine-tuning with custom datasets,This tutorial will take you through several examples of using 🤗 Transformers models with your own datasets.,natural-language-processing +2185,2020-08-18 23:12:27,Language Interpretability Tool (LIT),"The Language Interpretability Tool (LIT) is a visual, interactive model-understanding tool for NLP models.",natural-language-processing +2188,2020-08-19 15:16:46,Great Expectations,Always know what to expect from your data.,mlops +2193,2020-08-20 00:39:05,Effective testing for machine learning systems,"Why testing machine learning systems can be different, and discuss some strategies for writing effective tests for machine learning systems.",mlops +2202,2020-08-22 03:55:27,Graph Representation Learning Book,"Introduction to graph representation learning, including methods for embedding graph data, graph neural networks, and deep generative models of graphs.",graph-learning +2203,2020-08-22 05:58:20,Image Similarity Search in PyTorch,"Simple Convolutional Auto-encoder based image similarity +search to find similar images to given image or features. +Fully written in PyTorch.",computer-vision +2204,2020-08-22 17:19:00,Tensorflow Object Detection with Tensorflow 2,Object Detection with Tensorflow 2 and the Tensorflow Object Detection API ,computer-vision +2207,2020-08-23 04:38:45,Rules of Machine Learning: Best Practices for ML Engineering,A basic knowledge of machine learning get the benefit of best practices in machine learning from around Google.,mlops +2214,2020-08-24 11:16:47,vedaseg,vedaseg is an open source semantic segmentation toolbox based on PyTorch.,computer-vision +2215,2020-08-24 11:52:10,vedastr,vedastr is an open source scene text recognition toolbox based on PyTorch.,computer-vision +2218,2020-08-25 13:57:49,CascadeTabNet,"An approach for end-to-end table detection and structure recognition from image-based documents +",computer-vision +2220,2020-08-25 16:13:31,"Table Detection, Information Extraction and Structuring using ML",Table Extraction (TE) is the task of detecting and decomposing table information in a document.,natural-language-processing +2223,2020-08-26 04:21:37,AxCell,Automatic Extraction of Results from Machine Learning Papers,computer-vision +2226,2020-08-27 01:54:16,Hyperparameter Optimization for 🤗 Transformers: A Guide,"Basic grid search is not the most optimal, and in fact, the hyperparameters we choose can have a significant impact on our final model performance.",natural-language-processing +2235,2020-08-27 16:03:12,Shift-Ctrl-F: Semantic Search for the Browser,🔎: Search the information available on a webpage using natural language instead of an exact string match.,natural-language-processing +2238,2020-08-28 01:24:08,Spinning Up in Deep RL (OpenAI),An educational resource to help anyone learn deep reinforcement learning.,reinforcement-learning +2239,2020-08-28 07:07:39,An Introduction to Adversarial Examples in Deep Learning,"This report provides an intuitive introduction to adversarial examples, discusses a wide variety of different adversarial attacks and, most notably, provides ad",computer-vision +2242,2020-08-29 08:10:21,Deep dive into ROI layer in Object Detection Models,In this blog post we will implement in torch ROI Pool and ROI Align models from scratch.,computer-vision +2245,2020-08-30 02:51:07,On the Bottleneck of Graph Neural Networks and its Implications,The mechanism of propagating information between neighbors creates a bottleneck when every node aggregates messages from its neighbors.,graph-learning +2247,2020-08-30 11:48:19,Unsupervised Keyphrase Extraction,Learn about unsupervised algorithms for automatically extracting representative keyword and phrases from documents,natural-language-processing +2251,2020-08-31 10:05:12,Practical AI: Using NLP word embeddings to solve localization ,"Using NLP word vectors (word2vec, glove, etc) in a novel way to solve the problem of localization in edtech.",natural-language-processing +2252,2020-08-31 23:40:26,Explore then Execute,Adapting without Rewards via Factorized Meta-Reinforcement Learning,reinforcement-learning +2255,2020-09-01 04:49:38,"Tensorflow, Pytorch, Transformer, Fastai, etc. Tutorials","BERT Classification, Question Answering, Seq2Seq Machine Translation, Contextual Topic Modeling, Large Scale Multilabelclassification, etc",natural-language-processing +2258,2020-09-02 09:05:08,Graph Convolutions for dummies,An article explaining Graph Convolutional Networks as simply as possible.,graph-learning +2259,2020-09-02 23:08:03,ECCV 2020: Some Highlights,A sort of a snapshot of the conference by summarizing some papers (& listing some) that grabbed my attention.,computer-vision +2260,2020-09-02 23:13:20,CVPR 2020: A Snapshot,A snapshot of the conference by summarizing some papers (& listing some) that grabbed my attention.,computer-vision +2263,2020-09-03 23:05:32,TTT: Fine-tuning Transformers with TPUs or GPUs acceleration,"TTT is short for a package for fine-tuning 🤗 Transformers with TPUs, written in Tensorflow2.0+.",natural-language-processing +2264,2020-09-04 01:24:22,MushroomRL,Python library for Reinforcement Learning.,reinforcement-learning +2267,2020-09-04 02:50:39,What Is MLOps?,"Machine learning operations, MLOps, are best practices for businesses to run AI successfully with help from an expanding software products and cloud services.",mlops +2268,2020-09-05 01:06:07,NLP Course | For You,This is an extension to the (ML for) Natural Language Processing course I teach at the Yandex School of Data Analysis (YSDA) since fall 2018. ,natural-language-processing +2269,2020-09-05 01:09:06,Learning to Summarize with Human Feedback,Human feedback models outperform much larger supervised models and reference summaries on TL;DR,natural-language-processing +2273,2020-09-05 18:22:44,ONNX Transformers,Accelerated NLP pipelines for fast inference 🚀 on CPU. Built with 🤗 Transformers and ONNX runtime.,natural-language-processing +2275,2020-09-06 07:26:21,hugdatafast: huggingface/nlp + fastai,The elegant integration of huggingface/nlp and fastai2 and handy transforms using pure huggingface/nlp ,natural-language-processing +2280,2020-09-06 18:59:46,Top 10 Deep Learning Breakthroughs — Deep Reinforcement Learning,The article unravels the journey behind reaching the point when Reinforcement Learning combined with Deep Learning defeated a Go player world champion.,reinforcement-learning +2283,2020-09-07 07:13:04,Data analysis made easy: Text2Code for Jupyter notebook,A jupyter notebook extension for Text2Code for basic pandas and plotly commands,natural-language-processing +2284,2020-09-07 10:42:32,electra_pytorch: ELECTRA in PyTorch (fastai + huggingface),Unofficial reimplementation of ,natural-language-processing +2285,2020-09-07 13:36:55,Images of radio boxes,I have collected about 15+k raw images of radio boxes across 500+ forms and hand-picked 200+ images that can be used to determine if a radio box is checked.,computer-vision +2287,2020-09-07 20:56:51,omega|ml - building and deploying ML models the easy way,Deploying ML is hard. It should not be. omega|ml makes it a breeze.,mlops +2290,2020-09-09 00:16:32,Fine-tune a non-English GPT-2 Model with Huggingface," In this tutorial, we are going to use the transformers library by Huggingface. We will use the new Trainer class and fine-tune out GPT-2 model.",natural-language-processing +2294,2020-09-09 16:14:37,Getting started with large-scale ETL jobs using Dask and AWS EMR,"EMR is AWS’s distributed data platform, which we can interact with and submit jobs to from a JupyterLab notebook running on our local machine.",mlops +2295,2020-09-09 16:36:45,How to Create a Cartoonizer with TensorFlow Lite?,An end-to-end tutorial on how to convert to TensorFlow Lite (TFLite) model and deploy it to an Android app for cartoonizing an image captured by camera.,computer-vision +2296,2020-09-10 01:15:57,How to Test Machine Learning Code and Systems,"🚦 Minimal examples of testing machine learning for correct implementation, expected learned behaviour, and model performance. + +",mlops +2298,2020-09-11 00:02:10,torchCDE,Differentiable controlled differential equation solvers for PyTorch with GPU support and memory-efficient adjoint backpropagation.,time-series +2299,2020-09-11 00:07:11,Latent graph neural networks: Manifold learning 2.0?,Parallels between recent works on latent graph learning and older techniques of manifold learning.,graph-learning +2300,2020-09-11 00:11:14,Real Python Recommendation Engine,A full stack data science project that performs document similarity on RealPython.com content. Content recommendations are implemented via a Chrome extension.,natural-language-processing +2304,2020-09-11 17:54:04,Graph Neural Networks,A descriptive guide for Graph Neural Networks.,graph-learning +2317,2020-09-14 05:32:45,End-to-end Object Detection in TensorFlow Lite,"This project shows how to train a custom detection model with the TFOD API, optimize it with TFLite, and perform inference with the optimized model.",computer-vision +2318,2020-09-14 11:55:33,Jepto - Digital Marketing Analytics,KPI Prediction and Anomaly Detection of digital marketing data for both technical and non-technical marketers and business owners.,time-series +2319,2020-09-14 19:21:33,Cartoonizer with TensorFlow.js,An app to turn your photos into cartoon-styled images 🎨 within your browsers using White-box Cartoonization GAN.,computer-vision +2325,2020-09-16 13:43:20,Implementing Content-Based Image Retrieval with Siamese Networks,"With content-based image retrieval, we refer to the task of finding images containing attributes which are not in the image metadata, but in its visual content.",computer-vision +2326,2020-09-17 00:18:51,NLP for Developers: Multilingual NLP | Rasa,"In this video, Rasa Developer Advocate Rachael will talk about common approaches to handle language input in more than one language.",natural-language-processing +2327,2020-09-17 15:36:45,Paint with Machine Learning,This web app allows you to create a landscape painting in the style of Bob Ross using a deep learning model served using a Spell model server.,computer-vision +2328,2020-09-17 16:04:29,Distilling Knowledge in Neural Networks,This project demonstrates the compelling model optimization technique - knowledge distillation with code walkthroughs in TensorFlow. ,computer-vision +2332,2020-09-18 08:49:55,Recurrent Neural Networks: building GRU cells VS LSTM cells ,What are the advantages of RNN’s over transformers? When to use GRU’s over LSTM? What are the equations of GRU really mean? How to build a GRU cell in Pytorch?,natural-language-processing +2341,2020-09-20 00:34:03,PyTorch Forecasting,Time series forecasting with PyTorch.,time-series +2342,2020-09-20 03:24:58,Norfair,Lightweight Python library for adding real-time 2D object tracking to any detector.,computer-vision +2344,2020-09-21 00:20:00,Labelai,"Labelai is an online tool designed to label images, useful for training AI models.",computer-vision +2345,2020-09-21 00:26:02,Remo,🐰 Python lib for remo - the app for annotations and images management in Computer Vision.,computer-vision +2348,2020-09-21 23:47:06,Layered Neural Rendering for Retiming People in Video,Manipulating and editing the time in which different motions of individuals in the video occur.,computer-vision +2351,2020-09-22 03:42:58,Simple Transformers: Transformers Made Easy,Simple Transformers removes complexity and lets you get down to what matters – model training and experimenting with the Transformer model architectures.,natural-language-processing +2353,2020-09-22 13:04:04,TF Geometric,Efficient and Friendly Graph Neural Network Library for TensorFlow 1.x and 2.x.,graph-learning +2356,2020-09-23 04:56:15,"Part 2: Deep Representations, a way towards neural style transfer",A top-down approach to conceiving neural style transfer,computer-vision +2357,2020-09-23 10:27:15,Sudoku Solver,Solving Sudoku by extracting the puzzle from photo using Computer Vision and OCR and solving it.,computer-vision +2360,2020-09-23 13:56:29,"3D Face: Fast, Accurate and Stable Reconstruction","This work extends the previous work 3DDFA, named 3DDFA_V2, titled Towards Fast, Accurate and Stable 3D Dense Face Alignment, accepted by ECCV 2020. ",computer-vision +2368,2020-09-25 07:47:27,TableQA,AI tool for querying natural language on tabular data like csvs and other dataframes.,natural-language-processing +2369,2020-09-25 15:44:08,GP-GAN: Towards Realistic High-Resolution Image Blending,Blending composite images using a generative model and a Gaussian-Poisson equation with a Laplacian Pyramid,computer-vision +2371,2020-09-25 18:10:13,From Research to Production with Deep Semi-Supervised Learning,Semi-Supervised Learning (SSL) has blossomed in the deep learning research community — we share lessons learned over 15 months of taking SSL into production.,mlops +2372,2020-09-25 18:39:59, A spaced repetition app for keeping your reinforcement learning,We aim to keep your reinforcement learning knowledge fresh by periodically reminding you of concepts making you a master of RL knowledge!!,reinforcement-learning +2373,2020-09-25 22:41:22,GraphNorm,A Principled Approach to Accelerating Graph Neural Network Training.,graph-learning +2384,2020-09-27 08:42:46,Intro to Facebook Prophet,Everything you need to know when starting out with Facebook’s time series forecasting tool,time-series +2387,2020-09-27 14:22:51,GitHub Actions for Machine Learning,This presentation discusses the use of GitHub Actions to automate certain steps of a toy ML project. ,mlops +2388,2020-09-27 22:09:32,SemTorch,Different deep learning architectures definitions that can be applied to image segmentation.,computer-vision +2389,2020-09-28 05:34:15,bingoset - CLI tool to create image dataset.,CLI Toolkit to quickly create an image dataset using Bing Image Search API.,computer-vision +2395,2020-09-28 22:51:23,Python caching in GitHub Actions,How to speed up slow Python builds in GitHub Actions with effective caching.,mlops +2396,2020-09-29 00:36:12,EfficientDet meets Pytorch Lightning,Beginner friendly guide to object detection using EfficientDet.,computer-vision +2397,2020-09-29 02:15:46,Optimizing MobileDet for Mobile Deployments,Learn about the criticalities of effectively optimizing MobileDet object detectors for mobile deployments.,computer-vision +2402,2020-09-30 22:11:07,Adapting Text Augmentation to Industry Problems,"In this post I will talk about the recent advances in exploiting language models for data generation and also show how, where we can implement them in Industry.",natural-language-processing +2404,2020-09-30 22:22:07,12 Factors of Reproducible Machine Learning in Production,We took our experience to deduce 12 factors (as a nod to the 12 factor app) that build the backbone of successful ML in production.,mlops +2410,2020-10-01 13:42:23,Serving PyTorch models in production with the Amazon SageMaker,TorchServe is now natively supported in Amazon SageMaker as the default model server for PyTorch inference. ,mlops +2411,2020-10-01 14:55:12,How to Make Sense of the Reinforcement Learning Agents?,What and Why I Log During Training and Debug?,reinforcement-learning +2412,2020-10-01 18:50:05,Introduction to 3D Medical Imaging: Preprocessing & Augmentations,"Learn how to apply 3D transformations for medical image preprocessing and augmentation, to setup your awesome deep learning pipeline.",computer-vision +2415,2020-10-01 23:55:36,Explainable ML Monitoring,"The video covers an overview of some of the risks of AI, the need for explainable monitoring, and what exactly we mean when we talk about it.",mlops +2417,2020-10-02 09:44:25,Parallelizing Prophet Cross-Validation with Dask,Applied Example w/ Code,time-series +2418,2020-10-02 10:16:17,Top Research Papers from the ECML-PKDD 2020 Conference,ECML-PKDD -> selectionof the best reaesch papers,reinforcement-learning +2419,2020-10-02 15:37:27,GANs in Computer Vision Free Ebook / Article-series,This free ebook/article-series follows the chronological order of 20 peer-reviewed highly-cited papers as they presented in a series of 6 articles.,computer-vision +2422,2020-10-02 21:48:21,Pattern-Exploiting Training (PET),"This repository contains the code for ""Exploiting Cloze Questions for Few-Shot Text Classification and Natural Language Inference""",natural-language-processing +2423,2020-10-03 20:27:36,Imaginaire,NVIDIA PyTorch GAN library with distributed and mixed precision support.,computer-vision +2430,2020-10-05 10:09:28,Transection: Transformers for English to Chinese Translation 基于t,Tutorials on how to fine-tune a BART based transformer for English to Chinese translation.,natural-language-processing +2431,2020-10-05 12:36:02,A Survey of the State of Explainable AI for NLP,Overview of the operations and explainability techniques currently available for generating explanations for NLP model predictions.,natural-language-processing +2432,2020-10-05 13:09:58,Topic Modeling with BERT,Leveraging 🤗 Transformers and a class-based TF-IDF to create dense clusters allowing for easily interpretable topics. ,natural-language-processing +2434,2020-10-06 02:13:01,OpenMMLab Computer Vision,"MMCV is a python library for CV research and supports many research projects such as object detection, segmentation, pose estimation, action classification. + +",computer-vision +2436,2020-10-06 13:29:44,Machine Learning Methods Explained (+ Examples),Most common techniques used in data science projects; get to know them through easy-to-understand examples and put them into practice in your own ML projects!,reinforcement-learning +2437,2020-10-06 14:53:39,Rasoee,"A powerful web and mobile application that identifies food dishes from a given input image, and provides an ingredient list along with relevant recipes.",computer-vision diff --git a/datasets/holdout.csv b/datasets/holdout.csv new file mode 100644 index 0000000..7f649cd --- /dev/null +++ b/datasets/holdout.csv @@ -0,0 +1,208 @@ +id,created_on,title,description,tag +19,2020-03-03 13:54:31,Diffusion to Vector,Reference implementation of Diffusion2Vec (Complenet 2018) built on Gensim and NetworkX. ,graph-learning +26,2020-03-07 23:11:58,Graph Wavelet Neural Network,"A PyTorch implementation of ""Graph Wavelet Neural Network"" (ICLR 2019) ",graph-learning +44,2020-03-08 00:32:58,Capsule Graph Neural Network,"A PyTorch implementation of ""Capsule Graph Neural Network"" (ICLR 2019).",graph-learning +80,2020-03-20 05:59:32,NeRF: Neural Radiance Fields,Representing scenes as neural radiance fields for view synthesis.,computer-vision +84,2020-03-20 15:18:43,Mention Classifier,"Category prediction model +This repo contains AllenNLP model for prediction of Named Entity categories by its mentions.",natural-language-processing +107,2020-03-21 23:09:03,Plant Fruit Classifier,Building a world-class image classifier model with a custom dataset.,computer-vision +126,2020-03-25 15:05:27,Unet Implementation is Keras with GPU,Vector Map generation from aerial imagery using deep learning GeoSpatial UNET,computer-vision +130,2020-03-25 16:55:31,Gymnast Pose Analysis,"Pose modelling for gymnasts using open-pose and open-cv. +",computer-vision +131,2020-03-25 17:00:54,EfficientDet: Scalable and Efficient Object Detection,Implementation EfficientDet: Scalable and Efficient Object Detection in PyTorch.,computer-vision +136,2020-03-26 17:22:36,Finetune: Scikit-learn Style Model Finetuning for NLP,Finetune is a library that allows users to leverage state-of-the-art pretrained NLP models for a wide variety of downstream tasks.,natural-language-processing +141,2020-03-28 17:41:42,First Order Motion Model for Image Animation,Generating a video sequence so that an object in a source image is animated according to the motion of a driving video.,computer-vision +142,2020-03-28 17:49:20,TorchIO: Medical Image Processing in Deep Learning and PyTorch,Tools for medical image processing in deep learning and PyTorch,computer-vision +144,2020-03-29 18:23:06,Finetuning Transformers with JAX + Haiku,"Walking through a port of the RoBERTa pre-trained model to JAX + Haiku, then fine-tuning the model to solve a downstream task.",natural-language-processing +218,2020-04-06 11:29:57,Distributional RL using TensorFlow2,🐳 Implementation of various Distributional Reinforcement Learning Algorithms using TensorFlow2.,reinforcement-learning +220,2020-04-06 15:19:59,Module 2: Convolutional Neural Networks - CS231n ,In Lecture 5 we move from fully-connected neural networks to convolutional neural networks.,computer-vision +249,2020-04-06 19:20:12,makesense.ai,Free to use online tool for labelling photos.,computer-vision +264,2020-04-06 21:33:32,The Unreasonable Effectiveness of Recurrent Neural Networks,A close look at how RNNs are able to perform so well.,natural-language-processing +268,2020-04-06 21:51:55,A Gentle Introduction to Text Summarization in Machine Learning,Text summarization is the technique for generating a concise and precise summary of voluminous texts while focusing on the sections that convey useful info.,natural-language-processing +285,2020-04-07 03:45:03,A (Long) Peek into Reinforcement Learning,"In this post, we are gonna briefly go over the field of Reinforcement Learning (RL), from fundamental concepts to classic algorithms.",reinforcement-learning +305,2020-04-07 20:00:37,Question Answering with a Fine-Tuned BERT,What does it mean for BERT to achieve “human-level performance on Question Answering”?,natural-language-processing +314,2020-04-08 00:06:21,The Autonomous Learning Library,A PyTorch library for building deep reinforcement learning agents.,reinforcement-learning +317,2020-04-08 00:14:27,COCO Annotator,"✏️ Web-based image segmentation tool for object detection, localization and key points.",computer-vision +328,2020-04-08 14:29:22,ProteinGCN: Protein model quality assessment using GCNs,Source code for the paper: ProteinGCN: Protein model quality assessment using Graph Convolutional Networks.,graph-learning +344,2020-04-08 16:11:28,Tokenizers,💥Fast State-of-the-Art Tokenizers optimized for Research and Production.,natural-language-processing +353,2020-04-08 17:08:41,Keras OCR,A packaged and flexible version of the CRAFT text detector and Keras CRNN recognition model. ,computer-vision +384,2020-04-08 21:22:25,Visualizing Memorization in RNNs,Inspecting gradient magnitudes in context can be a powerful tool to see when recurrent units use short-term or long-term contextual understanding.,natural-language-processing +407,2020-04-08 23:00:02,AllenNLP,"An open-source NLP research library, built on PyTorch.",natural-language-processing +410,2020-04-08 23:09:15,Frameworks for Machine Learning Model Management,This blog post will follow up by comparing three different tools developed to support reproducible machine learning model development.,mlops +414,2020-04-08 23:18:04,TensorBoard.dev ,"Easily host, track, and share your ML experiments for free.",mlops +415,2020-04-08 23:21:13,BertViz,"Tool for visualizing attention in the Transformer model (BERT, GPT-2, Albert, XLNet, RoBERTa, CTRL, etc.)",natural-language-processing +426,2020-04-09 16:37:10,The Transformer Family,"This post presents how the vanilla Transformer can be improved for longer-term attention span, less memory and computation consumption, RL task solving, etc.",natural-language-processing +437,2020-04-10 17:14:11,Pruning Bert to Accelerate Inference,"After previously discussing various ways of accelerating models like BERT, in this blog post we empirically evaluate the pruning approach.",natural-language-processing +438,2020-04-10 17:26:39,Compressing Bert for Faster Prediction,"In this blog post, we discuss ways to make huge models like BERT smaller and faster. ",natural-language-processing +451,2020-04-10 20:10:28,Evaluation Metrics for Language Modeling,"In this article, we will focus on traditional intrinsic metrics that are extremely useful during the process of training the language model itself. ",natural-language-processing +454,2020-04-10 20:27:12,All The Ways You Can Compress BERT,In this post I’ll list and briefly taxonomize all the papers I’ve seen compressing BERT. ,natural-language-processing +458,2020-04-10 20:58:41,"Limitations of Deep Learning for Vision, and How We Might Fix The",This is an opinion paper about the strengths and weaknesses of Deep Nets for vision.,computer-vision +487,2020-04-14 21:15:35,Face Alignment in Full Pose Range: A 3D Total Solution,Face Alignment in Full Pose Range: A 3D Total Solution.,computer-vision +488,2020-04-14 21:21:51,V2V-PoseNet Pytorch,PyTorch implementation of V2V-PoseNet with IntegralPose/PoseFix loss.,computer-vision +496,2020-04-14 23:14:59,Fast- Neural Style,Pytorch implementation of an algorithm for artistic style transfer. ,computer-vision +497,2020-04-14 23:21:16,Torchvision Object Detection Finetuning Tutorial,Finetuning a pre-trained Mask R-CNN model in the Penn-Fudan Database for Pedestrian Detection and Segmentation.,computer-vision +559,2020-04-16 16:18:26,Creating an End-to-End Machine Learning Application,"A complete, end-to-end ML application, implemented in both TensorFlow 2.0 and PyTorch.",mlops +561,2020-04-16 16:27:31,How Docker Can Help You Become A More Effective Data Scientist,A look at Docker from the perspective of a data scientist.,mlops +569,2020-04-18 13:32:36,An Introduction to Transfer Learning and HuggingFace,In this talk I'll start by introducing the recent breakthroughs in NLP that resulted from the combination of Transfer Learning schemes and Transformer architect,natural-language-processing +570,2020-04-19 17:40:48,Introduction to Image Inpainting With Deep Learning,"In this article, we are going to learn how to do “image inpainting”, i.e. fill in missing parts of images precisely using deep learning.",computer-vision +579,2020-04-20 00:53:19,Transfer Learning & Fine-Tuning With Keras,Your 100% up-to-date guide to transfer learning & fine-tuning with Keras.,computer-vision +582,2020-04-20 21:38:50,CS285: Deep Reinforcement Learning,"A course on deep reinforcement learning, transfer and multi-task learning.",reinforcement-learning +594,2020-04-21 23:25:53,TorchServe & TorchElastic PyTorch Libraries for Serving/Training,The officially supported way to deploy and manage models with PyTorch.,mlops +600,2020-04-22 17:37:25,Building a Simple Chatbot from Scratch in Python (using NLTK),A look at retrieval based and generative conversational AI for creating chatbots.,natural-language-processing +612,2020-04-23 13:56:46,Implementing DCGANs using PyTorch C++ API (Libtorch),"The blog discusses the paper review of DCGANs and implementation using PyTorch C++ API in detail. From loading models to visualizing batch of the data, in C++! ",computer-vision +620,2020-04-23 17:26:26,ELECTRA ,"Explaining the new self-supervised task for language representation learning, ELECTRA which uses ""replace token detection"".",natural-language-processing +624,2020-04-24 00:42:41,How to Train a New Language Model From Scratch Using Transformers,"In this post we’ll demo how to train a “small” model (84 M parameters = 6 layers, 768 hidden size, 12 attention heads).",natural-language-processing +629,2020-04-24 05:01:26,ARIMA Modeling - Guide to Time Series Forecasting in Python,"How ARIMA models works . How to train and forecast using ARIMA, SARIMA, SARIMAX and find the optimal model with Python",time-series +649,2020-04-28 03:42:29,Spektral,Graph Neural Networks with Keras and Tensorflow 2.,graph-learning +666,2020-04-29 12:10:43,AIDeveloper,"GUI-based software for training, evaluating and applying deep neural nets for image classification ",computer-vision +671,2020-04-29 23:22:43,MedCAT - Medical Concept Annotation Tool,A tool used to extract information from Electronic Health Records (EHRs) and link it to biomedical ontologies like SNOMED-CT and UMLS.,natural-language-processing +681,2020-05-01 16:25:34,The AI Economist,Improving Equality and Productivity with AI-Driven Tax Policies,reinforcement-learning +684,2020-05-01 16:48:19,WT5?! Training Text-to-Text Models to Explain their Predictions,We leverage the text-to-text framework proposed by Raffel et al.(2019) to train language models to output a natural text explanation alongside their prediction.,natural-language-processing +689,2020-05-01 17:51:53,Ensemble Forecasts ,"Time series forecasting using classical methods (ETS, Holt-Winter's, SARIMA) and Prophet. I show and discuss advantages of Ensemble Forecast",time-series +703,2020-05-04 05:09:59,Implementing Graph Neural Networks with JAX,I’ll talk about my experience on how to build and train Graph Neural Networks (GNNs) with JAX.,graph-learning +705,2020-05-04 14:13:13,Deep Learning With Graph-Structured Representations,Novel approaches based on the theme of structuring the representations and computations of neural network-based models in the form of a graph.,graph-learning +706,2020-05-04 14:18:58,GNNExplainer: Generating Explanations for Graph Neural Networks,General tool for explaining predictions made by graph neural networks (GNNs).,graph-learning +710,2020-05-05 04:01:24,Differential Subspace Search in High-Dimensional Latent Space,"Differential subspace search to allow efficient iterative user exploration in such a space, without relying on domain- or data-specific assumptions.",computer-vision +723,2020-05-05 19:45:50,DeepWay: Autonomous navigation for blind.,I have tried to make something which can be used by blind people to navigate around the streets. Have a look at the video and GitHub repo for details.,computer-vision +737,2020-05-06 18:06:04,Nature-Scene Classification using FASTAI,Classifying Nature-scene images using deep learning with fastai library,computer-vision +738,2020-05-06 20:33:00,Machine-Learning-Single-Layer-Multiclass-Perceptron,Implemented a Single Layer Perceptron and applied it on the MNIST dataset for multi-class classification using NumPy.,computer-vision +780,2020-05-08 12:06:30,Med7 - clinical natural language processing for EHR,"Med7 is a transferable clinical natural language processing model for electronic health records, compatible with spaCy, for named-entity recognition task",natural-language-processing +784,2020-05-08 14:59:08,Haystack — Neural Question Answering At Scale,Scaling Question Answering models to find answers in large document stores via retriever and reader approach.,natural-language-processing +785,2020-05-08 17:13:36,SimCLR in TensorFlow 2,(Minimally) implements SimCLR (https://arxiv.org/abs/2002.05709) in TensorFlow 2.,computer-vision +787,2020-05-08 18:15:56,Semantic Cord19 Paper Explorer,Semantic research paper explorer to search Research Papers in COVID and CoronaVirus. Can be easily modified to any Research Paper Database,natural-language-processing +807,2020-05-11 02:25:51,Introduction to Machine Learning Problem Framing,This course helps you frame machine learning (ML) problems.,mlops +834,2020-05-13 04:36:33,TailorGAN: Making User-Defined Fashion Designs,Generate a photo-realistic image which combines the texture from reference A and the new attribute from reference B.,computer-vision +843,2020-05-13 14:49:21,T5 fine-tuning,A colab notebook to showcase how to fine-tune T5 model on various NLP tasks (especially non text-2-text tasks with text-2-text approach),natural-language-processing +854,2020-05-14 12:05:20,ASAP: Pooling for Graph Neural Network (AAAI 2020),ASAP is a sparse and differentiable pooling method that addresses the limitations of previous graph pooling layers.,graph-learning +878,2020-05-16 05:27:56,Exploratory Data Analysis on MS COCO Style Datasets,A Simple Toolkit to do exploratory data analysis on MS COCO style formatted datasets.,computer-vision +898,2020-05-17 05:11:22,Single-Stage Semantic Segmentation from Image Labels,"We attain competitive results by training a single network model +for segmentation in a self-supervised fashion using only +image-level annotations",computer-vision +906,2020-05-18 14:50:45,NLPAug,Data augmentation for NLP,natural-language-processing +916,2020-05-19 08:11:05,Get Subreddit Suggestions for a Post,"Trained on 4M Reddit posts from 4k Subreddits. End-to-end ML pipeline built with fasttext and FastAPI, deployed to Valohai.",natural-language-processing +917,2020-05-19 13:45:03,Transfer Learning In NLP,A brief history of Transfer Learning In NLP,natural-language-processing +919,2020-05-20 02:29:48,IntelliCode Compose: Code Generation Using Transformer,"Code completion tool which is capable of predicting sequences of code tokens of arbitrary types, generating up to entire lines of syntactically correct code.",natural-language-processing +943,2020-05-22 06:27:43,Transfer Learning in NLP with Tensorflow Hub and Keras,Learn how to integrate and finetune tensorflow-hub modules in Tensorflow 2.0,natural-language-processing +946,2020-05-22 07:57:14,Replicating Airbnb's Amenity Detection (documentary series),Airbnb's engineering team shared an article on how they used computer vision to detection amenities in photos. It read like a recipe so I replicated it.,computer-vision +965,2020-05-24 08:14:30,GANs in Computer Vision : An article review series ,"An article series where we review the most important research papers on GANs from 2015 to today. 6 articles, 20 papers, 20000 words",computer-vision +991,2020-05-27 05:09:20,NLP Viewer 🤗,A simple website for browsing popular NLP datasets.,natural-language-processing +999,2020-05-28 03:32:05,MediaPipe,"Simplest way for researchers and developers to build world-class ML solutions and applications for mobile, edge, cloud and the web. ",computer-vision +1011,2020-05-29 02:57:44,ML in Production - Deployment Series,"A multi-part blog series on deploying machine learning models in an automated, reproducible, and auditable manner.",mlops +1019,2020-05-29 08:14:05,Visual Object Tracking using Adaptive Correlation Filters,This article gives step by step tutorial with code on understanding MOSSE tracking algorithm,computer-vision +1032,2020-05-29 14:50:28,Pix2Pix with Tf-js,"Implementation of web friendly ML models using TensorFlow.js. pix2pix, face segmentation, fast style transfer and many more ...",computer-vision +1056,2020-05-30 09:08:31,Font Recognition Using Deep Learning - DeepFont ( Adobe ),DeepFont Paper is a technique created by Adobe.Inc to detect font from images using deep learning . They published their work as a paper for the public .,computer-vision +1078,2020-05-31 05:04:44,Building Footprint Extraction,The project retrieves satellite imagery from Google and performs building footprint extraction using a U-Net. ,computer-vision +1114,2020-06-01 21:00:24,Reinforcement Learning in JAX,"Implementation of interesting Deep Reinforcement Learning Algorithms using JAX based libraries (flax, haiku and rlax) As of now tasks come from OpenAI gym",reinforcement-learning +1155,2020-06-03 15:22:11,GaborNet,Modified network architecture that focuses on improving convergence and reducing training complexity.,computer-vision +1159,2020-06-03 18:17:01,Learning To Classify Images Without Labels,A two-step approach where feature learning and clustering are decoupled.,computer-vision +1167,2020-06-04 03:58:21,From Pre-trained Word Embeddings to Pre-trained Language Models,from Static Word Embedding to Dynamic (Contextualized) Word Embedding.,natural-language-processing +1172,2020-06-04 07:01:13,Converting images to TF Records,A Colab Notebook showing how to convert an image dataset (for classification) to TF Records and more.,computer-vision +1266,2020-06-09 16:09:08,Text Classification using Bert from Tensorflow-Hub,This Tutorial helps to learn about Bert Models for Classification task on a #Tweet dataset.,natural-language-processing +1286,2020-06-10 17:24:19,Exploring Knowledge Captured in Probability of Strings,An exploration of simple knowledge captured by language models with code examples,natural-language-processing +1363,2020-06-13 13:46:44,Short Notes on Batch Constrained Deep Reinforcement Learning,Blog article on Off-Policy Deep Reinforcement Learning without Exploration paper by Fujimoto et al. (ICML 2019),reinforcement-learning +1426,2020-06-15 02:34:27,From GRU to Transformer,How recurrent units and self-attention are related to each other.,natural-language-processing +1430,2020-06-15 04:24:12,Melanoma Classification,This was Shubhamai 3-week project for working a new kaggle competition and deploying a web application to predicting benign or malignant based on images.,computer-vision +1434,2020-06-15 07:52:13,Universal Sentence Encoder Visually Explained,A deep-dive into how Universal Sentence Encoder learns to generate fixed-length sentence embeddings,natural-language-processing +1445,2020-06-15 17:49:16,Image Smoothing via L0 Gradient Minimization,This is a edge-aware image smoothing algorithm. This algorithm tries to smoothen the image while preserving the global structural information of the image. ,computer-vision +1450,2020-06-15 21:00:47,BERT NLP — How To Build a Question Answering Bot,Understanding the intuition with hands-on PyTorch code for BERT fine-tuned on SQuAD.,natural-language-processing +1451,2020-06-16 01:21:09,EfficientDet (PyTorch),A PyTorch implementation of EfficientDet faithful to the original Google implementation with ported weights.,computer-vision +1459,2020-06-16 03:06:10,SuperGlue: Learning Feature Matching with Graph Neural Networks,"SuperGlue, a neural network that matches two sets of local features by jointly finding correspondences and rejecting non-matchable points.",graph-learning +1462,2020-06-16 03:28:40,Open Compound Domain Adaptation,"Pytorch implementation for ""Open Compound Domain Adaptation""",computer-vision +1485,2020-06-17 16:33:50,Sudoku-Game-Solver,This is a Computer Vision Application that solves a 9x9 sudoku board game using Deep Learning and Backtracking algorithm.,computer-vision +1488,2020-06-17 19:27:36,Smart Picture Editor,Tool to automatically remove unwanted objects from photos,computer-vision +1494,2020-06-18 00:14:40,Object Goal Navigation using Goal-oriented Semantic Exploration,Embodied interactive learning for object detection by using semantic curiosity to learn an exploration policy on set of the training environments.,computer-vision +1501,2020-06-18 18:17:18,Traffic-Sign-Recognition-Using-Deep-Learning,"The training dataset contains around 39,000 images while test dataset contains around 12,000 images containing 43 different classes. We will be using Convolutio",computer-vision +1508,2020-06-19 06:43:47,Long Form Question Answering with ELI5,A model for open domain long form question answering.,natural-language-processing +1511,2020-06-19 06:54:23,RepNet - Class Agnostic Video Repetition Counting in the Wild,Counting Out Time: Class Agnostic Video Repetition Counting in the Wild,computer-vision +1515,2020-06-19 16:37:10,"Cut, Paste and Learn: Surprisingly Easy Synthesis for Detection",Generate synthetic scenes and bounding box annotations for object detection.,computer-vision +1524,2020-06-20 10:42:25,Machine Learning Projects ,"This Repo contains projects done by me while learning the basics. All the familiar types of regression, classification, and clustering methods have been used.",natural-language-processing +1540,2020-06-21 13:03:19,codeBERT - Masked Language Model for source code ,Tutorial to use codeBERT a MLM for Python code. Model trained from scratch using roBERTa,natural-language-processing +1588,2020-06-24 03:29:51,Multi-task Training with Hugging Face Transformers and NLP, A recipe for multi-task training with Transformers' Trainer and NLP datasets.,natural-language-processing +1600,2020-06-25 00:45:26,BERT Distillation with Catalyst,How to distill BERT with Catalyst.,natural-language-processing +1628,2020-06-28 06:12:20,Deep Reinforcement Learning Amidst Lifelong Non-Stationarity,"How can robots learn in changing, open-world environments? We introduce dynamic-parameter MDPs, to capture environments with persistent, unobserved changes. ",reinforcement-learning +1654,2020-06-30 03:58:46,3D Detection and Domain Adaptation,1st Place Solution for Waymo Open Dataset Challenge,computer-vision +1659,2020-07-01 02:26:20,Evaluation of Text Generation: A Survey,Evaluation methods of natural language generation (NLG) and language modeling.,natural-language-processing +1661,2020-07-01 06:42:59,SpineNet: A Novel Architecture for Object Detection,"A meta architecture called a scale-permuted model that enables two major improvements on backbone architecture design,iscovered with neural architecture search.",computer-vision +1665,2020-07-01 07:17:48,BERTology Meets Biology,Interpreting Attention in Protein Language Models.,natural-language-processing +1681,2020-07-03 04:02:52,A Survey on Deep Learning for Localization and Mapping,Towards the Age of Spatial Machine Intelligence,computer-vision +1685,2020-07-03 04:12:28,Text Data Cleanup - Dynamic Embedding Visualisation,Identify noisy text in a Machine Translation dataset through dynamic text embedding visualisation.,natural-language-processing +1689,2020-07-03 04:29:04,Offline Reinforcement Learning,"Challenges, algorithms and benchmarks.",reinforcement-learning +1692,2020-07-03 04:42:45,Low-Dimensional Hyperbolic Knowledge Graph Embeddings,Low-dimensional knowledge graph embeddings that simultaneously capture hierarchical relations and logical patterns.,graph-learning +1703,2020-07-04 09:22:50,Awesome Deep RL,This project is built for people who are learning and researching on the latest deep reinforcement learning methods.,reinforcement-learning +1709,2020-07-05 05:25:34,Anti-Patterns in NLP (8 types of NLP idiots),A talk which discusses the recurring industrial problems in making NLP solutions. ,natural-language-processing +1715,2020-07-06 18:25:16,Image Classifier,Pure JavaScript Image Classifier,computer-vision +1717,2020-07-07 04:09:35,TaBERT,Pretraining for Joint Understanding of Textual and Tabular Data,natural-language-processing +1719,2020-07-07 04:17:11,Texthero,"Text preprocessing, representation and visualization from zero to hero.",natural-language-processing +1743,2020-07-09 01:51:41,How to Benchmark Models with Transformers,HuggingFace's Transformer library allows users to benchmark models for both TensorFlow 2 and PyTorch using the PyTorchBenchmark and TensorFlowBenchmark classes.,natural-language-processing +1756,2020-07-10 02:53:13,Linear Attention Transformer,A fully featured Transformer that mixes (QKᵀ)V local attention with Q(KᵀV) global attention (scales linearly with respect to sequence length).,natural-language-processing +1770,2020-07-11 05:12:49,imgaug,"Image augmentation for machine learning experiments. + +",computer-vision +1779,2020-07-11 05:48:03,All Models and checkpoints - Hugging Face,"Massive (and growing) collection of NLP models are nearly any NLP tasks, especially those involving the use of transformers.",natural-language-processing +1799,2020-07-11 06:49:38,FlashText,"Extract Keywords from sentence or Replace keywords in sentences. + +",natural-language-processing +1804,2020-07-11 07:04:25,Text Preprocessing in Python using spaCy library,"In this article, we have explored Text Preprocessing in Python using spaCy library in detail. This is the fundamental step to prepare data for applications.",natural-language-processing +1805,2020-07-11 07:12:32,Segmentation Models,"Segmentation models with pretrained backbones. Keras and TensorFlow Keras. + +",computer-vision +1825,2020-07-11 08:43:20,MLflow: A Machine Learning Lifecycle Platform,Open source platform for the machine learning lifecycle.,mlops +1827,2020-07-11 08:56:02,token2index,"A lightweight but powerful library to build token indices for NLP tasks, compatible with major Deep Learning frameworks like PyTorch and Tensorflow.",natural-language-processing +1853,2020-07-13 20:23:32,The Transformer Neural Network Architecture Explained,"⚙️ It is time to explain how Transformers work. If you are looking for an easy explanation, you are exactly right!",natural-language-processing +1858,2020-07-14 03:30:14,QSVM,Quantum SVM for sentiment analysis,natural-language-processing +1866,2020-07-14 22:58:15,PYthon Automated Term Extraction,"Term extraction algorithms such as C-Value, Basic, Combo Basic, Weirdness and Term Extractor using spaCy POS tagging.",natural-language-processing +1870,2020-07-15 20:38:36,Interpretability and Analysis of Models for NLP,An in-depth look at interpretability and analysis of models for NLP (ACL 2020).,natural-language-processing +1888,2020-07-17 16:53:37,Monitoring Machine Learning Models in Production,Once you have deployed your machine learning model to production it rapidly becomes apparent that the work is not over.,mlops +1901,2020-07-19 08:31:43,Quora Question Pair Similarity,"Identify which questions asked on Quora are duplicates of questions that have already been asked. Using Text features, classifying them as duplicates or not. + +",natural-language-processing +1905,2020-07-19 14:51:57,PyTorch CNN Trainer,A simple package to fine-tune CNNs from torchvision and Pytorch Image models by Ross Wightman.,computer-vision +1934,2020-07-21 01:47:01,Graphein,Protein Graph Library,graph-learning +1935,2020-07-21 04:44:52,Integrated Gradients in TensorFlow 2,"In this tutorial, you will walk through an implementation of IG step-by-step in TensorFlow 2 to understand the pixel feature importances of an image classifier.",computer-vision +1950,2020-07-23 00:42:09,GPT-3: A Hitchhiker's Guide,Post to guide your thinking on GPT-3.,natural-language-processing +1959,2020-07-24 10:00:13,TeachEasy: Web app for Text Summarization & Q/A generation,An intuitive Streamlit based web app for Text Summarization and Question Answer generation so as to reduce the work for School teachers.,natural-language-processing +1961,2020-07-24 10:38:52,Python Template for All Projects,"A template that gives the batteries required to package code, CI checks, auto build and deploy docs, easy PyPi publishing support and docker files.",mlops +1964,2020-07-25 02:52:36,MLOps Tutorial Series,How to create an automatic model training & testing setup using GitHub Actions and Continuous Machine Learning (CML).,mlops +1972,2020-07-27 02:54:19,Evolution of Representations in the Transformer,"The evolution of representations of individual tokens in Transformers trained with different training objectives (MT, LM, MLM - BERT-style).",natural-language-processing +1975,2020-07-27 14:09:26,Ensemble methods for object detection,"In this repository, we provide the code for ensembling the output of object detection models, and applying test-time augmentation for object detection. This lib",computer-vision +1976,2020-07-27 14:12:03,Close-Domain fine-tuning for table detection,"In this project, we show the benefits of using models trained on a close domain, using the TableBank dataset, for fine-tuning table detection models. In additio",computer-vision +1997,2020-07-29 16:13:46,Image Classification by @carrycooldude,Image Classification using TFLite and ImageNet by @carrycooldude,computer-vision +2007,2020-07-30 14:47:39,CLoDSA: A Tool for Augmentation in Computer Vision tasks,"CLoDSA is an open-source image augmentation library for object classification, localization, detection, semantic segmentation and instance segmentation. It supp",computer-vision +2010,2020-07-30 15:00:43,FrImCla: A framework for image classification," +FrImCla is an open-source framework for Image Classification using traditional and deep learning techniques. It supports a wide variety of deep learning and c",computer-vision +2011,2020-07-30 15:02:04,UFOD: A Unified Framework for Object Detection,UFOD is an open-source framework that enables the training and comparison of object detection models on custom datasets using different underlying frameworks an,computer-vision +2023,2020-08-01 14:46:19,Why You Should Do NLP Beyond English,7000+ languages are spoken around the world but NLP research has mostly focused on English. This post outlines why you should work on languages other than Eng.,natural-language-processing +2025,2020-08-01 14:57:11,Haystack — Neural Question Answering At Scale,"🔍 Transformers at scale for question answering & search + +",natural-language-processing +2034,2020-08-03 04:00:29,Finding Similar Documents with Transformers,How transformers can help us distill text documents into points in N-dimensional vector spaces.,natural-language-processing +2040,2020-08-04 18:00:56,A Barebones Image Retrieval System,This project presents a simple framework to retrieve images similar to a query image.,computer-vision +2056,2020-08-06 00:30:49,Fast Sentence Embeddings (fse),Fast Sentence Embeddings is a Python library that serves as an addition to Gensim.,natural-language-processing +2131,2020-08-13 01:39:01,How to Trust Your Deep Learning Code,"We will focus on how to write reusable unit tests, so that you “Don’t repeat yourself”.",mlops +2137,2020-08-13 02:10:03,Unpopular Opinion - Data Scientists Should Be More End-to-End,I believe data scientists can be more effective by being end-to-end.,mlops +2172,2020-08-18 04:12:18,Compression of Deep Learning Models for Text: A Survey,"In this survey, we discuss six different types of methods for compression of such models to enable their deployment in real industry NLP projects.",natural-language-processing +2186,2020-08-18 23:24:41,AI in Medicine and Imaging - Stanford Symposium 2020,Through the AIMI Symposium we hope to address gaps and barriers in the field and catalyze more evidence-based solutions to improve health for all.,computer-vision +2195,2020-08-20 20:45:52,Streamlit Terran Timeline,A face-recognition timeline generator tool for any kind of video!,computer-vision +2199,2020-08-21 08:37:20,How to Set Up Continuous Integration for Machine Learning,How to Set Up Continuous Integration for Machine Learning with Github Actions and Neptune: Step by Step Guide.,mlops +2200,2020-08-21 12:45:54,Bad passwords and the NIST guidelines,"Example project provided by DataCamp. In this project, you will write code that automatically detects and flags the bad passwords.",natural-language-processing +2232,2020-08-27 11:00:34,GenRL,GenRL is a PyTorch-First Reinforcement Learning library centered around reproducible and generalizable algorithm implementations.,reinforcement-learning +2246,2020-08-30 06:05:21,Questgen- An NLP library for state-of-the-art Question Generation,"Questgen AI is an opensource, easy to use NLP library for Question generation. It can generate MCQs, Boolean (Yes/No), FAQs and also paraphrase any question. +",natural-language-processing +2250,2020-08-31 09:20:55,Text Data Augmentation with MarianMT,Learn how to use machine translation models in Hugging Face Transformers for data augmentation.,natural-language-processing +2262,2020-09-03 12:10:24,R.U.Stoked,NLP (Sentiment Analysis) project to demonstrate a pipeline of data from the very first stage of data collection through ML model deployment.,natural-language-processing +2266,2020-09-04 01:42:26,Wav2Lip: Accurately Lip-syncing Videos In The Wild,A Lip Sync Expert Is All You Need for Speech to Lip Generation In the Wild,computer-vision +2271,2020-09-05 07:10:06,Latest advancements in video streaming with AI,"AI developments in video streaming using Super-resolution, Per-title encoding, P2P",computer-vision +2289,2020-09-08 04:12:41,ElasticTransformers,Making BERT stretchy. Semantic Elasticsearch with Sentence Transformers.,natural-language-processing +2310,2020-09-12 12:33:20,Image Super-Resolution,In this project we learn how to train a super-resolution model ESPCN on DIV2K dataset to upscale images using AI by 3x,computer-vision +2312,2020-09-12 22:33:56,Codequestion,Ask coding questions directly from the terminal.,natural-language-processing +2336,2020-09-19 08:40:37,G-SimCLR,TensorFlow implementation of G-SimCLR. ,computer-vision +2339,2020-09-19 11:17:48,Neural CDEs for Long Time-Series via the Log-ODE Method,NCDEs for Long Time-Series via the Log-ODE Method.,time-series +2350,2020-09-22 03:07:29,"Part 1: Deep Representations, a way towards neural style transfer",A top down approach to conceiving neural style transfer,computer-vision +2366,2020-09-25 02:26:00,Help-Me-Read: Text Summarization using Flask and HuggingFace.,"Text summarization, translation and Questions Answers generation using HuggingFace and deployed using Flask, Streamlit. Detailed guide on github. ",natural-language-processing +2367,2020-09-25 07:39:43,Interactive Analysis of Sentence Embeddings,Learn how to interactively explore sentence embedding and labels in Tensorflow Embedding Projector.,natural-language-processing +2390,2020-09-28 05:46:03,mini-pokedex end to end tutorial - Gotta classify 'em all!,"Build a Pokemon image classifier to classify the awesome starters Pikachu, Charmander, Squirtle, and Bulbasaur.",computer-vision +2394,2020-09-28 22:46:36,Why Data Quality is Key to Successful ML Ops,A look at ML Ops and highlight how and why data quality is key to ML Ops workflows.,mlops +2403,2020-09-30 22:15:07,Easy Data Augmentation (EDA),Easy Data Augmentation Techniques for Boosting Performance on Text Classification Tasks,natural-language-processing +2413,2020-10-01 23:50:04,Keeping Data Pipelines healthy w/ Great Expectations GH Actions,"We show you how you can use GitHub Actions together with the open source project Great Expectations to automatically test, document, and profile data pipelines.",mlops +2428,2020-10-05 02:09:23,Efficient Transformers: A Survey,"Characterizes a large and thoughtful selection of recent efficiency-flavored ""X-former"" models.",natural-language-processing +2429,2020-10-05 02:16:34,Meta-learning for Few-shot Natural Language Processing: A Survey,"Clear definitions, progress summary and some common datasets of applying meta-learning to few-shot NLP.",natural-language-processing diff --git a/datasets/projects.csv b/datasets/projects.csv new file mode 100644 index 0000000..ea054f4 --- /dev/null +++ b/datasets/projects.csv @@ -0,0 +1,813 @@ +id,created_on,title,description +6,2020-02-20 06:43:18,Comparison between YOLO and RCNN on real world videos,Bringing theory to experiment is cool. We can easily train models in colab and find the results in minutes. +7,2020-02-20 06:47:21,"Show, Infer & Tell: Contextual Inference for Creative Captioning","The beauty of the work lies in the way it architects the fundamental idea that humans look at the overall image and then individual pieces of it. +" +9,2020-02-24 16:24:45,Awesome Graph Classification,"A collection of important graph embedding, classification and representation learning papers with implementations." +15,2020-02-28 23:55:26,Awesome Monte Carlo Tree Search,A curated list of Monte Carlo tree search papers with implementations. +25,2020-03-07 23:04:31,AttentionWalk,"A PyTorch Implementation of ""Watch Your Step: Learning Node Embeddings via Graph Attention"" (NeurIPS 2018). " +27,2020-03-07 23:18:15,APPNP and PPNP,"A PyTorch implementation of ""Predict then Propagate: Graph Neural Networks meet Personalized PageRank"" (ICLR 2019). " +28,2020-03-07 23:23:46,Attributed Social Network Embedding,"A sparsity aware and memory efficient implementation of ""Attributed Social Network Embedding"" (TKDE 2018). " +29,2020-03-07 23:45:38,Signed Graph Convolutional Network,"A PyTorch implementation of ""Signed Graph Convolutional Network"" (ICDM 2018). " +45,2020-03-08 00:39:08,SimGNN,"A PyTorch implementation of ""SimGNN: A Neural Network Approach to Fast Graph Similarity Computation"" (WSDM 2019). " +61,2020-03-16 17:35:22,Using JAX to Improve Separable Image Filters,Optimizing the filters to improve the filtered images for computer vision tasks. +65,2020-03-19 18:42:05,Coloring Greyscale Images,Coloring black and white images with neural networks. +67,2020-03-19 19:04:43,Fruit Detection using Convolution Neural Networks in TensorFlow,"Trained a Convolutional Neural Network Model to predict fruits of over 100+ Classes (types) with a training accuracy of over 95%, and testing accuracy of over 9" +73,2020-03-19 23:45:14,Face Verification,Implementation of Siamese Neural network model used for face verification. The dataset used for this task is IMDB-WIKI-face images Dataset. +77,2020-03-20 03:23:27,Sign Language Interpreter using Deep Learning,"A sign language interpreter using live video feed from the camera. The project was completed in 24 hours as part of HackUNT-19, the University of North Texas's " +78,2020-03-20 03:32:09,The Illustrated Self-Supervised Learning,A visual introduction to self-supervised learning methods in Computer Vision +81,2020-03-20 06:07:56,GradCAM for the BreaKHis Dataset,An NBDev package for fine-tuning ResNets to visualize gradient-weighted class activation for the BreaKHis dataset. +85,2020-03-20 17:35:59,Message Passing GNNs C++,C++ implementation using Eigen for the forward pass of Graph Convolutional Neural Networks. +89,2020-03-20 18:17:31,Rethinking Batch Normalization in Transformers,"We found that NLP batch statistics exhibit large variance throughout training, which leads to poor BN performance." +91,2020-03-20 18:30:04,Pytest Board,Continuous pytest runner with awesome visualization. +92,2020-03-20 18:43:50,Image Spam Buster - Kreate Hackathon,"""Spam Buster"" for user generated IMAGE content." +98,2020-03-20 19:16:43,Bachelorette Predictor,Predict the Bachelorette winners from profile images. +99,2020-03-20 21:32:14,Gender Change of People's Face using CycleGAN,CycleGAN architecture in Keras and train the model with CelebA faces dataset to perform gender change on people's faces. +101,2020-03-21 04:19:04,ELECTRA: Pre-training Text Encoders as Discriminators,PyTorch implementation of the electra model from the paper: ELECTRA - Pre-training Text Encoders as Discriminators Rather Than Generators +108,2020-03-21 23:17:38,Tuned ALBERT (ensemble model),Top 6 in Squad 2.0 +109,2020-03-21 23:25:33,iyasai: Book Recommendation System,Recommender system for books and stories that could help you and your loved ones lift up your mood whenever you are facing stress or unpleasant situations. +112,2020-03-21 23:58:46,Learning to See before Learning to Act: Visual Pre-training,We find that pre-training on vision tasks significantly improves generalization and sample efficiency for learning to manipulate objects. +115,2020-03-22 01:26:14,SOLT: Data Augmentation for Deep Learning,"Data augmentation library for Deep Learning, which supports images, segmentation masks, labels and key points." +116,2020-03-22 01:37:27,PCDet: 3D Point Cloud Detection,PCDet Toolbox in PyTorch for 3D Object Detection from Point Cloud +117,2020-03-22 01:47:09,SiamFC++: Towards Robust and Accurate Visual Tracking,"Implementation of a series of basic algorithms which is useful for video understanding, including Single Object Tracking (SOT), Video Object Segmentation (VOS)." +118,2020-03-22 21:46:52,Sinext,Sign language to text with OpenCV and MNIST sign-language dataset +120,2020-03-24 04:38:08,Gliding Vertex on Horizontal Bounding Box for Object Detection,Gliding vertex on the horizontal bounding box for multi-oriented object detection. +121,2020-03-24 04:56:38,Deep Reinforcement Learning in TensorFlow2,deep-rl-tf2 is a repository that implements a variety of polular Deep-RL algorithms using TF2. The key to this repo is an easy to understand code. +122,2020-03-24 17:51:35,Custom Classifier on Top of Bert-like Language Model,Take pre-trained language model and build custom classifier on top of it. +123,2020-03-24 18:20:55,Using Different Decoding Methods for LM with Transformers,A look at different decoding methods for generate subsequent tokens in language modeling. +124,2020-03-24 21:12:12,Unsupervised Toolbox,"Unsupervised learning Tool box : A micro framework for State of the Art Methods and models for unsupervised learning for NLU / NLG +" +128,2020-03-25 15:21:34,Multimodal Brain Tumor Segmentation,Segmentation of gliomas in pre-operative MRI scans. Use the provided clinically-acquired training data to produce segmentation labels. +133,2020-03-25 20:21:26,A Survey of Long-Term Context in Transformers,Over the past two years the NLP community has developed a veritable zoo of methods to combat expensive multi-head self-attention. +137,2020-03-27 14:39:53,Debugging Neural Networks with PyTorch and W&B,A closer look at debugging common issues when training neural networks. +138,2020-03-27 14:50:02,BachGAN: High-Res Image Synthesis from Salient Object Layout,We propose a new task towards more practical application for image generation - high-quality image synthesis from salient object layout. +140,2020-03-28 07:49:03,Visual Paper Summary: ALBERT(A Lite BERT),An illustrated summary of ALBERT paper and how it improves BERT and makes it resource efficient +145,2020-03-30 04:14:44,Controllable Person Image Synthesis with Attribute-Decomposed GAN,"A novel generative model for controllable person image synthesis, which can produce realistic person images with desired human attributes." +147,2020-03-30 05:39:57,Back Translation for Text Augmentation with Google Sheets,Learn how to augment existing labeled text data for free using Google Sheets. +148,2020-03-30 14:13:46,An Illustrated Guide to Graph Neural Networks,A breakdown of the inner workings of GNNs. +150,2020-04-01 08:26:46,The Illustrated FixMatch for Semi-Supervised Learning,Learn how to leverage unlabeled data using FixMatch for semi-supervised learning +152,2020-04-01 15:38:58,A Two-Step Graph Convolutional Decoder for Molecule Generation,A simple auto-encoder framework for molecule generation. +157,2020-04-03 01:56:32,TransMoMo: Invariance-Driven Unsupervised Motion Retargeting,A lightweight video motion retargeting approach that is capable of transferring motion of a person in a source video realistically to another video of a target +158,2020-04-03 04:41:07,Tracking Objects as Points,Simultaneous object detection and tracking using center points. +159,2020-04-03 14:57:11,Drifter-ML,A machine learning testing framework for sklearn and pandas. The goal is to help folks assess whether things have changed over time. +162,2020-04-03 20:17:50,Natural Language Processing News,Get the highlights from Natural Language Processing & Machine Learning research & industry straight to your inbox every month. +163,2020-04-03 20:21:13,NLP Newsletter,"Democratizing Artificial Intelligence Research, Education, and Technologies." +168,2020-04-04 17:54:28,Self-Supervised Scene De-occlusion,"We investigate the problem of scene de-occlusion, which aims to recover the underlying occlusion ordering and complete the invisible parts of occluded objects." +173,2020-04-05 03:00:05,Design Patterns for Production NLP Systems,Designs and tips for designing NLP production systems. +181,2020-04-05 14:56:34,Talking-Heads Attention,"A variation on multi-head attention which includes linear projections across the attention-heads dimension, immediately before and after the softmax operation." +183,2020-04-05 17:50:10,What does a CNN see?,First super clean notebook showcasing @TensorFlow 2.0. An example of end-to-end DL with interpretability. +219,2020-04-06 14:10:22,Natural Language Processing: Pretraining - d2l,"An interactive deep learning book with code, math, and discussions, based on the NumPy interface." +224,2020-04-06 16:48:44,Understanding Convolutional Neural Networks for NLP,More recently we’ve also started to apply CNNs to problems in Natural Language Processing and gotten some interesting results. +234,2020-04-06 17:42:52,An Overview of Semantic Image Segmentation,Image segmentation is a computer vision task in which we label specific regions of an image according to what's being shown. +237,2020-04-06 18:02:48,Common Architectures in Convolutional Neural Networks,"In this post, I'll discuss commonly used architectures for convolutional networks. " +238,2020-04-06 18:37:33,Googletrans,Googletrans: Free and Unlimited Google translate API for Python. Translates totally free of charge. +239,2020-04-06 18:39:48,Prophet: Forecasting At Scale,Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth. +250,2020-04-06 19:24:06,Doccano,Open source text annotation tool for machine learning practitioner. +251,2020-04-06 19:28:58,BRAT: Rapid Annotation Tool,BRAT (brat rapid annotation tool) is based on the stav visualiser which was originally made in order to visualise BioNLP'11 Shared Task data. +252,2020-04-06 20:23:46,Word Embeddings,This tutorial introduces word embeddings. It contains complete code to train word embeddings from scratch on a small dataset. +253,2020-04-06 20:26:27,On Word Embeddings,This post presents the most well-known models for learning word embeddings based on language modeling. +254,2020-04-06 20:28:43,NLP for Developers: Word Embeddings | Rasa,"In this video, Rasa Developer Advocate Rachael will talk about what word embeddings are, how they work, when they're used and some common errors. " +255,2020-04-06 20:30:27,NLP for Developers: Transformers | Rasa,"In this video, Rasa Developer Advocate Rachael will talk about what transformers are, how they work, when they're used and some common errors. " +256,2020-04-06 20:42:05,A Visual Guide to Using BERT for the First Time,Tutorial for how to use a variant of BERT to classify sentences. +257,2020-04-06 20:45:45,The Illustrated GPT-2 (Visualizing Transformer Language Models),Visuals explaining the inner-workings of transformers. +259,2020-04-06 20:51:58,The Illustrated Word2vec,"In this post, we’ll go over the concept of embedding, and the mechanics of generating embeddings with word2vec. " +260,2020-04-06 20:55:32,"The Illustrated BERT, ELMo, and co.",How NLP cracked transfer learning. +261,2020-04-06 21:00:34,The Illustrated Transformer,"In this post, we will look at The Transformer – a model that uses attention to boost the speed with which these models can be trained." +262,2020-04-06 21:11:40,Visualizing A Neural Machine Translation Model,Mechanics of seq2seq models with attention. +269,2020-04-06 22:46:54,Attention Mechanism,"Main concepts behind Attention, including an implementation of a sequence-to-sequence Attention model, followed by the application of Attention in Transformers." +270,2020-04-06 22:50:30,Attention? Attention!,"In this post, we are gonna look into how attention was invented, and various attention mechanisms and models, such as transformer and SNAIL." +271,2020-04-06 22:58:47,The Annotated Transformer,In this post I present an “annotated” version of the paper in the form of a line-by-line implementation. +272,2020-04-06 23:38:26,The Annotated GPT-2,GPT-2 explained with visualization and PyTorch code. +273,2020-04-06 23:41:52,Transformers - Hugging Face,🤗 Transformers: State-of-the-art Natural Language Processing for TensorFlow 2.0 and PyTorch. +277,2020-04-07 00:30:33,Curriculum for Reinforcement Learning,"Curriculum learning applied to reinforcement learning, with a few exceptions of supervised learning." +278,2020-04-07 00:34:46,Self-Supervised Representation Learning,What if we can get labels for free for unlabelled data and train unsupervised dataset in a supervised manner? +279,2020-04-07 00:36:55,Evolution Strategies,Evolutionary algorithms refer to a division of population-based optimization algorithms inspired by natural selection. +280,2020-04-07 00:38:25,Meta Reinforcement Learning,Explore cases when we try to “meta-learn” Reinforcement Learning (RL) tasks by developing an agent that can solve unseen tasks fast and efficiently. +281,2020-04-07 00:40:59,Generalized Language Models,Trend in large unsupervised pre-trained language models which have achieved amazing SOTA results on a variety of language tasks. +284,2020-04-07 00:57:12,Policy Gradient Algorithms,"In this post, we are going to look deep into policy gradient, why it works, and many new policy gradient algorithms proposed in recent years." +286,2020-04-07 03:49:15,Object Detection for Dummies,"We will go through several basic concepts, algorithms, and popular deep learning models for image processing and object detection." +287,2020-04-07 03:59:53,Learning Word Embedding,This post introduces several models for learning word embedding and how their loss functions are designed for the purpose. +290,2020-04-07 13:38:36,GANSpace: Discovering Interpretable GAN Controls,This paper describes a simple technique to analyze Generative Adversarial Networks (GANs) and create interpretable controls for image synthesis. +291,2020-04-07 14:07:59,Kornia: Differentiable Computer Vision Library for PyTorch,Set of routines and differentiable modules to solve generic computer vision problems. +294,2020-04-07 15:36:13,PyTorch Geometric ,Geometric deep learning extension library for PyTorch. +295,2020-04-07 15:40:00,DGL: Deep Graph Library,"Python package built to ease deep learning on graph, on top of existing DL frameworks. " +306,2020-04-07 20:07:28,BERT Research - Key Concepts & Sources,Video series on BERT's key concepts and sources. +307,2020-04-07 20:11:29,GLUE Explained: Understanding BERT Through Benchmarks,In this post we take a look at an important NLP benchmark used to evaluate BERT and other transfer learning models! +308,2020-04-07 23:22:18,TinyBERT,TinyBERT is 7.5x smaller and 9.4x faster on inference than BERT-base and achieves competitive performances in the tasks of natural language understanding. +313,2020-04-08 00:02:27,NVIDIA Neural Modules: NeMo,A toolkit for conversational AI. +315,2020-04-08 00:10:21,VoTT: Visual Object Tagging Tool,An electron app for building end to end Object Detection Models from Images and Videos. +316,2020-04-08 00:12:26,Clinical BERT,Repository for Publicly Available Clinical BERT Embeddings +318,2020-04-08 00:16:55,Computer Vision Annotation Tool (CVAT),"Free, online, interactive video and image annotation tool for computer vision." +319,2020-04-08 00:19:04,LabelImg,🖍️ A graphical image annotation tool and label object bounding boxes in images. +327,2020-04-08 14:16:28,How to Steal Modern NLP Systems with Gibberish?,"It’s possible to steal BERT-based models without any real training data, even using gibberish word sequences." +334,2020-04-08 15:04:28,BioWordVec & BioSentVec,Pre-trained embeddings for biomedical words and sentences +335,2020-04-08 15:07:44,BioBERT: a pre-trained biomedical language representation model ,"Code for fine-tuning BioBERT for biomedical text mining tasks such as biomedical NER, relation extraction, QA, etc." +341,2020-04-08 15:42:56,How to Unit Test Machine Learning Code,Wouldn’t suck to have to throw away perfectly good ideas because our implementations were buggy? +343,2020-04-08 15:52:19,Machine Learning Systems Design,Designing a machine learning system. +345,2020-04-08 16:14:23,HMTL: Hierarchical Multi-Task Learning,🌊 A State-of-the-Art neural network model for several NLP tasks based on PyTorch and AllenNLP +347,2020-04-08 16:26:05,The State of Transfer Learning in NLP,This post expands on the NAACL 2019 tutorial on Transfer Learning in NLP. It highlights key insights and takeaways and provides updates based on recent work. +349,2020-04-08 16:35:52,The Dark Secrets of BERT,How much of the linguistically interpretable self-attention patterns that are presumed to be its strength are actually used to solve downstream tasks? +364,2020-04-08 17:53:15,Named Entity Recognition Tagging,"In this post, we go through an example from Natural Language Processing, in which we learn how to load text data and perform NER tagging for each token." +372,2020-04-08 18:22:46,An introduction to Q-Learning: Reinforcement Learning,Q-Learning algorithm along with an implementation in Python using Numpy. +378,2020-04-08 19:37:57,Ray,Ray is a fast and simple framework for building and running distributed applications. +380,2020-04-08 21:05:06,Graph Nets,"PyTorch Implementation and Explanation of Graph Representation Learning papers involving DeepWalk, GCN, GraphSAGE, ChebNet & GAT." +388,2020-04-08 21:36:39,ConvNet Playground,An interactive visualization for exploring Convolutional Neural Networks applied to the task of semantic image search. +392,2020-04-08 21:53:06,Embedding Projector,"Visualization of high dimensional data, namely embeddings." +395,2020-04-08 22:12:24,Word2Viz: Explore Word Analogies,Interactive visualization of word analogies in GloVe. +397,2020-04-08 22:17:06,Image-to-Image Translation with Conditional Adversarial Networks,Tensorflow port of Image-to-Image Translation with Conditional Adversarial Nets +401,2020-04-08 22:29:09,"Quick, Draw",Can a neural network learn to recognize doodling? +403,2020-04-08 22:44:04,A 2019 Guide to Speech Synthesis with Deep Learning,A look at recent deep learning based speech synthesis research and techniques. +408,2020-04-08 23:03:13,FlashTorch,Visualization toolkit for neural networks in PyTorch +411,2020-04-08 23:11:09,W&B: Weights and Biases,Track model training at scale. +419,2020-04-09 00:41:03,Text Feature Selection for Causal Inference,"Identifying the linguistic features that cause people to act a certain way after reading a text, regardless of confounding variables, is something people do." +423,2020-04-09 00:57:49,3D Ken Burns Effect from a Single Image,Implementation of 3D Ken Burns Effect from a Single Image using PyTorch. +424,2020-04-09 01:02:59,Sparse Sinkhorn Attention,A new efficient and sparse method for learning to attend based on differentiable sorting of internal representations. +425,2020-04-09 01:41:48,Backtester,A backtesting framework for timeseries data. +427,2020-04-09 18:57:01,An Overview of Early Vision in InceptionV1,"A guided tour of the first five layers of InceptionV1, +taxonomized into “neuron groups.”" +428,2020-04-10 04:57:53,AiLight: Automatic Highlighting Using BERT,"Automatically highlight pdfs using BERT embeddings and clustering. +https://anishthite.github.io/ailight" +430,2020-04-10 15:28:43,Controlling Text Generation with Plug and Play Language Models,"This article discusses an alternative approach to controlled text generation, titled the Plug and Play Language Model (PPLM)." +431,2020-04-10 15:35:00,Genomic ULMFiT,ULMFiT for Genomic Sequence Data +432,2020-04-10 15:39:29,Self-Supervised Learning and Computer Vision,"So, what do you do if there are no pre-trained models in your domain? " +434,2020-04-10 15:51:52,scispaCy,A full spaCy pipeline and models for scientific/biomedical documents. +439,2020-04-10 17:33:38,Universal Adversarial Triggers for Attacking and Analyzing NLP,We create short phrases that cause a specific model prediction when concatenated to 𝘢𝘯𝘺 input from a dataset. +440,2020-04-10 17:39:19,lazynlp,Library to scrape and clean web pages to create massive datasets. +443,2020-04-10 17:51:39,AllenNLP Interpret,A Framework for Explaining Predictions of NLP Models +445,2020-04-10 18:00:50,Natural Language Processing With spaCy in Python,A comprehensive guide to NLP with spaCy. +446,2020-04-10 18:45:15,Tips for Successfully Training Transformers on Small Datasets,It turns out that you can easily train transformers on small datasets when you use tricks (and have the patience to train a very long time). +448,2020-04-10 19:14:59,🦄 How to build a SOTA Conversational AI with Transfer Learning,Train a dialog agent leveraging transfer Learning from an OpenAI GPT and GPT-2 Transformer language model. +452,2020-04-10 20:18:20,CS224n: Natural Language Processing with Deep Learning,"In this course, students will gain a thorough introduction to cutting-edge research in Deep Learning for NLP." +453,2020-04-10 20:23:21,CS231n: Convolutional Neural Networks for Visual Recognition,"Deep dive into details of the deep learning architectures with a focus on learning end-to-end models for these tasks, particularly image classification." +455,2020-04-10 20:31:09,Illustrated: Self-Attention,Step-by-step guide to self-attention with illustrations and code. +459,2020-04-10 21:05:32,Beyond the Pixel Plane: Sensing and Learning in 3d,Recent deep learning techniques that enable 3D object classification and semantic segmentation. +462,2020-04-11 16:52:35,A Visual Guide to Self-Labelling Images,A self-supervised method to generate labels via simultaneous clustering and representation learning +465,2020-04-13 02:18:51,3D Photography using Context-aware Layered Depth Inpainting,A multi-layer representation for novel view synthesis that contains hallucinated color and depth structures in regions occluded in the original view. +466,2020-04-13 18:48:40,Tokenizers: How Machines Read,A survey of different tokenization strategies in NLP. +467,2020-04-13 19:43:35,Practical Text Classification With Python and Keras,You will get a grasp of current advancements of (deep) neural networks and how they can be applied to text. +468,2020-04-13 19:45:46,Text Classification With Torchtext,This example shows how to train a supervised learning algorithm for classification using one of these TextClassification datasets. +469,2020-04-13 21:17:44,Understanding Text With Bert,Building a machine reading comprehension system using the latest advances in deep learning for NLP. +470,2020-04-13 21:38:20,Transfer Learning with T5: the Text-To-Text Transfer Transformer,"In the paper, we demonstrate how to achieve state-of-the-art results on multiple NLP tasks using a text-to-text transformer pre-trained on a large text corpus." +471,2020-04-13 21:48:48,Building a COVID-19 Project Recommendation System,"How to create a GitHub open source repo recommendation system web app with MLflow, Sagemaker, and Booklet.ai." +473,2020-04-13 22:33:21,Neural Machine Translation With Attention,This notebook trains a sequence to sequence (seq2seq) model for Spanish to English translation. +474,2020-04-13 22:48:49,PyTorch Tutorial for Deep Learning Researchers,This repository provides tutorial code for deep learning researchers to learn PyTorch. +476,2020-04-14 00:40:10,Show and Tell: A Neural Image Caption Generator,A TensorFlow implementation of the image-to-text model. +477,2020-04-14 01:46:32,SimpleGAN,A Tensorflow-based framework to ease the training of generative models +478,2020-04-14 02:41:43,Semantic Segmentation on MIT ADE20K dataset in PyTorch,Pytorch implementation for Semantic Segmentation/Scene Parsing on MIT ADE20K dataset. +480,2020-04-14 03:46:09,ViLBERT-MT: Multi-Task Vision & Language Representation Learning,A single ViLBERT Multi-Task model can perform 8 different vision and language tasks learnt from 12 datasets! +481,2020-04-14 03:50:18,Training an Image Classifier in PyTorch,"Torchvision, that has data loaders for common datasets such as Imagenet, CIFAR10, MNIST, etc. and data transformers for images, vizualization and data loaders." +482,2020-04-14 17:28:37,A Visual Exploration of DeepCluster,DeepCluster is a self-supervised method to combine clustering and representation learning +486,2020-04-14 20:12:43,A 2019 guide to Human Pose Estimation with Deep Learning,The basics of Human Pose Estimation (2D) and review the literature on this topic. +489,2020-04-14 22:22:40,"Deep Learning Based Super Resolution, Without Using a GAN","Techniques and training a deep learning model for image improvement, image restoration, inpainting and super resolution." +490,2020-04-14 22:35:21,U-Net Deep Learning Colorization of Greyscale Images,This article describes experiments training a neural network to generate 3 channel colour images from single channel greyscale images using deep learning. +491,2020-04-14 22:38:54,Deep Learning for Image Super-resolution: A Survey,This article aims to provide a comprehensive survey on recent advances of image super-resolution using deep learning approaches. +492,2020-04-14 22:41:52,Second-order Attention Network for Single Image Super-resolution,We propose a second-order attention network (SAN) for more powerful feature expression and feature correlation learning. +493,2020-04-14 22:52:49,DeepSORT: Deep Learning to Track Custom Objects in a Video,A look at deep learning based approached for object tracking. +494,2020-04-14 22:59:56,Fast Online Object Tracking and Segmentation: A Unifying Approach,We illustrate how to perform both realtime object tracking and semi-supervised video object segmentation using a fully-convolutional Siamese approach. +495,2020-04-14 23:10:48,Neural Style Transfer,This tutorial uses deep learning to compose one image in the style of another image (ever wish you could paint like Picasso or Van Gogh?). +499,2020-04-14 23:34:32,Deep Learning for Videos: A 2018 Guide to Action Recognition,"In this post, I summarize the literature on action recognition from videos. " +501,2020-04-15 15:20:56,Shakespeare Meets Google's Flax,Application of RNNs in Flax: Character-Level Language Model. +505,2020-04-15 15:59:30,"Anomaly detection with Keras, TensorFlow, and Deep Learning",Perform anomaly detection in your own image datasets using deep learning. +507,2020-04-15 16:12:41,Almost Everything You Need to Know About Time Series,"Understand moving average, exponential smoothing, stationarity, autocorrelation, SARIMA, and more." +508,2020-04-15 16:29:08,STEFANN: Scene Text Editor using Font Adaptive Neural Network,A generalized method for realistic modification of textual content present in a scene image. ⭐️ Accepted in CVPR 2020. +509,2020-04-15 16:34:04,Time Series Prediction with LSTM Using PyTorch,Time series applied to forecasting on the Airplane Passengers Dataset. +513,2020-04-15 17:05:36,lda2vec: Tools for interpreting natural language,The lda2vec model tries to mix the best parts of word2vec and LDA into a single framework. +516,2020-04-15 17:21:53,Deep Learning for Object Detection: A Comprehensive Review,"A closer look at Tensorflow’s object detection models: Faster R-CNN, R-FCN, and SSD." +517,2020-04-15 17:31:22,An Intuitive Guide to Deep Network Architectures,"Intuition behind base network architectures like MobileNets, Inception, and ResNet." +529,2020-04-15 19:39:24,Real-Time Voice Cloning,Clone a voice in 5 seconds to generate arbitrary speech in real-time. Code for Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech. +549,2020-04-16 03:48:35,15 Best Tools for Tracking Machine Learning Experiments,A feature comparison of all the open-source and commercial options for experiment tracking. +550,2020-04-16 08:14:50,Cycle GAN in TensorFlow 2.0 with Custom Loops,"Implementation of ""Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks"" by Jun-Yan Zhu et al. " +552,2020-04-16 10:13:12,Holopix50k: A Large-Scale In-the-wild Stereo Image Dataset,The largest dataset of in-the-wild stereo image pairs (50K) crowd-sourced from the Holopix lightfield image-sharing social network. +558,2020-04-16 15:49:29,PyTorch Notebooks,🔥A collection of PyTorch notebooks for learning and practicing deep learning +564,2020-04-17 13:16:09,Optimize your ML models,Learn to use optimize your custom image classification models (built-in tf.keras) using TensorFlow Lite and gain 10x reduction in model's size. +566,2020-04-17 21:57:35,Machine learning deserves its own flavor of Continuous Delivery,"When traveling in the data science world, I'm homesick for a smooth continuous delivery flow. My thoughts on approachable CD4ML." +574,2020-04-20 00:23:44,The Abstraction and Reasoning Corpus (ARC),"Can a computer learn complex, abstract tasks from just a few examples? ARC can be used to measure a human-like form of general fluid intelligence." +580,2020-04-20 00:57:03,GitHub Actions & Machine Learning Workflows with Hamel Husain," In this talk, Hamel will provide a brief tutorial on GitHub Actions, and will show you how you can use this new tool to automate your ML workflows." +581,2020-04-20 01:01:38,How To Create Semantic Search For Arbitrary Objects,An end-to-end example of how to build a system that can search objects semantically. By Hamel Husain & Ho-Hsiang Wu +598,2020-04-22 16:33:59,The Future of (Transfer Learning in) Natural Language Processing,"Transfer Learning in Natural Language Processing (NLP): Open questions, current trends, limits, and future directions." +599,2020-04-22 16:43:13,MONAI,AI Toolkit for Healthcare Imaging. +601,2020-04-22 17:41:06,How I Used Deep Learning To Train A Chatbot To Talk Like Me,Facebook chatbot that I trained to talk like me using Seq2Seq. +602,2020-04-23 00:36:02,DialoGPT: Toward Human-Quality Conversational Response Generation,Large-scale pre-training for dialogue. +605,2020-04-23 03:59:57,Upside Down Reinforcement Learning,Implementation of UDRL as outlined by Juergen Schmidhuber in https://arxiv.org/abs/1912.02875 +608,2020-04-23 12:52:02,PyImageSearch,An online platform of blogs on Computer Vision and Deep Learning. +619,2020-04-23 16:55:27,Implementing Portrait Bokeh Mode using OpenCV and NumPy (Python),"Do you love the portrait mode in your smartphone? This code will help you do the same using OpenCV and NumPy! Detects the faces, asks if you want to blur them!" +621,2020-04-23 18:17:12,MixNMatch,Multifactor Disentanglement and Encoding for Conditional Image Generation +622,2020-04-23 21:40:09,MT-Clinical BERT,Scaling Clinical Information Extraction with Multitask Learning +623,2020-04-24 00:30:02,medaCy,🏥 Medical Text Mining and Information Extraction with spaCy +632,2020-04-24 11:37:13,Lagrangian Neural Networks,"Trying to learn a simulation? Try Lagrangian Neural Networks, which explicitly conserve energy and may generalize better!" +639,2020-04-24 20:51:18,ML Foundations and Methods for Precision Medicine and Healthcare,"This tutorial will discuss ideas from machine learning that enable personalization (useful for applications in education, retail, medicine and recsys)." +643,2020-04-26 04:34:02,Albert-base for Sanskrit,Trained Albert-base from scratch on Sanskrit corpus of Wikipedia. I have also added a link to how to train your own Language model from scratch. +644,2020-04-26 05:42:37,Adversarial Latent Autoencoders,"Introducing the Adversarial Latent Autoencoder (ALAE), a general architecture that can leverage recent improvements on GAN training procedures." +652,2020-04-28 15:14:00,Optimal Transport and the Sinkhorn Transformer,Understand optimal transport and the Sinkhorn-Knopp algorithm before diving into the Sinkhorn Transformer. +653,2020-04-28 16:20:29,Semantic Graphs for Generating Deep Questions,"Deep Question Generation (DQG), which aims to generate complex questions that require reasoning over multiple pieces of information of the input passage. " +658,2020-04-28 21:34:00,Gutenberg Dialog,Build a dialog dataset from online books in many languages. +661,2020-04-29 02:41:24,Better NLP project,This is a wrapper program/library that encapsulates a couple of NLP libraries that are popular among the AI and ML communities. +663,2020-04-29 04:42:16,Recipes for building an open-domain chatbot,"Python framework for sharing, training and testing dialogue models, from open-domain chitchat to VQA (Visual Question Answering)." +665,2020-04-29 10:46:20,Object-detection with multi-template matching,"This python package allows to perform object detection using one or a few template images, it provides a simpler alternative to deep-learning methods" +667,2020-04-29 18:34:28,No Trump Social Chrome Plugin,An AI-driven Browser Extension to Replace Trump Pics with Puppies! +670,2020-04-29 19:35:22,Attribute2Font: Creating Fonts You Want From Attributes,Official PyTorch implementation of the Attribute2Font: Creating Fonts You Want From Attributes. +674,2020-04-30 17:52:55,YOLOv4: Optimal Speed and Accuracy of Object Detection,A minimal implementation of YOLOv4. +679,2020-05-01 16:17:32,Geometric and Relational Deep Learning,Videos from emerging fields of Graph Representation Learning and Geometric Deep Learning. +683,2020-05-01 16:35:06,TAPAS: Weakly Supervised Table Parsing via Pre-training,Using neural networks to find answers in tables. +686,2020-05-01 16:59:48,Jukebox: A Generative Model for Music,"We’re introducing Jukebox, a neural net that generates music, including rudimentary singing, as raw audio in a variety of genres and artist styles. " +687,2020-05-01 17:17:48,Exploratory Data Analysis of Time Series,"Exploratory Data Analysis of Time Series data in Python. It uses lot of the principles and concepts discussed in Prof. Hyndman's book. The focus is on understa +" +688,2020-05-01 17:47:40,Gotchas of Transfer Learning for Image Classification,Discover the things you should care about while doing transfer learning for image classification. +693,2020-05-02 05:05:44,SciTLDR: Extreme Summarization of Scientific Documents,A new automatic summarization task with high source compression requiring expert background knowledge and complex language understanding. +694,2020-05-02 15:29:06,BLINK: Better entity LINKing,Entity Linking python library that uses Wikipedia as the target knowledge base. +695,2020-05-02 21:33:31,Five Cool Python Libraries for Data Science,Python is a best friend for the majority of the Data Scientists. Libraries make their life simpler. I have come across five cool Python libraries while working +700,2020-05-03 13:49:29,Fastai2 Vision Module,A detailed guide to using fastai2 Datablock API for common computer vision tasks +702,2020-05-03 20:19:10,Unsupervised Question Decomposition for Question Answering,"Decompose hard (multi-hop) questions into several, easier (single-hop) questions using unsupervised learning, and get better accuracy on multi-hop QA." +704,2020-05-04 11:58:27,Training Batch Norm and Only Batch Norm,Experiments with the ideas presented in https://arxiv.org/abs/2003.00152 by Frankle et al. +707,2020-05-05 03:36:50,The Big Bad NLP Database,A collection of 400+ NLP datasets with papers included. +708,2020-05-05 03:51:53,POINTER: Constrained Text Generation,Constrained Text Generation via Insertion-based Generative Pre-training +712,2020-05-05 05:55:46,Covid-19: A-Geo-Statistical-Analysis,Analysis with the time series data available for various countries. +713,2020-05-05 07:13:49,Cognito : Data wrangling toolkit,Cognito is an exclusive python data preprocessing library and command-line utility that helps any developer to transform raw data into a machine-learning format +717,2020-05-05 14:46:57,Synthesizer: Rethinking Self-Attention in Transformer Models,The dot product self-attention is known to be central and indispensable to state-of-the-art Transformer models. But is it really required? +726,2020-05-06 01:10:55,ConvNets-TensorFlow2,Implementing a variety of popular and important CNN architectures +732,2020-05-06 04:20:43,StellarGraph - Machine Learning on Graphs,"State-of-the-art algorithms for graph machine learning, making it easy to discover patterns and answer questions about graph-structured data." +733,2020-05-06 04:30:47,LandCover.ai,"Dataset for automatic mapping of buildings, woodlands and water from aerial imagery." +734,2020-05-06 04:33:15,Generating SOAP Notes from Doctor-Patient Conversations,Evaluate complete pipelines for leveraging these transcripts to train machine learning model to generate these notes. +741,2020-05-07 01:15:12,Zero-shot Neural Retrieval via Domain-targeted Synthetic Queries,Zero-shot learning for ad-hoc retrieval models that relies on synthetic query generation. +778,2020-05-07 21:28:34,Harry Potter and the Deep Learning Experiment,RNN built with TensorFlow to generate text based on Harry Potter's books. +783,2020-05-08 14:44:04,NeuralCook — Image2Ingredients and Cooking Recommendation,"Deep learning application to identify ingredients from cooking dishes images and recommend dishes to cook, given a set of ingredients." +788,2020-05-09 04:12:10,NER model for 40 languages trained with the new TFTrainer,This model is a fine-tuned XLM-Roberta-base over the 40 languages proposed in XTREME from Wikiann. +791,2020-05-09 14:30:08,Pose Animator,Takes a 2D vector illustration and animates its containing curves in real-time based on the recognition result from PoseNet and FaceMesh. +792,2020-05-09 16:59:54,A Commit History of BERT and its Forks,What a commit history of version-controlled research papers could look like? +795,2020-05-10 04:51:17,U^2-Net,"The code for our newly accepted paper in Pattern Recognition 2020: ""U^2-Net: Going Deeper with Nested U-Structure for Salient Object Detection.""" +796,2020-05-10 05:08:27,Age and Gender Estimation using Multi-Task CNN,Used a multi task CNN to predict the age group and gender of the person in the image. +797,2020-05-10 15:31:27,Data augmentation recipes in tf.keras image-based models,Learn about different ways of doing data augmentation when training an image classifier in tf.keras. +799,2020-05-11 00:40:49,Injecting Inductive Bias in Graph Neural Networks (MIT talk),Equivariant Mesh Neural Networks and Neural Augmented (Factor) Graph Neural Networks. +800,2020-05-11 00:44:10,Feature Stores for ML,List of production ML groups and their open-source feature store architectures. +803,2020-05-11 02:13:32,Image Semantic Segmentation of UAV mining area based on Deeplabv3,"Data: UAV mining area image +Tools: PyTorch +Frame: Deeplabv3 +Semantic Segmentation " +820,2020-05-11 14:19:18,A Comprehensive Survey on Graph Neural Networks,A Comprehensive Survey on Graph Neural Networks. +821,2020-05-11 15:03:57,Hidden Technical Debt in Machine Learning Systems,"Using the software engineering framework of technical debt, we find it is common to incur massive ongoing maintenance costs in real-world ML systems. " +822,2020-05-11 15:10:09,In-Domain GAN Inversion for Real Image Editing,"We propose an in-domain GAN inversion method, which faithfully reconstructs the input image but also ensures the inverted code to be semantically meaningful." +825,2020-05-11 23:07:39,Neural Networks for NLP (CMU CS 11-747),"This class will start with a brief overview of neural networks, then spend the majority of the class demonstrating how to apply neural networks to language." +826,2020-05-12 03:02:02,DANet PyTorch,A Pytorch implementation of Dual Attention Network for Scene Segmentation +828,2020-05-12 05:04:58,BART version of closed-book QA,"This is a BART version of sequence-to-sequence model for open-domain QA in a closed-book setup, based on PyTorch and Huggingface's Transformers." +829,2020-05-12 05:07:35,Unsupervised Reinforcement Learning,Lecture on unsupervised reinforcement learning by Sergey Levine. Originally prepared for AAMAS 2020. +831,2020-05-13 02:24:24,CCNet_PyTorch,A PyTorch Implementation of CCNet: Criss-Cross Attention for Semantic Segmentation +832,2020-05-13 04:22:09,Image segmentation in 2020,"Architectures, Losses, Datasets, and Frameworks" +833,2020-05-13 04:27:08,Plan2Explore: Plan to Explore via Self-Supervised World Models,A self-supervised reinforcement learning agent that tackles task-specific and the sample efficiency challenges. +835,2020-05-13 04:39:31,Toward Better Storylines with Sentence-Level Language Models,We propose a sentence-level language model which selects the next sentence in a story from a finite set of fluent alternatives. +836,2020-05-13 04:43:57,Epipolar Transformers,"Differentiable ""epipolar transformer"", which enables the 2D detector to leverage 3D-aware features to improve 2D pose estimation." +840,2020-05-13 05:03:33,Machine Learning on Graphs: A Model and Comprehensive Taxonomy,We propose a simple framework (GraphEDM) and a comprehensive Taxonomy to review and unify several graph representation learning methods. +841,2020-05-13 05:10:58,BLEURT: Learning Robust Metrics for Text Generation,A metric for Natural Language Generation based on transfer learning. +842,2020-05-13 13:20:07,Identifying Brain Tumor from MRI images using FastAI -DynamicUnet,"To use FASTAI unet learner to identify tumours from MRI of Brain, logging loss metrics in Neptune AI logger and compare the results after hyperparameter tuning." +847,2020-05-13 22:53:36,HuggingTweets,Tweet Generation with Huggingface. +849,2020-05-13 22:59:38,Top Down Introduction to BERT with HuggingFace and PyTorch,I will also provide some intuition into how BERT works with a top down approach (applications to algorithm). +850,2020-05-13 23:02:29,Transformers from Scratch,"Attempt to explain directly how modern transformers work, and why, without some of the historical baggage." +852,2020-05-14 07:11:26,Scene Classification using Pytorch and Fast.ai,The objective is to classify Multi-label images using deep learning. Here I have used Fast.ai library for implementing the model. +855,2020-05-14 12:32:20,Fake new detection Pytorch,Fake News Detection by Learning Convolution Filters through Contextualized Attention. +857,2020-05-14 14:25:11,FastHugs: Sequence Classification with Transformers and Fastai,Fine-tune a text classification model with HuggingFace 🤗 transformers and fastai-v2. +858,2020-05-14 14:35:37,Open-Dialog Chatbots for Learning New Languages,A tutorial for automatically generate code comments using Deep Learning. +860,2020-05-14 17:35:04,Electra,ELECTRA: Pre-training Text Encoders as Discriminators Rather Than Generators +862,2020-05-14 19:13:59,DQN In Pytorch Livestream Series,I'm doing a series of streams about reinforcement learning (starting from Q learning) focused on showing the work in as much detail as possible (e.g. debugging) +863,2020-05-15 04:24:58,S2IGAN: Speech-to-Image Generation via Adversarial Learning,A speech-to-image generation (S2IG) framework is proposed which translates speech descriptions to photo-realistic images without using any text information. +864,2020-05-15 13:04:19,Twitter Sentiment Analysis,"This project is based on Natural Language processing (NLP), in this we do sentiment analysis(i.e, how much it is positive or negative) of tweets of any account." +866,2020-05-15 13:51:56,HuggingFace nlp library,"nlp is a lightweight and extensible library to easily share and load dataset and evaluation metrics, already providing access to ~100 datasets and ~10 evaluatio" +868,2020-05-15 14:07:47,RXNMapper: Unsupervised Attention-Guided Atom-Mapping,The atom-mapping information was learned by an ALBERT model trained in an unsupervised fashion on a large dataset of chemical reactions. +869,2020-05-15 14:08:12,ICLR 2020 Trends: Better & Faster Transformers for NLP,A summary of promising directions from ICLR 2020 for better and faster pretrained tranformers language models. +875,2020-05-15 22:53:58,Differentiable Reasoning over Text,We consider the task of answering complex multi-hop questions using a corpus as a virtual knowledge base (KB). +877,2020-05-16 02:42:32,Semi-supervised image classification with GANs,"Shows how to perform semi-supervised image classification with GANs. The cover image is from Chapter 7, GANs in Action." +879,2020-05-16 10:57:53,HighRes-net: Multi-Frame Super-Resolution of satellite imagery,"Pytorch implementation of HighRes-net, a neural network for multi-frame super-resolution, trained and tested on the European Space Agency’s Kelvin competition." +880,2020-05-16 11:50:31,How Deep Is Your Love For Transfer Learning In NLP?,A review of NLP research +881,2020-05-16 13:32:51,Time Series Forecasting with TensorFlow.js,Machine learning is becoming increasingly popular these days and a growing number of the world’s population see it is as a magic crystal ball: predicting when a +882,2020-05-16 13:35:31,Phrases extraction and D3 Wordcloud,100% JavaScript solution to extracting phrases from text and display key points in a beautiful D3 wordcloud. +883,2020-05-16 13:37:44,Reinforcement Learning Tic Tac Toe with Value Function,"A reinforcement learning algorithm for agents to learn the tic-tac-toe, using the value function + +" +884,2020-05-16 13:40:07,Build a Textual Similarity Web App with TensorFlow.js,Have you wondered how search engines understand your queries and retrieve relevant results? How chatbots extract your intent from your questions and provide the +890,2020-05-16 19:51:33,cyBERT: Applying BERT to Windows event logs,"This blog shows how interpreting cybersecurity logs as a natural language, improving upon the standard regex-based parsing of log data." +892,2020-05-17 02:08:12,DPOD: Pose Estimator,PyTorch recreation of a SOTA 6D Pose estimation research paper. +893,2020-05-17 04:44:04,ESTorch,ESTorch is an Evolution Strategy Library build around PyTorch. +894,2020-05-17 04:47:40,"A Large-Scale, Open-Domain, Mixed-Interface Dialogue-Based ITS ","Korbit, a large-scale, open-domain, mixed-interface, dialogue-based intelligent tutoring system (ITS)." +900,2020-05-17 08:14:24,A Visual Survey of Data Augmentation in NLP,An extensive overview of text data augmentation techniques for Natural Language Processing +901,2020-05-17 09:57:38,DoYouEvenLearn,Essential Guide to keep up with AI/ML/DL/CV +902,2020-05-18 00:57:27,Differentiable Adaptive Computation Time for Visual Reasoning ,"DACT, a new algorithm for achieving adaptive computation time that, unlike existing approaches, is fully differentiable. " +903,2020-05-18 11:15:12,Semixup: In- and Out-of-Manifold Regularization,Semixup is a semi-supervised learning method based on in/out-of-manifold regularization. +905,2020-05-18 14:40:51,Deep Reinforcement Learning for Supply Chain & Price Optimization,Explore how deep reinforcement learning methods can be applied in several basic supply chain and price management scenarios. +907,2020-05-18 14:53:33,TextAttack,A Python framework for building adversarial attacks on NLP models. +913,2020-05-19 03:19:59,aitextgen,A robust Python tool for text-based AI training and generation using GPT-2. +914,2020-05-19 03:25:11,How Hugging Face achieved a 2x performance boost for QA,Question Answering with DistilBERT in Node.js +918,2020-05-19 22:36:09,Accelerate your NLP pipelines using Hugging Face and ONNX,How the ONNX Runtime team and Hugging Face are working together to address challenges in training and deployment of Transformer models. +920,2020-05-20 02:35:11,Attentron,Few-shot text-to-speech exploiting attention-based variable length embedding +921,2020-05-20 02:39:09,Torch Points3D,Pytorch framework for doing deep learning on point clouds. +922,2020-05-20 07:23:50,NLP Model Selection ,NLP model selection guide to make it easier to select models. This is prescriptive in nature and has to be used with caution. +925,2020-05-20 16:20:28,Model-Agnostic Meta-Learning for Reinforcement Learning with TF2,Reimplementation of Model-Agnostic Meta-Learning (MAML) applied on Reinforcement Learning problems in TensorFlow 2. +927,2020-05-21 03:16:17,FashionBERT,Text and image matching with adaptive loss for cross-modal retrieval. +934,2020-05-21 03:45:38,📈 Automated Time Series Forecasting,This data app uses Facebook's open-source Prophet library to automatically forecast values into the future. +935,2020-05-21 14:22:01,"Look inside the workings of ""Label Smoothing""","This blog post describes how and why does ""trick"" of label smoothing improves the model accuracy and when should we use it " +938,2020-05-22 01:01:32,Content and Style Disentanglement for Artistic Style Transfer,Hi-Res style transfer and interpolation between styles +939,2020-05-22 03:08:40,Time Series Classification Using Deep Learning,"In this article, I will introduce you to a new package called timeseries for fastai2 that I lately developed. " +940,2020-05-22 03:16:29,TAO: A Large-Scale Benchmark for Tracking Any Object,"A diverse dataset for Tracking Any Object (TAO) consisting of 2,907 high resolution videos, captured in diverse environments, which are half a minute long on " +941,2020-05-22 03:21:10,BiT: Exploring Large-Scale Pre-training for Compute,"We are excited to share the best BiT models pre-trained on public datasets, along with code in TF2, Jax, and PyTorch. " +947,2020-05-22 13:34:30,Self Driving Car,This project is a demonstration of a working model of self driving car 🚗🚗 identifying and following lanes using powerful computer vision 🕶🕶 algorithms. +948,2020-05-22 13:39:15,Plant Disease Detection,This website help you to detect disease in your plant🌳 based to the plant's leaf🍃 image +951,2020-05-23 03:19:00,YoloV3 implementation in keras and tensorflow 2.2,YoloV3 Real Time Object Detector in tensorflow 2.2. +952,2020-05-23 03:22:11,Face Mask Detector,A simple Streamlit frontend for face mask detection in images using a pre-trained Keras CNN model + OpenCV and model interpretability. +957,2020-05-23 09:18:52,Colbert AI,Colbert AI is a Deep Learning Language Model that generates text in the style of Stephen Colbert's famous monologues. +961,2020-05-23 16:01:21,How to Build Robust Embeddings for Visual Similarity Tasks,This repository I package a bunch of tips and tricks to efficiently train deep learning models in computer vision +962,2020-05-24 00:09:28,Basic ML Algorithms from scratch.,Implement basic Machine Learning Algorithms from scratch in python. +963,2020-05-24 03:13:28,Build your first data warehouse with Airflow on GCP,What are the steps in building a data warehouse? What cloud technology should you use? How to use Airflow to orchestrate your pipeline? +966,2020-05-24 10:24:03,Building an Intelligent Twitter Bot,The volume of information going through Twitter per day makes it one of the best platforms to get information on any subject of interest. +968,2020-05-24 16:40:46,Self Supervised Representation Learning in NLP,An overview of self-supervised pretext tasks in Natural Language Processing +970,2020-05-24 20:01:29,Job Classification,"Job Classification done using Techniques of NLP and ML. + +Dataset used from Kaggle of Indeeed job posting." +972,2020-05-25 03:23:16,Next Word Prediction,Using transformers to predict next word and predict word. +974,2020-05-25 03:28:32,PixelLib,Pixellib is a library for performing segmentation of images. +978,2020-05-25 05:53:46,TensorFlow.js - Gesture Controlled 2048,Gesture Controlled 2048 built with TensorFlow.js +979,2020-05-25 11:04:50,Taxi Demand Prediction NewYorkCity,Predict the number of pickups as accurately as possible for each region in a 10 -min interval. +980,2020-05-25 14:52:17,Super-BPD for Fast Image Segmentation,"We propose direction-based super-BPD, an alternative to superpixel, for fast generic image segmentation, achieving state-of-the-art real-time result." +986,2020-05-26 03:47:15,Neural Topological SLAM for Visual Navigation,Topological representations for space that effectively leverage semantics and afford approximate geometric reasoning. +987,2020-05-26 13:16:48,Zero To One For NLP,A collection of all resources for learning NLP +989,2020-05-26 17:17:14,NLP for Developers: Shrinking Transformers | Rasa,"In this video, Rasa Senior Developer Advocate Rachael will talk about different approaches to make transformer models smaller." +993,2020-05-27 05:26:33,DETR: End-to-End Object Detection with Transformers,A new method that views object detection as a direct set prediction problem. +997,2020-05-28 03:20:06,AutoSweep: Recovering 3D Editable Objects from a Single Photo,Fully automatic framework for extracting editable 3D objects directly from a single photograph. +1000,2020-05-28 03:33:52,CMU LTI Low Resource NLP Bootcamp 2020,A low-resource natural language and speech processing bootcamp held by the Carnegie Mellon University Language Technologies Institute in May 2020. +1007,2020-05-28 21:30:37,Humour.ai : Language Model that can crack Jokes,"A Language model that can make you laugh. Humour.ai model tries to +complete a sentence in a humourous way given some input words. " +1008,2020-05-29 02:28:53,face mask detection ,detects whether a person wearing a mask or not +1009,2020-05-29 02:47:06,Train ALBERT for NLP with TensorFlow on Amazon SageMaker,"To train BERT in 1 hour, we efficiently scaled out to 2,048 NVIDIA V100 GPUs by improving the underlying infrastructure, network, and ML framework. " +1010,2020-05-29 02:51:39,GPT-3: Language Models are Few-Shot Learners,"We show that scaling up language models greatly improves task-agnostic, few-shot performance, sometimes even reaching competitiveness with prior SOTA." +1013,2020-05-29 03:06:41,Guided Uncertainty-Aware Policy Optimization,Combining learning and model-based strategies for sample-efficient policy learning. +1018,2020-05-29 08:09:04,GOTURN-PyTorch,"PyTorch implementation of ""Learning to Track at 100 FPS with Deep Regression Networks""" +1020,2020-05-29 09:54:04,Applying Modern Best Practices to Autoencoders,This project applies best modern practices found in other areas of image research to autoencoders. Comparing models from other areas of image research. +1021,2020-05-29 10:33:26,Sentiment analysis ,"Sentiment analysis by combining three dataset amazon,yelp, IMDb reviews to train our,model to classify if a comment is negative or positive denoted by 0 and 1." +1022,2020-05-29 13:27:20,The designer - gpt2 bot that talks about UX Design,"This twitter profile spits out thoughts on design and development. Trained with hundreds of Books on UX design and Front end development, it has opinions." +1024,2020-05-29 14:15:30,Sentiment Classification for UtaPass & KKBOX Reviews,Text classification for reviews of UtaPass & KKBOX using different deep learning models. +1025,2020-05-29 14:18:59,Forex Prediction,Using neural networks to predict movement of forex direction. +1026,2020-05-29 14:24:07,Lyrics-Based Music Genre Classifier,"Classify the genre (Rock, Pop, Hip-Hop, Not Available, Metal, Other, Country, Jazz, Electronic, R&B, Indie, Folk) of the song by its lyrics." +1028,2020-05-29 14:39:16,ARBML,"Implementation of many Arabic NLP and ML projects. Providing real time experience using many interfaces like web, command line and notebooks." +1035,2020-05-29 16:11:11,Zero Shot Topic Classification,Bart with a classification head trained on MNLI. +1045,2020-05-30 01:35:24,Illustrated Guide to Transformers: Step by Step Explanation,"In this post, we’ll focus on the one paper that started it all, “Attention is all you need”." +1046,2020-05-30 01:39:25,Illustrated Guide to Transformers,A component by component breakdown analysis. +1055,2020-05-30 09:02:27,Automatic-Face-Detection-Annotation-and-Preprocessing,"Automatically detect , annotate , collect the coordinates , convert to csv and to tfrecord" +1058,2020-05-30 09:43:39,SmartFeed.ai,NLP Based Article Recommendation System +1059,2020-05-30 10:50:55,Wheat Detection 🌾,This is a project for detecting and creating bounding box of wheat heads 🌾. +1068,2020-05-30 18:20:40,Effects of News Sentiments on Stock Predictions,Project is based on the Natural Language Processing technique called Sentiment Analysis. Stock market and news related to it as the subject of analysis. +1069,2020-05-30 20:04:49,NLP News Category,The objective of this repository is to create a NLP bot for when you give the robot the headline of the news and a short description it will return the genre. +1070,2020-05-30 20:06:48,AI Debate Master,"Created and deployed a bot made to debate with a human on any +given topic. Employed a Doc2Vec model using Gensim library in Python" +1075,2020-05-31 04:44:27,Zero-Shot Learning for Text Classification,"A visual summary of “Train Once, Test Anywhere” paper for zero-shot text classification" +1080,2020-05-31 05:23:23,Dash DETR Detection App,A User Interface for DETR built with Dash. 100% Python. +1081,2020-05-31 05:28:53,AI Basketball Analysis,🏀 AI web app and API to analyze basketball shots and shooting pose. +1083,2020-05-31 08:20:06,Reverse Image Search,Have you ever wondered how google image search works or How amazon can retrieve products similar to the image that we upload in the app/site? To achieve this ta +1084,2020-05-31 08:22:45,Beginner’s guide to Machine Learning Model Deployment,Are you a beginner in the field of machine learning and wondering how to bring your project to live. I'm was in the same situation when I started learning ML. M +1093,2020-05-31 17:39:22,MedicalZoo PyTorch,A pytorch-based deep learning framework for multi-modal 2D/3D medical image segmentation +1094,2020-05-31 19:11:28,Paraphrase Any Question with T5 (Text-To-Text Transformer),"Given a question, generate paraphrased versions of the question with T5 transformer. Pretrained model and training script provided." +1100,2020-06-01 05:56:43,Movie Recommendation System,This is a web app which recommends movies based on their plots found on IMDb. +1104,2020-06-01 10:02:09,Convnet Galaxy Morphology Classifier,Classify galaxies from Hubble Tuning Fork using Convnet. +1107,2020-06-01 14:52:29,2nd Place Solution to Ship Identification Hackathon ,The problem statement was to identify the type of ship from photos taken from the survey boats. The hackathon was organized by Analytics Vidhya. +1110,2020-06-01 16:44:55,Deep learning Architecture: AlexNet,Explaining network architecture for AlexNet +1111,2020-06-01 18:13:26,Movement Pruning: Adaptive Sparsity by Fine-Tuning,"We propose the use of movement pruning, a simple, deterministic first-order weight pruning method that is more adaptive to pretrained model fine-tuning." +1112,2020-06-01 18:57:31,Document search engine,NLP based search engine for single page pdf files. +1115,2020-06-01 21:07:53,Softbot design with WANNS,"Soft robots are robots built from highly compliant materials, similar to those found in living organisms. This project explored CPPNs and WANNs to design them" +1121,2020-06-02 05:07:17,Motion2Vec,Semi-Supervised Representation Learning from Surgical Videos +1122,2020-06-02 05:10:18,Machine Learning: Tests and Production,Best practices for testing ML-based systems. +1130,2020-06-02 11:51:38,Generate True or False questions from any content,"Automatically generate “True or False” questions like the ones you see in school textbooks using OpenAI GPT2, Sentence BERT, and Berkley parser" +1131,2020-06-02 13:41:32,Sized Fill-in-the-blank or Multi Mask filling with RoBERTa,Sized fill-in-the-blank or conditional text filling is the idea of filling missing words of a sentence with the most probable choice of words. +1132,2020-06-02 14:56:10,T5 for Sentiment Span Extraction,Exploring how T5 works and applying it for sentiment span extraction. +1133,2020-06-02 14:58:58,Getting Started with Time Series analysis using Pandas,An introductory guide to get started with the Time Series datasets in Python +1135,2020-06-02 15:06:34,Melanoma Detection with Pytorch,"In this video, I show you how you can build a deep learning model to detect melanoma with a very high accuracy." +1139,2020-06-02 19:53:37,"RoBERTa → Longformer: Build a ""Long"" Version of Pretrained Models",This notebook replicates the procedure descriped in the Longformer paper to train a Longformer model starting from the RoBERTa checkpoint. +1145,2020-06-03 01:51:14,Learning Dexterity End-to-End,We trained a human-like robot hand to manipulate physical objects with unprecedented dexterity. +1148,2020-06-03 02:28:20,A Practical guide to building a conversational chatbot,Building a Chatbot from scratch using Keras and NLTK library for a customer service company +1151,2020-06-03 07:25:27,Web Mining and Information theory,"Mining the Web and playing with Natural Language processing. Implementing Information retrieval System tasks. Going towards the NLP and Performing Machine Learning algorithms. Through these codes and problems, I have understood the information retrieval process of any search engine. These are very useful problems towards sentiment analysis." +1162,2020-06-03 22:05:30,Deep Q-Network on Space Invaders. ,This is a PyTorch implementation of a Deep Q-Network agent trained to play the Atari 2600 game of Space Invaders. +1165,2020-06-04 03:53:43,YOLOv4,A TensorFlow 2.0 implementation of YOLOv4: Optimal Speed and Accuracy of Object Detection. +1166,2020-06-04 03:55:53,Acme: A Research Framework for Reinforcement Learning,A library of reinforcement learning components and agents. +1176,2020-06-04 09:10:07,doc2vec Paragraph Embeddings for Text Classification,Text classification model which uses gensim's Doc2Vec for generating paragraph embeddings and scikit-learn Logistic Regression for classification. +1178,2020-06-04 12:19:52,Machine Learning with Fastai,"The fastai library is based on research into deep learning best practices undertaken at fast.ai, and includes support for Vision, Text, tabular and Collab" +1180,2020-06-04 14:58:19,The Transformer … “Explained”?,"An intuitive explanation of the Transformer by motivating it through the lens of CNNs, RNNs, etc." +1181,2020-06-04 16:28:24,TensorflowTTS: Real-Time SOTA Speech Synthesis for Tensorflow 2.0,"TensorflowTTS provides real-time state-of-the-art speech synthesis architectures such as Tacotron2, Melgan, FastSpeech." +1185,2020-06-04 22:36:31,PyTorch Transformers Tutorials,"A set of annotated Jupyter notebooks, that give user a template to fine-tune transformers model to downstream NLP tasks such as classification, NER etc. " +1192,2020-06-05 04:28:52,BERT Summarization,This folder contains colab notebooks that guide you through the summarization by BERT and GPT-2 to play with your data. +1194,2020-06-05 04:35:14,Divide Hugging Face Transformers Training Time By 2,Reducing training time helps to iterate more in a fixed budget time and thus achieve better results. +1199,2020-06-05 15:39:56,How NLP has evolved for Financial Sentiment Analysis,Do we still need humans to read boring financial statements? +1202,2020-06-05 17:51:33,The NLP Pandect - All NLP resources in one place,The NLP Pandect was created to help you find almost anything related to Natural Language Processing that is available online. +1203,2020-06-05 18:18:18,Summary of 🤗 Transformers Models,A high-level summary of the differences between each model in HuggingFace's Transformer library. +1204,2020-06-05 22:56:38,Snaked: Classifying Snake Species using Images,Proof of concept that it is possible to identify snake species and whether poisonous from photographs (PyTorch code/model with Android app) +1211,2020-06-06 15:13:13,Literate Lamp: Answering Question with Common Sense,We study the problem of answering questions that require common sense to be answered using Transformer-based models and the ConceptNet knowledge base. +1215,2020-06-06 19:00:39,Pytorch Faster RCNN,Fine Tune Faster RCNN in pytorch for your task. +1222,2020-06-07 04:34:58,Paragraph Summarizer,Uses the extractive way of summarizing the text by finding the score and ranking it. +1223,2020-06-07 04:39:32,Leafy: Plant Leaf Classifier,The sequential model trained on images from the leafsnap.com +1236,2020-06-07 21:03:31,"COVID-Q: A Dataset of 1,690 Questions about COVID-19","This dataset consists of COVID-19 questions which have been annotated into a broad category (e.g. Transmission, Prevention) and a more specific class such that " +1237,2020-06-08 03:43:45,Keras notifications on Slack!,Get slack notifications of your model's training progress when training with Keras (or tf.keras) +1239,2020-06-08 07:05:15,Zero-shot Text Classification With Generative Language Models,An overview of a text generation approach to zero-shot text classification with GPT-2 +1241,2020-06-08 08:25:01,Funnel-Transformer: Filtering out Sequential Redundancy,Funnel-Transformer is a self-attention model that gradually compresses the sequence of hidden states to a shorter one and hence reduces the computation cost. +1243,2020-06-08 08:39:34,Timeseries Anomaly Detection using an Autoencoder,Detect anomalies in a timeseries using an Autoencoder. +1246,2020-06-08 09:47:02,Fairseq-tagging,"a Fairseq fork for sequence tagging/labeling tasks +" +1249,2020-06-08 16:59:01,Know-Corona : Kaggle COVID-19 Open Research Dataset Challenge (CO,"NLP/state-of-the-art language model (BERT) based Question & Answering pipeline to answer all task questions after analyzing articles abstract of COVID-19, SARS-" +1251,2020-06-08 18:38:49,Automatic Asset Classification,This project aims to automate the task of labelling images of flood defence assets as well as clustering images to find possibly better groupings. +1255,2020-06-09 01:50:33,TransformerTTS,🤖💬 Transformer TTS: Implementation of a non-autoregressive Transformer based neural network for text to speech. +1257,2020-06-09 01:58:48,How Big Should My Language Model Be?,Tool to explore language model training and optimize the compute costs. +1258,2020-06-09 02:04:49,MSeg: A Composite Dataset for Multi-domain Semantic Segmentation,A composite dataset that unifies semantic segmentation datasets from different domains. +1259,2020-06-09 02:11:15,Network Fusion for Content Creation With Conditional Inns,"We present a method to repurpose powerful, existing models for new tasks, even though they have never been designed for them." +1260,2020-06-09 02:14:59,Advanced Deep Learning for Computer Vision (ADL4CV),"The Visual Computing Group offers a variety of lectures and seminars on a regular basis, covering hot areas in computer graphics, vision, and machine learning." +1272,2020-06-10 05:13:41,Linformer: Self-Attention with Linear Complexity,We demonstrate that the self-attention mechanism can be approximated by a low-rank matrix. +1274,2020-06-10 05:21:00,Getting Machine Learning to Production,"Machine learning is hard and there are a lot, a lot of moving pieces." +1275,2020-06-10 05:24:07,Exploration Strategies in Deep Reinforcement Learning,Exploitation versus exploration is a critical topic in reinforcement learning. This post introduces several common approaches for better exploration in Deep RL. +1278,2020-06-10 12:50:41,Automatically Generate Multiple Choice Questions (MCQs) ,"Automatically Generate Multiple Choice Questions (MCQs) from any content with BERT Summarizer, Wordnet, and Conceptnet" +1287,2020-06-10 18:27:24,BERT Loses Patience: Fast and Robust Inference with Early Exit,"Patience-based Early Exit, a inference method that can be used as a plug-and-play technique to simultaneously improve the efficiency of a pretrained LM." +1298,2020-06-11 04:18:27,PEGASUS: a SOTA model for Abstractive Text Summarization,A State-of-the-Art Model for Abstractive Text Summarization. +1301,2020-06-11 04:29:24,Big GANs Are Watching You, We demonstrate that object saliency masks for GAN-produced images can be obtained automatically with BigBiGAN. +1309,2020-06-11 19:04:31,Sentiment Analysis on News Article,Used Twitter API to extract news-related tweets. Did some preprocessing and then calculated the tweets' polarity. +1310,2020-06-11 20:30:38,GPT-3 Language Model: A Technical Overview,"Technical details of the GPT-3 model, training, inference and what to expect next. " +1312,2020-06-11 20:37:47,OpenAI API,API for accessing new AI models developed by OpenAI. +1320,2020-06-12 04:17:08,Implementation of a Contextual Chatbot in PyTorch,Simple chatbot implementation with PyTorch. +1325,2020-06-12 11:06:34,Author Identification using Doc2Vec,Web app of an author identification model trained on PAN 2012 dataset and Kaggle's Spooky Authorship Dataset +1329,2020-06-12 12:44:18,Training game agents with supervised learning,This is a continuing research project trying find ways to learn complex tasks such as games without using Reinforcement Learning. +1371,2020-06-13 17:16:07,Baymax - ChatBot,"Baymax Chatbot is a part of my summer training program @AdHoc Networks, Jaipur. + +A chatbot that allows user to signup and login to maintain their record. When c" +1372,2020-06-13 17:21:43,How to Evaluate Longformer on TriviaQA using NLP,We will evaluate a pretrained LongformerForQuestionAnswering model on the validation dataset of TriviaQA. +1374,2020-06-13 17:28:13,Extracting Structured Data from Templatic Documents,"Automatically extract data from structured documents—invoices, receipts, etc.—with the potential to streamline many business workflows." +1392,2020-06-13 20:58:33,StackOver Flow Data Analysis,"Analysing certain aspects of the stack overflow data and creating ""Tag Predictor"" which predicts tag based on the post posted. " +1398,2020-06-14 05:51:06,Super-resolution Variational Auto-Encoders,VAE with RealNVP prior and Super-Resolution VAE in PyTorch. +1399,2020-06-14 05:57:16,Video object grounding,Video object grounding using semantic roles in language description. +1418,2020-06-14 17:43:34,Short Notes on Behavior Regularized Offline RL,Blog Article on Behavior Regularized Offline Reinforcement Learning by Yifan Wu et al. (2019) +1423,2020-06-14 22:10:57,Entity Embedding with LSTM for Time-Series,"Demonstration of using LSTM for forecasting with structured time-series data, containing categorical and numerical features." +1424,2020-06-15 02:27:55,Why We Switched from Flask to FastAPI for Production ML,The most popular tool isn’t always the best. +1425,2020-06-15 02:31:48,Building a Captcha OCR in TF2.0,A Kaggle notebook showcasing the use of an Endpoint layer for CTC loss function used for building a Captcha Reader in TensorFlow. +1427,2020-06-15 02:40:48,101 Ways to Solve Search - Dair AI ft. Pratik Bhavsar,A comprehensive overview of explaining how NLP is used for search. +1438,2020-06-15 11:06:35,Multimodal Meme Classification,UNITER has given state of the art results in various image-text related problems. This project aims at finetuning UNITER to solve Hateful memes challenge +1453,2020-06-16 01:32:49,Interpretable Machine Learning for Computer Vision,"Recent progress we made on visualization, interpretation, and explanation methodologies for analyzing both the data and the models in computer vision." +1455,2020-06-16 02:32:53,Predicting Unintentional Action in Video,"We introduce a dataset of in-the-wild videos of unintentional action, as well as a suite of tasks for recognizing, localizing, and anticipating its onset. " +1457,2020-06-16 02:46:25, Synthesizing High-Resolution Images with StyleGAN2,"Developed by NVIDIA Researchers, StyleGAN2 yields state-of-the-art results in data-driven unconditional generative image modeling." +1458,2020-06-16 02:51:13,PIFuHD: High-Resolution 3D Human Digitization ,"This repository contains a pytorch implementation of ""Multi-Level Pixel-Aligned Implicit Function for High-Resolution 3D Human Digitization""." +1460,2020-06-16 03:21:07,Instance Shadow Detection,Instance shadow detection aims to find shadow instances paired with object instances. +1461,2020-06-16 03:24:02,Detectron2,FAIR's next-generation platform for object detection and segmentation. +1473,2020-06-16 22:37:58,tslearn,A machine learning toolkit dedicated to time-series data. +1475,2020-06-16 22:45:15,PyTorch3D,FAIR's library of reusable components for deep learning with 3D data. +1476,2020-06-16 22:48:45,Course Review - Causal Inference,Types of understanding that causal inference researchers value. +1478,2020-06-16 22:56:31,Unsupervised Learning of Probably Symmetric Deformable 3D Objects,"A method to learn 3D deformable object categories from raw single-view images, without external supervision." +1480,2020-06-16 23:06:13,A Guide to Natural Language Processing With AllenNLP,basics of using AllenNLP +1482,2020-06-17 12:12:03,Real Time Object Detection using CNN YOLO,"This project is done on real time object detection using a deep learning object detection algorithm i.e., YOLO." +1483,2020-06-17 14:38:33,Short Notes on Model-Based Offline Reinforcement Learning (MOReL),Blog article on Model-Based Offline Reinforcement Learning (MOReL) paper by Rahul Kidambi & Aravind Rajeswaran et al. +1491,2020-06-18 00:04:34,Image GPT: Generative Pretraining from Pixels, Transformers trained on pixel sequences can generate coherent image completions and samples. +1492,2020-06-18 00:06:53,Q*BERT,Agents that build knowledge graphs and explore textual worlds by asking questions. +1499,2020-06-18 13:41:39,History of Language Models - Alec Radford,A quick history of language models +1502,2020-06-18 19:45:49,Generate Boolean (Yes/No) Questions From Any Content ,Question generation algorithm trained on the BoolQ dataset using T5 text-to-text transformer model. +1504,2020-06-19 06:19:25,Fast Neural Style Transfer (feed-forward method) ⚡💻 + 🎨 = ❤️,This repo contains a concise PyTorch implementation of the original feed-forward NST paper. +1505,2020-06-19 06:22:56,Diverse Image Generation via Self-Conditioned GANs,A simple but effective unsupervised method for generating realistic & diverse images using a class-conditional GAN model without using manually annotated class. +1506,2020-06-19 06:26:17,Using GitHub Actions for MLOps & Data Science,A collection of resources on how to facilitate Machine Learning Ops with GitHub. +1519,2020-06-20 05:40:46,Image and Bounding Box Annotation Slicer,This easy-to-use library slices (also resizes) images and its bounding box annotations into tiles of specific sizes or any arbitrary number of equal parts. ✂️ +1525,2020-06-20 16:21:38,Huggingtweets,This is a streamlit app built around the huggingtweets project. I fine-tune a pre-trained gpt2 model to tweet like a user given twitter handle. +1528,2020-06-20 22:06:48,The Future of Computer Vision is Self-Supervised Learning,Talk by Yann Lecun on the applications of self-supervised learning on computer vision during CVPR 2020. +1529,2020-06-20 22:11:14,Using Selective Attention in Reinforcement Learning Agents,"In this work, we establish that self-attention can be viewed as a form of indirect encoding, which enables us to construct highly parameter-efficient agents." +1539,2020-06-21 12:45:42,A Visual Guide to FastText Word Embeddings,A deep-dive into how FastText enriches word vectors with sub-word information +1542,2020-06-21 20:46:12,Autocoder - Finetuning GPT-2 for Auto Code Completion,"A basic and simple tool for code auto completion, built upon GPT-2" +1546,2020-06-22 00:46:32,DeepSNAP,Python library assists deep learning on graphs. +1547,2020-06-22 00:50:30,RoBERTa meets TPUs,Understanding and applying the RoBERTa model to the current challenge. +1549,2020-06-22 01:00:45,Deep Model-Based RL for Real-World Robotic Control,Short talk about model-based RL by Sergey Levine. +1551,2020-06-22 03:17:48,Pokemon Classifier,I want to build a classifier that can classify 150 types of Pokemon. +1552,2020-06-22 03:45:01,Workshop on Scalability in Autonomous Driving - Andrej Karpathy,An overview of autonomous driving and computer vision at Tesla. +1560,2020-06-22 15:56:00,Battle-Tested Techniques for Scoping Machine Learning Projects,One of the challenges of managing an ML project is project scoping. Even small changes in data or architecture can create huge differences in model outputs. +1563,2020-06-22 16:04:10,Classify photos in 600 classes using nine million Open Images,"If you’re looking build an image classifier but need training data, look no further than Google Open Images." +1569,2020-06-22 16:52:01,Trackable,The project deals with tracking humans in a narrow hallway under different lighting conditions. +1571,2020-06-23 02:04:12,Stochastic Segmentation Networks,An efficient probabilistic method for modelling aleatoric uncertainty with any image segmentation network architecture. +1575,2020-06-23 02:30:20,Deep Learning for Computer Vision ,Special topics class on deep learning for computer vision from the University of Michigan taught by Justin Johnson. +1576,2020-06-23 02:37:15,VPSNet for Video Panoptic Segmentation,Video panoptic segmentation by generating consistent panoptic segmentation as well as an association of instance ids across video frames. +1580,2020-06-24 03:00:16,What I Learned From Looking at 200 Machine Learning Tools,"To better understand the landscape of available tools for machine learning production, I decided to look up every AI/ML tool I could find." +1581,2020-06-24 03:04:31,Discovering Symbolic Models from Deep Learning w/ Inductive Bias,A general approach to distill symbolic representations of a learned deep model by introducing strong inductive biases. +1585,2020-06-24 03:18:20,Breaking the cycle—Colleagues are all you need,A novel approach to performing image-to-image translation between unpaired domains. +1587,2020-06-24 03:25:25,Deep Learning Based Text Classification: A Comprehensive Review,An overview of deep learning approaches to text classification. +1589,2020-06-24 03:33:09,jiant,A software toolkit for research on general-purpose text understanding models. +1592,2020-06-24 04:27:58,Text Classification,"Re-implemented an article (link is given below) which was on Text classification with CNN, beside this I tried out some ML classification algorithm." +1595,2020-06-24 15:42:20,multi-task-NLP,A utility toolkit enabling NLP developers to easily train and infer a single model for multiple tasks. +1597,2020-06-25 00:17:39,Maximizing Business Impact with Machine Learning,how to effectively leverage machine learning to build intelligent products as efficiently as possible. +1598,2020-06-25 00:29:18,Automatic Data Augmentation for Generalization in Deep RL,We compare three approaches for automatically finding an appropriate augmentation combined with two novel regularization terms for the policy and value function +1599,2020-06-25 00:42:36,High-Fidelity Generative Image Compression,How to combine Generative Adversarial Networks and learned compression to obtain a state-of-the-art generative lossy compression system. +1602,2020-06-25 04:03:38,Unet Model for Image Segmentation With EfficientNet Encoder,Implemented using tensorflow 2.2.0 with custom train and test step. +1603,2020-06-25 10:40:56,A Million of ML Predictions at the Tip of Your Fingers,Announcement - SashiDo is breaking the barrier to Machine Learning by introducing a fully open-sourced Content Moderation Service. +1605,2020-06-26 02:19:39,NetHack Learning Environment (NLE),A procedurally-generated grid-world dungeon-crawl game that strikes a great balance between complexity and speed for single-agent RL research. +1606,2020-06-26 02:24:53,Paraphrase Generation Using T5 model,Simple application using T5 base model fine tuned in Quora Question Pairs to generate paraphrased questions. +1607,2020-06-26 02:28:15,Message Passing Query Embedding,"MPQE is a model for answering complex queries over knowledge graphs, that learns embeddings of entities in the knowledge graph, & embeddings for variable types." +1608,2020-06-26 02:31:17,Quantifying Attention Flow in Transformers,"I explain two simple but effective methods, called Attention Rollout and Attention Flow" +1614,2020-06-27 04:15:51,Natural Language Processing Roadmap,Roadmap for learning NLP topics. +1615,2020-06-27 04:29:04,Weight Poisoning Attacks on Pre-trained Models,"How Bert can be infused with nefarious behavior, even after fine-tuning." +1616,2020-06-27 04:37:16,Leveraging Temporal Context for Object Detection,"Object detection architecture leveraging contextual clues across time for each camera deployment in a network, improving recognition of objects" +1617,2020-06-27 04:42:47,Expressive Power of Graph Neural Networks,"Graph isomorphism problem, the Weisfeiler-Lehman heuristic for graph isomorphism testing, and how it can be used to analyse the expressive power of GNNs." +1620,2020-06-27 10:27:43,rlx: A modular Deep RL library for research,"""rlx"" is a Deep RL library written on top of PyTorch & built for educational and research purpose." +1622,2020-06-27 14:18:13,Building AI Trading Systems,Lessons learned building a profitable algorithmic trading system using Reinforcement Learning techniques. +1623,2020-06-27 14:20:49,Introduction to NLP using Fastai,Implementing and decoding the revolutionary ULMFiT approach to train a language model on any downstream NLP task. +1629,2020-06-28 07:37:00,TF Lite Semantic Segmentation Models,Faster and lighter TF Lite models can perform semantic segmentation. +1630,2020-06-28 07:40:40,Semantic Segmentation + Background Removal + Style Transfer,"Running multiple TF Lite models to perform semantic segmentation, remove background, and apply style transfer. " +1636,2020-06-29 00:00:47,Automatic translation of the SQUAD dataset to spanish,"Machine translation is used on the SQuAD dataset to produce an equivalent dataset in Spanish. Word alignment is applied to produce a synthetic spanisQA corpus. +" +1638,2020-06-29 02:56:43,Dakshina Dataset,A collection of text in both Latin and native scripts for 12 South Asian languages. +1639,2020-06-29 02:58:52,Computer Vision Recipes,This repository provides examples and best practice guidelines for building computer vision systems. +1644,2020-06-29 12:42:44,A research guide for data scientists,Tips on research from top data scientists +1645,2020-06-29 17:16:17,Using Data Science Pipelines for Disaster Response,Uses ETL and ML pipeline to build an NLP system for classification of messages into appropriate disaster categories +1646,2020-06-29 19:47:58,Twitter Turing Test,Can you guess whether this tweet is written by a human or generated by a neural network? +1648,2020-06-30 02:34:54,STUMPY: A Powerful and Scalable Python Library for Time Series,"STUMPY is a powerful and scalable Python library for computing a Matrix Profile, which can be used for a variety of time series data mining tasks." +1649,2020-06-30 02:39:32,Model Serving using FastAPI and streamlit,Simple example of usage of streamlit and FastAPI for ML model serving. +1650,2020-06-30 02:49:57,The Reformer - Pushing the Limits of Language Modeling,An in-depth understanding of each of the key features of the Reformer. +1651,2020-06-30 02:52:41,High-Resolution Image Inpainting,"High-Resolution Image Inpainting with Iterative Confidence Feedback and Guided Upsampling. +" +1653,2020-06-30 03:01:50,MARGE: Pre-training via Paraphrasing,"A retrieval model maps a document to a set of related documents, which a reconstruction model paraphrases to maximize the likelihood of the original. " +1657,2020-06-30 18:00:11,Fast Api with Dockerization of your ML Models,In this GitHub repo you can able to know and learn how to build a fast API for testing your ML model and can test your ML model with UI and to Dockerize your ML +1658,2020-07-01 02:22:10,SimCLR - Contrastive Learning of Visual Representations,How to load pretrained/finetuned SimCLR models from hub modules for fine-tuning. +1662,2020-07-01 07:00:50,Image synthesis at CVPR 2020,An overview of the different approaches to image synthesis at CVPR 2020. +1663,2020-07-01 07:08:45,Sktime,A python toolbox for machine learning with time series. +1664,2020-07-01 07:14:00,"Sentiment Analysis: Key Milestones, Challenges and New Directions","An overview of sentiment analysis, it's progress and what's ahead." +1666,2020-07-01 07:20:52,Serverless BERT with HuggingFace and AWS Lambda,"Build a serverless question-answering API with BERT, HuggingFace, the Serverless Framework, and AWS Lambda." +1668,2020-07-01 13:33:49,Model-based Reinforcement Learning: A Survey,"A survey of the integration of both fields, better known as model-based reinforcement learning." +1677,2020-07-02 04:06:19,Building Level 3 Conversational AI Assistants,"Presentations, panels, and fireside chats addressing all topics related to the creation of Level 3 AI assistants." +1678,2020-07-02 12:13:19,NSFW Image Classification REST API built with TensorFlow.JS,A ready-to-use & open-source NSFW Image Classification REST API built with TensorFlow.JS and NSFW.JS for effortless Content Moderation +1688,2020-07-03 04:23:58,Python Implementation of Reinforcement Learning: An Introduction ,"Plot replications, exercise solutions and Anki flashcards for the entire book by chapters." +1691,2020-07-03 04:40:05,The Simplest Way to Serve your NLP Model in Production w/ Python ,"From scikit-learn to Hugging Face Pipelines, learn the simplest way to deploy ML models using Ray Serve." +1698,2020-07-04 01:07:48,Learning to Cartoonize Using White-box Cartoon Representations,An approach for image cartoonization using GANs. +1699,2020-07-04 01:10:18,Reinforcement Learning Tutorial,"Important reinforcement learning (RL) algorithms, including policy iteration, Q-Learning, and Neural Fitted Q." +1702,2020-07-04 04:51:18,Face Recognition Techniques,Face Detection and Recognition techniques using traditional CV and also using new deep learning method. +1704,2020-07-04 10:42:53,LSTM Forecast Model for Stock Price Prediction using Keras," Easy to understand LSTM forecast model for Stock Price Prediction. The dataset contains daywise details of the GOOGL stock from May,2019-May 2018." +1706,2020-07-04 11:05:28,PokeZoo,A deep learning based web-app developed using the MERN stack and Tensorflow.js. +1710,2020-07-05 05:47:35,NLP-task-visualizer-app,This application designed with streamlit library will help in visualizing NLP tasks on text entered by you. +1721,2020-07-07 04:21:20,TensorflowTTS,Real-Time State-of-the-art Speech Synthesis for Tensorflow 2. +1722,2020-07-07 04:23:38,spaczz: Fuzzy matching and more for spaCy,Fuzzy matching and more functionality for spaCy. +1723,2020-07-07 04:26:45,BioSyn,Biomedical Entity Representations with Synonym Marginalization +1724,2020-07-08 04:02:50,Image Classifier: In the Browser,Using Tensorflow.js to make the prediction directly in the browser. +1726,2020-07-08 04:15:07,Photon: A Robust Cross-Domain Text-to-SQL System,"A robust, modular, cross-domain NLIDB that can flag natural language input to which a SQL mapping cannot be immediately determined. " +1728,2020-07-08 04:24:07,Bounding Box Prediction from Scratch using PyTorch,Multi-Task learning — Bounding Box Regression + Image Classification +1729,2020-07-08 04:28:13,Comment Classification Using BERT (multi-language) Fine-Tuning,We are going to use BERT layer in a model applying Keras. +1730,2020-07-08 04:30:28,TextBrewer,a PyTorch-based model distillation toolkit for natural language processing. +1737,2020-07-08 18:22:40,codeBERT - Automated code docstring review with transformers,"codeBERT provide a one command line to check if your code docstrings are up-to-date. +" +1748,2020-07-09 02:23:25,Continuous Machine Learning (CML),CML helps to organize MLOps infrastructure on top of the traditional software engineering stack instead of creating separate AI platforms. +1750,2020-07-09 10:30:30,picTranslate: Seamless live Image Text translator,"Given an image with text on it, this app can give you a new image with text modified into a different language." +1753,2020-07-10 02:44:11,TUDatasets,A collection of benchmark datasets for graph classification and regression. +1754,2020-07-10 02:46:07,Full Stack Deep Learning,Full Stack Deep Learning helps you bridge the gap from training machine learning models to deploying AI systems in the real world. +1755,2020-07-10 02:51:24,Easy OCR,"Ready-to-use OCR with 40+ languages supported including Chinese, Japanese, Korean and Thai. + +" +1759,2020-07-10 18:54:54,Emotion Recognition from Tom and Jerry videos,"Developed an application that classifies the emotion depicted by Tom and Jerry in each frame into one of the following : happy, angry, sad or suprised." +1767,2020-07-11 05:05:31,Imagenette,Imagenette is a subset of 10 easily classified classes from Imagenet. +1768,2020-07-11 05:08:02,TextAugment,Improving Short Text Classification through Global Augmentation Methods +1769,2020-07-11 05:10:10,niacin,"A Python library for replacing the missing variation in your text data. + +" +1771,2020-07-11 05:16:17,Albumentations,Fast image augmentation library and easy to use wrapper around other libraries. +1772,2020-07-11 05:19:05,Augmentor,Image augmentation library in Python for machine learning. +1777,2020-07-11 05:37:12,tsfresh,Automatic extraction of relevant features from time series. +1792,2020-07-11 06:28:58,Anomaly Detection Toolkit (ADTK),"A Python toolkit for rule-based/unsupervised anomaly detection in time series + +" +1795,2020-07-11 06:37:35,Chakin ,Simple downloader for pre-trained word vectors. +1796,2020-07-11 06:39:39,Top2Vec,"Top2Vec learns jointly embedded topic, document and word vectors. + +" +1797,2020-07-11 06:42:29,Contextualized Topic Models,A python package to run contextualized topic modeling. +1800,2020-07-11 06:51:58,jellyfish,🎐 a python library for doing approximate and phonetic matching of strings. +1802,2020-07-11 06:57:28,SentencePiece,"Unsupervised text tokenizer for Neural Network-based text generation. + +" +1803,2020-07-11 06:59:08,A Deep Dive into the Wonderful World of Preprocessing in NLP,A glimpse into the surprisingly deep and interesting world of preprocessing in NLP. +1813,2020-07-11 07:45:01,Pytest,"The pytest framework makes it easy to write small tests, yet scales to support complex functional testing + +" +1817,2020-07-11 07:55:23,Artifacts - Weights & Biases,"Effortless pipeline tracking and production model management + +" +1818,2020-07-11 08:07:35,DeepkitAI,The Open-Source Machine Learning Devtool and Training Suite. +1819,2020-07-11 08:14:03,Neptune.ai,The most lightweight experiment management tool that fits any workflow. +1820,2020-07-11 08:17:17,Rasa,An open source machine learning framework to automate text-and voice-based conversations. +1831,2020-07-11 11:36:26,TF Sprinkles,Fast and efficient sprinkles augmentation implemented in TensorFlow. +1834,2020-07-11 17:19:43,Laplacian Pyramid Reconstruction and Refinement for Semantic Seg., Pytorch implementation of multi-resolution reconstruction architecture based on a Laplacian pyramid that uses skip connections. +1836,2020-07-11 18:15:19,Training a pets detector model with TFOD API (TF 2),"In this notebook, we will be training a custom object detection model using the latest TensorFlow Object Detection (TFOD) API which is based on TensorFlow 2.2. " +1840,2020-07-12 00:59:27,TensorFlow 2 meets the Object Detection API,TF Object Detection API (OD API) officially supports TensorFlow 2! +1843,2020-07-12 13:35:20,Cortex,Build machine learning APIs. +1844,2020-07-12 16:24:10,Semi-Supervised Learning in Computer Vision,A comprehensive overview of recent semi-supervised learning methods in Computer Vision +1845,2020-07-12 21:42:52,Face Predicting Web App,Interactive Deep Learning Model that utilizes your computer webcam to predict your age and gender in seconds! +1847,2020-07-13 03:46:32,Driver Identification Based on Vehicle's telematics data,"In this paper, we proposed a deep learning model, which can identify drivers from their driving behaviors based on vehicle telematics data." +1848,2020-07-13 05:00:40,Comprehensive analysis of important metrics in ML,"In this work, the authors present a comprehensive analysis of important metrics in practical applications." +1851,2020-07-13 15:21:13,StreamAlert,"A serverless, realtime data analysis framework which empowers you to ingest, analyze, and alert on data from any environment, using datasources and alerts." +1855,2020-07-14 03:17:25,ULMFiT Airline Sentiment Analysis,Transfer Learning using pretrained ULMFiT model +1856,2020-07-14 03:21:00,DeepDream Video Style Transfer,DeepDream on Video +1859,2020-07-14 04:01:18,"You Trained a Machine Learning Model, Now What?","Three often overlooked parts of this process occur after the model is actually built: model evaluation, deployment, and monitoring." +1860,2020-07-14 09:53:19,NSFW Image Moderation Automation Engine built with TensorFlow.JS ,"An open-source NSFW Image Classifier including an Automation Engine for fast deletion & moderation built with Node.js, TensorFlow, and Parse Server" +1865,2020-07-14 22:55:08,PDFTableExtract,Build a parser to extract the table in PDF document with RetinaNet +1867,2020-07-14 23:03:02,YOLOv4 With TensorFlow,"YOLOv4, YOLOv4-tiny, YOLOv3, YOLOv3-tiny Implemented in Tensorflow 2.0, Android. Convert YOLO v4 .weights tensorflow, tensorrt and tflite." +1868,2020-07-15 03:52:31,Selfie2Anime with TFLite,An end-to-end tutorial with TensorFlow Lite for Selfie2Anime (U-GAT-IT). +1869,2020-07-15 20:31:37,Bridging PyTorch and TVM,"Taking Hugging Face transformer BERT from PyTorch and running it on +ApacheTVM for both inference (with reasonable timings) and training." +1871,2020-07-16 03:58:21,Summarize a webapge,A Flask application that extracts and summarizes webpage using Natural Language Processing. Powered by nlp-akash. +1872,2020-07-16 04:19:37,An Icon Classifier with TensorFlow Lite Model Maker,An Icon Classifier with TensorFlow Lite Model Maker +1879,2020-07-16 17:40:33,Cross-lingual Transfer Learning - Sebastian Ruder,"An overview of approaches that transfer knowledge across languages and enable us to scale NLP models to more of the world's 7,000 languages." +1880,2020-07-16 17:43:48,AdapterHub: A Framework for Adapting Transformers,Huggingface Transformers + Adapters +1882,2020-07-16 17:51:48,Object Detection with RetinaNet,Implementing RetinaNet: Focal Loss for Dense Object Detection. +1884,2020-07-17 01:41:33,Deploying your ML Model with TorchServe,"In this talk, Brad Heintz walks through how to use TorchServe to deploy trained models at scale without writing custom code. " +1886,2020-07-17 08:27:56,Medical Zoo - 3D Multi-modal Medical Image Segmentation,My articles on deep learning in medical imaging +1887,2020-07-17 16:48:13,Computer Vision Pretrained Models,A collection of computer vision pre-trained models. +1889,2020-07-17 17:20:20,NLP Pretrained Models,"A collection of Natural language processing pre-trained models. + +" +1896,2020-07-19 00:40:37,Machine Learning Production Pipeline,"Project Flow and Landscape +" +1898,2020-07-19 00:47:53,Tempering Expectations for GPT-3 and OpenAI’s API,"A closer look at the ""magic"" behind GPT-3 and caveats to be aware of." +1899,2020-07-19 03:59:41,StyleGAN Encoder,Encodes real images into the latent space of a StyleGAN model. +1900,2020-07-19 04:12:40,WikiArt StyleGAN 2 Model,A conditional StyleGAN 2 model trained on images from WikiArt +1902,2020-07-19 10:19:24,Indian Paper Currency Prediction,"The trained model takes an image (Indian Paper Currency) as an input and predict the class of image from 10, 20, 50, 100, 200, 500, 2000 denomination." +1903,2020-07-19 11:31:25,"Neural Style Transfer (Gatys et al., PyTorch)",My implementation of the original neural style transfer paper by Gatys et al. (In PyTorch). +1904,2020-07-19 12:44:53,Implementation of Face Net in TensorFlow - 2.0,This repository is a naive unofficial implementation of Face Net paper - 2015 .This implementation opts online mode of semi - hard triplet mining. +1910,2020-07-19 15:44:21,Azure Machine Learning Template,Azure Machine Learning template for MNIST classifier +1913,2020-07-19 16:55:33,Teachable Machine (Image Classifier),A teachable image classifier that runs on any browser built using TensorFlow JS. +1914,2020-07-19 16:59:37,TensorFlow JS- Object Detection in Browser,A real-time object detection model in your browser using TensorFlow JS. +1916,2020-07-20 00:01:38,How to Stop Worrying About Compositionality,"Review the tenets of compositionality, and to highlight how each theory has evolved to match particular theoretical positions about the nature of language." +1918,2020-07-20 05:48:38,Spacy-Go,spacy-go is Golang interface for accessing linguistic annotations provided by spaCy using Google's gRPC. This module only supports basic functionalities like lo +1919,2020-07-20 05:53:12,Dframcy,DframCy is a light-weight utility module to integrate Pandas Dataframe to spaCy's linguistic annotation and training tasks. +1921,2020-07-20 14:04:48,NSFW Image Moderation Admin App with ReactJS,"A fully-functional NSFW Admin Application for simplified image classification & moderation built with Node.js, TensorFlow.js, and React" +1923,2020-07-20 18:59:04,PyTorch Geometric Temporal,A Temporal Extension Library for PyTorch Geometric +1924,2020-07-20 20:34:47,Why is it Important to Monitor Machine Learning Models?,The importance of monitoring and how monitoring ML is different from application performance management (APM). +1925,2020-07-20 20:54:00,PyTorch Implementation of PaletteNet,"PyTorch implementation of PaletteNet: Image Recolorization with Given Color Palette (Cho et al., 2017)." +1927,2020-07-20 21:21:12,ECG arrhythmia classification using a convolutional neural net,This is an implementation of the paper on ECG arrhythmia classification https://arxiv.org/pdf/1804.06812.pdf. +1929,2020-07-20 23:55:33,Structured Self Attention,Implementation for the paper A Structured Self-Attentive Sentence Embedding (https://arxiv.org/abs/1703.03130 ). Model interpretability / explainability. +1933,2020-07-21 01:42:42,TurboTransformers,A fast and user-friendly runtime for transformer inference on CPU and GPU. +1938,2020-07-21 11:50:53,Rasa NLU Examples,Experimental components for Rasa NLU pipelines. +1940,2020-07-21 19:01:54,Change Detection using Siamese networks,"The blog is a primer on Siamese Networks and how they're used for observing change in satellite images over time, or observing facial changes as people age" +1941,2020-07-21 19:13:05,My Artificial Intelligence Bookmarks,"A curated list of my reads, implementations, and core concepts of Artificial Intelligence, Deep Learning, Machine Learning by best folk in the world." +1943,2020-07-22 03:32:30,Do we Need Deep Graph Neural Networks?,Does depth in graph neural network architectures bring any advantage? +1945,2020-07-22 03:39:13,Pandera,A flexible and expressive pandas data validation library. +1952,2020-07-24 06:28:15,TensorFlow Serving,"A flexible, high-performance serving system for machine learning models, designed for production environments. " +1953,2020-07-24 06:30:44,BentoML,BentoML is an open-source framework for high-performance ML model serving. +1954,2020-07-24 06:43:59,Azure ML,MLOps using Azure ML. +1955,2020-07-24 06:47:29,Shape and Viewpoint without Keypoints,"Recover the 3D shape, pose and texture from a single image, trained on an image collection without any ground truth 3D shape, multi-view, camera viewpoints." +1965,2020-07-25 02:58:40,model-logger,Model-Logger is a Python library for storing model's profile and rapid inter model comparison. +1968,2020-07-26 04:48:40,Sentiment Analysis With Transformers,"Sentiment analysis neural network trained by fine-tuning BERT, ALBERT, or DistilBERT on the Stanford Sentiment Treebank." +1971,2020-07-27 02:30:42,Attention based YOLO: Object Detection,"An easy to follow, YOLO implementation with keras lib. Used a attention based architecture to extract more fine grained information about object." +1977,2020-07-27 14:14:10,LabelDetection: simplifying the use and construction of deep dete,LabelDetection is a graphical tool that aims to facilitate all the steps required in the pipeline to construct and use a deep-learning base object detection mod +1978,2020-07-27 14:34:12,How to Set Up a Python Project For Automation and Collaboration,"How to set up a Python repo with unit tests, code coverage, lint checking, type checking, Makefile wrapper, and automated build with GitHub Actions." +1980,2020-07-27 14:51:03,Understanding & Implementing SimCLR - an ELI5 guide,"I explain the SimCLR and its contrastive loss function step by step, build image embeddings and then show how to use them to train image classifier on top." +1983,2020-07-28 04:14:12,CoreML Model Zoo,Collection of unified and converted pre-trained models. +1984,2020-07-28 04:18:00,How GPT3 Works - Visualizations and Animations,A compilation of my threads explaining GPT3. +1985,2020-07-28 04:19:58,Temporal Graph Networks,"In this post, we describe Temporal Graph Network, a generic framework for deep learning on dynamic graphs." +1986,2020-07-28 07:44:13,Behavioral Testing of NLP models with CheckList,An overview of the “CheckList” framework for fine-grained evaluation of NLP models +1992,2020-07-29 03:41:04,Time series forecasting,A thorough introduction to time series forecasting using TensorFlow. +1993,2020-07-29 04:47:55,Real-time text detection with EAST in TFLite,Demonstrates the conversion process from the original EAST model to TFLite and how to use it on static images and also on real-time video feeds. +1994,2020-07-29 04:51:30,Understanding the Effectivity of Ensembles in Deep Learning,"The report explores the ideas presented in Deep Ensembles: A Loss Landscape Perspective by Stanislav Fort, Huiyi Hu, and Balaji Lakshminarayanan." +1999,2020-07-30 03:57:32,Small differences in BLEU are meaningless,Only big differences in metric scores are meaningful in MT. +2002,2020-07-30 04:08:46,Multi-target in Albumentations,"Many images, many masks, bounding boxes, and key points. How to transform them in sync?" +2005,2020-07-30 11:19:02,Social Distance Detection,"If people are very close to each other, a red bounding box is displayed around them indicating that they are not maintaining social distance." +2006,2020-07-30 11:30:56,Deep Learning Techniques for NLP in Healthcare,A talk discussing the recent advancements of deep learning to facilitate the adaption of NLP in the healthcare domain. +2008,2020-07-30 14:50:30,Extension to block NSFW content using AI,"NSFW Filter is an extension that blocks NSFW content from your browser. +It uses a computer vision model to detect NSFW content and hides it from the user." +2009,2020-07-30 14:55:57,ATLASS: AutoML using Transfer and Semi-Supervised Learning,"This repository includes the code, application, and notebooks for the work ""AutoML using Transfer and Semi-Supervised Learning"". The tools presented here can be" +2012,2020-07-30 15:04:28,LabelStoma: stomata detection using YOLO,LabelStoma is a graphical image tool for automatically detecting stomata in images. +2013,2020-07-30 15:07:54,DeepClas4Bio,DeepClas4Bio is a project that aims to facilitate the interoperability of bioimaging tools with deep learning frameworks. +2016,2020-07-31 15:30:38,Meme Classifier Using TFlite and flutter,Meme classifier using fine tuned mobilenet. This app showcases how you can perform low latency realtime classification apps using TFlite +2020,2020-08-01 12:14:26,Text Summarization using TF-IDF Algorithm,This Article explains the TF-IDF algorithm and shows the implemtnation from scratch to summarize the text. +2022,2020-08-01 14:41:37,Simple Transformers,"Transformers for Classification, NER, QA, Language Modeling, Language Generation, T5, Multi-Modal, and Conversational AI." +2024,2020-08-01 14:49:31,DeText: A Deep Neural Text Understanding Framework,DeText: A Deep Neural Text Understanding Framework for Ranking and Classification Tasks. +2026,2020-08-01 15:04:37,Efficient Serverless Deployment of PyTorch Models on Azure,A tutorial for serving models cost-effectively at scale using Azure Functions and ONNX Runtime. +2027,2020-08-01 15:27:29,Nearest Celebrity Face,Implementation of FaceNet: A Unified Embedding for Face Recognition and Clustering to find the celebrity whose face matches the closest to yours. The input face +2030,2020-08-02 12:38:08,A Few Favorite Recipes in Computer Vision & Deep Learning,This blog post enlists a few of my favorite recipes in deep learning in the context of computer vision (as of August 2020). +2031,2020-08-02 14:46:10,NeuralQA - API and Visual Interface for Extractive QA,A Usable Library for Question Answering on Large Datasets with BERT +2032,2020-08-02 20:00:23,Object tracking in 75 lines of code,"Object tracking is straightforward conceptually. And if you have a good detector, simple methods can be pretty effective." +2033,2020-08-03 03:49:22,FARM: Framework for Adapting Representation Models,🏡 Fast & easy transfer learning for NLP. Harvesting language models for the industry. +2035,2020-08-04 02:49:24,Act - GitHub Actions locally,Run your GitHub Actions locally. +2038,2020-08-04 03:53:36,Curated papers & articles on DS & ML in production,"Learn how organizations & business solved machine learning problems, including problem statement, research, methodology, and results." +2039,2020-08-04 16:45:09,Tensorflow2 Object Detection Tutorial,"In this tutorial, we will be going step by step the complete training process of Tensorflow2 Object Detection. " +2042,2020-08-05 02:07:24,ONNX T5,"Summarization, translation, Q&A, text generation and more at blazing speed using a T5 version implemented in ONNX." +2043,2020-08-05 02:17:10,DeLighT: Very Deep and Light-weight Transformers,Similar or better performance than transformer-based models with significantly fewer parameters +2045,2020-08-05 06:40:32,Evaluation Metrics For Information Retrieval,Learn about common metrics used to evaluate performance of information retrieval systems +2047,2020-08-05 15:18:46,Test-Time Data Augmentation,Tutorial on how to properly implement test-time image data augmentation in a production environment with limited computational resources. +2048,2020-08-05 16:50:22,SadedeGel: An extraction based Turkish news summarizer,"""Sadede Gel"" in Turkish, means ""cut to the chase"". " +2051,2020-08-05 20:13:51,MobyDick word frequency,Getting the count of the words in Moby Dick story using both web scraping and NLP +2053,2020-08-05 20:30:33,Image Classification with Keras,Build a pipeline to train an image classifier in Keras and tune hyperparameters to optimize the performance of our classifier. +2054,2020-08-05 20:34:09,Dropout in PyTorch – An Example,"An example of adding Dropout to a PyTorch model, and observe the effect dropout has on the model's performance by tracking our models in Weights & Biases." +2057,2020-08-06 04:06:11,"Data Science Meets Devops: MLOps with Jupyter, Git, & Kubernetes","An end-to-end example of deploying a machine learning product using Jupyter, Papermill, Tekton, GitOps and Kubeflow." +2061,2020-08-06 04:59:21,Detectron 2 Demo from Facebook,This Project contains the process of getting started with Facebook FAIR's detectron2 project on windows 10 without any Nvidia GPU. +2062,2020-08-06 12:38:55,Predict Vehicle Speed From Dash Cam Video,A series of experiments attempting to predict vehicle speed from dash cam videos using optical flow and neural networks. +2098,2020-08-06 23:15:45,Digital Image Processing in Python,Play around with pixel values with Python programming language. +2100,2020-08-07 04:24:28,A 2020 guide to Semantic Segmentation,"Concept of image segmentation, discuss the relevant use-cases, different neural network architectures involved in achieving the results, metrics and datasets." +2106,2020-08-08 15:06:18,Fast NST for Videos (+ person segmentation) 🎥 + ⚡💻 + 🎨 = ❤️,Create NST videos and pick separate styles for the person in the video and for the background. +2109,2020-08-09 07:24:57,Live demo : State-of-the-art MCQ Generator from any content,"Demo for state-of-the-art MCQ (Multiple Choice Questions) generator from any content built using T5 transformer, HuggingFace, and Sense2vec +" +2111,2020-08-10 03:26:16,InvoiceNet,"Deep neural network to extract intelligent information from PDF invoice documents. +" +2112,2020-08-10 03:41:31,Search for visual datasets,"By task, application, class, label or format." +2113,2020-08-10 04:01:03,GAN-BERT,Enhancing the BERT training with Semi-supervised Generative Adversarial Networks. +2114,2020-08-10 04:03:51,tsaug,A Python package for time series augmentation. +2116,2020-08-10 04:15:38,Machine Learning Pipelines for Kubeflow.,Kubeflow pipelines are reusable end-to-end ML workflows built using the Kubeflow Pipelines SDK. +2117,2020-08-10 04:17:57,Structuring Unit Tests in Python,"Where to put tests, how to write fixtures and the awesomeness of test parametrization." +2121,2020-08-10 21:59:41,DeepR — Training TensorFlow Models for Production,DeepR is a Python library to build complex pipelines as easily as possible on top of Tensorflow. +2124,2020-08-11 00:20:42,Neural Architecture Search,"A look at neural architecture search w.r.t search space, search algorithms and evolution strategies." +2135,2020-08-13 01:52:06,Temporal Convolutional Networks for Time-Series,"We introduce several novels using TCN, including improving traffic prediction, sound event localization & detection, and probabilistic forecasting." +2136,2020-08-13 02:05:11,Machine Learning Deployment: Shadow Mode,"“How do I test my new model in production?” One answer, and a method I often employ when initially deploying models, is shadow mode." +2138,2020-08-13 18:12:46,Extract Stock Sentiment from News Headlines," In this project, you will generate investing insight by applying sentiment analysis on financial news headlines from Finviz. " +2141,2020-08-14 03:15:38,hloc - the hierarchical localization toolbox,Visual localization made easy. +2147,2020-08-15 01:17:07,Practical Tips and Tricks for Successful Transfer Learning,Training models to learn knowledge and skills from other related tasks that will transfer and boost performance on tasks of interest. +2148,2020-08-15 01:22:01,txtai: AI-powered search engine,AI-powered search engine. +2151,2020-08-15 05:32:22,Drowsiness Detection System using OpenCV and Flask in Python ,"This system provides an overview of a system that detects whether a person is drowsy while driving and if so, alerts him by using voice messages in real-time. " +2155,2020-08-15 14:49:16,"GPT-3, The model simply knows!",Brief Introduction about the gigantic GPT-3. a new leap in AI and Natural Language processing. +2159,2020-08-16 01:02:18,Solaris,CosmiQ Works Geospatial Machine Learning Analysis Toolkit. +2163,2020-08-17 03:19:46,Safe Space - Github Action,Github action that checks the toxicity level of comments and PR reviews to help make repos safe spaces. +2164,2020-08-17 03:24:46,Intro to Autoencoders,"This tutorial introduces autoencoders with three examples: the basics, image denoising, and anomaly detection." +2166,2020-08-17 05:19:41,Pix2Pix,"Tensorflow 2.0 Implementation of the paper Image-to-Image Translation using Conditional GANs by Philip Isola, Jun-Yan Zhu, Tinghui Zhou and Alexei A. Efros." +2167,2020-08-17 06:27:31,Insight,Project Insight is designed to create NLP as a service with code base for both front end GUI (streamlit) and backend server (FastAPI) the usage of transformers +2168,2020-08-17 10:55:43,Onceupon.space,NLP experiment in story-telling that creates illustrations (text to sketch) and content (text generation) +2173,2020-08-18 04:16:33,Fine-tuning with custom datasets,This tutorial will take you through several examples of using 🤗 Transformers models with your own datasets. +2185,2020-08-18 23:12:27,Language Interpretability Tool (LIT),"The Language Interpretability Tool (LIT) is a visual, interactive model-understanding tool for NLP models." +2188,2020-08-19 15:16:46,Great Expectations,Always know what to expect from your data. +2193,2020-08-20 00:39:05,Effective testing for machine learning systems,"Why testing machine learning systems can be different, and discuss some strategies for writing effective tests for machine learning systems." +2202,2020-08-22 03:55:27,Graph Representation Learning Book,"Introduction to graph representation learning, including methods for embedding graph data, graph neural networks, and deep generative models of graphs." +2203,2020-08-22 05:58:20,Image Similarity Search in PyTorch,"Simple Convolutional Auto-encoder based image similarity +search to find similar images to given image or features. +Fully written in PyTorch." +2204,2020-08-22 17:19:00,Tensorflow Object Detection with Tensorflow 2,Object Detection with Tensorflow 2 and the Tensorflow Object Detection API +2207,2020-08-23 04:38:45,Rules of Machine Learning: Best Practices for ML Engineering,A basic knowledge of machine learning get the benefit of best practices in machine learning from around Google. +2214,2020-08-24 11:16:47,vedaseg,vedaseg is an open source semantic segmentation toolbox based on PyTorch. +2215,2020-08-24 11:52:10,vedastr,vedastr is an open source scene text recognition toolbox based on PyTorch. +2218,2020-08-25 13:57:49,CascadeTabNet,"An approach for end-to-end table detection and structure recognition from image-based documents +" +2220,2020-08-25 16:13:31,"Table Detection, Information Extraction and Structuring using ML",Table Extraction (TE) is the task of detecting and decomposing table information in a document. +2223,2020-08-26 04:21:37,AxCell,Automatic Extraction of Results from Machine Learning Papers +2226,2020-08-27 01:54:16,Hyperparameter Optimization for 🤗 Transformers: A Guide,"Basic grid search is not the most optimal, and in fact, the hyperparameters we choose can have a significant impact on our final model performance." +2235,2020-08-27 16:03:12,Shift-Ctrl-F: Semantic Search for the Browser,🔎: Search the information available on a webpage using natural language instead of an exact string match. +2238,2020-08-28 01:24:08,Spinning Up in Deep RL (OpenAI),An educational resource to help anyone learn deep reinforcement learning. +2239,2020-08-28 07:07:39,An Introduction to Adversarial Examples in Deep Learning,"This report provides an intuitive introduction to adversarial examples, discusses a wide variety of different adversarial attacks and, most notably, provides ad" +2242,2020-08-29 08:10:21,Deep dive into ROI layer in Object Detection Models,In this blog post we will implement in torch ROI Pool and ROI Align models from scratch. +2245,2020-08-30 02:51:07,On the Bottleneck of Graph Neural Networks and its Implications,The mechanism of propagating information between neighbors creates a bottleneck when every node aggregates messages from its neighbors. +2247,2020-08-30 11:48:19,Unsupervised Keyphrase Extraction,Learn about unsupervised algorithms for automatically extracting representative keyword and phrases from documents +2251,2020-08-31 10:05:12,Practical AI: Using NLP word embeddings to solve localization ,"Using NLP word vectors (word2vec, glove, etc) in a novel way to solve the problem of localization in edtech." +2252,2020-08-31 23:40:26,Explore then Execute,Adapting without Rewards via Factorized Meta-Reinforcement Learning +2255,2020-09-01 04:49:38,"Tensorflow, Pytorch, Transformer, Fastai, etc. Tutorials","BERT Classification, Question Answering, Seq2Seq Machine Translation, Contextual Topic Modeling, Large Scale Multilabelclassification, etc" +2258,2020-09-02 09:05:08,Graph Convolutions for dummies,An article explaining Graph Convolutional Networks as simply as possible. +2259,2020-09-02 23:08:03,ECCV 2020: Some Highlights,A sort of a snapshot of the conference by summarizing some papers (& listing some) that grabbed my attention. +2260,2020-09-02 23:13:20,CVPR 2020: A Snapshot,A snapshot of the conference by summarizing some papers (& listing some) that grabbed my attention. +2263,2020-09-03 23:05:32,TTT: Fine-tuning Transformers with TPUs or GPUs acceleration,"TTT is short for a package for fine-tuning 🤗 Transformers with TPUs, written in Tensorflow2.0+." +2264,2020-09-04 01:24:22,MushroomRL,Python library for Reinforcement Learning. +2267,2020-09-04 02:50:39,What Is MLOps?,"Machine learning operations, MLOps, are best practices for businesses to run AI successfully with help from an expanding software products and cloud services." +2268,2020-09-05 01:06:07,NLP Course | For You,This is an extension to the (ML for) Natural Language Processing course I teach at the Yandex School of Data Analysis (YSDA) since fall 2018. +2269,2020-09-05 01:09:06,Learning to Summarize with Human Feedback,Human feedback models outperform much larger supervised models and reference summaries on TL;DR +2273,2020-09-05 18:22:44,ONNX Transformers,Accelerated NLP pipelines for fast inference 🚀 on CPU. Built with 🤗 Transformers and ONNX runtime. +2275,2020-09-06 07:26:21,hugdatafast: huggingface/nlp + fastai,The elegant integration of huggingface/nlp and fastai2 and handy transforms using pure huggingface/nlp +2280,2020-09-06 18:59:46,Top 10 Deep Learning Breakthroughs — Deep Reinforcement Learning,The article unravels the journey behind reaching the point when Reinforcement Learning combined with Deep Learning defeated a Go player world champion. +2283,2020-09-07 07:13:04,Data analysis made easy: Text2Code for Jupyter notebook,A jupyter notebook extension for Text2Code for basic pandas and plotly commands +2284,2020-09-07 10:42:32,electra_pytorch: ELECTRA in PyTorch (fastai + huggingface),Unofficial reimplementation of +2285,2020-09-07 13:36:55,Images of radio boxes,I have collected about 15+k raw images of radio boxes across 500+ forms and hand-picked 200+ images that can be used to determine if a radio box is checked. +2287,2020-09-07 20:56:51,omega|ml - building and deploying ML models the easy way,Deploying ML is hard. It should not be. omega|ml makes it a breeze. +2290,2020-09-09 00:16:32,Fine-tune a non-English GPT-2 Model with Huggingface," In this tutorial, we are going to use the transformers library by Huggingface. We will use the new Trainer class and fine-tune out GPT-2 model." +2294,2020-09-09 16:14:37,Getting started with large-scale ETL jobs using Dask and AWS EMR,"EMR is AWS’s distributed data platform, which we can interact with and submit jobs to from a JupyterLab notebook running on our local machine." +2295,2020-09-09 16:36:45,How to Create a Cartoonizer with TensorFlow Lite?,An end-to-end tutorial on how to convert to TensorFlow Lite (TFLite) model and deploy it to an Android app for cartoonizing an image captured by camera. +2296,2020-09-10 01:15:57,How to Test Machine Learning Code and Systems,"🚦 Minimal examples of testing machine learning for correct implementation, expected learned behaviour, and model performance. + +" +2298,2020-09-11 00:02:10,torchCDE,Differentiable controlled differential equation solvers for PyTorch with GPU support and memory-efficient adjoint backpropagation. +2299,2020-09-11 00:07:11,Latent graph neural networks: Manifold learning 2.0?,Parallels between recent works on latent graph learning and older techniques of manifold learning. +2300,2020-09-11 00:11:14,Real Python Recommendation Engine,A full stack data science project that performs document similarity on RealPython.com content. Content recommendations are implemented via a Chrome extension. +2304,2020-09-11 17:54:04,Graph Neural Networks,A descriptive guide for Graph Neural Networks. +2317,2020-09-14 05:32:45,End-to-end Object Detection in TensorFlow Lite,"This project shows how to train a custom detection model with the TFOD API, optimize it with TFLite, and perform inference with the optimized model." +2318,2020-09-14 11:55:33,Jepto - Digital Marketing Analytics,KPI Prediction and Anomaly Detection of digital marketing data for both technical and non-technical marketers and business owners. +2319,2020-09-14 19:21:33,Cartoonizer with TensorFlow.js,An app to turn your photos into cartoon-styled images 🎨 within your browsers using White-box Cartoonization GAN. +2325,2020-09-16 13:43:20,Implementing Content-Based Image Retrieval with Siamese Networks,"With content-based image retrieval, we refer to the task of finding images containing attributes which are not in the image metadata, but in its visual content." +2326,2020-09-17 00:18:51,NLP for Developers: Multilingual NLP | Rasa,"In this video, Rasa Developer Advocate Rachael will talk about common approaches to handle language input in more than one language." +2327,2020-09-17 15:36:45,Paint with Machine Learning,This web app allows you to create a landscape painting in the style of Bob Ross using a deep learning model served using a Spell model server. +2328,2020-09-17 16:04:29,Distilling Knowledge in Neural Networks,This project demonstrates the compelling model optimization technique - knowledge distillation with code walkthroughs in TensorFlow. +2332,2020-09-18 08:49:55,Recurrent Neural Networks: building GRU cells VS LSTM cells ,What are the advantages of RNN’s over transformers? When to use GRU’s over LSTM? What are the equations of GRU really mean? How to build a GRU cell in Pytorch? +2341,2020-09-20 00:34:03,PyTorch Forecasting,Time series forecasting with PyTorch. +2342,2020-09-20 03:24:58,Norfair,Lightweight Python library for adding real-time 2D object tracking to any detector. +2344,2020-09-21 00:20:00,Labelai,"Labelai is an online tool designed to label images, useful for training AI models." +2345,2020-09-21 00:26:02,Remo,🐰 Python lib for remo - the app for annotations and images management in Computer Vision. +2348,2020-09-21 23:47:06,Layered Neural Rendering for Retiming People in Video,Manipulating and editing the time in which different motions of individuals in the video occur. +2351,2020-09-22 03:42:58,Simple Transformers: Transformers Made Easy,Simple Transformers removes complexity and lets you get down to what matters – model training and experimenting with the Transformer model architectures. +2353,2020-09-22 13:04:04,TF Geometric,Efficient and Friendly Graph Neural Network Library for TensorFlow 1.x and 2.x. +2356,2020-09-23 04:56:15,"Part 2: Deep Representations, a way towards neural style transfer",A top-down approach to conceiving neural style transfer +2357,2020-09-23 10:27:15,Sudoku Solver,Solving Sudoku by extracting the puzzle from photo using Computer Vision and OCR and solving it. +2360,2020-09-23 13:56:29,"3D Face: Fast, Accurate and Stable Reconstruction","This work extends the previous work 3DDFA, named 3DDFA_V2, titled Towards Fast, Accurate and Stable 3D Dense Face Alignment, accepted by ECCV 2020. " +2368,2020-09-25 07:47:27,TableQA,AI tool for querying natural language on tabular data like csvs and other dataframes. +2369,2020-09-25 15:44:08,GP-GAN: Towards Realistic High-Resolution Image Blending,Blending composite images using a generative model and a Gaussian-Poisson equation with a Laplacian Pyramid +2371,2020-09-25 18:10:13,From Research to Production with Deep Semi-Supervised Learning,Semi-Supervised Learning (SSL) has blossomed in the deep learning research community — we share lessons learned over 15 months of taking SSL into production. +2372,2020-09-25 18:39:59, A spaced repetition app for keeping your reinforcement learning,We aim to keep your reinforcement learning knowledge fresh by periodically reminding you of concepts making you a master of RL knowledge!! +2373,2020-09-25 22:41:22,GraphNorm,A Principled Approach to Accelerating Graph Neural Network Training. +2384,2020-09-27 08:42:46,Intro to Facebook Prophet,Everything you need to know when starting out with Facebook’s time series forecasting tool +2387,2020-09-27 14:22:51,GitHub Actions for Machine Learning,This presentation discusses the use of GitHub Actions to automate certain steps of a toy ML project. +2388,2020-09-27 22:09:32,SemTorch,Different deep learning architectures definitions that can be applied to image segmentation. +2389,2020-09-28 05:34:15,bingoset - CLI tool to create image dataset.,CLI Toolkit to quickly create an image dataset using Bing Image Search API. +2395,2020-09-28 22:51:23,Python caching in GitHub Actions,How to speed up slow Python builds in GitHub Actions with effective caching. +2396,2020-09-29 00:36:12,EfficientDet meets Pytorch Lightning,Beginner friendly guide to object detection using EfficientDet. +2397,2020-09-29 02:15:46,Optimizing MobileDet for Mobile Deployments,Learn about the criticalities of effectively optimizing MobileDet object detectors for mobile deployments. +2402,2020-09-30 22:11:07,Adapting Text Augmentation to Industry Problems,"In this post I will talk about the recent advances in exploiting language models for data generation and also show how, where we can implement them in Industry." +2404,2020-09-30 22:22:07,12 Factors of Reproducible Machine Learning in Production,We took our experience to deduce 12 factors (as a nod to the 12 factor app) that build the backbone of successful ML in production. +2410,2020-10-01 13:42:23,Serving PyTorch models in production with the Amazon SageMaker,TorchServe is now natively supported in Amazon SageMaker as the default model server for PyTorch inference. +2411,2020-10-01 14:55:12,How to Make Sense of the Reinforcement Learning Agents?,What and Why I Log During Training and Debug? +2412,2020-10-01 18:50:05,Introduction to 3D Medical Imaging: Preprocessing & Augmentations,"Learn how to apply 3D transformations for medical image preprocessing and augmentation, to setup your awesome deep learning pipeline." +2415,2020-10-01 23:55:36,Explainable ML Monitoring,"The video covers an overview of some of the risks of AI, the need for explainable monitoring, and what exactly we mean when we talk about it." +2417,2020-10-02 09:44:25,Parallelizing Prophet Cross-Validation with Dask,Applied Example w/ Code +2418,2020-10-02 10:16:17,Top Research Papers from the ECML-PKDD 2020 Conference,ECML-PKDD -> selectionof the best reaesch papers +2419,2020-10-02 15:37:27,GANs in Computer Vision Free Ebook / Article-series,This free ebook/article-series follows the chronological order of 20 peer-reviewed highly-cited papers as they presented in a series of 6 articles. +2422,2020-10-02 21:48:21,Pattern-Exploiting Training (PET),"This repository contains the code for ""Exploiting Cloze Questions for Few-Shot Text Classification and Natural Language Inference""" +2423,2020-10-03 20:27:36,Imaginaire,NVIDIA PyTorch GAN library with distributed and mixed precision support. +2430,2020-10-05 10:09:28,Transection: Transformers for English to Chinese Translation 基于t,Tutorials on how to fine-tune a BART based transformer for English to Chinese translation. +2431,2020-10-05 12:36:02,A Survey of the State of Explainable AI for NLP,Overview of the operations and explainability techniques currently available for generating explanations for NLP model predictions. +2432,2020-10-05 13:09:58,Topic Modeling with BERT,Leveraging 🤗 Transformers and a class-based TF-IDF to create dense clusters allowing for easily interpretable topics. +2434,2020-10-06 02:13:01,OpenMMLab Computer Vision,"MMCV is a python library for CV research and supports many research projects such as object detection, segmentation, pose estimation, action classification. + +" +2436,2020-10-06 13:29:44,Machine Learning Methods Explained (+ Examples),Most common techniques used in data science projects; get to know them through easy-to-understand examples and put them into practice in your own ML projects! +2437,2020-10-06 14:53:39,Rasoee,"A powerful web and mobile application that identifies food dishes from a given input image, and provides an ingredient list along with relevant recipes." diff --git a/datasets/tags.csv b/datasets/tags.csv new file mode 100644 index 0000000..51eae3c --- /dev/null +++ b/datasets/tags.csv @@ -0,0 +1,765 @@ +tag +computer-vision +computer-vision +graph-learning +reinforcement-learning +graph-learning +graph-learning +graph-learning +graph-learning +graph-learning +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +graph-learning +natural-language-processing +mlops +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +reinforcement-learning +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +mlops +computer-vision +natural-language-processing +computer-vision +natural-language-processing +graph-learning +computer-vision +graph-learning +computer-vision +computer-vision +mlops +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +computer-vision +computer-vision +natural-language-processing +time-series +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +reinforcement-learning +reinforcement-learning +natural-language-processing +reinforcement-learning +computer-vision +natural-language-processing +computer-vision +computer-vision +graph-learning +graph-learning +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +mlops +mlops +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +reinforcement-learning +reinforcement-learning +graph-learning +computer-vision +natural-language-processing +natural-language-processing +computer-vision +computer-vision +natural-language-processing +computer-vision +mlops +natural-language-processing +computer-vision +natural-language-processing +time-series +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +natural-language-processing +computer-vision +time-series +computer-vision +time-series +natural-language-processing +computer-vision +computer-vision +natural-language-processing +mlops +computer-vision +computer-vision +natural-language-processing +computer-vision +mlops +natural-language-processing +mlops +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +graph-learning +reinforcement-learning +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +natural-language-processing +computer-vision +graph-learning +natural-language-processing +natural-language-processing +time-series +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +time-series +time-series +natural-language-processing +computer-vision +graph-learning +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +computer-vision +computer-vision +graph-learning +mlops +computer-vision +graph-learning +mlops +computer-vision +natural-language-processing +computer-vision +natural-language-processing +reinforcement-learning +computer-vision +computer-vision +reinforcement-learning +natural-language-processing +computer-vision +graph-learning +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +natural-language-processing +time-series +natural-language-processing +reinforcement-learning +natural-language-processing +natural-language-processing +computer-vision +reinforcement-learning +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +reinforcement-learning +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +reinforcement-learning +natural-language-processing +time-series +computer-vision +computer-vision +time-series +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +natural-language-processing +computer-vision +natural-language-processing +mlops +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +time-series +computer-vision +computer-vision +natural-language-processing +natural-language-processing +computer-vision +computer-vision +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +computer-vision +mlops +computer-vision +natural-language-processing +natural-language-processing +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +mlops +natural-language-processing +natural-language-processing +natural-language-processing +time-series +computer-vision +natural-language-processing +reinforcement-learning +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +reinforcement-learning +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +time-series +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +computer-vision +computer-vision +computer-vision +natural-language-processing +mlops +reinforcement-learning +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +reinforcement-learning +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +computer-vision +reinforcement-learning +time-series +mlops +computer-vision +natural-language-processing +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +time-series +computer-vision +reinforcement-learning +computer-vision +natural-language-processing +computer-vision +reinforcement-learning +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +computer-vision +mlops +computer-vision +natural-language-processing +computer-vision +reinforcement-learning +natural-language-processing +natural-language-processing +graph-learning +natural-language-processing +reinforcement-learning +computer-vision +computer-vision +mlops +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +mlops +graph-learning +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +mlops +reinforcement-learning +computer-vision +computer-vision +computer-vision +reinforcement-learning +natural-language-processing +graph-learning +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +graph-learning +reinforcement-learning +reinforcement-learning +natural-language-processing +computer-vision +computer-vision +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +time-series +computer-vision +natural-language-processing +computer-vision +natural-language-processing +mlops +computer-vision +computer-vision +time-series +natural-language-processing +natural-language-processing +reinforcement-learning +natural-language-processing +computer-vision +reinforcement-learning +mlops +computer-vision +reinforcement-learning +computer-vision +time-series +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +mlops +computer-vision +graph-learning +mlops +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +computer-vision +computer-vision +time-series +time-series +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +mlops +mlops +mlops +mlops +natural-language-processing +computer-vision +computer-vision +computer-vision +computer-vision +mlops +computer-vision +computer-vision +computer-vision +computer-vision +mlops +natural-language-processing +computer-vision +mlops +computer-vision +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +computer-vision +mlops +computer-vision +computer-vision +natural-language-processing +mlops +natural-language-processing +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +mlops +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +graph-learning +mlops +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +graph-learning +mlops +mlops +mlops +mlops +computer-vision +mlops +natural-language-processing +computer-vision +computer-vision +mlops +computer-vision +computer-vision +natural-language-processing +graph-learning +natural-language-processing +time-series +computer-vision +computer-vision +natural-language-processing +computer-vision +computer-vision +natural-language-processing +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +mlops +computer-vision +computer-vision +natural-language-processing +computer-vision +natural-language-processing +mlops +mlops +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +mlops +natural-language-processing +natural-language-processing +computer-vision +computer-vision +mlops +computer-vision +computer-vision +computer-vision +computer-vision +computer-vision +natural-language-processing +computer-vision +computer-vision +natural-language-processing +time-series +mlops +mlops +mlops +reinforcement-learning +time-series +mlops +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +computer-vision +natural-language-processing +computer-vision +natural-language-processing +computer-vision +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +mlops +mlops +graph-learning +computer-vision +computer-vision +mlops +computer-vision +computer-vision +computer-vision +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +reinforcement-learning +computer-vision +computer-vision +graph-learning +natural-language-processing +natural-language-processing +reinforcement-learning +natural-language-processing +graph-learning +computer-vision +computer-vision +natural-language-processing +reinforcement-learning +mlops +natural-language-processing +natural-language-processing +natural-language-processing +natural-language-processing +reinforcement-learning +natural-language-processing +natural-language-processing +computer-vision +mlops +natural-language-processing +mlops +computer-vision +mlops +time-series +graph-learning +natural-language-processing +graph-learning +computer-vision +time-series +computer-vision +computer-vision +natural-language-processing +computer-vision +computer-vision +natural-language-processing +time-series +computer-vision +computer-vision +computer-vision +computer-vision +natural-language-processing +graph-learning +computer-vision +computer-vision +computer-vision +natural-language-processing +computer-vision +mlops +reinforcement-learning +graph-learning +time-series +mlops +computer-vision +computer-vision +mlops +computer-vision +computer-vision +natural-language-processing +mlops +mlops +reinforcement-learning +computer-vision +mlops +time-series +reinforcement-learning +computer-vision +natural-language-processing +computer-vision +natural-language-processing +natural-language-processing +natural-language-processing +computer-vision +reinforcement-learning +computer-vision diff --git a/deploy/cluster_compute.yaml b/deploy/cluster_compute.yaml new file mode 100644 index 0000000..91e40c7 --- /dev/null +++ b/deploy/cluster_compute.yaml @@ -0,0 +1,22 @@ +cloud: madewithml-us-east-2 +region: us-east2 +head_node_type: + name: head_node_type + instance_type: m5.2xlarge # 8 CPU, 0 GPU, 32 GB RAM +worker_node_types: +- name: gpu_worker + instance_type: g4dn.xlarge # 4 CPU, 1 GPU, 16 GB RAM + min_workers: 0 + max_workers: 1 + use_spot: False +aws: + BlockDeviceMappings: + - DeviceName: "/dev/sda1" + Ebs: + VolumeSize: 500 + DeleteOnTermination: true + TagSpecifications: + - ResourceType: instance + Tags: + - Key: as-feature-multi-zone + Value: "true" diff --git a/deploy/cluster_env.yaml b/deploy/cluster_env.yaml new file mode 100644 index 0000000..3ba9b1f --- /dev/null +++ b/deploy/cluster_env.yaml @@ -0,0 +1,12 @@ +base_image: anyscale/ray:2.6.0-py310-cu118 +env_vars: {} +debian_packages: + - curl + +python: + pip_packages: [] + conda_packages: [] + +post_build_cmds: + - python3 -m pip install --upgrade pip setuptools wheel + - python3 -m pip install -r https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/requirements.txt diff --git a/deploy/jobs/workloads.sh b/deploy/jobs/workloads.sh new file mode 100644 index 0000000..4778ea1 --- /dev/null +++ b/deploy/jobs/workloads.sh @@ -0,0 +1,54 @@ +#!/bin/bash +export PYTHONPATH=$PYTHONPATH:$PWD +export RAY_AIR_REENABLE_DEPRECATED_SYNC_TO_HEAD_NODE=1 +mkdir results + +# Test data +export RESULTS_FILE=results/test_data_results.txt +export DATASET_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv" +pytest --dataset-loc=$DATASET_LOC tests/data --verbose --disable-warnings > $RESULTS_FILE +cat $RESULTS_FILE + +# Test code +export RESULTS_FILE=results/test_code_results.txt +python -m pytest tests/code --verbose --disable-warnings > $RESULTS_FILE +cat $RESULTS_FILE + +# Train +export EXPERIMENT_NAME="llm" +export RESULTS_FILE=results/training_results.json +export DATASET_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv" +export TRAIN_LOOP_CONFIG='{"dropout_p": 0.5, "lr": 1e-4, "lr_factor": 0.8, "lr_patience": 3}' +python madewithml/train.py \ + --experiment-name "$EXPERIMENT_NAME" \ + --dataset-loc "$DATASET_LOC" \ + --train-loop-config "$TRAIN_LOOP_CONFIG" \ + --num-workers 1 \ + --cpu-per-worker 10 \ + --gpu-per-worker 1 \ + --num-epochs 10 \ + --batch-size 256 \ + --results-fp $RESULTS_FILE + +# Get and save run ID +export RUN_ID=$(python -c "import os; from madewithml import utils; d = utils.load_dict(os.getenv('RESULTS_FILE')); print(d['run_id'])") +export RUN_ID_FILE=results/run_id.txt +echo $RUN_ID > $RUN_ID_FILE # used for serving later + +# Evaluate +export RESULTS_FILE=results/evaluation_results.json +export HOLDOUT_LOC="https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/holdout.csv" +python madewithml/evaluate.py \ + --run-id $RUN_ID \ + --dataset-loc $HOLDOUT_LOC \ + --results-fp $RESULTS_FILE + +# Test model +RESULTS_FILE=results/test_model_results.txt +pytest --run-id=$RUN_ID tests/model --verbose --disable-warnings > $RESULTS_FILE +cat $RESULTS_FILE + +# Save to S3 +export MODEL_REGISTRY=$(python -c "from madewithml import config; print(config.MODEL_REGISTRY)") +aws s3 cp $MODEL_REGISTRY s3://madewithml/$GITHUB_USERNAME/mlflow/ --recursive +aws s3 cp results/ s3://madewithml/$GITHUB_USERNAME/results/ --recursive diff --git a/deploy/jobs/workloads.yaml b/deploy/jobs/workloads.yaml new file mode 100644 index 0000000..b9fbffe --- /dev/null +++ b/deploy/jobs/workloads.yaml @@ -0,0 +1,11 @@ +name: workloads +project_id: prj_v9izs5t1d6b512ism8c5rkq4wm +cluster_env: madewithml-cluster-env +compute_config: madewithml-cluster-compute +runtime_env: + working_dir: . + upload_path: s3://madewithml/GokuMohandas/jobs # <--- CHANGE USERNAME (case-sensitive) + env_vars: + GITHUB_USERNAME: GokuMohandas # <--- CHANGE USERNAME (case-sensitive) +entrypoint: bash deploy/jobs/workloads.sh +max_retries: 0 diff --git a/deploy/services/serve_model.py b/deploy/services/serve_model.py new file mode 100644 index 0000000..151f797 --- /dev/null +++ b/deploy/services/serve_model.py @@ -0,0 +1,17 @@ +import os +import subprocess +import sys + +sys.path.append(".") + +from madewithml.config import MODEL_REGISTRY # NOQA: E402 +from madewithml.serve import ModelDeployment # NOQA: E402 + +# Copy from S3 +github_username = os.environ.get("GITHUB_USERNAME") +subprocess.check_output(["aws", "s3", "cp", f"s3://madewithml/{github_username}/mlflow/", str(MODEL_REGISTRY), "--recursive"]) +subprocess.check_output(["aws", "s3", "cp", f"s3://madewithml/{github_username}/results/", "./", "--recursive"]) + +# Entrypoint +run_id = [line.strip() for line in open("run_id.txt")][0] +entrypoint = ModelDeployment.bind(run_id=run_id, threshold=0.9) diff --git a/deploy/services/serve_model.yaml b/deploy/services/serve_model.yaml new file mode 100644 index 0000000..2055d66 --- /dev/null +++ b/deploy/services/serve_model.yaml @@ -0,0 +1,12 @@ +name: madewithml +project_id: prj_v9izs5t1d6b512ism8c5rkq4wm +cluster_env: madewithml-cluster-env +compute_config: madewithml-cluster-compute +ray_serve_config: + import_path: deploy.services.serve_model:entrypoint + runtime_env: + working_dir: . + upload_path: s3://madewithml/GokuMohandas/services # <--- CHANGE USERNAME (case-sensitive) + env_vars: + GITHUB_USERNAME: GokuMohandas # <--- CHANGE USERNAME (case-sensitive) +rollout_strategy: ROLLOUT # ROLLOUT or IN_PLACE diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..0942ee3 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,10 @@ +## Documentation + +- [madewithml](madewithml/data.md): documentation. + +## Lessons + +Learn how to combine machine learning with software engineering to design, develop, deploy and iterate on production ML applications. + +- **Lessons**: [https://madewithml.com/](https://madewithml.com/#course) +- **Code**: [GokuMohandas/Made-With-ML](https://github.com/GokuMohandas/Made-With-ML) diff --git a/docs/madewithml/data.md b/docs/madewithml/data.md new file mode 100644 index 0000000..d871bc5 --- /dev/null +++ b/docs/madewithml/data.md @@ -0,0 +1 @@ +::: madewithml.data diff --git a/docs/madewithml/evaluate.md b/docs/madewithml/evaluate.md new file mode 100644 index 0000000..9e0f7ac --- /dev/null +++ b/docs/madewithml/evaluate.md @@ -0,0 +1 @@ +::: madewithml.evaluate diff --git a/docs/madewithml/models.md b/docs/madewithml/models.md new file mode 100644 index 0000000..7d265a8 --- /dev/null +++ b/docs/madewithml/models.md @@ -0,0 +1 @@ +::: madewithml.models diff --git a/docs/madewithml/predict.md b/docs/madewithml/predict.md new file mode 100644 index 0000000..af9d057 --- /dev/null +++ b/docs/madewithml/predict.md @@ -0,0 +1 @@ +::: madewithml.predict diff --git a/docs/madewithml/serve.md b/docs/madewithml/serve.md new file mode 100644 index 0000000..6dc29ad --- /dev/null +++ b/docs/madewithml/serve.md @@ -0,0 +1 @@ +::: madewithml.serve diff --git a/docs/madewithml/train.md b/docs/madewithml/train.md new file mode 100644 index 0000000..f0fdc06 --- /dev/null +++ b/docs/madewithml/train.md @@ -0,0 +1 @@ +::: madewithml.train diff --git a/docs/madewithml/tune.md b/docs/madewithml/tune.md new file mode 100644 index 0000000..d580b19 --- /dev/null +++ b/docs/madewithml/tune.md @@ -0,0 +1 @@ +::: madewithml.tune diff --git a/docs/madewithml/utils.md b/docs/madewithml/utils.md new file mode 100644 index 0000000..cead4e3 --- /dev/null +++ b/docs/madewithml/utils.md @@ -0,0 +1 @@ +::: madewithml.utils diff --git a/madewithml/config.py b/madewithml/config.py new file mode 100644 index 0000000..2319419 --- /dev/null +++ b/madewithml/config.py @@ -0,0 +1,244 @@ +# config.py +import logging +import sys +from pathlib import Path + +import mlflow +import pretty_errors # NOQA: F401 (imported but unused) + +# Directories +ROOT_DIR = Path(__file__).parent.parent.absolute() +LOGS_DIR = Path(ROOT_DIR, "logs") +LOGS_DIR.mkdir(parents=True, exist_ok=True) + +# Config MLflow +MODEL_REGISTRY = Path("/tmp/mlflow") +Path(MODEL_REGISTRY).mkdir(parents=True, exist_ok=True) +MLFLOW_TRACKING_URI = "file://" + str(MODEL_REGISTRY.absolute()) +mlflow.set_tracking_uri(MLFLOW_TRACKING_URI) + +# Logger +logging_config = { + "version": 1, + "disable_existing_loggers": False, + "formatters": { + "minimal": {"format": "%(message)s"}, + "detailed": {"format": "%(levelname)s %(asctime)s [%(name)s:%(filename)s:%(funcName)s:%(lineno)d]\n%(message)s\n"}, + }, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "stream": sys.stdout, + "formatter": "minimal", + "level": logging.DEBUG, + }, + "info": { + "class": "logging.handlers.RotatingFileHandler", + "filename": Path(LOGS_DIR, "info.log"), + "maxBytes": 10485760, # 1 MB + "backupCount": 10, + "formatter": "detailed", + "level": logging.INFO, + }, + "error": { + "class": "logging.handlers.RotatingFileHandler", + "filename": Path(LOGS_DIR, "error.log"), + "maxBytes": 10485760, # 1 MB + "backupCount": 10, + "formatter": "detailed", + "level": logging.ERROR, + }, + }, + "root": { + "handlers": ["console", "info", "error"], + "level": logging.INFO, + "propagate": True, + }, +} + +# Logger +logging.config.dictConfig(logging_config) +logger = logging.getLogger() + +# Constraints +STOPWORDS = [ + "i", + "me", + "my", + "myself", + "we", + "our", + "ours", + "ourselves", + "you", + "you're", + "you've", + "you'll", + "you'd", + "your", + "yours", + "yourself", + "yourselves", + "he", + "him", + "his", + "himself", + "she", + "she's", + "her", + "hers", + "herself", + "it", + "it's", + "its", + "itself", + "they", + "them", + "their", + "theirs", + "themselves", + "what", + "which", + "who", + "whom", + "this", + "that", + "that'll", + "these", + "those", + "am", + "is", + "are", + "was", + "were", + "be", + "been", + "being", + "have", + "has", + "had", + "having", + "do", + "does", + "did", + "doing", + "a", + "an", + "the", + "and", + "but", + "if", + "or", + "because", + "as", + "until", + "while", + "of", + "at", + "by", + "for", + "with", + "about", + "against", + "between", + "into", + "through", + "during", + "before", + "after", + "above", + "below", + "to", + "from", + "up", + "down", + "in", + "out", + "on", + "off", + "over", + "under", + "again", + "further", + "then", + "once", + "here", + "there", + "when", + "where", + "why", + "how", + "all", + "any", + "both", + "each", + "few", + "more", + "most", + "other", + "some", + "such", + "no", + "nor", + "not", + "only", + "own", + "same", + "so", + "than", + "too", + "very", + "s", + "t", + "can", + "will", + "just", + "don", + "don't", + "should", + "should've", + "now", + "d", + "ll", + "m", + "o", + "re", + "ve", + "y", + "ain", + "aren", + "aren't", + "couldn", + "couldn't", + "didn", + "didn't", + "doesn", + "doesn't", + "hadn", + "hadn't", + "hasn", + "hasn't", + "haven", + "haven't", + "isn", + "isn't", + "ma", + "mightn", + "mightn't", + "mustn", + "mustn't", + "needn", + "needn't", + "shan", + "shan't", + "shouldn", + "shouldn't", + "wasn", + "wasn't", + "weren", + "weren't", + "won", + "won't", + "wouldn", + "wouldn't", +] diff --git a/madewithml/data.py b/madewithml/data.py new file mode 100644 index 0000000..c0f253f --- /dev/null +++ b/madewithml/data.py @@ -0,0 +1,147 @@ +import re +from typing import Dict, List, Tuple + +import numpy as np +import pandas as pd +import ray +from ray.data import Dataset +from ray.data.preprocessor import Preprocessor +from sklearn.model_selection import train_test_split +from transformers import BertTokenizer + +from madewithml.config import STOPWORDS + + +def load_data(dataset_loc: str, num_samples: int = None) -> Dataset: + """Load data from source into a Ray Dataset. + + Args: + dataset_loc (str): Location of the dataset. + num_samples (int, optional): The number of samples to load. Defaults to None. + + Returns: + Dataset: Our dataset represented by a Ray Dataset. + """ + ds = ray.data.read_csv(dataset_loc) + ds = ds.random_shuffle(seed=1234) + ds = ray.data.from_items(ds.take(num_samples)) if num_samples else ds + return ds + + +def stratify_split( + ds: Dataset, + stratify: str, + test_size: float, + shuffle: bool = True, + seed: int = 1234, +) -> Tuple[Dataset, Dataset]: + """Split a dataset into train and test splits with equal + amounts of data points from each class in the column we + want to stratify on. + + Args: + ds (Dataset): Input dataset to split. + stratify (str): Name of column to split on. + test_size (float): Proportion of dataset to split for test set. + shuffle (bool, optional): whether to shuffle the dataset. Defaults to True. + seed (int, optional): seed for shuffling. Defaults to 1234. + + Returns: + Tuple[Dataset, Dataset]: the stratified train and test datasets. + """ + + def _add_split(df: pd.DataFrame) -> pd.DataFrame: # pragma: no cover, used in parent function + """Naively split a dataframe into train and test splits. + Add a column specifying whether it's the train or test split.""" + train, test = train_test_split(df, test_size=test_size, shuffle=shuffle, random_state=seed) + train["_split"] = "train" + test["_split"] = "test" + return pd.concat([train, test]) + + def _filter_split(df: pd.DataFrame, split: str) -> pd.DataFrame: # pragma: no cover, used in parent function + """Filter by data points that match the split column's value + and return the dataframe with the _split column dropped.""" + return df[df["_split"] == split].drop("_split", axis=1) + + # Train, test split with stratify + grouped = ds.groupby(stratify).map_groups(_add_split, batch_format="pandas") # group by each unique value in the column we want to stratify on + train_ds = grouped.map_batches(_filter_split, fn_kwargs={"split": "train"}, batch_format="pandas") # combine + test_ds = grouped.map_batches(_filter_split, fn_kwargs={"split": "test"}, batch_format="pandas") # combine + + # Shuffle each split (required) + train_ds = train_ds.random_shuffle(seed=seed) + test_ds = test_ds.random_shuffle(seed=seed) + + return train_ds, test_ds + + +def clean_text(text: str, stopwords: List = STOPWORDS) -> str: + """Clean raw text string. + + Args: + text (str): Raw text to clean. + stopwords (List, optional): list of words to filter out. Defaults to STOPWORDS. + + Returns: + str: cleaned text. + """ + # Lower + text = text.lower() + + # Remove stopwords + pattern = re.compile(r"\b(" + r"|".join(stopwords) + r")\b\s*") + text = pattern.sub(" ", text) + + # Spacing and filters + text = re.sub(r"([!\"'#$%&()*\+,-./:;<=>?@\\\[\]^_`{|}~])", r" \1 ", text) # add spacing + text = re.sub("[^A-Za-z0-9]+", " ", text) # remove non alphanumeric chars + text = re.sub(" +", " ", text) # remove multiple spaces + text = text.strip() # strip white space at the ends + text = re.sub(r"http\S+", "", text) # remove links + + return text + + +def tokenize(batch: Dict) -> Dict: + """Tokenize the text input in our batch using a tokenizer. + + Args: + batch (Dict): batch of data with the text inputs to tokenize. + + Returns: + Dict: batch of data with the results of tokenization (`input_ids` and `attention_mask`) on the text inputs. + """ + tokenizer = BertTokenizer.from_pretrained("allenai/scibert_scivocab_uncased", return_dict=False) + encoded_inputs = tokenizer(batch["text"].tolist(), return_tensors="np", padding="longest") + return dict(ids=encoded_inputs["input_ids"], masks=encoded_inputs["attention_mask"], targets=np.array(batch["tag"])) + + +def preprocess(df: pd.DataFrame, class_to_index: Dict) -> Dict: + """Preprocess the data in our dataframe. + + Args: + df (pd.DataFrame): Raw dataframe to preprocess. + class_to_index (Dict): Mapping of class names to indices. + + Returns: + Dict: preprocessed data (ids, masks, targets). + """ + df["text"] = df.title + " " + df.description # feature engineering + df["text"] = df.text.apply(clean_text) # clean text + df = df.drop(columns=["id", "created_on", "title", "description"], errors="ignore") # clean dataframe + df = df[["text", "tag"]] # rearrange columns + df["tag"] = df["tag"].map(class_to_index) # label encoding + outputs = tokenize(df) + return outputs + + +class CustomPreprocessor(Preprocessor): + """Custom preprocessor class.""" + + def _fit(self, ds): + tags = ds.unique(column="tag") + self.class_to_index = {tag: i for i, tag in enumerate(tags)} + self.index_to_class = {v: k for k, v in self.class_to_index.items()} + + def _transform_pandas(self, batch): # could also do _transform_numpy + return preprocess(batch, class_to_index=self.class_to_index) diff --git a/madewithml/evaluate.py b/madewithml/evaluate.py new file mode 100644 index 0000000..a61aca4 --- /dev/null +++ b/madewithml/evaluate.py @@ -0,0 +1,154 @@ +import datetime +import json +from collections import OrderedDict +from typing import Dict + +import numpy as np +import ray +import ray.train.torch # NOQA: F401 (imported but unused) +import typer +from ray.data import Dataset +from ray.train.torch.torch_predictor import TorchPredictor +from sklearn.metrics import precision_recall_fscore_support +from snorkel.slicing import PandasSFApplier, slicing_function +from typing_extensions import Annotated + +from madewithml import predict, utils +from madewithml.config import logger + +# Initialize Typer CLI app +app = typer.Typer() + + +def get_overall_metrics(y_true: np.ndarray, y_pred: np.ndarray) -> Dict: # pragma: no cover, eval workload + """Get overall performance metrics. + + Args: + y_true (np.ndarray): ground truth labels. + y_pred (np.ndarray): predicted labels. + + Returns: + Dict: overall metrics. + """ + metrics = precision_recall_fscore_support(y_true, y_pred, average="weighted") + overall_metrics = { + "precision": metrics[0], + "recall": metrics[1], + "f1": metrics[2], + "num_samples": np.float64(len(y_true)), + } + return overall_metrics + + +def get_per_class_metrics(y_true: np.ndarray, y_pred: np.ndarray, class_to_index: Dict) -> Dict: # pragma: no cover, eval workload + """Get per class performance metrics. + + Args: + y_true (np.ndarray): ground truth labels. + y_pred (np.ndarray): predicted labels. + class_to_index (Dict): dictionary mapping class to index. + + Returns: + Dict: per class metrics. + """ + per_class_metrics = {} + metrics = precision_recall_fscore_support(y_true, y_pred, average=None) + for i, _class in enumerate(class_to_index): + per_class_metrics[_class] = { + "precision": metrics[0][i], + "recall": metrics[1][i], + "f1": metrics[2][i], + "num_samples": np.float64(metrics[3][i]), + } + sorted_per_class_metrics = OrderedDict(sorted(per_class_metrics.items(), key=lambda tag: tag[1]["f1"], reverse=True)) + return sorted_per_class_metrics + + +@slicing_function() +def nlp_llm(x): # pragma: no cover, eval workload + """NLP projects that use LLMs.""" + nlp_project = "natural-language-processing" in x.tag + llm_terms = ["transformer", "llm", "bert"] + llm_project = any(s.lower() in x.text.lower() for s in llm_terms) + return nlp_project and llm_project + + +@slicing_function() +def short_text(x): # pragma: no cover, eval workload + """Projects with short titles and descriptions.""" + return len(x.text.split()) < 8 # less than 8 words + + +def get_slice_metrics(y_true: np.ndarray, y_pred: np.ndarray, ds: Dataset) -> Dict: # pragma: no cover, eval workload + """Get performance metrics for slices. + + Args: + y_true (np.ndarray): ground truth labels. + y_pred (np.ndarray): predicted labels. + ds (Dataset): Ray dataset with labels. + Returns: + Dict: performance metrics for slices. + """ + slice_metrics = {} + df = ds.to_pandas() + df["text"] = df["title"] + " " + df["description"] + slices = PandasSFApplier([nlp_llm, short_text]).apply(df) + for slice_name in slices.dtype.names: + mask = slices[slice_name].astype(bool) + if sum(mask): + metrics = precision_recall_fscore_support(y_true[mask], y_pred[mask], average="micro") + slice_metrics[slice_name] = {} + slice_metrics[slice_name]["precision"] = metrics[0] + slice_metrics[slice_name]["recall"] = metrics[1] + slice_metrics[slice_name]["f1"] = metrics[2] + slice_metrics[slice_name]["num_samples"] = len(y_true[mask]) + return slice_metrics + + +@app.command() +def evaluate( + run_id: Annotated[str, typer.Option(help="id of the specific run to load from")] = None, + dataset_loc: Annotated[str, typer.Option(help="dataset (with labels) to evaluate on")] = None, + results_fp: Annotated[str, typer.Option(help="location to save evaluation results to")] = None, +) -> Dict: # pragma: no cover, eval workload + """Evaluate on the holdout dataset. + + Args: + run_id (str): id of the specific run to load from. Defaults to None. + dataset_loc (str): dataset (with labels) to evaluate on. + results_fp (str, optional): location to save evaluation results to. Defaults to None. + + Returns: + Dict: model's performance metrics on the dataset. + """ + # Load + ds = ray.data.read_csv(dataset_loc) + best_checkpoint = predict.get_best_checkpoint(run_id=run_id) + predictor = TorchPredictor.from_checkpoint(best_checkpoint) + + # y_true + preprocessor = predictor.get_preprocessor() + preprocessed_ds = preprocessor.transform(ds) + values = preprocessed_ds.select_columns(cols=["targets"]).take_all() + y_true = np.stack([item["targets"] for item in values]) + + # y_pred + z = predictor.predict(data=ds.to_pandas())["predictions"] + y_pred = np.stack(z).argmax(1) + + # Metrics + metrics = { + "timestamp": datetime.datetime.now().strftime("%B %d, %Y %I:%M:%S %p"), + "run_id": run_id, + "overall": get_overall_metrics(y_true=y_true, y_pred=y_pred), + "per_class": get_per_class_metrics(y_true=y_true, y_pred=y_pred, class_to_index=preprocessor.class_to_index), + "slices": get_slice_metrics(y_true=y_true, y_pred=y_pred, ds=ds), + } + logger.info(json.dumps(metrics, indent=2)) + if results_fp: # pragma: no cover, saving results + utils.save_dict(d=metrics, path=results_fp) + return metrics + + +if __name__ == "__main__": # pragma: no cover, checked during evaluation workload + app() diff --git a/madewithml/models.py b/madewithml/models.py new file mode 100644 index 0000000..40ca441 --- /dev/null +++ b/madewithml/models.py @@ -0,0 +1,19 @@ +import torch +import torch.nn as nn + + +class FinetunedLLM(nn.Module): # pragma: no cover, torch model + """Model architecture for a Large Language Model (LLM) that we will fine-tune.""" + + def __init__(self, llm, dropout_p, embedding_dim, num_classes): + super(FinetunedLLM, self).__init__() + self.llm = llm + self.dropout = torch.nn.Dropout(dropout_p) + self.fc1 = torch.nn.Linear(embedding_dim, num_classes) + + def forward(self, batch): + ids, masks = batch["ids"], batch["masks"] + seq, pool = self.llm(input_ids=ids, attention_mask=masks) + z = self.dropout(pool) + z = self.fc1(z) + return z diff --git a/madewithml/predict.py b/madewithml/predict.py new file mode 100644 index 0000000..c530488 --- /dev/null +++ b/madewithml/predict.py @@ -0,0 +1,139 @@ +import json +from typing import Any, Dict, Iterable, List +from urllib.parse import urlparse + +import pandas as pd +import ray +import torch +import typer +from numpyencoder import NumpyEncoder +from ray.air import Result +from ray.train.torch import TorchPredictor +from ray.train.torch.torch_checkpoint import TorchCheckpoint +from typing_extensions import Annotated + +from madewithml.config import logger, mlflow + +# Initialize Typer CLI app +app = typer.Typer() + + +def decode(indices: Iterable[Any], index_to_class: Dict) -> List: + """Decode indices to labels. + + Args: + indices (Iterable[Any]): Iterable (list, array, etc.) with indices. + index_to_class (Dict): mapping between indices and labels. + + Returns: + List: list of labels. + """ + return [index_to_class[index] for index in indices] + + +def format_prob(prob: Iterable, index_to_class: Dict) -> Dict: + """Format probabilities to a dictionary mapping class label to probability. + + Args: + prob (Iterable): probabilities. + index_to_class (Dict): mapping between indices and labels. + + Returns: + Dict: Dictionary mapping class label to probability. + """ + d = {} + for i, item in enumerate(prob): + d[index_to_class[i]] = item + return d + + +def predict_with_proba( + df: pd.DataFrame, + predictor: ray.train.torch.torch_predictor.TorchPredictor, +) -> List: # pragma: no cover, tested with inference workload + """Predict tags (with probabilities) for input data from a dataframe. + + Args: + df (pd.DataFrame): dataframe with input features. + predictor (ray.train.torch.torch_predictor.TorchPredictor): loaded predictor from a checkpoint. + + Returns: + List: list of predicted labels. + """ + preprocessor = predictor.get_preprocessor() + z = predictor.predict(data=df)["predictions"] + import numpy as np + + y_prob = torch.tensor(np.stack(z)).softmax(dim=1).numpy() + results = [] + for i, prob in enumerate(y_prob): + tag = decode([z[i].argmax()], preprocessor.index_to_class)[0] + results.append({"prediction": tag, "probabilities": format_prob(prob, preprocessor.index_to_class)}) + return results + + +@app.command() +def get_best_run_id(experiment_name: str = "", metric: str = "", mode: str = "") -> str: # pragma: no cover, mlflow logic + """Get the best run_id from an MLflow experiment. + + Args: + experiment_name (str): name of the experiment. + metric (str): metric to filter by. + mode (str): direction of metric (ASC/DESC). + + Returns: + str: best run id from experiment. + """ + sorted_runs = mlflow.search_runs( + experiment_names=[experiment_name], + order_by=[f"metrics.{metric} {mode}"], + ) + run_id = sorted_runs.iloc[0].run_id + print(run_id) + return run_id + + +def get_best_checkpoint(run_id: str) -> TorchCheckpoint: # pragma: no cover, mlflow logic + """Get the best checkpoint from a specific run. + + Args: + run_id (str): ID of the run to get the best checkpoint from. + + Returns: + TorchCheckpoint: Best checkpoint from the run. + """ + artifact_dir = urlparse(mlflow.get_run(run_id).info.artifact_uri).path # get path from mlflow + results = Result.from_path(artifact_dir) + return results.best_checkpoints[0][0] + + +@app.command() +def predict( + run_id: Annotated[str, typer.Option(help="id of the specific run to load from")] = None, + title: Annotated[str, typer.Option(help="project title")] = None, + description: Annotated[str, typer.Option(help="project description")] = None, +) -> Dict: # pragma: no cover, tested with inference workload + """Predict the tag for a project given it's title and description. + + Args: + run_id (str): id of the specific run to load from. Defaults to None. + title (str, optional): project title. Defaults to "". + description (str, optional): project description. Defaults to "". + + Returns: + Dict: prediction results for the input data. + """ + # Load components + best_checkpoint = get_best_checkpoint(run_id=run_id) + predictor = TorchPredictor.from_checkpoint(best_checkpoint) + preprocessor = predictor.get_preprocessor() + + # Predict + sample_df = pd.DataFrame([{"title": title, "description": description, "tag": "other"}]) + results = predict_with_proba(df=sample_df, predictor=predictor, index_to_class=preprocessor.index_to_class) + logger.info(json.dumps(results, cls=NumpyEncoder, indent=2)) + return results + + +if __name__ == "__main__": # pragma: no cover, application + app() diff --git a/madewithml/serve.py b/madewithml/serve.py new file mode 100644 index 0000000..2e30ab2 --- /dev/null +++ b/madewithml/serve.py @@ -0,0 +1,79 @@ +import argparse +from http import HTTPStatus +from typing import Dict + +import pandas as pd +import ray +from fastapi import FastAPI +from ray import serve +from ray.train.torch import TorchPredictor +from starlette.requests import Request + +from madewithml import evaluate, predict +from madewithml.config import MLFLOW_TRACKING_URI, mlflow + +# Define application +app = FastAPI( + title="Made With ML", + description="Classify machine learning projects.", + version="0.1", +) + + +@serve.deployment(route_prefix="/", num_replicas="1", ray_actor_options={"num_cpus": 8, "num_gpus": 0}) +@serve.ingress(app) +class ModelDeployment: + def __init__(self, run_id: str, threshold: int = 0.9): + """Initialize the model.""" + self.run_id = run_id + self.threshold = threshold + mlflow.set_tracking_uri(MLFLOW_TRACKING_URI) # so workers have access to model registry + best_checkpoint = predict.get_best_checkpoint(run_id=run_id) + self.predictor = TorchPredictor.from_checkpoint(best_checkpoint) + self.preprocessor = self.predictor.get_preprocessor() + + @app.get("/") + def _index(self) -> Dict: + """Health check.""" + response = { + "message": HTTPStatus.OK.phrase, + "status-code": HTTPStatus.OK, + "data": {}, + } + return response + + @app.get("/run_id/") + def _run_id(self) -> Dict: + """Get the run ID.""" + return {"run_id": self.run_id} + + @app.post("/evaluate/") + async def _evaluate(self, request: Request) -> Dict: + data = await request.json() + results = evaluate.evaluate(run_id=self.run_id, dataset_loc=data.get("dataset")) + return {"results": results} + + @app.post("/predict/") + async def _predict(self, request: Request) -> Dict: + # Get prediction + data = await request.json() + df = pd.DataFrame([{"title": data.get("title", ""), "description": data.get("description", ""), "tag": ""}]) + results = predict.predict_with_proba(df=df, predictor=self.predictor) + + # Apply custom logic + for i, result in enumerate(results): + pred = result["prediction"] + prob = result["probabilities"] + if prob[pred] < self.threshold: + results[i]["prediction"] = "other" + + return {"results": results} + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--run_id", help="run ID to use for serving.") + parser.add_argument("--threshold", type=float, default=0.9, help="threshold for `other` class.") + args = parser.parse_args() + ray.init() + serve.run(ModelDeployment.bind(run_id=args.run_id, threshold=args.threshold)) diff --git a/madewithml/train.py b/madewithml/train.py new file mode 100644 index 0000000..00e1a44 --- /dev/null +++ b/madewithml/train.py @@ -0,0 +1,256 @@ +import datetime +import json +from typing import Tuple + +import numpy as np +import ray +import ray.train as train +import torch +import torch.nn as nn +import torch.nn.functional as F +import typer +from ray.air import session +from ray.air.config import ( + CheckpointConfig, + DatasetConfig, + RunConfig, + ScalingConfig, +) +from ray.air.integrations.mlflow import MLflowLoggerCallback +from ray.data import Dataset +from ray.train.torch import TorchCheckpoint, TorchTrainer +from transformers import BertModel +from typing_extensions import Annotated + +from madewithml import data, models, utils +from madewithml.config import MLFLOW_TRACKING_URI, logger + +# Initialize Typer CLI app +app = typer.Typer() + + +def train_step( + ds: Dataset, + batch_size: int, + model: nn.Module, + num_classes: int, + loss_fn: torch.nn.modules.loss._WeightedLoss, + optimizer: torch.optim.Optimizer, +) -> float: # pragma: no cover, tested via train workload + """Train step. + + Args: + ds (Dataset): dataset to iterate batches from. + batch_size (int): size of each batch. + model (nn.Module): model to train. + num_classes (int): number of classes. + loss_fn (torch.nn.loss._WeightedLoss): loss function to use between labels and predictions. + optimizer (torch.optimizer.Optimizer): optimizer to use for updating the model's weights. + + Returns: + float: cumulative loss for the dataset. + """ + model.train() + loss = 0.0 + ds_generator = ds.iter_torch_batches(batch_size=batch_size, collate_fn=utils.collate_fn) + for i, batch in enumerate(ds_generator): + optimizer.zero_grad() # reset gradients + z = model(batch) # forward pass + targets = F.one_hot(batch["targets"], num_classes=num_classes).float() # one-hot (for loss_fn) + J = loss_fn(z, targets) # define loss + J.backward() # backward pass + optimizer.step() # update weights + loss += (J.detach().item() - loss) / (i + 1) # cumulative loss + return loss + + +def eval_step( + ds: Dataset, batch_size: int, model: nn.Module, num_classes: int, loss_fn: torch.nn.modules.loss._WeightedLoss +) -> Tuple[float, np.array, np.array]: # pragma: no cover, tested via train workload + """Eval step. + + Args: + ds (Dataset): dataset to iterate batches from. + batch_size (int): size of each batch. + model (nn.Module): model to train. + num_classes (int): number of classes. + loss_fn (torch.nn.loss._WeightedLoss): loss function to use between labels and predictions. + + Returns: + Tuple[float, np.array, np.array]: cumulative loss, ground truths and predictions. + """ + model.eval() + loss = 0.0 + y_trues, y_preds = [], [] + ds_generator = ds.iter_torch_batches(batch_size=batch_size, collate_fn=utils.collate_fn) + with torch.inference_mode(): + for i, batch in enumerate(ds_generator): + z = model(batch) + targets = F.one_hot(batch["targets"], num_classes=num_classes).float() # one-hot (for loss_fn) + J = loss_fn(z, targets).item() + loss += (J - loss) / (i + 1) + y_trues.extend(batch["targets"].cpu().numpy()) + y_preds.extend(torch.argmax(z, dim=1).cpu().numpy()) + return loss, np.vstack(y_trues), np.vstack(y_preds) + + +def train_loop_per_worker(config: dict) -> None: # pragma: no cover, tested via train workload + """Training loop that each worker will execute. + + Args: + config (dict): arguments to use for training. + """ + # Hyperparameters + dropout_p = config["dropout_p"] + lr = config["lr"] + lr_factor = config["lr_factor"] + lr_patience = config["lr_patience"] + batch_size = config["batch_size"] + num_epochs = config["num_epochs"] + num_classes = config["num_classes"] + + # Get datasets + utils.set_seeds() + train_ds = session.get_dataset_shard("train") + val_ds = session.get_dataset_shard("val") + + # Model + llm = BertModel.from_pretrained("allenai/scibert_scivocab_uncased", return_dict=False) + model = models.FinetunedLLM(llm=llm, dropout_p=dropout_p, embedding_dim=llm.config.hidden_size, num_classes=num_classes) + model = train.torch.prepare_model(model) + + # Training components + loss_fn = nn.BCEWithLogitsLoss() + optimizer = torch.optim.Adam(model.parameters(), lr=lr) + scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode="min", factor=lr_factor, patience=lr_patience) + + # Training + batch_size_per_worker = batch_size // session.get_world_size() + for epoch in range(num_epochs): + # Step + train_loss = train_step(train_ds, batch_size_per_worker, model, num_classes, loss_fn, optimizer) + val_loss, _, _ = eval_step(val_ds, batch_size_per_worker, model, num_classes, loss_fn) + scheduler.step(val_loss) + + # Checkpoint + metrics = dict(epoch=epoch, lr=optimizer.param_groups[0]["lr"], train_loss=train_loss, val_loss=val_loss) + checkpoint = TorchCheckpoint.from_model(model=model) + session.report(metrics, checkpoint=checkpoint) + + +@app.command() +def train_model( + experiment_name: Annotated[str, typer.Option(help="name of the experiment for this training workload.")] = None, + dataset_loc: Annotated[str, typer.Option(help="location of the dataset.")] = None, + train_loop_config: Annotated[str, typer.Option(help="arguments to use for training.")] = None, + num_workers: Annotated[int, typer.Option(help="number of workers to use for training.")] = 1, + cpu_per_worker: Annotated[int, typer.Option(help="number of CPUs to use per worker.")] = 1, + gpu_per_worker: Annotated[int, typer.Option(help="number of GPUs to use per worker.")] = 0, + num_samples: Annotated[int, typer.Option(help="number of samples to use from dataset.")] = None, + num_epochs: Annotated[int, typer.Option(help="number of epochs to train for.")] = 1, + batch_size: Annotated[int, typer.Option(help="number of samples per batch.")] = 256, + results_fp: Annotated[str, typer.Option(help="filepath to save results to.")] = None, +) -> ray.air.result.Result: + """Main train function to train our model as a distributed workload. + + Args: + experiment_name (str): name of the experiment for this training workload. + dataset_loc (str): location of the dataset. + train_loop_config (str): arguments to use for training. + num_workers (int, optional): number of workers to use for training. Defaults to 1. + cpu_per_worker (int, optional): number of CPUs to use per worker. Defaults to 1. + gpu_per_worker (int, optional): number of GPUs to use per worker. Defaults to 0. + num_samples (int, optional): number of samples to use from dataset. + If this is passed in, it will override the config. Defaults to None. + num_epochs (int, optional): number of epochs to train for. + If this is passed in, it will override the config. Defaults to None. + batch_size (int, optional): number of samples per batch. + If this is passed in, it will override the config. Defaults to None. + results_fp (str, optional): filepath to save results to. Defaults to None. + + Returns: + ray.air.result.Result: training results. + """ + # Set up + train_loop_config = json.loads(train_loop_config) + train_loop_config["num_samples"] = num_samples + train_loop_config["num_epochs"] = num_epochs + train_loop_config["batch_size"] = batch_size + + # Scaling config + scaling_config = ScalingConfig( + num_workers=num_workers, + use_gpu=bool(gpu_per_worker), + resources_per_worker={"CPU": cpu_per_worker, "GPU": gpu_per_worker}, + _max_cpu_fraction_per_node=0.8, + ) + + # Checkpoint config + checkpoint_config = CheckpointConfig( + num_to_keep=1, + checkpoint_score_attribute="val_loss", + checkpoint_score_order="min", + ) + + # MLflow callback + mlflow_callback = MLflowLoggerCallback( + tracking_uri=MLFLOW_TRACKING_URI, + experiment_name=experiment_name, + save_artifact=True, + ) + + # Run config + run_config = RunConfig( + callbacks=[mlflow_callback], + checkpoint_config=checkpoint_config, + ) + + # Dataset + ds = data.load_data(dataset_loc=dataset_loc, num_samples=train_loop_config["num_samples"]) + train_ds, val_ds = data.stratify_split(ds, stratify="tag", test_size=0.2) + tags = train_ds.unique(column="tag") + train_loop_config["num_classes"] = len(tags) + + # Dataset config + dataset_config = { + "train": DatasetConfig(fit=False, transform=False, randomize_block_order=False), + "val": DatasetConfig(fit=False, transform=False, randomize_block_order=False), + } + + # Preprocess + preprocessor = data.CustomPreprocessor() + train_ds = preprocessor.fit_transform(train_ds) + val_ds = preprocessor.transform(val_ds) + train_ds = train_ds.materialize() + val_ds = val_ds.materialize() + + # Trainer + trainer = TorchTrainer( + train_loop_per_worker=train_loop_per_worker, + train_loop_config=train_loop_config, + scaling_config=scaling_config, + run_config=run_config, + datasets={"train": train_ds, "val": val_ds}, + dataset_config=dataset_config, + preprocessor=preprocessor, + ) + + # Train + results = trainer.fit() + d = { + "timestamp": datetime.datetime.now().strftime("%B %d, %Y %I:%M:%S %p"), + "run_id": utils.get_run_id(experiment_name=experiment_name, trial_id=results.metrics["trial_id"]), + "params": results.config["train_loop_config"], + "metrics": utils.dict_to_list(results.metrics_dataframe.to_dict(), keys=["epoch", "train_loss", "val_loss"]), + } + logger.info(json.dumps(d, indent=2)) + if results_fp: # pragma: no cover, saving results + utils.save_dict(d, results_fp) + return results + + +if __name__ == "__main__": # pragma: no cover, application + if ray.is_initialized(): + ray.shutdown() + ray.init() + app() diff --git a/madewithml/tune.py b/madewithml/tune.py new file mode 100644 index 0000000..77e21f4 --- /dev/null +++ b/madewithml/tune.py @@ -0,0 +1,182 @@ +import datetime +import json + +import ray +import typer +from ray import tune +from ray.air.config import ( + CheckpointConfig, + DatasetConfig, + RunConfig, + ScalingConfig, +) +from ray.air.integrations.mlflow import MLflowLoggerCallback +from ray.train.torch import TorchTrainer +from ray.tune import Tuner +from ray.tune.schedulers import AsyncHyperBandScheduler +from ray.tune.search import ConcurrencyLimiter +from ray.tune.search.hyperopt import HyperOptSearch +from typing_extensions import Annotated + +from madewithml import data, train, utils +from madewithml.config import MLFLOW_TRACKING_URI, logger + +# Initialize Typer CLI app +app = typer.Typer() + + +@app.command() +def tune_models( + experiment_name: Annotated[str, typer.Option(help="name of the experiment for this training workload.")] = None, + dataset_loc: Annotated[str, typer.Option(help="location of the dataset.")] = None, + initial_params: Annotated[str, typer.Option(help="initial config for the tuning workload.")] = None, + num_workers: Annotated[int, typer.Option(help="number of workers to use for training.")] = 1, + cpu_per_worker: Annotated[int, typer.Option(help="number of CPUs to use per worker.")] = 1, + gpu_per_worker: Annotated[int, typer.Option(help="number of GPUs to use per worker.")] = 0, + num_runs: Annotated[int, typer.Option(help="number of runs in this tuning experiment.")] = 1, + num_samples: Annotated[int, typer.Option(help="number of samples to use from dataset.")] = None, + num_epochs: Annotated[int, typer.Option(help="number of epochs to train for.")] = 1, + batch_size: Annotated[int, typer.Option(help="number of samples per batch.")] = 256, + results_fp: Annotated[str, typer.Option(help="filepath to save results to.")] = None, +) -> ray.tune.result_grid.ResultGrid: + """Hyperparameter tuning experiment. + + Args: + experiment_name (str): name of the experiment for this training workload. + dataset_loc (str): location of the dataset. + initial_params (str): initial config for the tuning workload. + num_workers (int, optional): number of workers to use for training. Defaults to 1. + cpu_per_worker (int, optional): number of CPUs to use per worker. Defaults to 1. + gpu_per_worker (int, optional): number of GPUs to use per worker. Defaults to 0. + num_runs (int, optional): number of runs in this tuning experiment. Defaults to 1. + num_samples (int, optional): number of samples to use from dataset. + If this is passed in, it will override the config. Defaults to None. + num_epochs (int, optional): number of epochs to train for. + If this is passed in, it will override the config. Defaults to None. + batch_size (int, optional): number of samples per batch. + If this is passed in, it will override the config. Defaults to None. + results_fp (str, optional): filepath to save the tuning results. Defaults to None. + + Returns: + ray.tune.result_grid.ResultGrid: results of the tuning experiment. + """ + # Set up + utils.set_seeds() + train_loop_config = {} + train_loop_config["num_samples"] = num_samples + train_loop_config["num_epochs"] = num_epochs + train_loop_config["batch_size"] = batch_size + + # Scaling config + scaling_config = ScalingConfig( + num_workers=num_workers, + use_gpu=bool(gpu_per_worker), + resources_per_worker={"CPU": cpu_per_worker, "GPU": gpu_per_worker}, + _max_cpu_fraction_per_node=0.8, + ) + + # Dataset + ds = data.load_data(dataset_loc=dataset_loc, num_samples=train_loop_config.get("num_samples", None)) + train_ds, val_ds = data.stratify_split(ds, stratify="tag", test_size=0.2) + tags = train_ds.unique(column="tag") + train_loop_config["num_classes"] = len(tags) + + # Dataset config + dataset_config = { + "train": DatasetConfig(fit=False, transform=False, randomize_block_order=False), + "val": DatasetConfig(fit=False, transform=False, randomize_block_order=False), + } + + # Preprocess + preprocessor = data.CustomPreprocessor() + train_ds = preprocessor.fit_transform(train_ds) + val_ds = preprocessor.transform(val_ds) + train_ds = train_ds.materialize() + val_ds = val_ds.materialize() + + # Trainer + trainer = TorchTrainer( + train_loop_per_worker=train.train_loop_per_worker, + train_loop_config=train_loop_config, + scaling_config=scaling_config, + datasets={"train": train_ds, "val": val_ds}, + dataset_config=dataset_config, + preprocessor=preprocessor, + ) + + # Checkpoint configuration + checkpoint_config = CheckpointConfig( + num_to_keep=1, + checkpoint_score_attribute="val_loss", + checkpoint_score_order="min", + ) + + # Run configuration + mlflow_callback = MLflowLoggerCallback( + tracking_uri=MLFLOW_TRACKING_URI, + experiment_name=experiment_name, + save_artifact=True, + ) + run_config = RunConfig( + callbacks=[mlflow_callback], + checkpoint_config=checkpoint_config, + ) + + # Hyperparameters to start with + initial_params = json.loads(initial_params) + search_alg = HyperOptSearch(points_to_evaluate=initial_params) + search_alg = ConcurrencyLimiter(search_alg, max_concurrent=2) # trade off b/w optimization and search space + + # Parameter space + param_space = { + "train_loop_config": { + "dropout_p": tune.uniform(0.3, 0.9), + "lr": tune.loguniform(1e-5, 5e-4), + "lr_factor": tune.uniform(0.1, 0.9), + "lr_patience": tune.uniform(1, 10), + } + } + + # Scheduler + scheduler = AsyncHyperBandScheduler( + max_t=train_loop_config["num_epochs"], # max epoch () per trial + grace_period=1, # min epoch () per trial + ) + + # Tune config + tune_config = tune.TuneConfig( + metric="val_loss", + mode="min", + search_alg=search_alg, + scheduler=scheduler, + num_samples=num_runs, + ) + + # Tuner + tuner = Tuner( + trainable=trainer, + run_config=run_config, + param_space=param_space, + tune_config=tune_config, + ) + + # Tune + results = tuner.fit() + best_trial = results.get_best_result(metric="val_loss", mode="min") + d = { + "timestamp": datetime.datetime.now().strftime("%B %d, %Y %I:%M:%S %p"), + "run_id": utils.get_run_id(experiment_name=experiment_name, trial_id=best_trial.metrics["trial_id"]), + "params": best_trial.config["train_loop_config"], + "metrics": utils.dict_to_list(best_trial.metrics_dataframe.to_dict(), keys=["epoch", "train_loss", "val_loss"]), + } + logger.info(json.dumps(d, indent=2)) + if results_fp: # pragma: no cover, saving results + utils.save_dict(d, results_fp) + return results + + +if __name__ == "__main__": # pragma: no cover, application + if ray.is_initialized(): + ray.shutdown() + ray.init() + app() diff --git a/madewithml/utils.py b/madewithml/utils.py new file mode 100644 index 0000000..5b65c15 --- /dev/null +++ b/madewithml/utils.py @@ -0,0 +1,123 @@ +import json +import os +import random +from typing import Any, Dict, List + +import numpy as np +import torch +from ray.data import DatasetContext +from ray.train.torch import get_device + +from madewithml.config import mlflow + +DatasetContext.get_current().execution_options.preserve_order = True + + +def set_seeds(seed: int = 42): + """Set seeds for reproducibility.""" + np.random.seed(seed) + random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + eval("setattr(torch.backends.cudnn, 'deterministic', True)") + eval("setattr(torch.backends.cudnn, 'benchmark', False)") + os.environ["PYTHONHASHSEED"] = str(seed) + + +def load_dict(path: str) -> Dict: + """Load a dictionary from a JSON's filepath. + + Args: + path (str): location of file. + + Returns: + Dict: loaded JSON data. + """ + with open(path) as fp: + d = json.load(fp) + return d + + +def save_dict(d: Dict, path: str, cls: Any = None, sortkeys: bool = False) -> None: + """Save a dictionary to a specific location. + + Args: + d (Dict): data to save. + path (str): location of where to save the data. + cls (optional): encoder to use on dict data. Defaults to None. + sortkeys (bool, optional): whether to sort keys alphabetically. Defaults to False. + """ + directory = os.path.dirname(path) + if directory and not os.path.exists(directory): # pragma: no cover + os.makedirs(directory) + with open(path, "w") as fp: + json.dump(d, indent=2, fp=fp, cls=cls, sort_keys=sortkeys) + fp.write("\n") + + +def pad_array(arr: np.ndarray, dtype=np.int32) -> np.ndarray: + """Pad an 2D array with zeros until all rows in the + 2D array are of the same length as a the longest + row in the 2D array. + + Args: + arr (np.array): input array + + Returns: + np.array: zero padded array + """ + max_len = max(len(row) for row in arr) + padded_arr = np.zeros((arr.shape[0], max_len), dtype=dtype) + for i, row in enumerate(arr): + padded_arr[i][: len(row)] = row + return padded_arr + + +def collate_fn(batch: Dict[str, np.ndarray]) -> Dict[str, torch.Tensor]: # pragma: no cover, air internal + """Convert a batch of numpy arrays to tensors (with appropriate padding). + + Args: + batch (Dict[str, np.ndarray]): input batch as a dictionary of numpy arrays. + + Returns: + Dict[str, torch.Tensor]: output batch as a dictionary of tensors. + """ + batch["ids"] = pad_array(batch["ids"]) + batch["masks"] = pad_array(batch["masks"]) + dtypes = {"ids": torch.int32, "masks": torch.int32, "targets": torch.int64} + tensor_batch = {} + for key, array in batch.items(): + tensor_batch[key] = torch.as_tensor(array, dtype=dtypes[key], device=get_device()) + return tensor_batch + + +def get_run_id(experiment_name: str, trial_id: str) -> str: # pragma: no cover, mlflow functionality + """Get the MLflow run ID for a specific Ray trial ID. + + Args: + experiment_name (str): name of the experiment. + trial_id (str): id of the trial. + + Returns: + str: run id of the trial. + """ + trial_name = f"TorchTrainer_{trial_id}" + run = mlflow.search_runs(experiment_names=[experiment_name], filter_string=f"tags.trial_name = '{trial_name}'").iloc[0] + return run.run_id + + +def dict_to_list(data: Dict, keys: List[str]) -> List[Dict[str, Any]]: + """Convert a dictionary to a list of dictionaries. + + Args: + data (Dict): input dictionary. + keys (List[str]): keys to include in the output list of dictionaries. + + Returns: + List[Dict[str, Any]]: output list of dictionaries. + """ + list_of_dicts = [] + for i in range(len(data[keys[0]])): + new_dict = {key: data[key][i] for key in keys} + list_of_dicts.append(new_dict) + return list_of_dicts diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..9ba8187 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,19 @@ +site_name: Made With ML +site_url: https://madewithml.com/ +repo_url: https://github.com/GokuMohandas/Made-With-ML/ +nav: + - Home: index.md + - madewithml: + - data: madewithml/data.md + - models: madewithml/models.md + - train: madewithml/train.md + - tune: madewithml/tune.md + - evaluate: madewithml/evaluate.md + - predict: madewithml/predict.md + - serve: madewithml/serve.md + - utils: madewithml/utils.md +theme: readthedocs +plugins: + - mkdocstrings +watch: + - . # reload docs for any file changes diff --git a/notebooks/benchmarks.ipynb b/notebooks/benchmarks.ipynb new file mode 100644 index 0000000..e3f91e7 --- /dev/null +++ b/notebooks/benchmarks.ipynb @@ -0,0 +1,1160 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "id": "abb04d61-c097-45a9-9201-e3649cbdc0cc", + "metadata": {}, + "source": [ + "
\n", + "

 Made With ML

\n", + "

ML for Developers

\n", + " Design · Develop · Deploy · Iterate\n", + "
\n", + "\n", + "
\n", + "\n", + "
\n", + "  \n", + "  \n", + "  \n", + " \n", + "
\n", + " 🔥  Among the top ML repositories on GitHub\n", + "
\n", + "\n", + "
\n", + "
" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3012ac29-11de-458c-9023-1a216812f943", + "metadata": {}, + "source": [ + "# Generative AI" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "9dffe7be-4a8f-499a-9531-fa4bbab228ef", + "metadata": {}, + "source": [ + "In our [Made With ML course](https://madewithml.com/) we will be fine-tuning an LLM for a supervised classification task. The specific class of LLMs we'll be using is called [BERT](https://en.wikipedia.org/wiki/BERT_(language_model)). Bert models are encoder-only models and are the gold-standard for supervised NLP tasks. However, you may be wondering how do all the (much larger) LLM, created for generative applications, fare ([GPT 4](https://openai.com/research/gpt-4), [Falcon 40B](https://huggingface.co/tiiuae/falcon-40b), [Llama 2](https://ai.meta.com/llama/), etc.)?\n", + "\n", + "> We chose the smaller BERT model for our course because it's easier to train and fine-tune. However, the workflow for fine-tuning the larger LLMs are quite similar as well. They do require much more compute but Ray abstracts away the scaling complexities involved with that." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "d877530b-f3c5-429a-8525-1238c5b8693b", + "metadata": {}, + "source": [ + "## Set up" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e2c96931-d511-4c6e-b582-87d24455a11e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "!pip install openai==0.27.8 tqdm==4.65.0 -q" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c9fb2cc9", + "metadata": {}, + "source": [ + "You'll need to first sign up for an [OpenAI account](https://platform.openai.com/signup) and then grab your API key from [here](https://platform.openai.com/account/api-keys)." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "953a577e-3cd0-4c6b-81f9-8bc32850214d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import openai\n", + "openai.api_key = \"YOUR_API_KEY\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3d40cf2d-afa2-41b6-8f03-77b50cc3baca", + "metadata": {}, + "source": [ + "### Load data" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "1790e2f5-6b8b-425c-8842-a2b0ea8f3f07", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6b9bfadb-ba49-4f5a-b216-4db14c8888ab", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idcreated_ontitledescriptiontag
062020-02-20 06:43:18Comparison between YOLO and RCNN on real world...Bringing theory to experiment is cool. We can ...computer-vision
172020-02-20 06:47:21Show, Infer & Tell: Contextual Inference for C...The beauty of the work lies in the way it arch...computer-vision
292020-02-24 16:24:45Awesome Graph ClassificationA collection of important graph embedding, cla...other
3152020-02-28 23:55:26Awesome Monte Carlo Tree SearchA curated list of Monte Carlo tree search pape...other
4252020-03-07 23:04:31AttentionWalkA PyTorch Implementation of \"Watch Your Step: ...other
\n", + "
" + ], + "text/plain": [ + " id created_on title \n", + "0 6 2020-02-20 06:43:18 Comparison between YOLO and RCNN on real world... \\\n", + "1 7 2020-02-20 06:47:21 Show, Infer & Tell: Contextual Inference for C... \n", + "2 9 2020-02-24 16:24:45 Awesome Graph Classification \n", + "3 15 2020-02-28 23:55:26 Awesome Monte Carlo Tree Search \n", + "4 25 2020-03-07 23:04:31 AttentionWalk \n", + "\n", + " description tag \n", + "0 Bringing theory to experiment is cool. We can ... computer-vision \n", + "1 The beauty of the work lies in the way it arch... computer-vision \n", + "2 A collection of important graph embedding, cla... other \n", + "3 A curated list of Monte Carlo tree search pape... other \n", + "4 A PyTorch Implementation of \"Watch Your Step: ... other " + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Load training data\n", + "DATASET_LOC = \"https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv\"\n", + "train_df = pd.read_csv(DATASET_LOC)\n", + "train_df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "aa5b95d5-d61e-48e4-9100-d9d2fc0d53fa", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['computer-vision', 'other', 'natural-language-processing', 'mlops']" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Unique labels\n", + "tags = train_df.tag.unique().tolist()\n", + "tags" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3c828129-8248-4e38-93a4-cabb097e7ba5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Load inference dataset\n", + "HOLDOUT_LOC = \"https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/holdout.csv\"\n", + "test_df = pd.read_csv(HOLDOUT_LOC)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "085dd167-0bee-4167-b1b7-d5797ebda30b", + "metadata": {}, + "source": [ + "### Utilities" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "5686dd79-02bc-4f11-8948-888b58bd504c", + "metadata": {}, + "source": [ + "We'll define a few utility functions to make the OpenAI request and to store our predictions. While we could perform batch prediction by loading samples until the context length is reached, we'll just perform one at a time since it's not too many data points and we can have fully deterministic behavior (if you insert new data, etc.). We'll also added some reliability in case we overload the endpoints with too many request at once." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8e3c3f44-2c19-4c32-9bc5-e9a7a917d19d", + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "from collections import Counter\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns; sns.set_theme()\n", + "from sklearn.metrics import precision_recall_fscore_support\n", + "import time\n", + "from tqdm import tqdm" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "4950bdb4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "I'm an AI with no emotions, just code,\n", + "But I'm here to help you, lighten your load.\n", + "So ask me questions, and I'll do my best,\n", + "To answer in rhymes, and put your mind at rest.\n" + ] + } + ], + "source": [ + "# Query OpenAI endpoint\n", + "system_content = \"you only answer in rhymes\" # system content (behavior)\n", + "assistant_content = \"\" # assistant content (context)\n", + "user_content = \"how are you\" # user content (message)\n", + "response = openai.ChatCompletion.create(\n", + " model=\"gpt-3.5-turbo-0613\",\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_content},\n", + " {\"role\": \"assistant\", \"content\": assistant_content},\n", + " {\"role\": \"user\", \"content\": user_content},\n", + " ],\n", + ")\n", + "print (response.to_dict()[\"choices\"][0].to_dict()[\"message\"][\"content\"])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "175dddcc", + "metadata": {}, + "source": [ + "Now let's create a function that can predict tags for a given sample." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "b2aae14c-9870-4a27-b5ad-90f339686620", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def get_tag(model, system_content=\"\", assistant_content=\"\", user_content=\"\"):\n", + " try:\n", + " # Get response from OpenAI\n", + " response = openai.ChatCompletion.create(\n", + " model=model,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system_content},\n", + " {\"role\": \"assistant\", \"content\": assistant_content},\n", + " {\"role\": \"user\", \"content\": user_content},\n", + " ],\n", + " )\n", + " predicted_tag = response.to_dict()[\"choices\"][0].to_dict()[\"message\"][\"content\"]\n", + " return predicted_tag\n", + "\n", + " except (openai.error.ServiceUnavailableError, openai.error.APIError) as e:\n", + " return None" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "03ee23e5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "natural-language-processing\n" + ] + } + ], + "source": [ + "# Get tag\n", + "model = \"gpt-3.5-turbo-0613\"\n", + "system_context = f\"\"\"\n", + " You are a NLP prediction service that predicts the label given an input's title and description.\n", + " You must choose between one of the following labels for each input: {tags}.\n", + " Only respond with the label name and nothing else.\n", + " \"\"\"\n", + "assistant_content = \"\"\n", + "user_context = \"Transfer learning with transformers: Using transformers for transfer learning on text classification tasks.\"\n", + "tag = get_tag(model=model, system_content=system_context, assistant_content=assistant_content, user_content=user_context)\n", + "print (tag)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3087ead2", + "metadata": {}, + "source": [ + "Next, let's create a function that can predict tags for a list of inputs." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "71c43e8c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'title': 'Diffusion to Vector',\n", + " 'description': 'Reference implementation of Diffusion2Vec (Complenet 2018) built on Gensim and NetworkX. '},\n", + " {'title': 'Graph Wavelet Neural Network',\n", + " 'description': 'A PyTorch implementation of \"Graph Wavelet Neural Network\" (ICLR 2019) '},\n", + " {'title': 'Capsule Graph Neural Network',\n", + " 'description': 'A PyTorch implementation of \"Capsule Graph Neural Network\" (ICLR 2019).'}]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# List of dicts w/ {title, description} (just the first 3 samples for now)\n", + "samples = test_df[[\"title\", \"description\"]].to_dict(orient=\"records\")[:3]\n", + "samples" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "c9359a91-ac19-48a4-babb-e65d53f39b42", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def get_predictions(inputs, model, system_content, assistant_content=\"\"):\n", + " y_pred = []\n", + " for item in tqdm(inputs):\n", + " # Convert item dict to string\n", + " user_content = str(item)\n", + "\n", + " # Get prediction\n", + " predicted_tag = get_tag(\n", + " model=model, system_content=system_content,\n", + " assistant_content=assistant_content, user_content=user_content)\n", + "\n", + " # If error, try again after pause (repeatedly until success)\n", + " while predicted_tag is None:\n", + " time.sleep(30) # could also do exponential backoff\n", + " predicted_tag = get_tag(\n", + " model=model, system_content=system_content,\n", + " assistant_content=assistant_content, user_content=user_content)\n", + "\n", + " # Add to list of predictions\n", + " y_pred.append(predicted_tag)\n", + "\n", + " return y_pred" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "5fac795e", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 0%| | 0/3 [00:00 Open AI has now released [function calling](https://openai.com/blog/function-calling-and-other-api-updates) and [custom instructions](https://openai.com/blog/custom-instructions-for-chatgpt) which is worth exploring to avoid this manual cleaning." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "f361ee27", + "metadata": {}, + "source": [ + "Next, we'll define a function that will plot our ground truth labels and predictions." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "de2d0416", + "metadata": {}, + "outputs": [], + "source": [ + "def plot_tag_dist(y_true, y_pred):\n", + " # Distribution of tags\n", + " true_tag_freq = dict(Counter(y_true))\n", + " pred_tag_freq = dict(Counter(y_pred))\n", + " df_true = pd.DataFrame({\"tag\": list(true_tag_freq.keys()), \"freq\": list(true_tag_freq.values()), \"source\": \"true\"})\n", + " df_pred = pd.DataFrame({\"tag\": list(pred_tag_freq.keys()), \"freq\": list(pred_tag_freq.values()), \"source\": \"pred\"})\n", + " df = pd.concat([df_true, df_pred], ignore_index=True)\n", + "\n", + " # Plot\n", + " plt.figure(figsize=(10, 3))\n", + " plt.title(\"Tag distribution\", fontsize=14)\n", + " ax = sns.barplot(x=\"tag\", y=\"freq\", hue=\"source\", data=df)\n", + " ax.set_xticklabels(list(true_tag_freq.keys()), rotation=0, fontsize=8)\n", + " plt.legend()\n", + " plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "1fc0b6ad", + "metadata": {}, + "source": [ + "And finally, we'll define a function that will combine all the utilities above to predict, clean and plot our results." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "ff3c37fb", + "metadata": {}, + "outputs": [], + "source": [ + "def evaluate(test_df, model, system_content, assistant_content, tags):\n", + " # Predictions\n", + " y_test = test_df.tag.to_list()\n", + " test_samples = test_df[[\"title\", \"description\"]].to_dict(orient=\"records\")\n", + " y_pred = get_predictions(\n", + " inputs=test_samples, model=model,\n", + " system_content=system_content, assistant_content=assistant_content)\n", + " y_pred = clean_predictions(y_pred=y_pred, tags=tags)\n", + "\n", + " # Performance\n", + " metrics = precision_recall_fscore_support(y_test, y_pred, average=\"weighted\")\n", + " performance = {\"precision\": metrics[0], \"recall\": metrics[1], \"f1\": metrics[2]}\n", + " print(json.dumps(performance, indent=2))\n", + " plot_tag_dist(y_true=y_test, y_pred=y_pred)\n", + " return y_pred, performance" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "1fb7ab2a", + "metadata": {}, + "source": [ + "## Benchmarks" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "83f00073", + "metadata": {}, + "source": [ + "Now we're ready to start benchmarking our different LLMs with different context." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "972fee2f-86e2-445e-92d0-923f5690132a", + "metadata": {}, + "outputs": [], + "source": [ + "y_pred = {\"zero_shot\": {}, \"few_shot\": {}}\n", + "performance = {\"zero_shot\": {}, \"few_shot\": {}}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "2029fff2-ae81-4cef-bef5-3cac717d0222", + "metadata": {}, + "source": [ + "### Zero-shot learning" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "341b9d90", + "metadata": {}, + "source": [ + "We'll start with zero-shot learning which involves providing the model with the `system_content` that tells it how to behave but no examples of the behavior." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "9ee4e745-ef56-4b76-8230-fcbe56ac46aa", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "system_content = f\"\"\"\n", + " You are a NLP prediction service that predicts the label given an input's title and description. \n", + " You must choose between one of the following labels for each input: {tags}. \n", + " Only respond with the label name and nothing else.\n", + " \"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "73780054-afeb-4ce6-8255-51bf91f9f820", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [01:26<00:00, 2.21it/s]\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"precision\": 0.7919133278407181,\n", + " \"recall\": 0.806282722513089,\n", + " \"f1\": 0.7807530967691199\n", + "}\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1YAAAE9CAYAAAAI8PPbAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABAUklEQVR4nO3deVxU9f7H8ffMAAIiiKjgnpmKlrjkguWKXivDTMmrldg1Ky23Um9YWi5lmXq1RC1N07qmlktamblkqz/RKG2TNHNLUkllEdlk5vz+8OFcJ1yAQWZGXs/Ho0fOWeb7OcP5zvDm+z1nTIZhGAIAAAAAFJvZ1QUAAAAAgKcjWAEAAACAkwhWAAAAAOAkghUAAAAAOIlgBQAAAABOIlgBAAAAgJMIVgAAAADgJIIVAAAAADiJYAUAAAAATiJYAQAKiI+PV8OGDQv139ixY11drmbNmqWGDRtqx44dkqSjR4+qYcOGGjNmTLGe78SJE8rKyrrqdpdqJzY2Vg0bNlR+fn6x2i5KXWPHjlXDhg11+PDhEm8LAFA0Xq4uAADgfv7xj3+odu3aDstefvllpaamatq0aQ7L/76dO6hUqZKmTZumWrVqFXnfVatWacqUKfroo4/k7+9/zdopibr69u2rtm3bqnLlyte8fQDAlRGsAAAFhIeHKzw83GHZa6+9ptTUVPXs2dNFVRWev79/setMSEgo1GiVs+0U1aXqat68uZo3b14q7QMAroypgAAAAADgJIIVAMBpGzdu1MMPP6w2bdro5ptvVps2bTRkyBD9/PPPBbb98MMP1bt3bzVr1kzt27fXjBkztHLlSodrpK7WVp8+fdSsWTN16NBBs2fPltVqddjmUtc+ZWdn6+WXX9add96piIgItWnTRoMHD9Z3331n3yYqKkofffSRJKlLly6KjY2VdP5apiZNmujLL79U586d1aRJE40aNeqK13Lt2bNHsbGxioiI0G233aZnn31WKSkpDttERUWpQ4cOBfa98HqsWbPmqnX9/Rorq9Wq//73v+rZs6ciIiLUokULDRgwQF9++aVDG2vWrFHDhg21fft2TZs2TZ06ddItt9yiO++8U4sXL77KTwEA8HdMBQQAOGXJkiV6+eWX1aZNGw0bNkze3t76+eeftXbtWu3cuVNbtmxRpUqVJEkLFizQf/7zH91888168skndebMGS1durTQbS1btkyTJk1SgwYNNHLkSGVlZWnZsmXKzs6+6r6jRo3Stm3b9OCDD+rGG2/UyZMn9e677+qhhx7SqlWrFB4ermeffVYLFy7Url279Mwzz6h+/fr2/fPz8zVmzBj1799fFStWVFhY2BXbe+ihh9S2bVvFxcVp7969WrlypRISEvTBBx8oKCio0Mcs6Yp1Xcxms2nYsGHaunWr2rRpo9GjR+vs2bNas2aNHnvsMY0dO1YDBw502GfcuHHy9/fXgAED5OXlpWXLlmnq1KkKCAhQnz59ilQnAJRlBCsAQLFZrVa98cYbatSokRYvXiyLxWJfFxgYqEWLFmnnzp268847deLECcXHx+vmm2/WihUr5OPjI0nq2bOnevTocdW2MjMzNX36dNWvX1/vv/++/Pz8JEm9e/e+6nVOp0+f1tatW3X//fcrLi7OvjwyMlJjx47VTz/9pPDwcHXt2lWffvqpdu3apa5du6pmzZr2bW02m/r376+RI0falx09evSybd57772aMGGC/XH9+vX14osvatGiRRo1atRVj/diV6rrYh9++KG2bt2qe++9V1OnTpXJZJIkDRgwQDExMZo+fbq6dOnicMOR8uXLa/Xq1fafR1RUlLp06aLVq1cTrACgCJgKCAAoNovFoq+++kpvv/22Q6jKysqSt7e3pPOBSJK2bNmivLw8Pfzww/Zf4qXzdxW85557rtrW9u3blZWVpfvuu88eqiSpWrVqio6OvuK+AQEBqlChgjZu3KiVK1fqr7/+knT+5g8XphYWxm233Vao7SRp6NChDo/79eunChUqaNOmTYV+jqL69NNPJUkjRoywhyrp/PEPHjxYVqtVGzdudNjnjjvucPh51KxZU8HBwTp58uQ1qxMArkeMWAEAnOLj46PvvvtOGzZs0MGDB5WcnKxjx47JMAxJsv//4MGDkqS6desWeI569epdtZ0jR45Ikm644YYi7+/j46OpU6fqmWee0fjx4yVJDRo0ULt27dSjRw81btz4qu1LUkhISKG2q1ixYoFboHt7e6tmzZr67bffCvUcxXHkyBH5+/urRo0aBdZdmD7491G2KlWqFNjWx8dHNpvt2hQJANcpRqwAAE4ZPXq0/vWvf+m7775T7dq1FRsbq7feekvPP/+8w3Z5eXmS5DA6coGvr2+h28vNzS2w7EJ4u5KuXbvqq6++Unx8vPr27au8vDy99dZb6t27t955551CtX3xqNyVXDxa9Pc6C/Mcxf1y4Su9DheC0t9ff7OZXwUAoCQwYgUAKLbExER9/PHHuuuuuzRr1iyHQLF7926HbS+MVB04cKDAzRcOHDhw1bbq1Klz2W0PHTp0xX0zMzO1d+9e1axZU926dVO3bt0kSUlJSRowYIDmzp2rAQMGXLWGwkpPT1dGRoYCAwPty/Ly8vTHH3/Yj0M6H9Qu9Z1ZxZ2GV7t2bR04cEDJyckFRq0ujJRVr169WM8NALgy/kwFACi2tLQ0SeenmV0cqk6fPq1Vq1ZJ+t/oS7du3eTl5aWlS5fq3Llz9m1TUlLstxK/kttvv11BQUF69913lZGRYV9+6tQprVu37or77t27Vw888IDmzZvnsLx+/fqqUKGCvLz+93fGCyNKhRkFuxybzaZly5Y5LHv77bd19uxZ3XXXXfZlVatWVVpamsP0vNzcXPu1UhcrTF133HGHJGn27NkO2509e1ZvvvmmLBaLunbtWryDAgBcESNWAIBia9GihSpWrKg333xTOTk5ql27to4eParVq1frzJkzkmT/f40aNfT4448rPj5e999/v6Kjo+23S78wanO5KXSS5Ofnp4kTJ2r06NHq3bu3+vbtK8MwtGzZMvuNMq5U52233aYVK1YoIyNDrVu3ltVq1YYNG5ScnOxwp8AL11EtXLhQ7du3L1YQ8fPz0/z583X06FE1adJEu3bt0gcffKCbb75ZDz/8sH27e++9V4mJiRo0aJAefPBB2Ww2rV69+pLhqTB19ezZU59++qnWrl2rY8eOqUuXLsrOztbq1at15MgRjRkzRrVq1Sry8QAAro5gBQAotkqVKumtt97SzJkz9f777ysvL0+hoaG64447NHDgQN155536+uuv9dhjj0mShg0bpsqVK2vp0qWaMWOGgoODFRMTo9zcXC1evPiS119drHv37goODtbcuXM1b948+fr6qkePHqpTp44mT5582f1MJpPi4+P11ltvacOGDfriiy8kSeHh4ZoxY4bD7d779++v77//XqtXr1ZCQkKxglVgYKBeffVVTZ06VevWrVNQUJAeeughjRgxwuF6sj59+igrK0vLly/XtGnTVLlyZfXs2VMdOnTQAw884PCchanLYrFo3rx5evvtt7V27VrNmDFDfn5+atKkiZ577rlLfhkx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3r17X3EfoChat26tzZs3Ky8vT3l5eRoyZIjOnj2rDRs2SJJ2796tlJQUNWjQoNDP+fXXXysjI0O5ublav3692rVrp6CgIKWlpSklJUVWq1WbNm2yb2+xWGS1Wgt9vjdp0kTr1q3TunXr7H/R7NGjhzZu3KikpCS1a9fOYfvExEQ9+uijioyMVFxcnOrVq6eDBw/a1zdt2lQ//vij/vjjD0nSe++9p9atWxfhVcS18tNPP+mGG27QwIED1bRpU3311VeyWq2S/nfeSOf/8v3rr79Kkj799NNLPldaWpoOHTqkJ598Uh07dtS2bdvs+19w//3328+ti29ucujQIZlMJj3++OOKjIx0qONybr/9dn3wwQeSpOPHj2vHjh0ymUwKDg7WoUOHlJ2drezsbH3xxRdXPNYbb7xRZ86c0S+//CJJDrMdIiMj7aNXhw4dUnR0tNLT0/Xmm2/ajyM0NFSStH79ens7aWlpBfp0QECAatWqdcm+37p1a/v+u3bt0qhRo9SmTRtt3rxZJ0+elCS9/PLLmjdv3mX726OPPqqDBw/qgQce0MiRI7Vnz54rvn4Xv44bNmxQbm6u8vLytGHDBv7IUQZERkZq5cqVkqTTp09ry5YtatmypaRLf8Z89NFHmjhxorp06aLx48fL39/fPtsBpYcRK5SKzp07KykpSffdd5/y8/N12223acCAAfrxxx91zz33aNWqVZfdd/r06Zo4caIWLlwoi8Wi1157TT4+PqVYPa5nXbt21Z49exQTEyObzaaYmBh17NhREydO1Lx58+Tt7a34+PginXNVqlTR4MGDdfr0aUVHR9unDw4ZMkT9+vVT5cqV1bJlS50+fVrS+emFEyZM0Msvv1zs871KlSoKDQ1VvXr1CvwF9NZbb9WNN95on07UuHFjdejQwf6LauXKlTV58mQNGzZM+fn5CgsL00svvVTo48W1065dO/3666/q3r27fHx8FBERoX379klyPG8GDx6suLg4ffDBB2rbtq19lPNiFStWVJ8+fXT33XcrICBATZs2VU5OTqGmA4aHh6tx48a666675Ovrq1atWik5OfmSozwXPP7443ruuefUo0cPValSRdWrV5evr6/q16+vbt26KTo6WqGhobr11lslnQ8Qy5cvL3CsPj4+mjlzpp577jkZhqHw8HD7tLjx48drwoQJ6tGjhwzD0JQpUy45DVA6P/rbq1cv2Ww2zZw585Ijzhf639/7/nPPPafx48dr2bJl8vHx0SuvvKLw8HANGzZMAwcOlM1mU7169TR27Fj5+/tfsr+FhIRo0qRJmjFjhry8vAp9G/uOHTvqp59+Uq9evVS+fHkFBwc7jGzh+jR06FBNnDhR0dHRslqteuyxxxQREaH9+/df8jMmNzdXn332me6++255e3vrjjvu4NbtLmAyrvSuCAAokgt3+5s6daqrSwFc6sMPP1RYWJhat26tzMxM9e7dWytXrlRQUFCRnscwDE2bNk1Dhw5VQECAtmzZog8//FCzZ88u9HPExsY63DXRk/zwww/at2+f+vTpI8MwNGLECMXExNj/YIOyhc8Y98aIFQAAKHE33nijJkyYYJ8yOHLkyCKHKun8tUYhISH65z//KW9vb4WEhOiFF14o6XLd1g033KC5c+fqnXfekXR+pJJQBbgnRqwAAAAAwEncvAIAAAAAnESwAgAAAAAnEawAAAAAwEkEKwBAmcPlxQCAkkawAgCUKZ999pni4uJcXQYA4DrD7dYBAGXKkiVLXF0CAOA6xIgVAAAAADiJ77ECAJQZsbGx2rlzp/3xO++8o6CgIM2ZM0eJiYk6c+aMKlWqpDvuuENjxoyRr6+vJCkzM1PTpk3T5s2blZOTo06dOqlp06Z6+eWXtXfvXlcdDgDAjRCsAABlxv79+/Xvf/9bkjRhwgRVqVJF99xzj5o1a6bY2Fj5+Pjoq6++0uLFizV69Gg99thjkqQBAwYoKSlJTz31lKpXr65ly5Zp+/btysvLI1gBACRxjRUAoAy56aabFBAQIElq1qyZvvnmGzVq1Eivvfaaffltt92mbdu2aceOHXrssce0fft27dixQ/Hx8erWrZskqUOHDoqOjtbvv//usmMBALgXghUAoMxq166d2rVrp3Pnzmn//v06fPiw9u3bp9OnT6tixYqSpISEBHl7e6tr1672/cxms7p37674+HgXVQ4AcDcEKwBAmWWz2TRz5ky9++67ysrKUrVq1RQREaFy5crZt0lNTVXFihVlNjve7ykkJKS0ywUAuDGCFQCgzFqwYIGWLFmiSZMmqVu3bqpQoYIk6b777rNvExoaqtTUVNlsNodwderUqVKvFwDgvrjdOgCgTLk4HH333Xe66aabFBMTYw9VJ06c0L59+2Sz2SRJrVu3Vn5+vrZu3WrfzzAMbdmypXQLBwC4NUasAABlSmBgoHbt2qXt27erTp06+uabb7RgwQI1a9ZMhw8f1vz585WXl6fs7GxJUqtWrXT77bdr3LhxOnnypKpXr65Vq1Zp7969MplMLj4aAIC74HbrAIAyJSEhQc8884z++usvvfDCC/rpp5+0adMmnTlzRtWqVdPdd98tk8mk+fPna9u2bQoMDFR6erqmTp2qLVu2KD8/X126dFFgYKDWrl2r77//3tWHBABwAwQrAACuIDk5Wbt371aXLl3sXxgsSSNGjNAff/yhDz74wIXVAQDcBVMBAQC4ArPZrLFjx6pLly667777ZLFY9PXXX2vTpk16+eWXXV0eAMBNMGIFAMBVJCQkaO7cuUpKSlJ+fr7q1aungQMHKjo62tWlAQDcBMEKAAAAAJzE7dYBAAAAwEkEKwAAAABwEsEKAAAAAJxEsAIAAAAAJxGsAAAAAMBJBCsAAAAAcBLBCgAAAACcRLACAAAAACcRrAAAAADASf8PQMJWiyTCF+QAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Zero-shot with GPT 3.5\n", + "method = \"zero_shot\"\n", + "model = \"gpt-3.5-turbo-0613\"\n", + "y_pred[method][model], performance[method][model] = evaluate(\n", + " test_df=test_df, model=model, system_content=system_content,\n", + " assistant_content=\"\", tags=tags)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "24af6d04-d29e-4adb-a289-4c34c2cc7ec8", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [06:33<00:00, 2.06s/it] " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"precision\": 0.9314722577069027,\n", + " \"recall\": 0.9267015706806283,\n", + " \"f1\": 0.9271956481845013\n", + "}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA00AAAE9CAYAAADXvonEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA8oElEQVR4nO3de3zP9f//8fv7/d5mmxkz2sgxYZQ5xIycSRSJ8aEyhYpyyuHTVsihlBBl+BSK+gglp0pySDr4Ga1IPpZDhizsg23MTvZ+v35/+Hp/vBtvO9l7m9v1cumSvU7Px+u913Pv3fd8vl5vk2EYhgAAAAAA12V2dQEAAAAAUJQRmgAAAADACUITAAAAADhBaAIAAAAAJwhNAAAAAOAEoQkAAAAAnCA0AQAAAIAThCYAAAAAcILQBAAAAABOEJoA4DYUFRWlunXr5ui/yMhIV5erOXPmqG7dutq1a5ck6eTJk6pbt67GjRuXp+OdOXNGqampN93ueu2Eh4erbt26ysrKylPbuakrMjJSdevW1fHjxwu8LQBAzrm5ugAAQOF74IEHVK1aNYdlb7zxhhITEzVjxgyH5X/frigoX768ZsyYoapVq+Z6388++0zTpk3TF198IW9v71vWTkHU1bdvX7Vo0UIVKlS45e0DAG6M0AQAt6GgoCAFBQU5LHvnnXeUmJioHj16uKiqnPP29s5zndHR0TkaZcpvO7l1vboaN26sxo0bF0r7AIAbY3oeAAAAADhBaAIA3NSmTZs0aNAgNW/eXPfcc4+aN2+uoUOHav/+/dm2/fzzz9WrVy81atRIrVu31qxZs7Rq1SqHe5Ju1lafPn3UqFEjtWnTRnPnzpXVanXY5nr3GqWlpemNN95Qly5dFBwcrObNm2vIkCH6+eef7dt06NBBX3zxhSSpY8eOCg8Pl3Tl3qEGDRrou+++U/v27dWgQQONGTPG6b1TBw4cUHh4uIKDg9WyZUu9/PLLSkhIcNimQ4cOatOmTbZ9r74ea9asuWldf7+nyWq16t///rd69Oih4OBgNWnSRAMGDNB3333n0MaaNWtUt25d7dy5UzNmzFC7du107733qkuXLlqyZMlNvgsAgGsxPQ8A4NTSpUv1xhtvqHnz5ho+fLjc3d21f/9+rVu3Trt379bWrVtVvnx5SdLChQv11ltv6Z577tELL7ygixcvatmyZTlua/ny5ZoyZYrq1KmjUaNGKTU1VcuXL1daWtpN9x0zZox27NihJ554QnfddZfOnj2rjz/+WE8++aQ+++wzBQUF6eWXX9bixYu1Z88evfTSS6pdu7Z9/6ysLI0bN079+/dXuXLlFBgY6LS9J598Ui1atFBERIQOHjyoVatWKTo6WmvXrlXZsmVzfM6SnNZ1LZvNpuHDh2vbtm1q3ry5xo4dq0uXLmnNmjV69tlnFRkZqYEDBzrsM378eHl7e2vAgAFyc3PT8uXLNX36dPn4+KhPnz65qhMAbleEJgDADVmtVr377ruqV6+elixZIovFYl/n6+ur999/X7t371aXLl105swZRUVF6Z577tHKlSvl4eEhSerRo4e6d+9+07ZSUlI0c+ZM1a5dW59++qm8vLwkSb169brpfUXnz5/Xtm3b9NhjjykiIsK+PDQ0VJGRkfrtt98UFBSkTp066euvv9aePXvUqVMnValSxb6tzWZT//79NWrUKPuykydP3rDNRx99VJMmTbJ/Xbt2bb322mt6//33NWbMmJue77Wc1XWtzz//XNu2bdOjjz6q6dOny2QySZIGDBigsLAwzZw5Ux07dnR4eEfp0qW1evVq+/ejQ4cO6tixo1avXk1oAoAcYnoeAOCGLBaLvv/+e3344YcOgSk1NVXu7u6SroQdSdq6dasyMzM1aNAg+y/o0pWn7z3yyCM3bWvnzp1KTU1V79697YFJkipVqqRu3bo53dfHx0dlypTRpk2btGrVKv33v/+VdOVBClen++VEy5Ytc7SdJA0bNszh6379+qlMmTLavHlzjo+RW19//bUkaeTIkfbAJF05/yFDhshqtWrTpk0O+zz44IMO348qVarIz89PZ8+evWV1AkBJw0gTAMApDw8P/fzzz9q4caPi4uIUHx+vU6dOyTAMSbL/Py4uTpJUs2bNbMeoVavWTds5ceKEJKlGjRq53t/Dw0PTp0/XSy+9pAkTJkiS6tSpo1atWql79+6qX7/+TduXJH9//xxtV65cuWyPAXd3d1eVKlV0+PDhHB0jL06cOCFvb2/deeed2dZdndL399GxihUrZtvWw8NDNpvt1hQJACUQI00AAKfGjh2rp556Sj///LOqVaum8PBwffDBB3rllVcctsvMzJQkh1GNqzw9PXPcXkZGRrZlV4OZM506ddL333+vqKgo9e3bV5mZ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ABQJP/30k5o3b17gx33sscfytR5F1626ZlC41q9f7+oSABQQQhMKxLvvvqvPP/9cFotF999/v9LS0iRJvXr1sv+Fc8qUKdqzZ48yMjL05ptvKjg4WCdOnNDkyZOVmJgoDw8PRUREqEmTJoqMjFRiYqJOnDihUaNGqUuXLq48PRRzs2fP1qZNm2SxWNSjRw917txZr7zyipKSkuTt7a3x48crODhYkZGR8vT01N69e5WUlKTRo0dr69atio2NVfv27TV+/HitWbNGmzZtUkpKihISEtS2bVuNHz9e8fHxGjBggLZt2ybpyl/xd+/erWbNmmn//v2aMGGC5s6dq9KlS+f6mp8+fbrKly+vZ599VpIUERGhkJAQ/fXXX5KkYcOG2fuXxWJRhw4dNGLECEVFRUmSRowYoW+//VZvv/22bDabqlatqqlTp6pChQrq0KGDevTooR07digpKUkTJ05U69atC/k7VPLt2rVL//rXv1SmTBn98ccfCgwM1OzZs/Xll19q3bp1Sk9Pl3TlWv3tt98crpnXX39dw4cPt4eounXr6uDBg4qKitLevXt1+vRp9enTR/Xr19fs2bOVkZGh5ORkjR07Vg8//HCO6tu4caOWLFmi9PR0paena+rUqQoNDVV4eLgaNmyomJgYJSQkaMSIEerZs6dSUlL08ssv6/Dhw6pYsaJMJpOef/55SdK8efP073//W5IcrsFly5ZlO9c6deooJiZGU6dOldlsVtOmTfXdd99py5YtOn/+vF555RX7dT58+HB16NAhW+3h4eGqWbOm9u/fr7S0NEVGRqpt27bZXp+2bdtet9+fOnVKL730ks6ePSsPDw9NnjxZwcHBWr9+vT788ENZrVbdfffdmjJliry9va/b1/bu3avXXntNhmGoVKlSeu2113TXXXc5fK/OnDmjEydOKD4+3l6LJL3zzjvasGGDypQpo1q1aqlq1aoaMWJEXi81uNCuXbs0f/58ubm56dixY2rdurUCAgK0detW2Ww2LVy40L5tWlqaJkyYoIMHD8pkMmnw4MF69NFHb/gek5GRoRdffFEnTpyQyWRS37591a9fPxee7W3IAPJp+/btRlhYmJGammpcvnzZGDp0qLFs2TKjTp069m3q1KljbNiwwTAMw/jwww+NESNGGIZhGP369TP27dtnGIZhHD9+3Gjfvr1x+fJlIyIi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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Zero-shot with GPT 4\n", + "method = \"zero_shot\"\n", + "model = \"gpt-4-0613\"\n", + "y_pred[method][model], performance[method][model] = evaluate(\n", + " test_df=test_df, model=model, system_content=system_content,\n", + " assistant_content=\"\", tags=tags)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "483f6d46-7a9e-4bce-a34f-96c1cf2df29a", + "metadata": {}, + "source": [ + "### Few-shot learning" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "8d6159b2", + "metadata": {}, + "source": [ + "Now, we'll be adding a `assistant_context` with a few samples from our training data for each class. The intuition here is that we're giving the model a few examples (few-shot learning) of what each class looks like so that it can learn to generalize better." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "e22ed1e1-b34d-43d1-ae8b-32b1fd5be53d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'title': 'Comparison between YOLO and RCNN on real world videos',\n", + " 'description': 'Bringing theory to experiment is cool. We can easily train models in colab and find the results in minutes.',\n", + " 'tag': 'computer-vision'},\n", + " {'title': 'Show, Infer & Tell: Contextual Inference for Creative Captioning',\n", + " 'description': 'The beauty of the work lies in the way it architects the fundamental idea that humans look at the overall image and then individual pieces of it.\\r\\n',\n", + " 'tag': 'computer-vision'},\n", + " {'title': 'Awesome Graph Classification',\n", + " 'description': 'A collection of important graph embedding, classification and representation learning papers with implementations.',\n", + " 'tag': 'other'},\n", + " {'title': 'Awesome Monte Carlo Tree Search',\n", + " 'description': 'A curated list of Monte Carlo tree search papers with implementations. ',\n", + " 'tag': 'other'},\n", + " {'title': 'Rethinking Batch Normalization in Transformers',\n", + " 'description': 'We found that NLP batch statistics exhibit large variance throughout training, which leads to poor BN performance.',\n", + " 'tag': 'natural-language-processing'},\n", + " {'title': 'ELECTRA: Pre-training Text Encoders as Discriminators',\n", + " 'description': 'PyTorch implementation of the electra model from the paper: ELECTRA - Pre-training Text Encoders as Discriminators Rather Than Generators',\n", + " 'tag': 'natural-language-processing'},\n", + " {'title': 'Pytest Board',\n", + " 'description': 'Continuous pytest runner with awesome visualization.',\n", + " 'tag': 'mlops'},\n", + " {'title': 'Debugging Neural Networks with PyTorch and W&B',\n", + " 'description': 'A closer look at debugging common issues when training neural networks.',\n", + " 'tag': 'mlops'}]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Create additional context with few samples from each class\n", + "num_samples = 2\n", + "additional_context = []\n", + "cols_to_keep = [\"title\", \"description\", \"tag\"]\n", + "for tag in tags:\n", + " samples = train_df[cols_to_keep][train_df.tag == tag][:num_samples].to_dict(orient=\"records\")\n", + " additional_context.extend(samples)\n", + "additional_context" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "294548a5-9edf-4dea-ab8d-dc7464246810", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Here are some examples with the correct labels: [{'title': 'Comparison between YOLO and RCNN on real world videos', 'description': 'Bringing theory to experiment is cool. We can easily train models in colab and find the results in minutes.', 'tag': 'computer-vision'}, {'title': 'Show, Infer & Tell: Contextual Inference for Creative Captioning', 'description': 'The beauty of the work lies in the way it architects the fundamental idea that humans look at the overall image and then individual pieces of it.\\r\\n', 'tag': 'computer-vision'}, {'title': 'Awesome Graph Classification', 'description': 'A collection of important graph embedding, classification and representation learning papers with implementations.', 'tag': 'other'}, {'title': 'Awesome Monte Carlo Tree Search', 'description': 'A curated list of Monte Carlo tree search papers with implementations. ', 'tag': 'other'}, {'title': 'Rethinking Batch Normalization in Transformers', 'description': 'We found that NLP batch statistics exhibit large variance throughout training, which leads to poor BN performance.', 'tag': 'natural-language-processing'}, {'title': 'ELECTRA: Pre-training Text Encoders as Discriminators', 'description': 'PyTorch implementation of the electra model from the paper: ELECTRA - Pre-training Text Encoders as Discriminators Rather Than Generators', 'tag': 'natural-language-processing'}, {'title': 'Pytest Board', 'description': 'Continuous pytest runner with awesome visualization.', 'tag': 'mlops'}, {'title': 'Debugging Neural Networks with PyTorch and W&B', 'description': 'A closer look at debugging common issues when training neural networks.', 'tag': 'mlops'}]\n" + ] + } + ], + "source": [ + "# Add additional context\n", + "assistant_content = f\"\"\"Here are some examples with the correct labels: {additional_context}\"\"\"\n", + "print (assistant_content)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "a087e14f", + "metadata": {}, + "source": [ + "> We could increase the number of samples by increasing the context length. We could also retrieve better few-shot samples by extracting examples from the training data that are similar to the current sample (ex. similar unique vocabulary)." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "29bca273-3ea8-4ce0-9fa9-fe19062b7c5b", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [01:16<00:00, 2.49it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"precision\": 0.8435247936255214,\n", + " \"recall\": 0.8586387434554974,\n", + " \"f1\": 0.8447984162323493\n", + "}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA00AAAE9CAYAAADXvonEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA9EklEQVR4nO3df3zN9f//8fs5Z5ttZrMNQ6gIo8yP/BjJ75CGGG/EFCoKyY+3rZAfpYQ3ZegHRb2F8ruS/Eg/fYxWFG+L5FctLOyH2S875/X9w3cnJxz7ZWfmdr1cuuS8fj0fr7PX85xzP8/X63VMhmEYAgAAAABcldnVBQAAAABAcUZoAgAAAAAnCE0AAAAA4AShCQAAAACcIDQBAAAAgBOEJgAAAABwgtAEAAAAAE4QmgAAAADACUITAAAAADhBaAKAW1B0dLRq166dq/+ioqJcXa7mzp2r2rVra9euXZKkP/74Q7Vr19a4cePytb3Tp08rLS3tustdrZ2IiAjVrl1b2dnZ+Wo7L3VFRUWpdu3aOn78eKG3BQDIPTdXFwAAKHoPPPCAqlWr5jDtlVdeUWJiombOnOkw/Z/LFQcBAQGaOXOmqlatmud1V69erenTp+uTTz6Rt7f3DWunMOrq06ePmjdvrnLlyt3w9gEA10ZoAoBbUHBwsIKDgx2mvf7660pMTFT37t1dVFXueXt757vOmJiYXI0yFbSdvLpaXQ0bNlTDhg2LpH0AwLVxeh4AAAAAOEFoAgBc1+bNmzV48GA1a9ZMd999t5o1a6Zhw4Zp//79Vyz78ccfq2fPnmrQoIHuv/9+zZ49W6tWrXK4Jul6bfXu3VsNGjRQq1atNG/ePFmtVodlrnatUXp6ul555RV17txZISEhatasmYYOHaoffvjBvky7du30ySefSJLat2+viIgISZeuHapXr56+/vprtW3bVvXq1dOYMWOcXjt14MABRUREKCQkRC1atNDzzz+vhIQEh2XatWunVq1aXbFuzvOxdu3a69b1z2uarFar/vvf/6p79+4KCQlRo0aNNHDgQH399dcObaxdu1a1a9fWzp07NXPmTLVp00b33HOPOnfurCVLllznrwAAuByn5wEAnFq6dKleeeUVNWvWTCNGjJC7u7v279+v9evXa/fu3dq2bZsCAgIkSW+//bb+85//6O6779azzz6r8+fPa9myZblua/ny5Zo6dapq1aqlUaNGKS0tTcuXL1d6evp11x0zZox27Nih/v37q3r16jpz5ow++OADPfroo1q9erWCg4P1/PPPa/HixdqzZ4+ee+451axZ075+dna2xo0bpwEDBqhs2bKqWLGi0/YeffRRNW/eXJGRkTp48KBWrVqlmJgYrVu3Tn5+frneZ0lO67qczWbTiBEjtH37djVr1kxjx47VhQsXtHbtWj355JOKiorSoEGDHNaZMGGCvL29NXDgQLm5uWn58uWaMWOGfHx81Lt37zzVCQC3KkITAOCarFar3nzzTdWpU0dLliyRxWKxz/P19dU777yj3bt3q3Pnzjp9+rSio6N19913a+XKlfLw8JAkde/eXV27dr1uW6mpqZo1a5Zq1qypjz76SF5eXpKknj17Xve6onPnzmn79u3q16+fIiMj7dNDQ0MVFRWlffv2KTg4WB06dNDnn3+uPXv2qEOHDqpSpYp9WZvNpgEDBmjUqFH2aX/88cc123z44Yc1efJk++OaNWvqpZde0jvvvKMxY8Zcd38v56yuy3388cfavn27Hn74Yc2YMUMmk0mSNHDgQIWHh2vWrFlq3769w807SpcurTVr1tj/Hu3atVP79u21Zs0aQhMA5BKn5wEArsliseibb77Re++95xCY0tLS5O7uLulS2JGkbdu2KSsrS4MHD7Z/QJcu3X2vW7du121r586dSktLU69eveyBSZIqVaqksLAwp+v6+PioTJky2rx5s1atWqW//vpL0qUbKeSc7pcbLVq0yNVykjR8+HCHx3379lWZMmW0ZcuWXG8jrz7//HNJ0jPPPGMPTNKl/R86dKisVqs2b97ssE6nTp0c/h5VqlSRv7+/zpw5c8PqBICShpEmAIBTHh4e+uGHH7Rp0yYdPXpU8fHxOnnypAzDkCT7/48ePSpJuvPOO6/YRo0aNa7bzokTJyRJd9xxR57X9/Dw0IwZM/Tcc89p4sSJkqRatWqpZcuW6tq1q+rWrXvd9iUpMDAwV8uVLVv2ituAu7u7q0qVKvr1119ztY38OHHihLy9vXXbbbddMS/nlL5/jo6VL1/+imU9PDxks9luTJEAUAIx0gQAcGrs2LF67LHH9MMPP6hatWqKiIjQu+++qxdeeMFhuaysLElyGNXI4enpmev2MjMzr5iWE8yc6dChg7755htFR0erT58+ysrK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CE0AAAAA4AShCQAAAACcIDQBAAAAgBOEJgAAAABwgtCEGyYiIsL+79q1a7uwEsC15s2bp9jY2ELf7ooVK7RixYp8z0fxVZjHTFRUlNauXXvF9LVr1yoqKqpQ2sDVde/e3dUloJjh89DNy83VBaDk2r17t6tLAIqF77//Xs2aNSv07fbr169A81F83ahjBkVrw4YNri4BQCEhNKFQvPnmm/r4449lsVh03333KT09XZLUs2dP+zecU6dO1Z49e5SZmalXX31VISEhOnHihKZMmaLExER5eHgoMjJSjRo1UlRUlBITE3XixAmNGjVKnTt3duXu4SY3Z84cbd68WRaLRd27d1fHjh31wgsvKCkpSd7e3powYYJCQkIUFRUlT09P7d27V0lJSRo9erS2bdumuLg4tW3bVhMmTNDatWu1efNmpaamKiEhQa1bt9aECRMUHx+vgQMHavv27ZIufYu/e/duNWnSRPv379fEiRM1b948lS5dOs/H/IwZMxQQEKAnn3xSkhQZGammTZvqzz//lCQNHz7c3r8sFovatWunkSNHKjo6WpI0cuRIffnll3rttddks9lUtWpVTZs2TeXKlVO7du3UvXt37dixQ0lJSZo0aZLuv//+Iv4LlXy7du3SG2+8oTJlyui3335TxYoVNWfOHH366adav369MjIyJF06Vvft2+dwzLz88ssaMWKEPUTVrl1bBw8eVHR0tPbu3atTp06pd+/eqlu3rubMmaPMzEwlJydr7Nixeuihh3JV36ZNm7RkyRJlZGQoIyND06ZNU2hoqCIiIlS/fn3FxsYqISFBI0eOVI8ePZSamqrnn39ev/76q8qXLy+TyaSnn35akjR//nz997//lSSHY3DZsmVX7GutWrUUGxuradOmyWw2q3Hjxvr666+1detWnTt3Ti+88IL9OB8xYoTatWt3Re0RERG68847tX//fqWnpysqKkqtW7e+4vlp3br1Vfv9yZMn9dxzz+nMmTPy8PDQlClTFBISog0bNui9996T1WrVXXfdpalTp8rb2/uqfW3v3r166aWXZBiGSpUqpZdeeknVq1d3+FudPn1aJ06cUHx8vL0WSXr99de1ceNGlSlTRjVq1FDVqlU1cuTI/B5qcKFdu3ZpwYIFcnNz07Fjx3T//fcrKChI27Ztk81m09tvv21fNj09XRMnTtTBgwdlMpk0ZMgQPfzww9d8j8nMzNT48eN14sQJmUwm9enTR3379nXh3t6CDKCAvvrqKyM8PNxIS0szLl68aAwbNsxYtmyZUatWLfsytWrVMjZu3GgYhmG89957xsiRIw3DMIy+ffsaP//8s2EYhnH8+HGjbdu2xsWLF43IyEhj7NixRb8zKHE2b95s9OnTx8jIyDAyMjKMXr16GU2aNDE+++wzwzAMY8+ePUabNm2MzMxMIzIy0hg2bJhhGIaxdu1a49577zXOnDljnD9/3mjYsKGRnJxsrFmzxggNDTUSEhKMzMxMo0+fPsZnn31m/P7770bbtm3t7a5Zs8aIjIw0DMMwBgwYYMTExBiGkb9jPi4uzujWrZthGIaRkZFhtGjRwjh//rwxb948Y968eUZcXJzRo0cP+/wxY8YYaWlp9vlnzpwx7rvvPuPEiROGYRjGokWL7H2wbdu2xjvvvGMYhmFs2bLFvh0UrpiYGKNBgwZGfHy8YRiGMWzYMGPp0qVGRESEkZaWZhiGYbz++uvGtGnTDMNwPGYu/7dhGPbX1nnz5hn9+vWzTx85cqRx6NAhwzAMY+fOnUZYWJhhGIYRGRlprFmz5oqaco5Rq9VqREREGGfOnDEMwzBWr15tDB061N52Tk3/+9//jKZNmxqGYRgzZswwXnrpJcMwDOPEiRNGgwYNjJiYGCMmJsYYMGCAvY2cY/D8+fNX3desrCyjVatW9j6xaNEiez8aM2aMsXnzZsMwDOPs2bNGhw4d7DVebsCAAcb48eMNm81mHDhwwAgNDTUyMzOveH7Cw8Ov2u+HDh1qLF261DAMw9i1a5cxZMgQ4/Dhw0bfvn2N9PR0wzAMY+HChcaMGTOu2deefvpp44svvjAMwzA2btxorF279oq/Vc+ePY3MzEwjNTXVaNmypfHLL78Y27dvN3r37m2kp6cbaWlpRs+ePY158+ZdsY+4OVzez9PS0owGDRoYK1asMAzDMKKiooylS5faj4lXX33VmDp1qmEYl47vdu3aGXFxcdd8j9m6dasxYsQIwzAM49y5c8a4ceNcs5O3MEaaUGAxMTEKCwuTl5eXJCk8PFzr16+/YrmOHTtKkmrVqqWtW7fqwoUL2rdvnyZOnGhfJjs7WydPnpQkNWzY8MYXjxJv165devDBB1WqVClJ0tKlS9WmTRs9+OCDkqQGDRrIz89PR44ckSS1adNGklS5cmXVrFlTgYGBkqSyZcsqJSVFktS2bVuVL19ektSlSxd9//33qlev3nVrye8xHxwcLEn67bffdOjQIYWGhsrHx8c+v1q1asrKylL//v3VunVrjR492t4fJennn39WSEiIqlatKknq06ePwzeerVu3treTlJR03f1A/tSsWVOVK1eWJNWpU0fnz5/X3Llz9dlnn+nYsWP69ttvVadOnTxts0GDBvZ/z5o1S19++aW2bNmin376SRcuXMjVNsxmsxYuXKjt27fr6NGj2r17t8zmvy95zjk+6tSpYz8+vvvuO82aNUuSVLVqVbVo0cJpGz4+Plfd10OHDikgIMDef/r06aPly5fb2/j111+1YMECSZf6ym+//Wbvk5fr3bu3TCaT6tSpo4oVK+rgwYMOz8+FCxd0/Pjxq/b7Xbt22feladOmatq0qZYtW6bjx4+rT58+9rarVq16zb7Wrl07TZw4UW3btlXbtm3VqVOnK2ps3ry5PDw85OHhodtvv13JycnasWOHwsLC5OnpKUnq1q2b/XUGN6fatWvb+7m/v7+aN28u6dJ7yuV/25iYGE2fPl2SFBAQoPbt22v37t3y8fG56nvM0KFDNX36dA0ZMkStW7dWZGRkEe8ZCE0oMJvNdsW07OzsK6a5uV063Ewmk309Dw8Ph3O+T58+bX+huPxDH5BfFovFfsxJUnJy8hXLGIZhP2bd3d3t03OO2X+6fLrNZpPZbJbJZJJhGPbpFy9evGK93B7zlwere+65R9OnT1f37t21adMmHTx4UL169XLYrre3t9avX69du3bpu+++U9++fe2nR+W0+8/9vby+nEB5+fOEwpfzPEuXnus///xTvXv3VkREhFq1aqVy5copLi7uquvmHFtZWVkO0y9/nXzkkUfUtGlThYaGqnnz5ho3bpzDsitWrNDKlSslSX379rXXc+HCBYWHh6tbt25q0qSJateurQ8++OCKui8/PiwWi8Pxfvl+/bMfuLu76+TJk+rfv/8V+2qxWK76HiJdOm7ff/99lS1bVpKUkJCggIAAPfHEE0pISJAke/i3WCwO6+U8znl+rlZrTr93c3Nz2Ldff/1VVqtVXbp0sffDtLQ0ZWVlXbOvhYeHq3nz5vrqq6+0dOlSffXVV3rppZcc2vvn398wDJnN5mvuP25Ol7+HSI7H5uX+eUxe/j50tfeY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GUlSr1697MsEBQUpMTFRNpvNITidPXu2yOsFABRP3HIcAFCiXB58fvjhB911110KDw+3B6bTp0/r0KFDstlskqSmTZsqOztb27dvt69nGIa2bdtWtIUDAIotRpoAACWKr6+v9uzZo507d+r222/Xd999p7ffflsNGjTQ8ePH9dZbbykrK0vp6emSpCZNmui+++7ThAkTdObMGVWuXFmrV6/WwYMHZTKZXLw3AIDigFuOAwBKlJiYGD333HP666+/9OKLL2rfvn3asmWLzp8/r0qVKumhhx6SyWTSW2+9pR07dsjX11fJycmaMWOGtm3bpuzsbLVv316+vr5av369fvzxR1fvEgDAxQhNAIBbWnx8vPbu3av27dvbf+xWkp555hn9/vvvWrdunQurAwAUB5yeBwC4pZnNZkVFRal9+/bq1auXLBaLvv32W23ZskWvvPKKq8sDABQDjDQBAG55MTExWrBggeLi4pSdna0aNWpo0KBBCgsLc3VpAIBigNAEAAAAAE5wy3EAAAAAcILQBAAAAABOEJoAAAAAwAlCEwAAAAA4QWgCAAAAACcITQAAAADgBKEJAAAAAJwgNAEAAACAE4QmAAAAAHDi/wHxKTsvTvZRlgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Few-shot with GPT 3.5\n", + "method = \"few_shot\"\n", + "model = \"gpt-3.5-turbo-0613\"\n", + "y_pred[method][model], performance[method][model] = evaluate(\n", + " test_df=test_df, model=model, system_content=system_content,\n", + " assistant_content=assistant_content, tags=tags)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "3e59a3b9-69d9-4bb5-8b88-0569fcc72f0c", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [02:13<00:00, 1.43it/s]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"precision\": 0.9407759040163695,\n", + " \"recall\": 0.9267015706806283,\n", + " \"f1\": 0.9302632275594479\n", + "}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "data": { + "image/png": "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LVq0kI+Pj5KSkpSQkKDs7Gxt2rTJtr3FYlF2dnaur/l69epp3bp1Wrdune0vkd26ddPGjRsVGxurFi1a2G0fExOjZ599VqGhoYqIiFCNGjUUFxdnW1+/fn3t3btXf/75pyTp008/VUhISB5eRdwO+/btU/Xq1TVgwADVr19fP/zwg7KzsyX975qRrvy1+vfff5ckffPNN9c9VlJSko4dO6YXX3xRrVu31vbt2237X/X444/brqtrJwk5duyYTCaTnn/+eYWGhtrVcSMPPvig1qxZI0k6ffq0du7cKZPJJF9fXx07dkxpaWlKS0vTtm3bHJ7rPffco4sXL+o///mPJNndpRAaGmobdTp27Ji6du2q5ORkLViwwHYeAQEBkqT169fb2klKSsrRn728vFSlSpXr9vuQkBDb/rt379aoUaPUtGlTbd68WWfPnpUkvfXWW5o3b94N+9qzzz6ruLg4PfHEExo5cqQOHDjg8PW79nXcsGGDMjIylJmZqQ0bNvDHiztEaGioVq5cKUk6f/68tmzZosaNG0u6/nvMl19+qYkTJ6p9+/YaN26cPD09bXcpoHAw0oRb1rZtW8XGxqpXr17KyspS8+bN1b9/f+3du1ePPvqoPv/88xvuO336dE2cOFELFy6UxWLRe++9Jzc3t0KsHiVdhw4ddODAAYWFhclqtSosLEytW7fWxIkTNW/ePLm6uioqKipP11358uU1ePBgnT9/Xl27drXd0jdkyBD17dtX5cqVU+PGjXX+/HlJV275mzBhgt566618X/Ply5dXQECAatSokeMvlw888IDuuece220+devWVatWrWy/iJYrV06TJ0/WsGHDlJWVpcDAQL355pu5Pl/cHi1atNDvv/+uLl26yM3NTcHBwTp06JAk+2tm8ODBioiI0Jo1a9SsWTPbyOS1ypYtq969e+uRRx6Rl5eX6tevr/T09FzdohcUFKS6deuqc+fOcnd3V5MmTRQfH3/d0Zmrnn/+eY0fP17dunVT+fLlValSJbm7u6tmzZrq2LGjunbtqoCAAD3wwAOSroSD5cuX5zhXNzc3zZw5U+PHj5dhGAoKCrLdqjZu3DhNmDBB3bp1k2EYmjJlynVvzZOujNj26NFDVqtVM2fOvO4o8dW+9/d+P378eI0bN07Lli2Tm5ub3n77bQUFBWnYsGEaMGCArFaratSoocjISHl6el63r/n7+2vSpEmaMWOGXFxccj2Ve+vWrbVv3z716NFDpUuXlq+vr92IFEquoUOHauLEieratauys7P13HPPKTg4WEeOHLnue0xGRoa+/fZbPfLII3J1ddXDDz/M9OWFzGQ4+qkIALBzdVa8qVOnOrsUwGm++OILBQYGKiQkRCkpKerZs6dWrlwpHx+fPB3HMAxNmzZNQ4cOlZeXl7Zs2aIvvvhCs2fPzvUxwsPD7WYXLE5+++03HTp0SL1795ZhGBoxYoTCwsJsf4jBnYf3mKKLkSYAAJAn99xzjyZMmGC7jW/kyJF5DkzSlWd7/P399Y9//EOurq7y9/fX66+/XtDlFlnVq1fX3Llz9fHHH0u6MsJIYAKKJkaaAAAAAMABJoIAAAAAAAcITQAAAADgAKEJAAAAABwgNAEAShwe1wUAFCRCEwCgRPn2228VERHh7DIAACUIU44DAEqUJUuWOLsEAEAJw0gTAAAAADjA5zQBAEqM8PBw7dq1y/b1xx9/LB8fH82ZM0cxMTG6ePGi/Pz89PDDD2vMmDFyd3eXJKWkpGjatGnavHmz0tPT1aZNG9WvX19vvfWWDh486KzTAQAUEYQmAECJceTIEf3zn/+UJE2YMEHly5fXo48+qgYNGig8PFxubm764YcftHjxYo0ePVrPPfecJKl///6KjY3VSy+9pEqVKmnZsmXasWOHMjMzCU0AAJ5pAgCUHPfee6+8vLwkSQ0aNNBPP/2kOnXq6L333rMtb968ubZv366dO3fqueee044dO7Rz505FRUWpY8eOkqRWrVqpa9eu+uOPP5x2LgCAooPQBAAosVq0aKEWLVro8uXLOnLkiI4fP65Dhw7p/PnzKlu2rCQpOjparq6u6tChg20/s9msLl26KCoqykmVAwCKEkITAKDEslqtmjlzpj755BOlpqaqYsWKCg4OVqlSpWzbJCYmqmzZsjKb7edG8vf3L+xyAQBFFKEJAFBizZ8/X0uWLNGkSZPUsWNHlSlTRpLUq1cv2zYBAQFKTEyU1Wq1C07nzp0r9HoBAEUTU44DAEqUa4PPL7/8onvvvVdhYWG2wHTmzBkdOnRIVqtVkhQSEqKsrCxt3brVtp9hGNqyZUvhFg4AKLIYaQIAlCje3t7avXu3duzYoWrVqumnn37S/Pnz1aBBAx0/flwffPCBMjMzlZaWJklq0qSJHnzwQY0dO1Znz55VpUqV9Pnnn+vgwYMymUxOPhsAQFHAlOMAgBIlOjpar7zyiv773//q9ddf1759+7Rp0yZdvHhRFStW1COPPCKTyaQPPvhA27dvl7e3t5KTkzV16lRt2bJFWVlZat++vby9vbV27Vr9+uuvzj4lAICTEZoAAHe0+Ph47dmzR+3bt7d92K0kjRgxQn/++afWrFnjxOoAAEUBt+cBAO5oZrNZkZGRat++vXr16iWLxaIff/xRmzZt0ltvveXs8gAARQAjTQCAO150dLTmzp2r2NhYZWVlqUaNGhowYIC6du3q7NIAAEUAoQkAAAAAHGDKcQAAAABwgNAEAAAAAA4QmgAAAADAAUITAAAAADhAaAIAAAAABwhNAAAAAOAAoQkAAAAAHCA0AQAAAIADhCYAAAAAcOD/A9Es/zlA6gXfAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Few-shot with GPT 4\n", + "method = \"few_shot\"\n", + "model = \"gpt-4-0613\"\n", + "y_pred[method][model], performance[method][model] = evaluate(\n", + " test_df=test_df, model=model, system_content=system_content,\n", + " assistant_content=assistant_content, tags=tags)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "61521970", + "metadata": {}, + "source": [ + "As we can see, few shot learning performs better than it's respective zero shot counter part. GPT 4 has had considerable improvements in reducing hallucinations but for our supervised task this comes at an expense of high precision but lower recall and f1 scores. When GPT 4 is not confident, it would rather predict `other`." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "e04b53bf", + "metadata": {}, + "source": [ + "## OSS LLMs" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c6c72add", + "metadata": {}, + "source": [ + "So far, we've only been using closed-source models from OpenAI. While these are *currently* the gold-standard, there are many open-source models that are rapidly catching up ([Falcon 40B](https://huggingface.co/tiiuae/falcon-40b), [Llama 2](https://ai.meta.com/llama/), etc.). Before we see how these models perform on our task, let's first consider a few reasons why we should care about open-source models.\n", + "\n", + "- **data ownership**: you can serve your models and pass data to your models, without having to share it with a third-party API endpoint.\n", + "- **fine-tune**: with access to our model's weights, we can actually fine-tune them, as opposed to experimenting with fickle prompting strategies.\n", + "- **optimization**: we have full freedom to optimize our deployed models for inference (ex. quantization, pruning, etc.) to reduce costs." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "15ea136e", + "metadata": {}, + "outputs": [], + "source": [ + "# Coming soon in August!" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "3724d63b-58f8-4374-a89d-275a83c8190e", + "metadata": {}, + "source": [ + "## Results" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "ec0b498a-97c1-488c-a6b9-dc63a8a9df4d", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"zero_shot\": {\n", + " \"gpt-3.5-turbo-0613\": {\n", + " \"precision\": 0.7919133278407181,\n", + " \"recall\": 0.806282722513089,\n", + " \"f1\": 0.7807530967691199\n", + " },\n", + " \"gpt-4-0613\": {\n", + " \"precision\": 0.9314722577069027,\n", + " \"recall\": 0.9267015706806283,\n", + " \"f1\": 0.9271956481845013\n", + " }\n", + " },\n", + " \"few_shot\": {\n", + " \"gpt-3.5-turbo-0613\": {\n", + " \"precision\": 0.8435247936255214,\n", + " \"recall\": 0.8586387434554974,\n", + " \"f1\": 0.8447984162323493\n", + " },\n", + " \"gpt-4-0613\": {\n", + " \"precision\": 0.9407759040163695,\n", + " \"recall\": 0.9267015706806283,\n", + " \"f1\": 0.9302632275594479\n", + " }\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "print(json.dumps(performance, indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "4cc80311", + "metadata": {}, + "outputs": [], + "source": [ + "# Transform data into a new dictionary with four keys\n", + "by_model_and_context = {}\n", + "for context_type, models_data in performance.items():\n", + " for model, metrics in models_data.items():\n", + " key = f\"{model}_{context_type}\"\n", + " by_model_and_context[key] = metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "6771b1d2", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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NgAAwFMsp29Amn68p1myB2zALFavdLJarJq9b5kuhMS8jnpyy+kboN6V3pLVaiFgAwAAPIUcDkN2h129K72V5I9td9gT9Bl0wYIPYp3eqNEratQobYyDZSYCNtKcCyGXderGueQuAwAAAHBhGIZuh4QnyxWDHA5DhsFBnsRGwAYAAACAJGIYhux2gm5alXJHgwIAAAAAIBUhYAMAAAAAYAICNgAAAAAAJiBgAwAAAECi4LfWaUP8n0cCNgAAAACYyN3dXRaLFB4entylwATh4eGyWKKf10dhFHEAAAAAMJHNZpOfn59u3LgpSfL09JSU9JfmwpMyFB4ertu3bypTJj/ZbLZH3oOADQAAAAAmy549uyTp5s2bun07mYtBglksUqZMfs7n81EI2AAAAABgMovFohw5cihbtmyKjIxM7nKQQO7u7vE6cn0fARsAAAAAEonNZnusgIbUjUHOAAAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAE7gl9I4RERFat26dfvzxR129elXjx4/XgQMHVKJECZUuXdrMGgEAAAAASPESdAT7+vXratGihcaNG6czZ87o8OHDCgsL065du9SuXTsdOnTI7DoBAAAAAEjREhSwJ0+erLt372r79u3auHGjDMOQJM2ePVulSpXS7NmzTS0SAAAAAICULkEBe+fOnerTp4/y5s0ri8XinO7p6am33npLf/zxh2kFAgAAAACQGiQoYIeHh8vPzy/WeTabTZGRkU9SEwAAAAAAqU6CAnapUqX0ySefxDpvy5YtKlmyZLyX5XA4NHv2bFWtWlXPPfecOnfurHPnzsXZPjIy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AgAAAAAgtYn3EexSpUqpf//+mjRpkgzDUI8ePeIcLdxisejrr782rUgAAAAAAFK6eAfs6dOna/ny5bp586Y2btyo4sWLy9/fPzFrAwAAAAAg1Yh3wM6WLZsGDx4sSfrqq6/Ur18/BQYGJlphAAAAAACkJgm6DraXl5f++ecfs2sBAAAAACDVSlDAjoyMVKZMmUwpwOFwaPbs2apataqee+45de7cWefOnYvXfT///HMVLVpU58+fN6UWAAAAAAASKkEBu3379po5c6YOHTqk0NDQJypg/vz5+uSTTzRmzBitWbNGDodDnTp1UkRExEPvd+HCBY0ePfqJHhsAAAAAALPE+zfYD9q8ebMuXryo119/Pdb5FotFR48efeRyIiIitGzZMg0YMEDVq1eXJM2YMUNVq1bVjh071KhRo1jv53A4NHDgQJUoUUL79u1LyCoAAAAAAGCqBAXsV155xZQHP378uO7evavKlSs7p/n6+qp48eL66aef4gzYCxcuVGRkpHr27EnABgAAAACkCAkK2D179jTlwS9fvixJyp49u8v0rFmzOuf91+HDh7Vs2TKtW7dOV65cMaUOSXJzS9DZ8qaz2VJGHUg8PMePj22W9vEcPz62WdrHc/z42GZpH88xUroEBez7vvvuO/3444+6evWq+vXrp2PHjqlEiRLKmTNnvO5///fbHh4eLtM9PT1169atGO3v3bunAQMGaMCAAcqXL59pAdtqtShTpnSmLAt4FF9f7+QuAUhx6BdATPQLICb6BVK6BAXs0NBQ9ejRQz/++KPSp0+vu3fv6u2339bq1at19OhRrVq1SoULF37kcry8vCRF/xb7/t+SFB4eLm/vmJ1n7Nixyp8/v9q0aZOQsuPkcBgKCbln6jITymaz8saRxoWEhMpudyR3GakK/SLto188PvpF2ke/eHz0i7QvpfQLX19vjqYjVgkK2NOnT9cff/yh5cuXq1y5cipZsqQkadKkSerUqZNmzZqluXPnPnI5908NDw4OVp48eZzTg4ODVbRo0Rjt169fLw8PD5UpU0aSZLfbJUmNGjVSt27d1K1bt4SsjiQpKir5OyqeDna7g9cb8B/0CyAm+gUQE/0CKV2CAnZQUJDeffddVapUyRlypejfTr/zzjvxvnxWYGCg0qdPr/379zsDdkhIiI4ePaq2bdvGaL9jxw6X27/99psGDhyoxYsXq0iRIglZFQAAAAAATJGggB0SEhLn76wzZsyoe/fid7q1h4eH2rZtq6lTp8rf3185c+bUlClTFBAQoDp16shut+v69evKkCGDvLy8lDdvXpf73x8ILUeOHPLz80vIqgAAAAAAYIoE/XCgcOHC2rJlS6zzvv3223j9/vq+3r17q2XLlho2bJhee+012Ww2LV26VO7u7rp06ZKqVKmi7du3J6RMAAAAAACSTIKOYL/zzjvq2bOnbt68qRo1ashiseinn37Shg0btGbNGk2bNi3ey7LZbBo4cKAGDhwYY16uXLn0559/xnnfihUrPnQ+AAAAAABJJUEBu1atWpoyZYqmTZum7777TpI0ceJEZc6cWSNHjlS9evVMLRIAAAAAgJTusQP24cOHdeHCBRUoUEC7du3SP//8o5s3b8rX11cFChSQ1cpw9QAAAACAp0+8A3ZISIi6du2qX3/9VYZhyGKxqEyZMpo2bZoKFCiQmDUCAAAAAJDixftw88yZM3X06FH16tVLixcv1uDBg/XPP/9o+PDhiVkfAAAAAACpQryPYO/cuVPvvvuu3nzzTUlStWrVlC1bNg0YMED37t2Tj49PohUJAAAAAEBKF+8j2FevXlWJEiVcplWsWFF2u12XLl0yvTAAAAAAAFKTeAfsqKgoeXh4uEzLmDGjJCk8PNzcqgAAAAAASGVMGfLbMAwzFgMAAAAAQKplSsC2WCxmLAYAAAAAgFTrsa6DPXLkSKVPn955+/6R6//7v/9TunTpnNMtFos++ugjk0oEAAAAACDli3fALl++vKSYp4PHNp1TxgEAAAAAT5t4B+yVK1cmZh0AAAAAAKRqpvwGGwAAAACApx0BGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAAMAEBGwAAAAAAExCwAQAAAAAwAQEbAAAAAAATELABAAAAADABARsAAAAAABMQsAEAAAAA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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Extracting the model names and the metric values\n", + "models = list(by_model_and_context.keys())\n", + "metrics = list(by_model_and_context[models[0]].keys())\n", + "\n", + "# Plotting the bar chart with metric scores on top of each bar\n", + "fig, ax = plt.subplots(figsize=(10, 4))\n", + "width = 0.2\n", + "x = range(len(models))\n", + "\n", + "for i, metric in enumerate(metrics):\n", + " metric_values = [by_model_and_context[model][metric] for model in models]\n", + " ax.bar([pos + width * i for pos in x], metric_values, width, label=metric)\n", + " # Displaying the metric scores on top of each bar\n", + " for pos, val in zip(x, metric_values):\n", + " ax.text(pos + width * i, val, f'{val:.3f}', ha='center', va='bottom', fontsize=9)\n", + "\n", + "ax.set_xticks([pos + width for pos in x])\n", + "ax.set_xticklabels(models, rotation=0, ha='center', fontsize=8)\n", + "ax.set_ylabel('Performance')\n", + "ax.set_title('GPT Benchmarks')\n", + "ax.legend(loc='upper left', bbox_to_anchor=(1, 1))\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "eeb8c5ba-c22f-4fae-b63c-d13f8c23ade7", + "metadata": { + "tags": [] + }, + "source": [ + "Our best model is GPT 4 with few shot learning at an f1 score of ~92%. We will see in the [Made With ML course](https://madewithml.com/) how fine-tuning an LLM with a proper training dataset to change the actual weights of the last N layers (as opposed to the hard prompt tuning here) will yield similar/slightly better results to GPT 4 (at a fraction of the model size and inference costs).\n", + "\n", + "However, the best system might actually be a combination of using these few-shot hard prompt LLMs alongside fine-tuned LLMs. For example, our fine-tuned LLMs in the course will perform well when the test data is similar to the training data (similar distributions of vocabulary, etc.) but may not perform well on out of distribution. Whereas, these hard prompted LLMs, by themselves or augmented with additional context (ex. arXiv plugins in our case), could be used when our primary fine-tuned model is not so confident." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/madewithml.ipynb b/notebooks/madewithml.ipynb new file mode 100644 index 0000000..b0f4089 --- /dev/null +++ b/notebooks/madewithml.ipynb @@ -0,0 +1,48862 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "acbetMKBt825" + }, + "source": [ + "
\n", + "

 Made With ML

\n", + "

ML for Developers

\n", + " Design · Develop · Deploy · Iterate\n", + "
\n", + "\n", + "
\n", + "\n", + "
\n", + "  \n", + "  \n", + "  \n", + " \n", + "
\n", + " 🔥  Among the top ML repositories on GitHub\n", + "
\n", + "\n", + "
\n", + "
" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "oh-HuNfDrPg0" + }, + "source": [ + "This notebooks contains the code for the 🔢  Data and 📈  Modeling lessons. After this proof of concept (PoC), we'll be moving all of this code to Python scripts to serve our application to production. Follow the accompanying [lessons](https://madewithml.com/) along with the code here to develop a deeper understanding of all the concepts." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "XTNsIiUrqoJW" + }, + "source": [ + "
\n", + " \n", + " \n", + "\"Open\n", + "
" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "# 🛠️  Setup" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We'll be using [Ray](https://ray.io) to develop our application using distributed workloads." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import ray" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Snapshotting files: 100%|██████████| 4/4 [00:00<00:00, 578.90file/s]\n", + "2023-07-24 18:09:33,959\tINFO worker.py:1431 -- Connecting to existing Ray cluster at address: 10.0.56.150:6379...\n", + "2023-07-24 18:09:34,005\tINFO worker.py:1612 -- Connected to Ray cluster. View the dashboard at \u001b[1m\u001b[32mhttps://session-cqhhlg21by7asj3ryvctbha9ek.i.anyscaleuserdata.com \u001b[39m\u001b[22m\n", + "2023-07-24 18:09:34,010\tINFO packaging.py:346 -- Pushing file package 'gcs://_ray_pkg_6914fbe58df99e42f77368975fb6b629.zip' (1.24MiB) to Ray cluster...\n", + "2023-07-24 18:09:34,014\tINFO packaging.py:359 -- Successfully pushed file package 'gcs://_ray_pkg_6914fbe58df99e42f77368975fb6b629.zip'.\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "58d1ddc62cd74bf19166797b77a5da12", + "version_major": 2, + "version_minor": 0 + }, + "text/html": [ + "
\n", + "
\n", + "
\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n", + "\n", + "
Python version:3.10.8
Ray version:2.6.0
Dashboard:http://session-cqhhlg21by7asj3ryvctbha9ek.i.anyscaleuserdata.com
\n", + "\n", + "
\n", + "
\n" + ], + "text/plain": [ + "RayContext(dashboard_url='session-cqhhlg21by7asj3ryvctbha9ek.i.anyscaleuserdata.com', python_version='3.10.8', ray_version='2.6.0', ray_commit='0db82e31e249eac614f7c8e7da1c4f8f05c9064a', protocol_version=None)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Initialize Ray\n", + "if ray.is_initialized():\n", + " ray.shutdown()\n", + "ray.init()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'CPU': 8.0,\n", + " 'object_store_memory': 9492578304.0,\n", + " 'memory': 34359738368.0,\n", + " 'node:__internal_head__': 1.0,\n", + " 'node:10.0.56.150': 1.0}" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ray.cluster_resources()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "These cluster resources only reflect our head node ([m5.2xlarge](https://instances.vantage.sh/aws/ec2/m5.2xlarge)). But recall in our [setup lesson](https://madewithml.com/courses/mlops/setup/) that our [compute configuration](https://madewithml.com/courses/mlops/setup/#compute) that we also added [g4dn.xlarge](https://instances.vantage.sh/aws/ec2/g4dn.xlarge) worker nodes (each has 1 GPU and 4 CPU) to our cluster. But because we set `min_workers=0`, our worker nodes will autoscale ( up to `max_workers`) as they're needed for specific workloads (ex. training). " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Workers (1 g4dn.xlarge)\n", + "num_workers = 1\n", + "resources_per_worker={\"CPU\": 3, \"GPU\": 1}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are running this on a local laptop (no GPU), use the CPU count from `ray.cluster_resources()` to set your resources. For example if your machine has 10 CPUs:\n", + "\n", + "```python\n", + "num_workers = 6 # prefer to do a few less than total available CPU (1 for head node + 1 for background tasks)\n", + "resources_per_worker={\"CPU\": 1, \"GPU\": 0}\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## 🔢  Data ingestion" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idcreated_ontitledescriptiontag
062020-02-20 06:43:18Comparison between YOLO and RCNN on real world...Bringing theory to experiment is cool. We can ...computer-vision
172020-02-20 06:47:21Show, Infer & Tell: Contextual Inference for C...The beauty of the work lies in the way it arch...computer-vision
292020-02-24 16:24:45Awesome Graph ClassificationA collection of important graph embedding, cla...other
3152020-02-28 23:55:26Awesome Monte Carlo Tree SearchA curated list of Monte Carlo tree search pape...other
4252020-03-07 23:04:31AttentionWalkA PyTorch Implementation of \"Watch Your Step: ...other
\n", + "
" + ], + "text/plain": [ + " id created_on title \n", + "0 6 2020-02-20 06:43:18 Comparison between YOLO and RCNN on real world... \\\n", + "1 7 2020-02-20 06:47:21 Show, Infer & Tell: Contextual Inference for C... \n", + "2 9 2020-02-24 16:24:45 Awesome Graph Classification \n", + "3 15 2020-02-28 23:55:26 Awesome Monte Carlo Tree Search \n", + "4 25 2020-03-07 23:04:31 AttentionWalk \n", + "\n", + " description tag \n", + "0 Bringing theory to experiment is cool. We can ... computer-vision \n", + "1 The beauty of the work lies in the way it arch... computer-vision \n", + "2 A collection of important graph embedding, cla... other \n", + "3 A curated list of Monte Carlo tree search pape... other \n", + "4 A PyTorch Implementation of \"Watch Your Step: ... other " + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Data ingestion\n", + "DATASET_LOC = \"https://raw.githubusercontent.com/GokuMohandas/Made-With-ML/main/datasets/dataset.csv\"\n", + "df = pd.read_csv(DATASET_LOC)\n", + "df.head()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## ✂️  Data splitting" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tag\n", + "natural-language-processing 310\n", + "computer-vision 285\n", + "other 106\n", + "mlops 63\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Value counts\n", + "df.tag.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Split dataset\n", + "test_size = 0.2\n", + "train_df, val_df = train_test_split(df, stratify=df.tag, test_size=test_size, random_state=1234)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tag\n", + "natural-language-processing 248\n", + "computer-vision 228\n", + "other 85\n", + "mlops 50\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Train value counts\n", + "train_df.tag.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "tag\n", + "natural-language-processing 248\n", + "computer-vision 228\n", + "other 84\n", + "mlops 52\n", + "Name: count, dtype: int64" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Validation (adjusted) value counts\n", + "val_df.tag.value_counts() * int((1-test_size) / test_size)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "WuCrsbxbNkSV" + }, + "source": [ + "## 🔍  Exploratory Data Analysis (EDA)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "eOJ3nlEgnSTJ" + }, + "source": [ + "Exploratory data analysis to understand the signals and nuances of our dataset. It's a cyclical process that can be done at various points of our development process (before/after labeling, preprocessing, etc.) depending on how well the problem is defined." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "id": "tHdQmqTBNkSV", + "tags": [] + }, + "outputs": [], + "source": [ + "from collections import Counter\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns; sns.set_theme()\n", + "import warnings; warnings.filterwarnings(\"ignore\")\n", + "from wordcloud import WordCloud, STOPWORDS" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[('natural-language-processing', 310),\n", + " ('computer-vision', 285),\n", + " ('other', 106),\n", + " ('mlops', 63)]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Most common tags\n", + "all_tags = Counter(df.tag)\n", + "all_tags.most_common()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Gl-E8d2HaCsx", + "outputId": "22afb969-0335-42ec-b58b-c36ca1db8bf8", + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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zJkaBUVERERERFRTaJR0lYRcLodYrLXmiYiIiIiIqgWtZUXXrl2DiYmJtponIiIiIiKqFko8kcaIESNUlvfu3YuEhAS1egqFAg8fPkRKSgp8fX3LHiEREREREVE1VuKk6+UESyQSISUlBSkpKWr1xGIxTExM0Lt3b8yaNat8oiQiIiIiIqqmSpx0vTxbYatWrTB+/HiMHz9eK0ERERERERHVFBo9p2vTpk1o2rRpecdCRERERERU42g0kYarqytMTEygUCiKXC+Xy5GZmQm5XF6m4IiIiIiIiKo7jZKukJAQeHh4IC0trcj16enp6NSpE9asWVOW2IiIiIiIiKo9jZKuEydOwMPDA+bm5kWuNzc3R6dOnXDs2LEyBUdERERERFTdaZR03b17F7a2tq+tY2Njg3v37mkUFBERERERUU2hUdJVUFAAkUj0xnq5ubmaNE9ERERERFRjaJR0WVtbIz4+/rV14uPjYWVlpVFQRERERERENYVGSVfPnj1x7do1rFixQm2GQrlcjuXLl+PatWvo3bt3uQRJRERERERUXWn0nK5PPvkEBw4cwM8//4zIyEi4u7ujYcOGePToEeLj43Hnzh20aNECn376aXnHS0REREREVK1olHQZGhpi69atmDdvHg4fPozk5GTlOrFYjF69euHrr7+GoaFhuQVKRERERERUHWmUdAEvpoUPDg7Gf//9h8uXLyMjIwMSiQRt27ZF/fr1yzNGIiIiIiKiakvjpKtQgwYN8M4775RDKERERERERDWPRhNpFMrLy8PJkycRHh6OVatWKctzc3Px5MkTKBSKUrd58OBBfPbZZ/D29oazszP69euH3bt3QxAElXq7du1Cr1694ODggPfeew/Hjx9XaysjIwOzZs2Cm5sbXFxcMHHiRDx69Kj0B0pERERERKQhjZOuo0ePomvXrggMDMTixYsREhKiXPfPP//Ay8sLBw4cKHW7GzduRN26dREUFIQ1a9bA29sbc+bMUUnqDhw4gDlz5sDX1xehoaFwdnbG+PHjcf78eZW2Jk+ejNjYWMybNw8//vgjkpKSMHr0aBQUFGh62ERERERERKWiUffCs2fPYtKkSbCwsMBXX32F8+fPqyRYjo6OsLa2RnR0NN59991Stb1mzRqYm5srlz08PJCWlobw8HCMGzcOYrEYwcHB6NOnDyZPngwA6NixI27c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TLqIiIiIiIi0iEkXERERERGRFjHpIiIiIiIi0iImXURERERERFrEpIuIiIiIiEiLmHQRERERERFpEZMuIiIiIiIiLWLSRUREREREpEVMuoiIiIiIiLSISRcREREREZEWMekiIiIiIiLSIiZdREREREREWsSki4iIiIiISIuYdBEREREREWkRky4iIiIiIiItqvFJ17///otPPvkEzs7O8PT0xJIlS5CXl1fZYRERERERUS2hW9kBaFN6ejo++ugjNG/eHCtXrkRqaiq+//575OTkYO7cuZUdHhERERER1QI1Ounavn07nj9/jpCQEJiamgIA5HI55s+fj7Fjx8LS0rJyAyQiIiIiohqvRncvjImJgYeHhzLhAgBfX18oFArExsZWXmBERERERFRr1OikKzExEba2tiplEokEFhYWSExMrKSoiIiIiIioNqnR3QtlMhkkEolauYmJCdLT0zVuVywWwdzcsCyhAQBEohf/nzHSB3K5osztERVHR+fF7ysmJnUhCJUczCsKr4O3B06GoJBXbjBUo4nEOgCq9nUwtUcgCngdkBbpVtHroPAa6DB9CoQCXgOkPSLd8r0GxGJRierV6KRLW0QiEXR0SvYCl4SJUZ1ya4vodcTiqntzW89Q/QcSIm2oyteBpK5xZYdAtURVvQ4MivixnEgbKvoaqJpXXDmRSCTIyMhQK09PT4eJiUklRERERERERLVNjU66bG1t1cZuZWRk4PHjx2pjvYiIiIiIiLShRidd3t7e+OuvvyCTyZRlhw4dglgshqenZyVGRkREREREtYVIEKrSMMrylZ6ejj59+sDGxgZjx45VPhz53Xff5cORiYiIiIioQtTopAsA/v33X3z77bc4d+4cDA0N0a9fP3zxxRfQ19ev7NCIiIiIiKgWqPFJFxERERERUWWq0WO6iIiIiIiIKhuTLiIiIiIiIi1i0kVERERERKRFTLqIiIiIiIi0iEkXERERERGRFjHpIiIiIiIi0iImXURERERERFrEpKuaCggIQEBAwBvrxcfHQyqVIj4+vgKiopqM5xIBgFQqxcqVK0u1TVBQEHx8fLQUEdUmPj4+GDt2bGWHQVRh7t27B6lUij179lR2KFRGTLpKaevWrTzxiUjrfv75Zxw5cqSywyCqcLdu3cLKlStx7969yg6FiKjc6FZ2ANXNtm3bYGZmhgEDBlR2KEQVqkOHDrh48SL09PQqO5RaYe3atejVqxe6d+9e2aGouHjxInR0dEq1zbfffgtBELQUEdU0t27dQkhICNzc3GBlZVXZ4RARlQve6aoCBEFATk5OZYdBWlQT3mOxWAwDAwOIxfzYqK5yc3OhUCjK1IaBgQF0dUv3e52enh709fXLtF+iilJQUIC8vLzKDoOIapga/+1p5cqVkEqlSE5ORlBQENq3bw9XV1fMnDkT2dnZynoREREYMWIEPDw80LZtW/j5+eHXX39VacvHxwc3b95EQkICpFIppFKpclxV4X5etWfPHkilUpVuEoV90v/8808MGDAAjo6O2L59e4njKKszZ85g4sSJeOedd9C2bVt06dIFCxcuVEsKgoKC4OLigtTUVIwbNw4uLi7o2LEjFi9eDLlcrlL32bNnmD59Otq1a4f27dtjxowZuH79ulo/5OLGohU15iMsLAxDhgyBu7s7HB0dMWDAABw6dEht25ycHHz33Xdwd3eHi4sLAgMDkZqaWuTYk9TUVMycOROdOnVC27Zt0adPH+zevbtEr1vhe3n69GnMnTsX7u7uaNeuHb788kukp6er1H3de3z37l1MnDgRbm5ucHJywuDBg3HixAm1/eXm5mLlypXo1asXHBwc4OXlhfHjx+POnTvKOgqFAhs3bkSfPn3g4OCATp06Ye7cuWrxXLp0CSNHjlS+lj4+Ppg5c6ZKnQMHDmDAgAFwcXFBu3bt8O677+KXX35Rri9qTFdAQAD69u2LW7duISAgAE5OTujcuTNCQ0PVjiclJQWBgYFwdnaGh4cHFi5ciD///LNM48RSU1Mxa9YseHl5oW3btvDx8cHXX3+t/MJUkte68LgiIyMREhKCzp07w8XFBRMnTkRGRgby8vKwYMECeHh4wMXFBTNnzlT7QiaVSvHNN9/g999/V75fAwYMwOnTp1XqFTe26dXPD6lUiqysLOzdu1f5WRMUFKRy3G86jwuP68CBA1i2bBk6d+4MJycnZGZmqu2/b9++RV6XCoUCnTt3xsSJE1Vie/m6yszMxIIFC+Dj44O2bdvCw8MDn3zyCa5cufLa487KysL333+PLl26oG3btujVqxfCwsLU7ogVvrZHjhxB3759lccbExOjFi9VD1evXsWoUaPQrl07uLi44KOPPsL58+cBvPicnTRpEgBgxIgRyvP/1c+IM2fO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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot tag frequencies\n", + "tags, tag_counts = zip(*all_tags.most_common())\n", + "plt.figure(figsize=(10, 3))\n", + "ax = sns.barplot(x=list(tags), y=list(tag_counts))\n", + "ax.set_xticklabels(tags, rotation=0, fontsize=12)\n", + "plt.title(\"Tag distribution\", fontsize=16)\n", + "plt.ylabel(\"# of projects\", fontsize=14)\n", + "plt.show()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "pfjVstecaFC5" + }, + "source": [ + "> We'll address the [data imbalance](https://madewithml.com/courses/mlops/baselines#data-imbalance) after splitting into our train split and prior to training our model." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 335, + "referenced_widgets": [ + "af9c5bab12c64dc396c28154ea13f516", + "7d1b4a63fa924fa6b136204ce1e67a42", + "795b443fc1834645937b199e1214fcc3", + "ccc7456ad5484dd2b7ccdd62bbc27d0c", + "53f5b6e055864bb19eadba0aa640668d", + "8a9678ac8f3e4af49c02181ce0eb6241", + "8c6ffc9537344c709b47a5acea0e3075" + ] + }, + "id": "NgMGuIQrNkSV", + "outputId": "0e58055f-0482-4ae0-f6cf-e2a8c2a8552c", + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Most frequent tokens for each tag\n", + "tag=\"natural-language-processing\"\n", + "plt.figure(figsize=(10, 3))\n", + "subset = df[df.tag==tag]\n", + "text = subset.title.values\n", + "cloud = WordCloud(\n", + " stopwords=STOPWORDS, background_color=\"black\", collocations=False,\n", + " width=500, height=300).generate(\" \".join(text))\n", + "plt.axis(\"off\")\n", + "plt.imshow(cloud)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "b8ua3MFhrOaX" + }, + "source": [ + "Looks like the `title` text feature has some good signal for the respective classes and matches our intuition. We can repeat this for the `description` text feature as well. This information will become useful when we decide how to use our features for modeling." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "HFifXKl_eKsN" + }, + "source": [ + "## ✨  Data Preprocessing" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "RxAZ1AmteRaD" + }, + "source": [ + "Preprocessing the data via feature engineering, filtering and cleaning. Certain preprocessing steps are global (don't depend on our dataset, ex. lower casing text, removing stop words, etc.) and others are local (constructs are learned only from the training split, ex. vocabulary, standardization, etc.). For the local, dataset-dependent preprocessing steps, we want to ensure that we [split](https://madewithml.com/courses/mlops/splitting) the data first before preprocessing to avoid data leaks." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import json\n", + "import nltk\n", + "from nltk.corpus import stopwords\n", + "from nltk.stem import PorterStemmer\n", + "import re" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "6VgTwEQboTGc" + }, + "source": [ + "### Feature engineering" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "U_001GPyMZsC" + }, + "source": [ + "We can combine existing input features to create new meaningful signal (helping the model learn). " + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "id": "3x1ldAFQNkSU", + "tags": [] + }, + "outputs": [], + "source": [ + "# Feature engineering\n", + "df[\"text\"] = df.title + \" \" + df.description" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Clean text" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "VDXLH6QeLd0F", + "outputId": "2202b045-1830-477a-94ad-85e648946319", + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[nltk_data] Downloading package stopwords to /home/ray/nltk_data...\n", + "[nltk_data] Package stopwords is already up-to-date!\n" + ] + } + ], + "source": [ + "nltk.download(\"stopwords\")\n", + "STOPWORDS = stopwords.words(\"english\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "id": "VfdWkkV8LlNR", + "tags": [] + }, + "outputs": [], + "source": [ + "def clean_text(text, stopwords=STOPWORDS):\n", + " \"\"\"Clean raw text string.\"\"\"\n", + " # Lower\n", + " text = text.lower()\n", + "\n", + " # Remove stopwords\n", + " pattern = re.compile(r'\\b(' + r\"|\".join(stopwords) + r\")\\b\\s*\")\n", + " text = pattern.sub('', text)\n", + "\n", + " # Spacing and filters\n", + " text = re.sub(r\"([!\\\"'#$%&()*\\+,-./:;<=>?@\\\\\\[\\]^_`{|}~])\", r\" \\1 \", text) # add spacing\n", + " text = re.sub(\"[^A-Za-z0-9]+\", \" \", text) # remove non alphanumeric chars\n", + " text = re.sub(\" +\", \" \", text) # remove multiple spaces\n", + " text = text.strip() # strip white space at the ends\n", + " text = re.sub(r\"http\\S+\", \"\", text) # remove links\n", + " \n", + " return text" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "3LRaq0_5LpE4", + "outputId": "4f7beaa6-6713-4e02-80a2-22474260f406", + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Comparison between YOLO and RCNN on real world videos Bringing theory to experiment is cool. We can easily train models in colab and find the results in minutes.\n", + "comparison yolo rcnn real world videos bringing theory experiment cool easily train models colab find results minutes\n" + ] + } + ], + "source": [ + "# Apply to dataframe\n", + "original_df = df.copy()\n", + "df.text = df.text.apply(clean_text)\n", + "print (f\"{original_df.text.values[0]}\\n{df.text.values[0]}\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Clean DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
texttag
0comparison yolo rcnn real world videos bringin...computer-vision
1show infer tell contextual inference creative ...computer-vision
2awesome graph classification collection import...other
3awesome monte carlo tree search curated list m...other
4attentionwalk pytorch implementation watch ste...other
\n", + "
" + ], + "text/plain": [ + " text tag\n", + "0 comparison yolo rcnn real world videos bringin... computer-vision\n", + "1 show infer tell contextual inference creative ... computer-vision\n", + "2 awesome graph classification collection import... other\n", + "3 awesome monte carlo tree search curated list m... other\n", + "4 attentionwalk pytorch implementation watch ste... other" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# DataFrame cleanup\n", + "df = df.drop(columns=[\"id\", \"created_on\", \"title\", \"description\"], errors=\"ignore\") # drop cols\n", + "df = df.dropna(subset=[\"tag\"]) # drop nulls\n", + "df = df[[\"text\", \"tag\"]] # rearrange cols\n", + "df.head()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Label encoding" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We need to encode our data into numerical values so that our models can process them. We'll start by encoding our text labels into unique indices." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'mlops': 0,\n", + " 'natural-language-processing': 1,\n", + " 'computer-vision': 2,\n", + " 'other': 3}" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Label to index\n", + "tags = train_df.tag.unique().tolist()\n", + "num_classes = len(tags)\n", + "class_to_index = {tag: i for i, tag in enumerate(tags)}\n", + "class_to_index" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
texttag
0comparison yolo rcnn real world videos bringin...2
1show infer tell contextual inference creative ...2
2awesome graph classification collection import...3
3awesome monte carlo tree search curated list m...3
4attentionwalk pytorch implementation watch ste...3
\n", + "
" + ], + "text/plain": [ + " text tag\n", + "0 comparison yolo rcnn real world videos bringin... 2\n", + "1 show infer tell contextual inference creative ... 2\n", + "2 awesome graph classification collection import... 3\n", + "3 awesome monte carlo tree search curated list m... 3\n", + "4 attentionwalk pytorch implementation watch ste... 3" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Encode labels\n", + "df[\"tag\"] = df[\"tag\"].map(class_to_index)\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def decode(indices, index_to_class):\n", + " return [index_to_class[index] for index in indices]" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['computer-vision', 'computer-vision', 'other', 'other', 'other']" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "index_to_class = {v:k for k, v in class_to_index.items()}\n", + "decode(df.head()[\"tag\"].values, index_to_class=index_to_class)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Tokenizer" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next we'll encode our text as well. Instead of using a random dictionary, we'll use a [tokenizer](https://huggingface.co/allenai/scibert_scivocab_uncased/blob/main/vocab.txt) that was used for a pretrained LLM ([scibert](https://huggingface.co/allenai/scibert_scivocab_uncased)) to tokenize our text. We'll be fine-tuning this exact model later when we train our model." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import numpy as np\n", + "from transformers import BertTokenizer" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "input_ids: [[ 102 2268 1904 190 29155 168 3267 2998 205 103]]\n", + "attention_mask: [[1 1 1 1 1 1 1 1 1 1]]\n", + "[CLS] transfer learning with transformers for text classification. [SEP]\n" + ] + } + ], + "source": [ + "# Bert tokenizer\n", + "tokenizer = BertTokenizer.from_pretrained(\"allenai/scibert_scivocab_uncased\", return_dict=False)\n", + "text = \"Transfer learning with transformers for text classification.\"\n", + "encoded_inputs = tokenizer([text], return_tensors=\"np\", padding=\"longest\") # pad to longest item in batch\n", + "print (\"input_ids:\", encoded_inputs[\"input_ids\"])\n", + "print (\"attention_mask:\", encoded_inputs[\"attention_mask\"])\n", + "print (tokenizer.decode(encoded_inputs[\"input_ids\"][0]))" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def tokenize(batch):\n", + " tokenizer = BertTokenizer.from_pretrained(\"allenai/scibert_scivocab_uncased\", return_dict=False)\n", + " encoded_inputs = tokenizer(batch[\"text\"].tolist(), return_tensors=\"np\", padding=\"longest\")\n", + " return dict(ids=encoded_inputs[\"input_ids\"], masks=encoded_inputs[\"attention_mask\"], targets=np.array(batch[\"tag\"]))" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'ids': array([[ 102, 2029, 1778, 609, 6446, 4857, 1332, 2399, 13572,\n", + " 19125, 1983, 1954, 6240, 3717, 7434, 1262, 537, 201,\n", + " 1040, 545, 4714, 103]]),\n", + " 'masks': array([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]),\n", + " 'targets': array([2])}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Tokenization\n", + "tokenize(df.head(1))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We'll combine all of our preprocessing steps into function:" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def preprocess(df, class_to_index):\n", + " \"\"\"Preprocess the data.\"\"\"\n", + " df[\"text\"] = df.title + \" \" + df.description # feature engineering\n", + " df[\"text\"] = df.text.apply(clean_text) # clean text\n", + " df = df.drop(columns=[\"id\", \"created_on\", \"title\", \"description\"], errors=\"ignore\") # clean dataframe\n", + " df = df[[\"text\", \"tag\"]] # rearrange columns\n", + " df[\"tag\"] = df[\"tag\"].map(class_to_index) # label encoding\n", + " outputs = tokenize(df)\n", + " return outputs" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'ids': array([[ 102, 856, 532, ..., 0, 0, 0],\n", + " [ 102, 2177, 29155, ..., 0, 0, 0],\n", + " [ 102, 2180, 3241, ..., 0, 0, 0],\n", + " ...,\n", + " [ 102, 453, 2068, ..., 5730, 432, 103],\n", + " [ 102, 11268, 1782, ..., 0, 0, 0],\n", + " [ 102, 1596, 122, ..., 0, 0, 0]]),\n", + " 'masks': array([[1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " ...,\n", + " [1, 1, 1, ..., 1, 1, 1],\n", + " [1, 1, 1, ..., 0, 0, 0],\n", + " [1, 1, 1, ..., 0, 0, 0]]),\n", + " 'targets': array([0, 1, 1, 1, 1, 2, 1, 2, 3, 1, 2, 2, 1, 1, 2, 2, 2, 2, 1, 2, 0, 1,\n", + " 1, 1, 1, 1, 2, 1, 2, 0, 3, 2, 0, 1, 1, 1, 1, 2, 1, 1, 0, 2, 3, 3,\n", + " 3, 0, 2, 1, 3, 3, 1, 1, 1, 1, 2, 1, 2, 2, 2, 3, 2, 1, 1, 3, 1, 0,\n", + " 1, 2, 2, 2, 3, 2, 3, 2, 3, 2, 1, 1, 3, 3, 3, 1, 1, 2, 3, 0, 1, 1,\n", + " 1, 1, 3, 3, 0, 2, 3, 2, 2, 1, 1, 3, 2, 3, 1, 1, 1, 1, 2, 0, 0, 2,\n", + " 1, 1, 2, 2, 1, 1, 0, 3, 1, 2, 2, 1, 0, 2, 3, 1, 3, 1, 2, 3, 1, 1,\n", + " 3, 3, 2, 1, 1, 0, 1, 3, 1, 1, 2, 2, 0, 0, 2, 1, 1, 1, 2, 3, 2, 1,\n", + " 1, 2, 0, 1, 1, 3, 2, 1, 1, 2, 1, 2, 3, 1, 2, 2, 1, 2, 1, 2, 1, 3,\n", + " 2, 2, 0, 1, 2, 2, 1, 2, 2, 1, 3, 2, 2, 1, 2, 2, 3, 2, 1, 1, 1, 1,\n", + " 2, 2, 2, 0, 2, 1, 0, 2, 1, 3, 1, 1, 1, 1, 2, 1, 3, 3, 2, 1, 0, 1,\n", + " 2, 0, 2, 2, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2,\n", + " 0, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 1, 2, 3, 2, 1, 0, 2, 1, 2, 2, 1,\n", + " 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 2, 3, 2, 1, 2, 0, 2, 2, 1, 2, 3,\n", + " 2, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 3, 2, 1, 2, 2, 2, 1, 2, 2, 2,\n", + " 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 1, 1, 2, 1, 2, 2, 1, 3, 3, 0, 1, 3,\n", + " 0, 2, 1, 1, 1, 1, 1, 0, 2, 1, 3, 2, 1, 2, 2, 1, 1, 3, 0, 3, 3, 2,\n", + " 1, 1, 3, 3, 2, 3, 1, 1, 3, 1, 0, 1, 1, 1, 3, 0, 2, 2, 2, 1, 1, 2,\n", + " 2, 1, 3, 2, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 2, 0, 3, 0, 1, 2, 1,\n", + " 3, 2, 3, 2, 2, 0, 2, 3, 2, 2, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1,\n", + " 2, 2, 1, 2, 1, 1, 2, 2, 3, 1, 2, 2, 3, 2, 1, 1, 2, 0, 2, 0, 1, 1,\n", + " 2, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 2, 1, 0, 3, 1, 3, 2, 2, 1, 1, 3,\n", + " 2, 1, 2, 1, 3, 1, 2, 2, 1, 2, 2, 2, 1, 0, 3, 2, 1, 3, 1, 1, 2, 1,\n", + " 2, 2, 0, 1, 2, 1, 2, 2, 3, 1, 1, 2, 2, 1, 2, 2, 0, 0, 1, 2, 1, 1,\n", + " 2, 1, 1, 2, 1, 1, 3, 2, 3, 1, 2, 2, 3, 0, 1, 1, 2, 1, 2, 1, 1, 1,\n", + " 1, 1, 2, 1, 3, 1, 0, 2, 1, 3, 1, 2, 2, 1, 0, 2, 3, 2, 3, 2, 1, 1,\n", + " 1, 2, 1, 2, 1, 2, 1, 3, 2, 2, 2, 2, 2, 1, 2, 0, 1, 0, 1, 2, 2, 1,\n", + " 2, 3, 2, 1, 2, 2, 2, 3, 1, 3, 2, 1, 2, 2, 2, 1, 3, 1, 1, 2, 2, 1,\n", + " 2, 3, 2, 2, 0, 1, 2, 2, 2, 0, 1, 2, 1, 3, 0, 2, 3])}" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Apply\n", + "preprocess(df=train_df, class_to_index=class_to_index)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Distributed preprocessing" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The main issue with our approach above is that we're limited by our single machine in terms how much data our dataframe can hold and that we can preprocess. With the increasing trend in ML for larger unstructured datasets and larger models (LLMs), we can quickly outgrow our single machine constraints and will need to go distributed." + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append(\"..\")\n", + "from madewithml.data import stratify_split\n", + "ray.data.DatasetContext.get_current().execution_options.preserve_order = True" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:09:40,715\tINFO read_api.py:374 -- To satisfy the requested parallelism of 16, each read task output will be split into 16 smaller blocks.\n", + "2023-07-24 18:09:40,719\tINFO dataset.py:2180 -- Tip: Use `take_batch()` instead of `take() / show()` to return records in pandas or numpy batch format.\n", + "2023-07-24 18:09:40,720\tINFO streaming_executor.py:92 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle]\n", + "2023-07-24 18:09:40,721\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:40,722\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:09:41,438\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:41,439\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:09:45,960\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:45,961\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", + "2023-07-24 18:09:47,955\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:47,957\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", + "2023-07-24 18:09:48,802\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:48,802\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00\n" + ] + } + ], + "source": [ + "# Initialize model\n", + "model = FinetunedLLM(llm=llm, dropout_p=0.5, embedding_dim=embedding_dim, num_classes=num_classes)\n", + "print (model.named_parameters)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 📦  Batching" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can iterate through our dataset in batches however we may have batches of different sizes. Recall that our tokenizer padded the inputs to the longest item in the batch (`padding=\"longest\"`). However, our batches for training will be smaller than our large data processing batches and so our batches here may have inputs with different lengths. To address this, we're going to define a custom `collate_fn` to repad the items in our training batches." + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Created a temporary directory at /tmp/tmpmgh7ddc7\n", + "Writing /tmp/tmpmgh7ddc7/_remote_module_non_scriptable.py\n" + ] + } + ], + "source": [ + "from ray.train.torch import get_device" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def pad_array(arr, dtype=np.int32):\n", + " max_len = max(len(row) for row in arr)\n", + " padded_arr = np.zeros((arr.shape[0], max_len), dtype=dtype)\n", + " for i, row in enumerate(arr):\n", + " padded_arr[i][:len(row)] = row\n", + " return padded_arr" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def collate_fn(batch):\n", + " batch[\"ids\"] = pad_array(batch[\"ids\"])\n", + " batch[\"masks\"] = pad_array(batch[\"masks\"])\n", + " dtypes = {\"ids\": torch.int32, \"masks\": torch.int32, \"targets\": torch.int64}\n", + " tensor_batch = {}\n", + " for key, array in batch.items():\n", + " tensor_batch[key] = torch.as_tensor(array, dtype=dtypes[key], device=get_device())\n", + " return tensor_batch" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> `pad=(0, max_len)` in [F.pad](https://pytorch.org/docs/stable/generated/torch.nn.functional.pad.html#torch-nn-functional-pad) refers to (left_padding, right_padding) on the input. There will be no left-padding (hence the `0`) and only right-padding. And the `constant` mode refers to each element being padded to a constant size (size of longest element in the input)." + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:09:52,025\tINFO streaming_executor.py:92 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", + "2023-07-24 18:09:52,026\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:52,026\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:09:53,142\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:53,143\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:09:53,361\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:53,362\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", + "2023-07-24 18:09:53,953\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:53,953\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:09:54,693\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:54,693\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(16)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:09:55,680\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:09:55,681\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/16 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/16 [00:00\n", + "
\n", + "
\n", + "

Tune Status

\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Current time:2023-07-24 18:11:25
Running for: 00:01:29.04
Memory: 7.6/30.9 GiB
\n", + "
\n", + "
\n", + "
\n", + "

System Info

\n", + " Using FIFO scheduling algorithm.
Logical resource usage: 4.0/12 CPUs, 1.0/1 GPUs\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "

Trial Status

\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Trial name status loc iter total time (s) epoch lr train_loss
TorchTrainer_f80f6_00000TERMINATED10.0.56.150:281250 10 77.6459 90.0001 0.0364764
\n", + "
\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(autoscaler +30s) Tip: use `ray status` to view detailed cluster status. To disable these messages, set RAY_SCHEDULER_EVENTS=0.\n", + "(autoscaler +30s) Resized to 12 CPUs, 1 GPUs.\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "(TorchTrainer pid=281250) The dict form of `dataset_config` is deprecated. Use the DataConfig class instead. Support for this will be dropped in a future release.\n", + "(TorchTrainer pid=281250) The `preprocessor` arg to Trainer is deprecated. Apply preprocessor transformations ahead of time by calling `preprocessor.transform(ds)`. Support for the preprocessor arg will be dropped in a future release.\n", + "(TorchTrainer pid=281250) Starting distributed worker processes: ['2349 (10.0.6.57)']\n", + "(RayTrainWorker pid=2349, ip=10.0.6.57) Setting up process group for: env:// [rank=0, world_size=1]\n", + "Downloading (…)lve/main/config.json: 100%|██████████| 385/385 [00:00<00:00, 2.83MB/s]\n", + "Downloading pytorch_model.bin: 0%| | 0.00/442M [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochlrtrain_lossval_losstimestamptime_this_iter_sshould_checkpointdonetraining_iterationtrial_iddatetime_total_spidhostnamenode_iptime_since_restoreiterations_since_restore
000.00010.5781650.492538169024742119.374968TrueFalse1f80f6_000002023-07-24_18-10-2519.374968281250ip-10-0-56-15010.0.56.15019.3749681
110.00010.4862760.41953016902474286.751568TrueFalse2f80f6_000002023-07-24_18-10-3126.126536281250ip-10-0-56-15010.0.56.15026.1265362
220.00010.3984470.31716116902474356.416867TrueFalse3f80f6_000002023-07-24_18-10-3832.543403281250ip-10-0-56-15010.0.56.15032.5434033
330.00010.2869600.23488916902474416.434473TrueFalse4f80f6_000002023-07-24_18-10-4438.977876281250ip-10-0-56-15010.0.56.15038.9778764
440.00010.2089550.19911916902474486.407677TrueFalse5f80f6_000002023-07-24_18-10-5145.385553281250ip-10-0-56-15010.0.56.15045.3855535
550.00010.1417840.16173816902474546.420556TrueFalse6f80f6_000002023-07-24_18-10-5751.806109281250ip-10-0-56-15010.0.56.15051.8061096
660.00010.0981220.15262016902474606.416981TrueFalse7f80f6_000002023-07-24_18-11-0358.223091281250ip-10-0-56-15010.0.56.15058.2230917
770.00010.0698490.13382816902474676.472243TrueFalse8f80f6_000002023-07-24_18-11-1064.695333281250ip-10-0-56-15010.0.56.15064.6953338
880.00010.0463680.13519716902474736.461530TrueFalse9f80f6_000002023-07-24_18-11-1671.156864281250ip-10-0-56-15010.0.56.15071.1568649
990.00010.0364760.12304716902474806.489086TrueFalse10f80f6_000002023-07-24_18-11-2377.645949281250ip-10-0-56-15010.0.56.15077.64594910
\n", + "" + ], + "text/plain": [ + " epoch lr train_loss val_loss timestamp time_this_iter_s \n", + "0 0 0.0001 0.578165 0.492538 1690247421 19.374968 \\\n", + "1 1 0.0001 0.486276 0.419530 1690247428 6.751568 \n", + "2 2 0.0001 0.398447 0.317161 1690247435 6.416867 \n", + "3 3 0.0001 0.286960 0.234889 1690247441 6.434473 \n", + "4 4 0.0001 0.208955 0.199119 1690247448 6.407677 \n", + "5 5 0.0001 0.141784 0.161738 1690247454 6.420556 \n", + "6 6 0.0001 0.098122 0.152620 1690247460 6.416981 \n", + "7 7 0.0001 0.069849 0.133828 1690247467 6.472243 \n", + "8 8 0.0001 0.046368 0.135197 1690247473 6.461530 \n", + "9 9 0.0001 0.036476 0.123047 1690247480 6.489086 \n", + "\n", + " should_checkpoint done training_iteration trial_id \n", + "0 True False 1 f80f6_00000 \\\n", + "1 True False 2 f80f6_00000 \n", + "2 True False 3 f80f6_00000 \n", + "3 True False 4 f80f6_00000 \n", + "4 True False 5 f80f6_00000 \n", + "5 True False 6 f80f6_00000 \n", + "6 True False 7 f80f6_00000 \n", + "7 True False 8 f80f6_00000 \n", + "8 True False 9 f80f6_00000 \n", + "9 True False 10 f80f6_00000 \n", + "\n", + " date time_total_s pid hostname node_ip \n", + "0 2023-07-24_18-10-25 19.374968 281250 ip-10-0-56-150 10.0.56.150 \\\n", + "1 2023-07-24_18-10-31 26.126536 281250 ip-10-0-56-150 10.0.56.150 \n", + "2 2023-07-24_18-10-38 32.543403 281250 ip-10-0-56-150 10.0.56.150 \n", + "3 2023-07-24_18-10-44 38.977876 281250 ip-10-0-56-150 10.0.56.150 \n", + "4 2023-07-24_18-10-51 45.385553 281250 ip-10-0-56-150 10.0.56.150 \n", + "5 2023-07-24_18-10-57 51.806109 281250 ip-10-0-56-150 10.0.56.150 \n", + "6 2023-07-24_18-11-03 58.223091 281250 ip-10-0-56-150 10.0.56.150 \n", + "7 2023-07-24_18-11-10 64.695333 281250 ip-10-0-56-150 10.0.56.150 \n", + "8 2023-07-24_18-11-16 71.156864 281250 ip-10-0-56-150 10.0.56.150 \n", + "9 2023-07-24_18-11-23 77.645949 281250 ip-10-0-56-150 10.0.56.150 \n", + "\n", + " time_since_restore iterations_since_restore \n", + "0 19.374968 1 \n", + "1 26.126536 2 \n", + "2 32.543403 3 \n", + "3 38.977876 4 \n", + "4 45.385553 5 \n", + "5 51.806109 6 \n", + "6 58.223091 7 \n", + "7 64.695333 8 \n", + "8 71.156864 9 \n", + "9 77.645949 10 " + ] + }, + "execution_count": 62, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Metrics per epoch\n", + "results.metrics_dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[(TorchCheckpoint(local_path=/home/ray/ray_results/llm/TorchTrainer_f80f6_00000_0_2023-07-24_18-09-56/checkpoint_000009),\n", + " {'epoch': 9,\n", + " 'lr': 0.0001,\n", + " 'train_loss': 0.03647640720009804,\n", + " 'val_loss': 0.12304694950580597,\n", + " 'timestamp': 1690247480,\n", + " 'time_this_iter_s': 6.489085674285889,\n", + " 'should_checkpoint': True,\n", + " 'done': True,\n", + " 'training_iteration': 10,\n", + " 'trial_id': 'f80f6_00000',\n", + " 'date': '2023-07-24_18-11-23',\n", + " 'time_total_s': 77.6459493637085,\n", + " 'pid': 281250,\n", + " 'hostname': 'ip-10-0-56-150',\n", + " 'node_ip': '10.0.56.150',\n", + " 'config': {'train_loop_config': {'dropout_p': 0.5,\n", + " 'lr': 0.0001,\n", + " 'lr_factor': 0.8,\n", + " 'lr_patience': 3,\n", + " 'num_epochs': 10,\n", + " 'batch_size': 256,\n", + " 'num_classes': 4}},\n", + " 'time_since_restore': 77.6459493637085,\n", + " 'iterations_since_restore': 10,\n", + " 'experiment_tag': '0'})]" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Best checkpoints\n", + "results.best_checkpoints" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Evaluation" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from ray.train.torch.torch_predictor import TorchPredictor\n", + "from sklearn.metrics import precision_recall_fscore_support" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Predictor\n", + "best_checkpoint = results.best_checkpoints[0][0]\n", + "predictor = TorchPredictor.from_checkpoint(best_checkpoint)\n", + "preprocessor = predictor.get_preprocessor()" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:11:26,923\tINFO read_api.py:374 -- To satisfy the requested parallelism of 24, each read task output will be split into 24 smaller blocks.\n", + "2023-07-24 18:11:26,927\tINFO streaming_executor.py:92 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:11:26,927\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:26,928\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)->MapBatches()]\n", + "2023-07-24 18:11:27,397\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:27,397\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)->MapBatches()]\n", + "2023-07-24 18:11:36,377\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:36,379\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:11:40,817\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:40,818\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:11:41,067\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:41,068\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", + "2023-07-24 18:11:41,891\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:41,892\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:11:42,979\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:42,982\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:11:44,083\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:11:44,083\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00\n", + "
\n", + "
\n", + "

Tune Status

\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Current time:2023-07-24 18:13:07
Running for: 00:01:22.27
Memory: 8.3/30.9 GiB
\n", + "
\n", + "
\n", + "
\n", + "

System Info

\n", + " Using FIFO scheduling algorithm.
Logical resource usage: 4.0/12 CPUs, 1.0/1 GPUs\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "

Trial Status

\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Trial name status loc iter total time (s) epoch lr train_loss
TorchTrainer_38d2b_00000TERMINATED10.0.56.150:282335 10 75.3763 90.0001 0.0344348
\n", + "
\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "(TorchTrainer pid=282335) The dict form of `dataset_config` is deprecated. Use the DataConfig class instead. Support for this will be dropped in a future release.\n", + "(TorchTrainer pid=282335) The `preprocessor` arg to Trainer is deprecated. Apply preprocessor transformations ahead of time by calling `preprocessor.transform(ds)`. Support for the preprocessor arg will be dropped in a future release.\n", + "(TorchTrainer pid=282335) Starting distributed worker processes: ['2994 (10.0.6.57)']\n", + "(RayTrainWorker pid=2994, ip=10.0.6.57) Setting up process group for: env:// [rank=0, world_size=1]\n", + "(RayTrainWorker pid=2994, ip=10.0.6.57) Some weights of the model checkpoint at allenai/scibert_scivocab_uncased were not used when initializing BertModel: ['cls.seq_relationship.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.bias', 'cls.predictions.decoder.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.dense.weight', 'cls.predictions.bias']\n", + "(RayTrainWorker pid=2994, ip=10.0.6.57) - This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", + "(RayTrainWorker pid=2994, ip=10.0.6.57) - This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", + "(RayTrainWorker pid=2994, ip=10.0.6.57) Moving model to device: cuda:0\n", + "(RayTrainWorker pid=2994, ip=10.0.6.57) /tmp/ipykernel_280376/1209796013.py:7: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at ../torch/csrc/utils/tensor_numpy.cpp:206.)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/progress.csv -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/events.out.tfevents.1690247508.ip-10-0-56-150 -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/result.json -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts\n", + "creating /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000008\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000008/.is_checkpoint -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000008\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000008/.tune_metadata -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000008\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000008/dict_checkpoint.pkl -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000008\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000008/.metadata.pkl -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000008\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/params.json -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/params.pkl -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts\n", + "creating /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000009/.is_checkpoint -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000009/.tune_metadata -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000009/dict_checkpoint.pkl -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-11-45/TorchTrainer_38d2b_00000_0_2023-07-24_18-11-45/checkpoint_000009/.metadata.pkl -> /tmp/mlflow/598544898920467811/8991516da6674b5395affb9fb6217964/artifacts/checkpoint_000009\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:13:07,524\tINFO tune.py:1148 -- Total run time: 82.33 seconds (82.27 seconds for the tuning loop).\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.82 s, sys: 981 ms, total: 2.8 s\n", + "Wall time: 1min 22s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Train\n", + "results = trainer.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochlrtrain_lossval_losstimestamptime_this_iter_sshould_checkpointdonetraining_iterationtrial_iddatetime_total_spidhostnamenode_iptime_since_restoreiterations_since_restore
000.00010.5810920.493169169024752014.871574TrueFalse138d2b_000002023-07-24_18-12-0314.871574282335ip-10-0-56-15010.0.56.15014.8715741
110.00010.4786630.42361116902475276.952936TrueFalse238d2b_000002023-07-24_18-12-1021.824510282335ip-10-0-56-15010.0.56.15021.8245102
220.00010.3861110.36797516902475346.707607TrueFalse338d2b_000002023-07-24_18-12-1728.532117282335ip-10-0-56-15010.0.56.15028.5321173
330.00010.2872100.30464316902475416.656057TrueFalse438d2b_000002023-07-24_18-12-2435.188173282335ip-10-0-56-15010.0.56.15035.1881734
440.00010.2099510.27813316902475476.671985TrueFalse538d2b_000002023-07-24_18-12-3041.860158282335ip-10-0-56-15010.0.56.15041.8601585
550.00010.1528470.25878716902475546.679954TrueFalse638d2b_000002023-07-24_18-12-3748.540112282335ip-10-0-56-15010.0.56.15048.5401126
660.00010.1027870.24839616902475616.690619TrueFalse738d2b_000002023-07-24_18-12-4455.230731282335ip-10-0-56-15010.0.56.15055.2307317
770.00010.0663640.23244916902475676.750745TrueFalse838d2b_000002023-07-24_18-12-5061.981476282335ip-10-0-56-15010.0.56.15061.9814768
880.00010.0494730.21969816902475746.681975TrueFalse938d2b_000002023-07-24_18-12-5768.663451282335ip-10-0-56-15010.0.56.15068.6634519
990.00010.0344350.22159816902475816.712862TrueFalse1038d2b_000002023-07-24_18-13-0475.376313282335ip-10-0-56-15010.0.56.15075.37631310
\n", + "
" + ], + "text/plain": [ + " epoch lr train_loss val_loss timestamp time_this_iter_s \n", + "0 0 0.0001 0.581092 0.493169 1690247520 14.871574 \\\n", + "1 1 0.0001 0.478663 0.423611 1690247527 6.952936 \n", + "2 2 0.0001 0.386111 0.367975 1690247534 6.707607 \n", + "3 3 0.0001 0.287210 0.304643 1690247541 6.656057 \n", + "4 4 0.0001 0.209951 0.278133 1690247547 6.671985 \n", + "5 5 0.0001 0.152847 0.258787 1690247554 6.679954 \n", + "6 6 0.0001 0.102787 0.248396 1690247561 6.690619 \n", + "7 7 0.0001 0.066364 0.232449 1690247567 6.750745 \n", + "8 8 0.0001 0.049473 0.219698 1690247574 6.681975 \n", + "9 9 0.0001 0.034435 0.221598 1690247581 6.712862 \n", + "\n", + " should_checkpoint done training_iteration trial_id \n", + "0 True False 1 38d2b_00000 \\\n", + "1 True False 2 38d2b_00000 \n", + "2 True False 3 38d2b_00000 \n", + "3 True False 4 38d2b_00000 \n", + "4 True False 5 38d2b_00000 \n", + "5 True False 6 38d2b_00000 \n", + "6 True False 7 38d2b_00000 \n", + "7 True False 8 38d2b_00000 \n", + "8 True False 9 38d2b_00000 \n", + "9 True False 10 38d2b_00000 \n", + "\n", + " date time_total_s pid hostname node_ip \n", + "0 2023-07-24_18-12-03 14.871574 282335 ip-10-0-56-150 10.0.56.150 \\\n", + "1 2023-07-24_18-12-10 21.824510 282335 ip-10-0-56-150 10.0.56.150 \n", + "2 2023-07-24_18-12-17 28.532117 282335 ip-10-0-56-150 10.0.56.150 \n", + "3 2023-07-24_18-12-24 35.188173 282335 ip-10-0-56-150 10.0.56.150 \n", + "4 2023-07-24_18-12-30 41.860158 282335 ip-10-0-56-150 10.0.56.150 \n", + "5 2023-07-24_18-12-37 48.540112 282335 ip-10-0-56-150 10.0.56.150 \n", + "6 2023-07-24_18-12-44 55.230731 282335 ip-10-0-56-150 10.0.56.150 \n", + "7 2023-07-24_18-12-50 61.981476 282335 ip-10-0-56-150 10.0.56.150 \n", + "8 2023-07-24_18-12-57 68.663451 282335 ip-10-0-56-150 10.0.56.150 \n", + "9 2023-07-24_18-13-04 75.376313 282335 ip-10-0-56-150 10.0.56.150 \n", + "\n", + " time_since_restore iterations_since_restore \n", + "0 14.871574 1 \n", + "1 21.824510 2 \n", + "2 28.532117 3 \n", + "3 35.188173 4 \n", + "4 41.860158 5 \n", + "5 48.540112 6 \n", + "6 55.230731 7 \n", + "7 61.981476 8 \n", + "8 68.663451 9 \n", + "9 75.376313 10 " + ] + }, + "execution_count": 84, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "results.metrics_dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
run_idexperiment_idstatusartifact_uristart_timeend_timemetrics.time_since_restoremetrics.time_this_iter_smetrics.config/train_loop_config/lrmetrics.done...metrics.val_lossparams.train_loop_config/num_classesparams.train_loop_config/dropout_pparams.train_loop_config/num_epochsparams.train_loop_config/lr_patienceparams.train_loop_config/lrparams.train_loop_config/lr_factorparams.train_loop_config/batch_sizetags.trial_nametags.mlflow.runName
08991516da6674b5395affb9fb6217964598544898920467811FINISHEDfile:///tmp/mlflow/598544898920467811/8991516d...2023-07-25 01:11:48.948000+00:002023-07-25 01:13:07.513000+00:0075.3763136.7128620.00010.0...0.22159840.51030.00010.8256TorchTrainer_38d2b_00000TorchTrainer_38d2b_00000
\n", + "

1 rows × 35 columns

\n", + "
" + ], + "text/plain": [ + " run_id experiment_id status \n", + "0 8991516da6674b5395affb9fb6217964 598544898920467811 FINISHED \\\n", + "\n", + " artifact_uri \n", + "0 file:///tmp/mlflow/598544898920467811/8991516d... \\\n", + "\n", + " start_time end_time \n", + "0 2023-07-25 01:11:48.948000+00:00 2023-07-25 01:13:07.513000+00:00 \\\n", + "\n", + " metrics.time_since_restore metrics.time_this_iter_s \n", + "0 75.376313 6.712862 \\\n", + "\n", + " metrics.config/train_loop_config/lr metrics.done ... metrics.val_loss \n", + "0 0.0001 0.0 ... 0.221598 \\\n", + "\n", + " params.train_loop_config/num_classes params.train_loop_config/dropout_p \n", + "0 4 0.5 \\\n", + "\n", + " params.train_loop_config/num_epochs params.train_loop_config/lr_patience \n", + "0 10 3 \\\n", + "\n", + " params.train_loop_config/lr params.train_loop_config/lr_factor \n", + "0 0.0001 0.8 \\\n", + "\n", + " params.train_loop_config/batch_size tags.trial_name \n", + "0 256 TorchTrainer_38d2b_00000 \\\n", + "\n", + " tags.mlflow.runName \n", + "0 TorchTrainer_38d2b_00000 \n", + "\n", + "[1 rows x 35 columns]" + ] + }, + "execution_count": 85, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Sorted runs\n", + "sorted_runs = mlflow.search_runs(experiment_names=[experiment_name], order_by=[\"metrics.val_loss ASC\"])\n", + "sorted_runs" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "run_id 8991516da6674b5395affb9fb6217964\n", + "experiment_id 598544898920467811\n", + "status FINISHED\n", + "artifact_uri file:///tmp/mlflow/598544898920467811/8991516d...\n", + "start_time 2023-07-25 01:11:48.948000+00:00\n", + "end_time 2023-07-25 01:13:07.513000+00:00\n", + "metrics.time_since_restore 75.376313\n", + "metrics.time_this_iter_s 6.712862\n", + "metrics.config/train_loop_config/lr 0.0001\n", + "metrics.done 0.0\n", + "metrics.pid 282335.0\n", + "metrics.iterations_since_restore 10.0\n", + "metrics.training_iteration 10.0\n", + "metrics.config/train_loop_config/num_classes 4.0\n", + "metrics.lr 0.0001\n", + "metrics.config/train_loop_config/num_epochs 10.0\n", + "metrics.timestamp 1690247581.0\n", + "metrics.time_total_s 75.376313\n", + "metrics.config/train_loop_config/lr_patience 3.0\n", + "metrics.config/train_loop_config/batch_size 256.0\n", + "metrics.epoch 9.0\n", + "metrics.should_checkpoint 1.0\n", + "metrics.train_loss 0.034435\n", + "metrics.config/train_loop_config/dropout_p 0.5\n", + "metrics.config/train_loop_config/lr_factor 0.8\n", + "metrics.val_loss 0.221598\n", + "params.train_loop_config/num_classes 4\n", + "params.train_loop_config/dropout_p 0.5\n", + "params.train_loop_config/num_epochs 10\n", + "params.train_loop_config/lr_patience 3\n", + "params.train_loop_config/lr 0.0001\n", + "params.train_loop_config/lr_factor 0.8\n", + "params.train_loop_config/batch_size 256\n", + "tags.trial_name TorchTrainer_38d2b_00000\n", + "tags.mlflow.runName TorchTrainer_38d2b_00000\n", + "Name: 0, dtype: object" + ] + }, + "execution_count": 86, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Best run\n", + "best_run = sorted_runs.iloc[0]\n", + "best_run" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dashboard" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's view what we've tracked from our experiment. MLFlow serves a dashboard for us to view and explore our experiments on a localhost port:\n", + "\n", + "```bash\n", + "mlflow server -h 0.0.0.0 -p 8080 --backend-store-uri /tmp/mlflow/\n", + "```" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "MLFlow creates a main dashboard with all your experiments and their respective runs. We can sort runs by clicking on the column headers.\n", + "\n", + "\"mlflow\n", + "\n", + "And within each run, we can view metrics, parameters, artifacts, etc.\n", + "\n", + "\"mlflow\n", + "\n", + "And we can even create custom plots to help us visualize our results.\n", + "\n", + "\"mlflow" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Loading" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from ray.air import Result\n", + "from urllib.parse import urlparse" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def get_best_checkpoint(run_id):\n", + " artifact_dir = urlparse(mlflow.get_run(run_id).info.artifact_uri).path # get path from mlflow\n", + " results = Result.from_path(artifact_dir)\n", + " return results.best_checkpoints[0][0]" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:13:08,541\tINFO streaming_executor.py:92 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)->MapBatches()]\n", + "2023-07-24 18:13:08,542\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:13:08,543\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:13:12,895\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:13:12,895\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", + "2023-07-24 18:13:14,122\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:13:14,123\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", + "2023-07-24 18:13:15,060\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:13:15,061\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:13:16,029\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:13:16,032\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)]\n", + "2023-07-24 18:13:17,237\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:13:17,237\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "- RandomShuffle 1: 0%| | 0/24 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/24 [00:00) per trial\n", + " grace_period=5, # min epoch () per trial\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Tune config\n", + "tune_config = tune.TuneConfig(\n", + " metric=\"val_loss\",\n", + " mode=\"min\",\n", + " search_alg=search_alg,\n", + " scheduler=scheduler,\n", + " num_samples=num_runs,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Tuner\n", + "tuner = Tuner(\n", + " trainable=trainer,\n", + " run_config=run_config,\n", + " param_space=param_space,\n", + " tune_config=tune_config,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + "
\n", + "

Tune Status

\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Current time:2023-07-24 18:15:25
Running for: 00:02:06.87
Memory: 9.0/30.9 GiB
\n", + "
\n", + "
\n", + "
\n", + "

System Info

\n", + " Using AsyncHyperBand: num_stopped=2
Bracket: Iter 5.000: -0.3085140064358711
Logical resource usage: 4.0/12 CPUs, 1.0/1 GPUs\n", + "
\n", + " \n", + "
\n", + "
\n", + "
\n", + "

Trial Status

\n", + " \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Trial name status loc train_loop_config/dr\n", + "opout_p train_loop_config/lr train_loop_config/lr\n", + "_factor train_loop_config/lr\n", + "_patience iter total time (s) epoch lr train_loss
TorchTrainer_578373f0TERMINATED10.0.56.150:2833230.5 0.0001 0.8 3 10 76.0183 90.0001 0.0386915
TorchTrainer_50d8c90fTERMINATED10.0.56.150:2841490.356927 2.63429e-050.1487252.50789 5 42.2436 42.63429e-05 0.407936
\n", + "
\n", + "
\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "(TorchTrainer pid=283323) The dict form of `dataset_config` is deprecated. Use the DataConfig class instead. Support for this will be dropped in a future release.\n", + "(TorchTrainer pid=283323) The `preprocessor` arg to Trainer is deprecated. Apply preprocessor transformations ahead of time by calling `preprocessor.transform(ds)`. Support for the preprocessor arg will be dropped in a future release.\n", + "(TorchTrainer pid=283323) Starting distributed worker processes: ['3541 (10.0.6.57)']\n", + "(RayTrainWorker pid=3541, ip=10.0.6.57) Setting up process group for: env:// [rank=0, world_size=1]\n", + "(RayTrainWorker pid=3541, ip=10.0.6.57) Some weights of the model checkpoint at allenai/scibert_scivocab_uncased were not used when initializing BertModel: ['cls.predictions.transform.LayerNorm.weight', 'cls.predictions.decoder.weight', 'cls.predictions.bias', 'cls.predictions.transform.dense.bias', 'cls.seq_relationship.bias', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.weight', 'cls.predictions.decoder.bias', 'cls.predictions.transform.LayerNorm.bias']\n", + "(RayTrainWorker pid=3541, ip=10.0.6.57) - This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", + "(RayTrainWorker pid=3541, ip=10.0.6.57) - This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", + "(RayTrainWorker pid=3541, ip=10.0.6.57) Moving model to device: cuda:0\n", + "(RayTrainWorker pid=3541, ip=10.0.6.57) /tmp/ipykernel_280376/1209796013.py:7: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at ../torch/csrc/utils/tensor_numpy.cpp:206.)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/events.out.tfevents.1690247602.ip-10-0-56-150 -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/progress.csv -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/result.json -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/params.json -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/.lazy_checkpoint_marker -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/params.pkl -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts\n", + "creating /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/checkpoint_000009/.is_checkpoint -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/checkpoint_000009/.tune_metadata -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/checkpoint_000009/dict_checkpoint.pkl -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts/checkpoint_000009\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_578373f0_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-07-24_18-13-18/checkpoint_000009/.metadata.pkl -> /tmp/mlflow/598544898920467811/6b854ffda94844e28013fc6deb157af4/artifacts/checkpoint_000009\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "(TorchTrainer pid=284149) The dict form of `dataset_config` is deprecated. Use the DataConfig class instead. Support for this will be dropped in a future release.\n", + "(TorchTrainer pid=284149) The `preprocessor` arg to Trainer is deprecated. Apply preprocessor transformations ahead of time by calling `preprocessor.transform(ds)`. Support for the preprocessor arg will be dropped in a future release.\n", + "(TorchTrainer pid=284149) Starting distributed worker processes: ['3934 (10.0.6.57)']\n", + "(RayTrainWorker pid=3934, ip=10.0.6.57) Setting up process group for: env:// [rank=0, world_size=1]\n", + "(RayTrainWorker pid=3934, ip=10.0.6.57) Some weights of the model checkpoint at allenai/scibert_scivocab_uncased were not used when initializing BertModel: ['cls.predictions.transform.dense.weight', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.bias', 'cls.seq_relationship.bias', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.decoder.weight']\n", + "(RayTrainWorker pid=3934, ip=10.0.6.57) - This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n", + "(RayTrainWorker pid=3934, ip=10.0.6.57) - This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n", + "(RayTrainWorker pid=3934, ip=10.0.6.57) Moving model to device: cuda:0\n", + "(RayTrainWorker pid=3934, ip=10.0.6.57) /tmp/ipykernel_280376/1209796013.py:7: UserWarning: The given NumPy array is not writable, and PyTorch does not support non-writable tensors. This means writing to this tensor will result in undefined behavior. You may want to copy the array to protect its data or make it writable before converting it to a tensor. This type of warning will be suppressed for the rest of this program. (Triggered internally at ../torch/csrc/utils/tensor_numpy.cpp:206.)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/progress.csv -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/events.out.tfevents.1690247682.ip-10-0-56-150 -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts\n", + "creating /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts/checkpoint_000004\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/checkpoint_000004/.is_checkpoint -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts/checkpoint_000004\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/checkpoint_000004/.tune_metadata -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts/checkpoint_000004\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/checkpoint_000004/dict_checkpoint.pkl -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts/checkpoint_000004\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/checkpoint_000004/.metadata.pkl -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts/checkpoint_000004\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/result.json -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/params.json -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/.lazy_checkpoint_marker -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts\n", + "copying /home/ray/ray_results/TorchTrainer_2023-07-24_18-13-18/TorchTrainer_50d8c90f_2_dropout_p=0.3569,lr=0.0000,lr_factor=0.1487,lr_patience=2.5079_2023-07-24_18-13-22/params.pkl -> /tmp/mlflow/598544898920467811/85444db0a2794c43a14accae3054d0e2/artifacts\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:15:25,696\tINFO tune.py:1148 -- Total run time: 126.91 seconds (126.86 seconds for the tuning loop).\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 3.49 s, sys: 1.41 s, total: 4.9 s\n", + "Wall time: 2min 6s\n" + ] + } + ], + "source": [ + "%%time\n", + "# Tune\n", + "results = tuner.fit()" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochlrtrain_lossval_losstimestamptime_this_iter_sshould_checkpointdonetraining_iterationtrial_id...pidhostnamenode_iptime_since_restoreiterations_since_restoreconfig/train_loop_config/dropout_pconfig/train_loop_config/lrconfig/train_loop_config/lr_factorconfig/train_loop_config/lr_patiencelogdir
090.0001000.0386920.22697116902476756.857913TrueTrue10578373f0...283323ip-10-0-56-15010.0.56.15076.018291100.5000000.0001000.8000003.000000/home/ray/ray_results/TorchTrainer_2023-07-24_...
140.0000260.4079360.38987716902477226.744698TrueTrue550d8c90f...284149ip-10-0-56-15010.0.56.15042.24363050.3569270.0000260.1487252.507894/home/ray/ray_results/TorchTrainer_2023-07-24_...
\n", + "

2 rows × 22 columns

\n", + "
" + ], + "text/plain": [ + " epoch lr train_loss val_loss timestamp time_this_iter_s \n", + "0 9 0.000100 0.038692 0.226971 1690247675 6.857913 \\\n", + "1 4 0.000026 0.407936 0.389877 1690247722 6.744698 \n", + "\n", + " should_checkpoint done training_iteration trial_id ... pid \n", + "0 True True 10 578373f0 ... 283323 \\\n", + "1 True True 5 50d8c90f ... 284149 \n", + "\n", + " hostname node_ip time_since_restore iterations_since_restore \n", + "0 ip-10-0-56-150 10.0.56.150 76.018291 10 \\\n", + "1 ip-10-0-56-150 10.0.56.150 42.243630 5 \n", + "\n", + " config/train_loop_config/dropout_p config/train_loop_config/lr \n", + "0 0.500000 0.000100 \\\n", + "1 0.356927 0.000026 \n", + "\n", + " config/train_loop_config/lr_factor config/train_loop_config/lr_patience \n", + "0 0.800000 3.000000 \\\n", + "1 0.148725 2.507894 \n", + "\n", + " logdir \n", + "0 /home/ray/ray_results/TorchTrainer_2023-07-24_... \n", + "1 /home/ray/ray_results/TorchTrainer_2023-07-24_... \n", + "\n", + "[2 rows x 22 columns]" + ] + }, + "execution_count": 106, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# All trials in experiment\n", + "results.get_dataframe()" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
epochlrtrain_lossval_losstimestamptime_this_iter_sshould_checkpointdonetraining_iterationtrial_iddatetime_total_spidhostnamenode_iptime_since_restoreiterations_since_restore
000.00010.5810370.501312169024761314.747473TrueFalse1578373f02023-07-24_18-13-3614.747473283323ip-10-0-56-15010.0.56.15014.7474731
110.00010.4869210.43275216902476207.031596TrueFalse2578373f02023-07-24_18-13-4421.779069283323ip-10-0-56-15010.0.56.15021.7790692
220.00010.3832750.35737716902476276.705714TrueFalse3578373f02023-07-24_18-13-5028.484783283323ip-10-0-56-15010.0.56.15028.4847833
330.00010.2766860.30071316902476346.760320TrueFalse4578373f02023-07-24_18-13-5735.245103283323ip-10-0-56-15010.0.56.15035.2451034
440.00010.2084690.28139316902476416.757150TrueFalse5578373f02023-07-24_18-14-0442.002253283323ip-10-0-56-15010.0.56.15042.0022535
550.00010.1461350.26096216902476476.796252TrueFalse6578373f02023-07-24_18-14-1148.798505283323ip-10-0-56-15010.0.56.15048.7985056
660.00010.0996080.26058916902476546.804206TrueFalse7578373f02023-07-24_18-14-1755.602711283323ip-10-0-56-15010.0.56.15055.6027117
770.00010.0723970.25375416902476616.785470TrueFalse8578373f02023-07-24_18-14-2462.388181283323ip-10-0-56-15010.0.56.15062.3881818
880.00010.0495090.23542816902476686.772196TrueFalse9578373f02023-07-24_18-14-3169.160377283323ip-10-0-56-15010.0.56.15069.1603779
990.00010.0386920.22697116902476756.857913TrueTrue10578373f02023-07-24_18-14-3876.018291283323ip-10-0-56-15010.0.56.15076.01829110
\n", + "
" + ], + "text/plain": [ + " epoch lr train_loss val_loss timestamp time_this_iter_s \n", + "0 0 0.0001 0.581037 0.501312 1690247613 14.747473 \\\n", + "1 1 0.0001 0.486921 0.432752 1690247620 7.031596 \n", + "2 2 0.0001 0.383275 0.357377 1690247627 6.705714 \n", + "3 3 0.0001 0.276686 0.300713 1690247634 6.760320 \n", + "4 4 0.0001 0.208469 0.281393 1690247641 6.757150 \n", + "5 5 0.0001 0.146135 0.260962 1690247647 6.796252 \n", + "6 6 0.0001 0.099608 0.260589 1690247654 6.804206 \n", + "7 7 0.0001 0.072397 0.253754 1690247661 6.785470 \n", + "8 8 0.0001 0.049509 0.235428 1690247668 6.772196 \n", + "9 9 0.0001 0.038692 0.226971 1690247675 6.857913 \n", + "\n", + " should_checkpoint done training_iteration trial_id \n", + "0 True False 1 578373f0 \\\n", + "1 True False 2 578373f0 \n", + "2 True False 3 578373f0 \n", + "3 True False 4 578373f0 \n", + "4 True False 5 578373f0 \n", + "5 True False 6 578373f0 \n", + "6 True False 7 578373f0 \n", + "7 True False 8 578373f0 \n", + "8 True False 9 578373f0 \n", + "9 True True 10 578373f0 \n", + "\n", + " date time_total_s pid hostname node_ip \n", + "0 2023-07-24_18-13-36 14.747473 283323 ip-10-0-56-150 10.0.56.150 \\\n", + "1 2023-07-24_18-13-44 21.779069 283323 ip-10-0-56-150 10.0.56.150 \n", + "2 2023-07-24_18-13-50 28.484783 283323 ip-10-0-56-150 10.0.56.150 \n", + "3 2023-07-24_18-13-57 35.245103 283323 ip-10-0-56-150 10.0.56.150 \n", + "4 2023-07-24_18-14-04 42.002253 283323 ip-10-0-56-150 10.0.56.150 \n", + "5 2023-07-24_18-14-11 48.798505 283323 ip-10-0-56-150 10.0.56.150 \n", + "6 2023-07-24_18-14-17 55.602711 283323 ip-10-0-56-150 10.0.56.150 \n", + "7 2023-07-24_18-14-24 62.388181 283323 ip-10-0-56-150 10.0.56.150 \n", + "8 2023-07-24_18-14-31 69.160377 283323 ip-10-0-56-150 10.0.56.150 \n", + "9 2023-07-24_18-14-38 76.018291 283323 ip-10-0-56-150 10.0.56.150 \n", + "\n", + " time_since_restore iterations_since_restore \n", + "0 14.747473 1 \n", + "1 21.779069 2 \n", + "2 28.484783 3 \n", + "3 35.245103 4 \n", + "4 42.002253 5 \n", + "5 48.798505 6 \n", + "6 55.602711 7 \n", + "7 62.388181 8 \n", + "8 69.160377 9 \n", + "9 76.018291 10 " + ] + }, + "execution_count": 107, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Best trial's epochs\n", + "best_trial = results.get_best_result(metric=\"val_loss\", mode=\"min\")\n", + "best_trial.metrics_dataframe" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'dropout_p': 0.5, 'lr': 0.0001, 'lr_factor': 0.8, 'lr_patience': 3.0}" + ] + }, + "execution_count": 108, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Best trial's hyperparameters\n", + "best_trial.config[\"train_loop_config\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
run_idexperiment_idstatusartifact_uristart_timeend_timemetrics.time_since_restoremetrics.time_this_iter_smetrics.config/train_loop_config/lrmetrics.done...metrics.val_lossparams.train_loop_config/num_classesparams.train_loop_config/dropout_pparams.train_loop_config/num_epochsparams.train_loop_config/lr_patienceparams.train_loop_config/lrparams.train_loop_config/lr_factorparams.train_loop_config/batch_sizetags.trial_nametags.mlflow.runName
08991516da6674b5395affb9fb6217964598544898920467811FINISHEDfile:///tmp/mlflow/598544898920467811/8991516d...2023-07-25 01:11:48.948000+00:002023-07-25 01:13:07.513000+00:0075.3763136.7128620.0001000.0...0.22159840.51030.00010.8256TorchTrainer_38d2b_00000TorchTrainer_38d2b_00000
16b854ffda94844e28013fc6deb157af4598544898920467811FINISHEDfile:///tmp/mlflow/598544898920467811/6b854ffd...2023-07-25 01:13:22.223000+00:002023-07-25 01:14:38.804000+00:0076.0182916.8579130.0001001.0...0.226971None0.5None3.00.00010.8NoneTorchTrainer_578373f0TorchTrainer_578373f0
285444db0a2794c43a14accae3054d0e2598544898920467811FINISHEDfile:///tmp/mlflow/598544898920467811/85444db0...2023-07-25 01:14:42.883000+00:002023-07-25 01:15:25.678000+00:0042.2436306.7446980.0000261.0...0.389877None0.3569270357483055None2.5078940407338572.6342924831000413e-050.14872459915992878NoneTorchTrainer_50d8c90fTorchTrainer_50d8c90f
\n", + "

3 rows × 35 columns

\n", + "
" + ], + "text/plain": [ + " run_id experiment_id status \n", + "0 8991516da6674b5395affb9fb6217964 598544898920467811 FINISHED \\\n", + "1 6b854ffda94844e28013fc6deb157af4 598544898920467811 FINISHED \n", + "2 85444db0a2794c43a14accae3054d0e2 598544898920467811 FINISHED \n", + "\n", + " artifact_uri \n", + "0 file:///tmp/mlflow/598544898920467811/8991516d... \\\n", + "1 file:///tmp/mlflow/598544898920467811/6b854ffd... \n", + "2 file:///tmp/mlflow/598544898920467811/85444db0... \n", + "\n", + " start_time end_time \n", + "0 2023-07-25 01:11:48.948000+00:00 2023-07-25 01:13:07.513000+00:00 \\\n", + "1 2023-07-25 01:13:22.223000+00:00 2023-07-25 01:14:38.804000+00:00 \n", + "2 2023-07-25 01:14:42.883000+00:00 2023-07-25 01:15:25.678000+00:00 \n", + "\n", + " metrics.time_since_restore metrics.time_this_iter_s \n", + "0 75.376313 6.712862 \\\n", + "1 76.018291 6.857913 \n", + "2 42.243630 6.744698 \n", + "\n", + " metrics.config/train_loop_config/lr metrics.done ... metrics.val_loss \n", + "0 0.000100 0.0 ... 0.221598 \\\n", + "1 0.000100 1.0 ... 0.226971 \n", + "2 0.000026 1.0 ... 0.389877 \n", + "\n", + " params.train_loop_config/num_classes params.train_loop_config/dropout_p \n", + "0 4 0.5 \\\n", + "1 None 0.5 \n", + "2 None 0.3569270357483055 \n", + "\n", + " params.train_loop_config/num_epochs params.train_loop_config/lr_patience \n", + "0 10 3 \\\n", + "1 None 3.0 \n", + "2 None 2.507894040733857 \n", + "\n", + " params.train_loop_config/lr params.train_loop_config/lr_factor \n", + "0 0.0001 0.8 \\\n", + "1 0.0001 0.8 \n", + "2 2.6342924831000413e-05 0.14872459915992878 \n", + "\n", + " params.train_loop_config/batch_size tags.trial_name \n", + "0 256 TorchTrainer_38d2b_00000 \\\n", + "1 None TorchTrainer_578373f0 \n", + "2 None TorchTrainer_50d8c90f \n", + "\n", + " tags.mlflow.runName \n", + "0 TorchTrainer_38d2b_00000 \n", + "1 TorchTrainer_578373f0 \n", + "2 TorchTrainer_50d8c90f \n", + "\n", + "[3 rows x 35 columns]" + ] + }, + "execution_count": 109, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Sorted runs\n", + "sorted_runs = mlflow.search_runs(experiment_names=[experiment_name], order_by=[\"metrics.val_loss ASC\"])\n", + "sorted_runs" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-07-24 18:15:26,376\tINFO streaming_executor.py:92 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)->MapBatches()]\n", + "2023-07-24 18:15:26,377\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:15:26,377\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/24 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> TaskPoolMapOperator[MapBatches(CustomPreprocessor._transform_pandas)->MapBatches()]\n", + "2023-07-24 18:15:30,005\tINFO streaming_executor.py:93 -- Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=False, preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", + "2023-07-24 18:15:30,006\tINFO streaming_executor.py:95 -- Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Running 0: 0%| | 0/24 [00:00\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idcreated_ontitledescriptiontagtextprediction
0192020-03-03 13:54:31Diffusion to VectorReference implementation of Diffusion2Vec (Com...otherDiffusion to Vector Reference implementation o...computer-vision
1262020-03-07 23:11:58Graph Wavelet Neural NetworkA PyTorch implementation of \"Graph Wavelet Neu...otherGraph Wavelet Neural Network A PyTorch impleme...other
2442020-03-08 00:32:58Capsule Graph Neural NetworkA PyTorch implementation of \"Capsule Graph Neu...otherCapsule Graph Neural Network A PyTorch impleme...other
3802020-03-20 05:59:32NeRF: Neural Radiance FieldsRepresenting scenes as neural radiance fields ...computer-visionNeRF: Neural Radiance Fields Representing scen...computer-vision
4842020-03-20 15:18:43Mention ClassifierCategory prediction model\\r\\nThis repo contain...natural-language-processingMention Classifier Category prediction model\\r...natural-language-processing
\n", + "" + ], + "text/plain": [ + " id created_on title \n", + "0 19 2020-03-03 13:54:31 Diffusion to Vector \\\n", + "1 26 2020-03-07 23:11:58 Graph Wavelet Neural Network \n", + "2 44 2020-03-08 00:32:58 Capsule Graph Neural Network \n", + "3 80 2020-03-20 05:59:32 NeRF: Neural Radiance Fields \n", + "4 84 2020-03-20 15:18:43 Mention Classifier \n", + "\n", + " description \n", + "0 Reference implementation of Diffusion2Vec (Com... \\\n", + "1 A PyTorch implementation of \"Graph Wavelet Neu... \n", + "2 A PyTorch implementation of \"Capsule Graph Neu... \n", + "3 Representing scenes as neural radiance fields ... \n", + "4 Category prediction model\\r\\nThis repo contain... \n", + "\n", + " tag \n", + "0 other \\\n", + "1 other \n", + "2 other \n", + "3 computer-vision \n", + "4 natural-language-processing \n", + "\n", + " text \n", + "0 Diffusion to Vector Reference implementation o... \\\n", + "1 Graph Wavelet Neural Network A PyTorch impleme... \n", + "2 Capsule Graph Neural Network A PyTorch impleme... \n", + "3 NeRF: Neural Radiance Fields Representing scen... \n", + "4 Mention Classifier Category prediction model\\r... \n", + "\n", + " prediction \n", + "0 computer-vision \n", + "1 other \n", + "2 other \n", + "3 computer-vision \n", + "4 natural-language-processing " + ] + }, + "execution_count": 117, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Add columns (for convenience)\n", + "test_df = test_ds.to_pandas()\n", + "test_df[\"text\"] = test_df[\"title\"] + \" \" + test_df[\"description\"]\n", + "test_df[\"prediction\"] = test_df.index.map(lambda i: preprocessor.index_to_class[y_pred[i]])\n", + "test_df.head()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "TiXcls5JoNA8" + }, + "source": [ + "### Coarse-grained metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "h2OQtNODrh6c", + "outputId": "4c15bd9d-3465-4476-f02a-282aaaae0a91", + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"precision\": 0.9281010510531216,\n", + " \"recall\": 0.9267015706806283,\n", + " \"f1\": 0.9269438615952555,\n", + " \"num_samples\": 191.0\n", + "}\n" + ] + } + ], + "source": [ + "# Overall metrics\n", + "overall_metrics = precision_recall_fscore_support(y_test, y_pred, average=\"weighted\")\n", + "metrics[\"overall\"][\"precision\"] = overall_metrics[0]\n", + "metrics[\"overall\"][\"recall\"] = overall_metrics[1]\n", + "metrics[\"overall\"][\"f1\"] = overall_metrics[2]\n", + "metrics[\"overall\"][\"num_samples\"] = np.float64(len(y_test))\n", + "print (json.dumps(metrics[\"overall\"], indent=4))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "zl3xSuXRutKG" + }, + "source": [ + "### Fine-grained metrics" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": { + "id": "jqetm3ybN9C1", + "tags": [] + }, + "outputs": [], + "source": [ + "from collections import OrderedDict" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": { + "id": "1zIAI4mwusoX", + "tags": [] + }, + "outputs": [], + "source": [ + "# Per-class metrics\n", + "class_metrics = precision_recall_fscore_support(y_test, y_pred, average=None)\n", + "for i, _class in enumerate(preprocessor.class_to_index):\n", + " metrics[\"class\"][_class] = {\n", + " \"precision\": class_metrics[0][i],\n", + " \"recall\": class_metrics[1][i],\n", + " \"f1\": class_metrics[2][i],\n", + " \"num_samples\": np.float64(class_metrics[3][i]),\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": 121, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Rhh-tgpP0dvj", + "outputId": "1de2a5eb-b9fb-4d23-d890-39f7310e868c", + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"precision\": 0.95,\n", + " \"recall\": 0.9743589743589743,\n", + " \"f1\": 0.9620253164556962,\n", + " \"num_samples\": 78.0\n", + "}\n" + ] + } + ], + "source": [ + "# Metrics for a specific class\n", + "tag = \"natural-language-processing\"\n", + "print (json.dumps(metrics[\"class\"][tag], indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "vQVA6G-j__t5", + "outputId": "960e8f1e-21e9-4bc7-f284-ae4800c77913", + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[\n", + " \"natural-language-processing\",\n", + " {\n", + " \"precision\": 0.95,\n", + " \"recall\": 0.9743589743589743,\n", + " \"f1\": 0.9620253164556962,\n", + " \"num_samples\": 78.0\n", + " }\n", + "]\n", + "[\n", + " \"computer-vision\",\n", + " {\n", + " \"precision\": 0.9552238805970149,\n", + " \"recall\": 0.9014084507042254,\n", + " \"f1\": 0.927536231884058,\n", + " \"num_samples\": 71.0\n", + " }\n", + "]\n", + "[\n", + " \"other\",\n", + " {\n", + " \"precision\": 0.8888888888888888,\n", + " \"recall\": 0.9230769230769231,\n", + " \"f1\": 0.9056603773584906,\n", + " \"num_samples\": 26.0\n", + " }\n", + "]\n", + "[\n", + " \"mlops\",\n", + " {\n", + " \"precision\": 0.7647058823529411,\n", + " \"recall\": 0.8125,\n", + " \"f1\": 0.787878787878788,\n", + " \"num_samples\": 16.0\n", + " }\n", + "]\n" + ] + } + ], + "source": [ + "# Sorted tags\n", + "sorted_tags_by_f1 = OrderedDict(sorted(\n", + " metrics[\"class\"].items(), key=lambda tag: tag[1][\"f1\"], reverse=True))\n", + "for item in sorted_tags_by_f1.items():\n", + " print (json.dumps(item, indent=2))" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "f-juex26zvBF" + }, + "source": [ + "### Confusion matrix" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "xPUao0S4k99c" + }, + "source": [ + "- **True positives (TP)**: learn about where our model performs well.\n", + "- **False positives (FP)**: potentially identify samples which may need to be relabeled.\n", + "- False negatives (FN): identify the model's less performant areas to oversample later.\n", + "\n", + "> It's a good to have our FP/FN samples feed back into our annotation pipelines in the event we want to fix their labels and have those changes be reflected everywhere." + ] + }, + { + "cell_type": "code", + "execution_count": 123, + "metadata": { + "id": "ZG2SgsPAzukL", + "tags": [] + }, + "outputs": [], + "source": [ + "# TP, FP, FN samples\n", + "tag = \"natural-language-processing\"\n", + "index = preprocessor.class_to_index[tag]\n", + "tp, fp, fn = [], [], []\n", + "for i, true in enumerate(y_test):\n", + " pred = y_pred[i]\n", + " if index==true==pred:\n", + " tp.append(i)\n", + " elif index!=true and index==pred:\n", + " fp.append(i)\n", + " elif index==true and index!=pred:\n", + " fn.append(i)" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ePrxeVkG0mmO", + "outputId": "c13e3881-e527-4a2a-b1dd-ef15187425ab", + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[4, 9, 12, 16, 17, 19, 23, 26, 29, 30, 31, 32, 33, 34, 42, 47, 49, 50, 54, 56, 65, 66, 68, 71, 75, 76, 77, 78, 79, 82, 92, 94, 95, 97, 99, 101, 109, 113, 114, 115, 118, 120, 122, 126, 128, 129, 130, 131, 133, 134, 135, 138, 139, 140, 141, 142, 144, 148, 149, 152, 159, 160, 161, 163, 166, 170, 172, 173, 174, 177, 179, 183, 184, 187, 189, 190]\n", + "[24, 104, 165, 188]\n", + "[25, 112]\n" + ] + } + ], + "source": [ + "print (tp)\n", + "print (fp)\n", + "print (fn)" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "=== True positives ===\n", + "Mention Classifier Category prediction model\n", + "This repo contains AllenNLP model for prediction of Named Entity categories by its mentions.\n", + " true: natural-language-processing\n", + " pred: natural-language-processing\n", + "\n", + "Finetune: Scikit-learn Style Model Finetuning for NLP Finetune is a library that allows users to leverage state-of-the-art pretrained NLP models for a wide variety of downstream tasks.\n", + " true: natural-language-processing\n", + " pred: natural-language-processing\n", + "\n", + "Finetuning Transformers with JAX + Haiku Walking through a port of the RoBERTa pre-trained model to JAX + Haiku, then fine-tuning the model to solve a downstream task.\n", + " true: natural-language-processing\n", + " pred: natural-language-processing\n", + "\n", + "\n", + "=== False positives ===\n", + "Keras OCR A packaged and flexible version of the CRAFT text detector and Keras CRNN recognition model. \n", + " true: computer-vision\n", + " pred: natural-language-processing\n", + "\n", + "Open Compound Domain Adaptation Pytorch implementation for \"Open Compound Domain Adaptation\"\n", + " true: computer-vision\n", + " pred: natural-language-processing\n", + "\n", + "Unpopular Opinion - Data Scientists Should Be More End-to-End I believe data scientists can be more effective by being end-to-end.\n", + " true: mlops\n", + " pred: natural-language-processing\n", + "\n", + "\n", + "=== False negatives ===\n", + "Visualizing Memorization in RNNs Inspecting gradient magnitudes in context can be a powerful tool to see when recurrent units use short-term or long-term contextual understanding.\n", + " true: natural-language-processing\n", + " pred: computer-vision\n", + "\n", + "Machine Learning Projects This Repo contains projects done by me while learning the basics. All the familiar types of regression, classification, and clustering methods have been used.\n", + " true: natural-language-processing\n", + " pred: other\n", + "\n" + ] + } + ], + "source": [ + "# Samples\n", + "num_samples = 3\n", + "cm = [(tp, \"True positives\"), (fp, \"False positives\"), (fn, \"False negatives\")]\n", + "for item in cm:\n", + " if len(item[0]):\n", + " print (f\"\\n=== {item[1]} ===\")\n", + " for index in item[0][:num_samples]:\n", + " print (f\"{test_df.iloc[index].text}\")\n", + " print (f\" true: {test_df.tag[index]}\")\n", + " print (f\" pred: {test_df.prediction[index]}\\n\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "6S5LZdP2Myjh" + }, + "source": [ + "### Confidence learning" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "ZW5nY_h-M08p" + }, + "source": [ + "While the confusion-matrix sample analysis was a coarse-grained process, we can also use fine-grained confidence based approaches to identify potentially mislabeled samples. Here we’re going to focus on the specific labeling quality as opposed to the final model predictions.\n", + "\n", + "Simple confidence based techniques include identifying samples whose:\n", + "\n", + "**Categorical**\n", + "- prediction is incorrect (also indicate TN, FP, FN)\n", + "- confidence score for the correct class is below a threshold\n", + "- confidence score for an incorrect class is above a threshold\n", + "- standard deviation of confidence scores over top N samples is low\n", + "- different predictions from same model using different parameters\n", + "\n", + "**Continuous**\n", + "- difference between predicted and ground-truth values is above some %\n", + "\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "OuN8xKFZlo2t" + }, + "source": [ + "> The operations in this section can be applied to entire labeled dataset to discover labeling errors via confidence learning." + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": { + "id": "3FCrRUb2GANr", + "tags": [] + }, + "outputs": [], + "source": [ + "# Tag to inspect\n", + "tag = \"natural-language-processing\"\n", + "index = class_to_index[tag]\n", + "indices = np.where(y_test==index)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "id": "sKQxFU0iU-w-", + "tags": [] + }, + "outputs": [], + "source": [ + "# Confidence score for the correct class is below a threshold\n", + "low_confidence = []\n", + "min_threshold = 0.5\n", + "for i in indices:\n", + " prob = y_prob[i][index]\n", + " if prob <= 0.5:\n", + " low_confidence.append({\n", + " \"text\": f\"{test_df.iloc[i].text}\",\n", + " \"true\": test_df.tag[i], \n", + " \"pred\": test_df.prediction[i], \n", + " \"prob\": prob})" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7DnkXhXFFMv_", + "outputId": "c93cd01b-8ad1-4e63-8254-79f885534ffb", + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "[{'text': 'Visualizing Memorization in RNNs Inspecting gradient magnitudes in context can be a powerful tool to see when recurrent units use short-term or long-term contextual understanding.',\n", + " 'true': 'natural-language-processing',\n", + " 'pred': 'computer-vision',\n", + " 'prob': 0.0070185387},\n", + " {'text': 'Machine Learning Projects This Repo contains projects done by me while learning the basics. All the familiar types of regression, classification, and clustering methods have been used.',\n", + " 'true': 'natural-language-processing',\n", + " 'pred': 'other',\n", + " 'prob': 0.006060462}]" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "low_confidence[0:3]" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "JwL1ltdiUjH2" + }, + "source": [ + "But these are fairly crude techniques because neural networks are easily [overconfident](https://arxiv.org/abs/1706.04599) and so their confidences cannot be used without calibrating them. \n", + "\n", + "
\n", + " \"accuracy\n", + "
\n", + "
\n", + " Modern (large) neural networks result in higher accuracies but are over confident.
On Calibration of Modern Neural Networks
\n", + "
\n", + "\n", + "* **Assumption**: *“the probability associated with the predicted class label should reflect its ground truth correctness likelihood.”*\n", + "* **Reality**: *“modern (large) neural networks are no longer well-calibrated”*\n", + "* **Solution**: apply temperature scaling (extension of [Platt scaling](https://en.wikipedia.org/wiki/Platt_scaling){:target=\"_blank\"}) on model outputs\n", + "\n", + "Recent work on [confident learning](https://arxiv.org/abs/1911.00068) focuses on identifying noisy labels while accounting for this overconfidence which can then be properly relabeled and used for training." + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": { + "id": "XX3cORGPPXXM", + "tags": [] + }, + "outputs": [], + "source": [ + "import cleanlab\n", + "from cleanlab.filter import find_label_issues" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "*** SIGTERM received at time=1690247734 on cpu 6 ***\n", + "*** SIGTERM received at time=1690247734 on cpu 1 ***\n", + "*** SIGTERM received at time=1690247734 on cpu 0 ***\n", + "*** SIGTERM received at time=1690247734 on cpu 4 ***\n", + "PC: @ 0x7fb69c9c011b (unknown) _Exit\n", + " @ 0x7fb69cc3d420 28547728 (unknown)\n", + "PC: @ 0x4edd8a (unknown) _PyEval_MakeFrameVector\n", + " @ 0x7fb69cc3d420 (unknown) (unknown)\n", + "PC: @ 0x4ef4bc (unknown) _PyEval_EvalFrameDefault\n", + "PC: @ 0x4eddcd (unknown) _PyEval_MakeFrameVector\n", + " @ 0x7260e0 (unknown) (unknown)\n", + " @ 0x7fb69cc3d420 (unknown) (unknown)\n", + " @ 0x7fb69cc3d420 (unknown) (unknown)\n", + " @ ... and at least 1 more frames\n", + "[2023-07-24 18:15:34,914 E 284736 280376] logging.cc:361: *** SIGTERM received at time=1690247734 on cpu 6 ***\n", + "[2023-07-24 18:15:34,915 E 284736 280376] logging.cc:361: PC: @ 0x7fb69c9c011b (unknown) _Exit\n", + "[2023-07-24 18:15:34,915 E 284738 280376] logging.cc:361: *** SIGTERM received at time=1690247734 on cpu 4 ***\n", + "[2023-07-24 18:15:34,915 E 284738 280376] logging.cc:361: PC: @ 0x4ef4bc (unknown) _PyEval_EvalFrameDefault\n", + "[2023-07-24 18:15:34,915 E 284738 280376] logging.cc:361: @ 0x7fb69cc3d420 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,915 E 284738 280376] logging.cc:361: @ ... and at least 1 more frames\n", + " @ 0x72c720 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,917 E 284737 280376] logging.cc:361: *** SIGTERM received at time=1690247734 on cpu 1 ***\n", + "[2023-07-24 18:15:34,917 E 284737 280376] logging.cc:361: PC: @ 0x4edd8a (unknown) _PyEval_MakeFrameVector\n", + "[2023-07-24 18:15:34,918 E 284736 280376] logging.cc:361: @ 0x7fb69cc3d420 28547728 (unknown)\n", + " @ 0x72c720 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,920 E 284737 280376] logging.cc:361: @ 0x7fb69cc3d420 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,920 E 284735 280376] logging.cc:361: *** SIGTERM received at time=1690247734 on cpu 0 ***\n", + "[2023-07-24 18:15:34,921 E 284735 280376] logging.cc:361: PC: @ 0x4eddcd (unknown) _PyEval_MakeFrameVector\n", + "[2023-07-24 18:15:34,922 E 284736 280376] logging.cc:361: @ 0x7260e0 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,924 E 284737 280376] logging.cc:361: @ 0x72c720 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,926 E 284735 280376] logging.cc:361: @ 0x7fb69cc3d420 (unknown) (unknown)\n", + "[2023-07-24 18:15:34,932 E 284735 280376] logging.cc:361: @ 0x72c720 (unknown) (unknown)\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
idcreated_ontitledescriptiontagprediction
16521372020-08-13 02:10:03Unpopular Opinion - Data Scientists Should Be ...I believe data scientists can be more effectiv...mlopsnatural-language-processing
10314592020-06-16 03:06:10SuperGlue: Learning Feature Matching with Grap...SuperGlue, a neural network that matches two s...othercomputer-vision
18824132020-10-01 23:50:04Keeping Data Pipelines healthy w/ Great Expect...We show you how you can use GitHub Actions tog...mlopsnatural-language-processing
11215242020-06-20 10:42:25Machine Learning ProjectsThis Repo contains projects done by me while l...natural-language-processingother
253842020-04-08 21:22:25Visualizing Memorization in RNNsInspecting gradient magnitudes in context can ...natural-language-processingcomputer-vision
\n", + "
" + ], + "text/plain": [ + " id created_on \n", + "165 2137 2020-08-13 02:10:03 \\\n", + "103 1459 2020-06-16 03:06:10 \n", + "188 2413 2020-10-01 23:50:04 \n", + "112 1524 2020-06-20 10:42:25 \n", + "25 384 2020-04-08 21:22:25 \n", + "\n", + " title \n", + "165 Unpopular Opinion - Data Scientists Should Be ... \\\n", + "103 SuperGlue: Learning Feature Matching with Grap... \n", + "188 Keeping Data Pipelines healthy w/ Great Expect... \n", + "112 Machine Learning Projects \n", + "25 Visualizing Memorization in RNNs \n", + "\n", + " description \n", + "165 I believe data scientists can be more effectiv... \\\n", + "103 SuperGlue, a neural network that matches two s... \n", + "188 We show you how you can use GitHub Actions tog... \n", + "112 This Repo contains projects done by me while l... \n", + "25 Inspecting gradient magnitudes in context can ... \n", + "\n", + " tag prediction \n", + "165 mlops natural-language-processing \n", + "103 other computer-vision \n", + "188 mlops natural-language-processing \n", + "112 natural-language-processing other \n", + "25 natural-language-processing computer-vision " + ] + }, + "execution_count": 130, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Find label issues\n", + "label_issues = find_label_issues(labels=y_test, pred_probs=y_prob, return_indices_ranked_by=\"self_confidence\")\n", + "test_df.iloc[label_issues].drop(columns=[\"text\"]).head()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "UtXjpKf9FU4C" + }, + "source": [ + "Not all of these are necessarily labeling errors but situations where the predicted probabilities were not so confident. Therefore, it will be useful to attach the predictions alongside the data. This way, we can know if we need to relabel, upsample, etc. to improve our performance. Analysis like this could also shed light on the task itself. For example, you may notice that some projects involve multiple data modalities and so it's difficult to just assing one tag. So perhaps it might be better to make this taks a multilabel classification task instead (it does but we simplified it for this course)." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "dvS3UpusXP_R" + }, + "source": [ + "### Slice metrics" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "eeWWMG38Ny4U" + }, + "source": [ + "Just inspecting the overall and class metrics isn't enough to deploy our new version to production. There may be key slices of our dataset that we need to do really well on:\n", + "\n", + "- Target / predicted classes (+ combinations)\n", + "- Features (explicit and implicit)\n", + "- Metadata (timestamps, sources, etc.)\n", + "- Priority slices / experience (minority groups, large customers, etc.)\n", + "\n", + "An easy way to create and evaluate slices is to define slicing functions." + ] + }, + { + "cell_type": "code", + "execution_count": 131, + "metadata": { + "id": "ZyueOtQsXdGm", + "tags": [] + }, + "outputs": [], + "source": [ + "from snorkel.slicing import PandasSFApplier\n", + "from snorkel.slicing import slice_dataframe\n", + "from snorkel.slicing import slicing_function" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "metadata": { + "id": "coutP2KtXdLG", + "tags": [] + }, + "outputs": [], + "source": [ + "@slicing_function()\n", + "def nlp_llm(x):\n", + " \"\"\"NLP projects that use LLMs.\"\"\"\n", + " nlp_project = \"natural-language-processing\" in x.tag\n", + " llm_terms = [\"transformer\", \"llm\", \"bert\"]\n", + " llm_project = any(s.lower() in x.text.lower() for s in llm_terms)\n", + " return (nlp_project and llm_project)" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "metadata": { + "id": "PbxmLvi-D7lq", + "tags": [] + }, + "outputs": [], + "source": [ + "@slicing_function()\n", + "def short_text(x):\n", + " \"\"\"Projects with short titles and descriptions.\"\"\"\n", + " return len(x.text.split()) < 8 # less than 8 words" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "2Vxg5X9OD-Ax" + }, + "source": [ + "Here we're using Snorkel's [`slicing_function`](https://snorkel.readthedocs.io/en/latest/packages/_autosummary/slicing/snorkel.slicing.slicing_function.html) to create our different slices. We can visualize our slices by applying this slicing function to a relevant DataFrame using [`slice_dataframe`](https://snorkel.readthedocs.io/en/latest/packages/_autosummary/slicing/snorkel.slicing.slice_dataframe.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 134, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 98 + }, + "id": "VRs93KeBMthW", + "outputId": "b58e5925-7b89-4925-8afc-2f1eaa9b91db", + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [00:00<00:00, 28411.25it/s]\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
texttag
12Finetuning Transformers with JAX + Haiku Walki...natural-language-processing
19Question Answering with a Fine-Tuned BERT What...natural-language-processing
29BertViz Tool for visualizing attention in the ...natural-language-processing
30The Transformer Family This post presents how ...natural-language-processing
31Pruning Bert to Accelerate Inference After pre...natural-language-processing
\n", + "
" + ], + "text/plain": [ + " text \n", + "12 Finetuning Transformers with JAX + Haiku Walki... \\\n", + "19 Question Answering with a Fine-Tuned BERT What... \n", + "29 BertViz Tool for visualizing attention in the ... \n", + "30 The Transformer Family This post presents how ... \n", + "31 Pruning Bert to Accelerate Inference After pre... \n", + "\n", + " tag \n", + "12 natural-language-processing \n", + "19 natural-language-processing \n", + "29 natural-language-processing \n", + "30 natural-language-processing \n", + "31 natural-language-processing " + ] + }, + "execution_count": 134, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nlp_llm_df = slice_dataframe(test_df, nlp_llm)\n", + "nlp_llm_df[[\"text\", \"tag\"]].head()" + ] + }, + { + "cell_type": "code", + "execution_count": 135, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 224 + }, + "id": "B7jmdmNaXuA2", + "outputId": "84b59a83-9e58-44f1-f5c4-98e1a31507ea", + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [00:00<00:00, 52118.41it/s]\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
texttag
75NLPAug Data augmentation for NLPnatural-language-processing
123Offline Reinforcement Learning Challenges, alg...other
127Image Classifier Pure JavaScript Image Classifiercomputer-vision
132imgaug Image augmentation for machine learning...computer-vision
140QSVM Quantum SVM for sentiment analysisnatural-language-processing
\n", + "
" + ], + "text/plain": [ + " text \n", + "75 NLPAug Data augmentation for NLP \\\n", + "123 Offline Reinforcement Learning Challenges, alg... \n", + "127 Image Classifier Pure JavaScript Image Classifier \n", + "132 imgaug Image augmentation for machine learning... \n", + "140 QSVM Quantum SVM for sentiment analysis \n", + "\n", + " tag \n", + "75 natural-language-processing \n", + "123 other \n", + "127 computer-vision \n", + "132 computer-vision \n", + "140 natural-language-processing " + ] + }, + "execution_count": 135, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "short_text_df = slice_dataframe(test_df, short_text)\n", + "short_text_df[[\"text\", \"tag\"]].head()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "id": "kZuDZwTNO93Q" + }, + "source": [ + "We can define even more slicing functions and create a slices record array using the [`PandasSFApplier`](https://snorkel.readthedocs.io/en/latest/packages/_autosummary/slicing/snorkel.slicing.PandasSFApplier.html). The slices array has N (# of data points) items and each item has S (# of slicing functions) items, indicating whether that data point is part of that slice. Think of this record array as a masking layer for each slicing function on our data." + ] + }, + { + "cell_type": "code", + "execution_count": 136, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "mQG8PFovXfEm", + "outputId": "22f16ecb-ed18-4502-e734-7fe73041d597", + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 191/191 [00:00<00:00, 25025.37it/s]\n" + ] + }, + { + "data": { + "text/plain": [ + "rec.array([(0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (1, 0), (1, 0), (1, 0),\n", + " (1, 0), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 1), (0, 0), (0, 0), (1, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (1, 0), (0, 0),\n", + " (0, 0), (1, 0), (0, 0), (0, 0), (0, 0), (1, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (1, 0), (1, 0), (1, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (1, 0), (0, 0), (0, 0), (0, 1), (0, 0), (0, 0), (0, 0), (0, 1),\n", + " (1, 0), (0, 0), (1, 0), (1, 0), (0, 1), (1, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (1, 0), (0, 1), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 1), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (1, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (1, 0), (1, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (1, 0), (0, 0), (0, 0),\n", + " (0, 0), (1, 0), (0, 0), (0, 0), (0, 1), (0, 0), (0, 0), (0, 0),\n", + " (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (1, 0), (0, 0)],\n", + " dtype=[('nlp_llm', '