Repository: GokuMohandas/madewithml Branch: main Commit: 3361aeb8ddfc Files: 56 Total size: 3.0 MB Directory structure: gitextract_lbngfpom/ ├── .github/ │ └── workflows/ │ ├── documentation.yaml │ ├── json_to_md.py │ ├── serve.yaml │ └── workloads.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── LICENSE ├── Makefile ├── README.md ├── datasets/ │ ├── dataset.csv │ ├── holdout.csv │ ├── projects.csv │ └── tags.csv ├── deploy/ │ ├── cluster_compute.yaml │ ├── cluster_env.yaml │ ├── jobs/ │ │ ├── workloads.sh │ │ └── workloads.yaml │ └── services/ │ ├── serve_model.py │ └── serve_model.yaml ├── docs/ │ ├── index.md │ └── madewithml/ │ ├── data.md │ ├── evaluate.md │ ├── models.md │ ├── predict.md │ ├── serve.md │ ├── train.md │ ├── tune.md │ └── utils.md ├── madewithml/ │ ├── __init__.py │ ├── config.py │ ├── data.py │ ├── evaluate.py │ ├── models.py │ ├── predict.py │ ├── serve.py │ ├── train.py │ ├── tune.py │ └── utils.py ├── mkdocs.yml ├── notebooks/ │ ├── benchmarks.ipynb │ ├── clear_cell_nums.py │ └── madewithml.ipynb ├── pyproject.toml ├── requirements.txt └── tests/ ├── code/ │ ├── conftest.py │ ├── test_data.py │ ├── test_predict.py │ ├── test_train.py │ ├── test_tune.py │ ├── test_utils.py │ └── utils.py ├── data/ │ ├── conftest.py │ └── test_dataset.py └── model/ ├── conftest.py ├── test_behavioral.py └── utils.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/documentation.yaml ================================================ 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 ================================================ FILE: .github/workflows/json_to_md.py ================================================ 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) ================================================ FILE: .github/workflows/serve.yaml ================================================ 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 ================================================ FILE: .github/workflows/workloads.yaml ================================================ 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 ================================================ FILE: .gitignore ================================================ # Data logs/ stores/ mlflow/ results/ workspaces/ efs/ # 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/ ================================================ FILE: .pre-commit-config.yaml ================================================ # 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.5.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 ================================================ FILE: LICENSE ================================================ 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. ================================================ FILE: Makefile ================================================ # Makefile SHELL = /bin/bash # Styling .PHONY: style style: black . flake8 python3 -m isort . pyupgrade # Cleaning .PHONY: clean clean: style python notebooks/clear_cell_nums.py 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* ================================================ FILE: README.md ================================================

 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 (design + development) to production (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 day, 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-g5.4xlarge` ``` > 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 . ``` ### Credentials ```bash touch .env ``` ```bash # Inside .env GITHUB_USERNAME="CHANGE_THIS_TO_YOUR_USERNAME" # ← CHANGE THIS ``` ```bash source .env ``` ### 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 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 ``` Once the application is running, we can use it via cURL, Python, etc.: ```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 ```
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 ``` Once the application is running, we can use it via cURL, Python, etc.: ```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 tests/code --cov madewithml --cov-report html --disable-warnings # html report python3 -m pytest tests/code --cov madewithml --cov-report term --disable-warnings # terminal report ``` ## 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-g5.4xlarge" 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. Create a new github branch to save our changes to and execute CI/CD workloads: ```bash git remote set-url origin https://github.com/$GITHUB_USERNAME/Made-With-ML.git # <-- CHANGE THIS to your username git checkout -b dev ``` 2. 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 ``` 3. 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 $GITHUB_USERNAME # <-- CHANGE THIS to your username 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. 4. 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.
5. 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 ``` ================================================ FILE: datasets/dataset.csv ================================================ 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.",other 15,2020-02-28 23:55:26,Awesome Monte Carlo Tree Search,A curated list of Monte Carlo tree search papers with implementations. ,other 25,2020-03-07 23:04:31,AttentionWalk,"A PyTorch Implementation of ""Watch Your Step: Learning Node Embeddings via Graph Attention"" (NeurIPS 2018). ",other 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). ",other 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). ",other 29,2020-03-07 23:45:38,Signed Graph Convolutional Network,"A PyTorch implementation of ""Signed Graph Convolutional Network"" (ICDM 2018). ",other 45,2020-03-08 00:39:08,SimGNN,"A PyTorch implementation of ""SimGNN: A Neural Network Approach to Fast Graph Similarity Computation"" (WSDM 2019). ",other 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.,other 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. ,other 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.,other 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.,other 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.,other 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.",other 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. ,other 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.,other 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.",other 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.,other 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. ",other 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.,other 378,2020-04-08 19:37:57,Ray,Ray is a fast and simple framework for building and running distributed applications.,other 380,2020-04-08 21:05:06,Graph Nets,"PyTorch Implementation and Explanation of Graph Representation Learning papers involving DeepWalk, GCN, GraphSAGE, ChebNet & GAT.",other 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.,other 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.",other 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.,other 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,other 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!",other 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).",other 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.,other 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 ",other 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.,other 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,other 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.",other 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.,other 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.,other 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.,other 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.,other 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.,other 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),other 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,other 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 ",other 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.,other 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.,other 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.,other 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. ,other 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. ",other 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.,other 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.,other 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",other 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,other 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.,other 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.,other 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.,other 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.,other 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.,other 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.,other 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),other 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.",other 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.,other 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.,other 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.,other 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.",other 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.,other 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.,other 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.,other 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,other 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.,other 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.",other 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.",other 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.",other 1622,2020-06-27 14:18:13,Building AI Trading Systems,Lessons learned building a profitable algorithmic trading system using Reinforcement Learning techniques.,other 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.",other 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.,other 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.",other 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.",other 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.",other 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.",other 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.,other 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.,other 1792,2020-07-11 06:28:58,Anomaly Detection Toolkit (ADTK),"A Python toolkit for rule-based/unsupervised anomaly detection in time series ",other 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 ,other 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?,other 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.",other 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.,other 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.,other 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.",other 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.",other 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.",other 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.,other 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.,other 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,other 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.,other 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.,other 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.,other 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.,other 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.,other 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.,other 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.,other 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.,other 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.,other 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!!,other 2373,2020-09-25 22:41:22,GraphNorm,A Principled Approach to Accelerating Graph Neural Network Training.,other 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,other 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?,other 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,other 2418,2020-10-02 10:16:17,Top Research Papers from the ECML-PKDD 2020 Conference,ECML-PKDD -> selectionof the best reaesch papers,other 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!,other 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 ================================================ FILE: datasets/holdout.csv ================================================ 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. ,other 26,2020-03-07 23:11:58,Graph Wavelet Neural Network,"A PyTorch implementation of ""Graph Wavelet Neural Network"" (ICLR 2019) ",other 44,2020-03-08 00:32:58,Capsule Graph Neural Network,"A PyTorch implementation of ""Capsule Graph Neural Network"" (ICLR 2019).",other 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.,other 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.",other 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.,other 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.,other 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.",other 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",other 649,2020-04-28 03:42:29,Spektral,Graph Neural Networks with Keras and Tensorflow 2.,other 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,other 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",other 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.,other 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.,other 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).,other 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.,other 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",other 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),other 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.",other 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. ",other 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.",other 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.,other 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.,other 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,other 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.,other 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.,other 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 ================================================ FILE: datasets/projects.csv ================================================ 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." ================================================ FILE: datasets/tags.csv ================================================ 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 ================================================ FILE: deploy/cluster_compute.yaml ================================================ cloud: education-us-west-2 region: us-west-2 head_node_type: name: head_node_type instance_type: g5.4xlarge worker_node_types: - name: gpu_worker instance_type: g5.4xlarge min_workers: 1 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" ================================================ FILE: deploy/cluster_env.yaml ================================================ base_image: anyscale/ray:2.7.0optimized-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 ================================================ FILE: deploy/jobs/workloads.sh ================================================ #!/bin/bash export PYTHONPATH=$PYTHONPATH:$PWD 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 ================================================ FILE: deploy/jobs/workloads.yaml ================================================ name: workloads project_id: prj_wn6el5cu9dqwktk6t4cv54x8zh 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 ================================================ FILE: deploy/services/serve_model.py ================================================ 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) ================================================ FILE: deploy/services/serve_model.yaml ================================================ name: madewithml project_id: prj_wn6el5cu9dqwktk6t4cv54x8zh 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 ================================================ FILE: docs/index.md ================================================ ## 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) ================================================ FILE: docs/madewithml/data.md ================================================ ::: madewithml.data ================================================ FILE: docs/madewithml/evaluate.md ================================================ ::: madewithml.evaluate ================================================ FILE: docs/madewithml/models.md ================================================ ::: madewithml.models ================================================ FILE: docs/madewithml/predict.md ================================================ ::: madewithml.predict ================================================ FILE: docs/madewithml/serve.md ================================================ ::: madewithml.serve ================================================ FILE: docs/madewithml/train.md ================================================ ::: madewithml.train ================================================ FILE: docs/madewithml/tune.md ================================================ ::: madewithml.tune ================================================ FILE: docs/madewithml/utils.md ================================================ ::: madewithml.utils ================================================ FILE: madewithml/__init__.py ================================================ from dotenv import load_dotenv load_dotenv() ================================================ FILE: madewithml/config.py ================================================ # config.py import logging import os import sys from pathlib import Path import mlflow # Directories ROOT_DIR = Path(__file__).parent.parent.absolute() LOGS_DIR = Path(ROOT_DIR, "logs") LOGS_DIR.mkdir(parents=True, exist_ok=True) EFS_DIR = Path(f"/efs/shared_storage/madewithml/{os.environ.get('GITHUB_USERNAME', '')}") try: Path(EFS_DIR).mkdir(parents=True, exist_ok=True) except OSError: EFS_DIR = Path(ROOT_DIR, "efs") Path(EFS_DIR).mkdir(parents=True, exist_ok=True) # Config MLflow MODEL_REGISTRY = Path(f"{EFS_DIR}/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", ] ================================================ FILE: madewithml/data.py ================================================ import re from typing import Dict, List, Tuple import numpy as np import pandas as pd import ray from ray.data import Dataset 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: """Custom preprocessor class.""" def __init__(self, class_to_index={}): self.class_to_index = class_to_index or {} # mutable defaults self.index_to_class = {v: k for k, v in self.class_to_index.items()} 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()} return self def transform(self, ds): return ds.map_batches(preprocess, fn_kwargs={"class_to_index": self.class_to_index}, batch_format="pandas") ================================================ FILE: madewithml/evaluate.py ================================================ 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 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 from madewithml.predict import TorchPredictor # 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 predictions = preprocessed_ds.map_batches(predictor).take_all() y_pred = np.array([d["output"] for d in predictions]) # 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() ================================================ FILE: madewithml/models.py ================================================ import json import os from pathlib import Path import torch import torch.nn as nn import torch.nn.functional as F from transformers import BertModel class FinetunedLLM(nn.Module): def __init__(self, llm, dropout_p, embedding_dim, num_classes): super(FinetunedLLM, self).__init__() self.llm = llm self.dropout_p = dropout_p self.embedding_dim = embedding_dim self.num_classes = num_classes 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 @torch.inference_mode() def predict(self, batch): self.eval() z = self(batch) y_pred = torch.argmax(z, dim=1).cpu().numpy() return y_pred @torch.inference_mode() def predict_proba(self, batch): self.eval() z = self(batch) y_probs = F.softmax(z, dim=1).cpu().numpy() return y_probs def save(self, dp): with open(Path(dp, "args.json"), "w") as fp: contents = { "dropout_p": self.dropout_p, "embedding_dim": self.embedding_dim, "num_classes": self.num_classes, } json.dump(contents, fp, indent=4, sort_keys=False) torch.save(self.state_dict(), os.path.join(dp, "model.pt")) @classmethod def load(cls, args_fp, state_dict_fp): with open(args_fp, "r") as fp: kwargs = json.load(fp=fp) llm = BertModel.from_pretrained("allenai/scibert_scivocab_uncased", return_dict=False) model = cls(llm=llm, **kwargs) model.load_state_dict(torch.load(state_dict_fp, map_location=torch.device("cpu"))) return model ================================================ FILE: madewithml/predict.py ================================================ import json from pathlib import Path from typing import Any, Dict, Iterable, List from urllib.parse import urlparse import numpy as np import ray import typer from numpyencoder import NumpyEncoder from ray.air import Result from ray.train.torch.torch_checkpoint import TorchCheckpoint from typing_extensions import Annotated from madewithml.config import logger, mlflow from madewithml.data import CustomPreprocessor from madewithml.models import FinetunedLLM from madewithml.utils import collate_fn # 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 class TorchPredictor: def __init__(self, preprocessor, model): self.preprocessor = preprocessor self.model = model self.model.eval() def __call__(self, batch): results = self.model.predict(collate_fn(batch)) return {"output": results} def predict_proba(self, batch): results = self.model.predict_proba(collate_fn(batch)) return {"output": results} def get_preprocessor(self): return self.preprocessor @classmethod def from_checkpoint(cls, checkpoint): metadata = checkpoint.get_metadata() preprocessor = CustomPreprocessor(class_to_index=metadata["class_to_index"]) model = FinetunedLLM.load(Path(checkpoint.path, "args.json"), Path(checkpoint.path, "model.pt")) return cls(preprocessor=preprocessor, model=model) def predict_proba( ds: ray.data.dataset.Dataset, 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 (TorchPredictor): loaded predictor from a checkpoint. Returns: List: list of predicted labels. """ preprocessor = predictor.get_preprocessor() preprocessed_ds = preprocessor.transform(ds) outputs = preprocessed_ds.map_batches(predictor.predict_proba) y_prob = np.array([d["output"] for d in outputs.take_all()]) results = [] for i, prob in enumerate(y_prob): tag = preprocessor.index_to_class[prob.argmax()] 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) # Predict sample_ds = ray.data.from_items([{"title": title, "description": description, "tag": "other"}]) results = predict_proba(ds=sample_ds, predictor=predictor) logger.info(json.dumps(results, cls=NumpyEncoder, indent=2)) return results if __name__ == "__main__": # pragma: no cover, application app() ================================================ FILE: madewithml/serve.py ================================================ import argparse import os from http import HTTPStatus from typing import Dict import ray from fastapi import FastAPI from ray import serve 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(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 = predict.TorchPredictor.from_checkpoint(best_checkpoint) @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): data = await request.json() sample_ds = ray.data.from_items([{"title": data.get("title", ""), "description": data.get("description", ""), "tag": ""}]) results = predict.predict_proba(ds=sample_ds, 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(runtime_env={"env_vars": {"GITHUB_USERNAME": os.environ["GITHUB_USERNAME"]}}) serve.run(ModelDeployment.bind(run_id=args.run_id, threshold=args.threshold)) ================================================ FILE: madewithml/train.py ================================================ import datetime import json import os import tempfile 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.integrations.mlflow import MLflowLoggerCallback from ray.data import Dataset from ray.train import ( Checkpoint, CheckpointConfig, DataConfig, RunConfig, ScalingConfig, ) from ray.train.torch import TorchTrainer from torch.nn.parallel.distributed import DistributedDataParallel from transformers import BertModel from typing_extensions import Annotated from madewithml import data, utils from madewithml.config import EFS_DIR, MLFLOW_TRACKING_URI, logger from madewithml.models import FinetunedLLM # 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"] num_epochs = config["num_epochs"] batch_size = config["batch_size"] num_classes = config["num_classes"] # Get datasets utils.set_seeds() train_ds = train.get_dataset_shard("train") val_ds = train.get_dataset_shard("val") # Model llm = BertModel.from_pretrained("allenai/scibert_scivocab_uncased", return_dict=False) model = 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 num_workers = train.get_context().get_world_size() batch_size_per_worker = batch_size // num_workers 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 with tempfile.TemporaryDirectory() as dp: if isinstance(model, DistributedDataParallel): # cpu model.module.save(dp=dp) else: model.save(dp=dp) metrics = dict(epoch=epoch, lr=optimizer.param_groups[0]["lr"], train_loss=train_loss, val_loss=val_loss) checkpoint = Checkpoint.from_directory(dp) train.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}, ) # 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, storage_path=EFS_DIR, local_dir=EFS_DIR) # 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 options = ray.data.ExecutionOptions(preserve_order=True) dataset_config = DataConfig(datasets_to_split=["train"], execution_options=options) # Preprocess preprocessor = data.CustomPreprocessor() preprocessor = preprocessor.fit(train_ds) train_ds = preprocessor.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, metadata={"class_to_index": preprocessor.class_to_index}, ) # 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(runtime_env={"env_vars": {"GITHUB_USERNAME": os.environ["GITHUB_USERNAME"]}}) app() ================================================ FILE: madewithml/tune.py ================================================ import datetime import json import os 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 EFS_DIR, 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}, ) # 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() preprocessor = preprocessor.fit(train_ds) train_ds = preprocessor.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, metadata={"class_to_index": preprocessor.class_to_index}, ) # 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, storage_path=EFS_DIR, local_dir=EFS_DIR) # 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(runtime_env={"env_vars": {"GITHUB_USERNAME": os.environ["GITHUB_USERNAME"]}}) app() ================================================ FILE: madewithml/utils.py ================================================ 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 ================================================ FILE: mkdocs.yml ================================================ 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 ================================================ FILE: notebooks/benchmarks.ipynb ================================================ { "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": null, "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": null, "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": null, "id": "1790e2f5-6b8b-425c-8842-a2b0ea8f3f07", "metadata": { "tags": [] }, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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": null, "id": "aa5b95d5-d61e-48e4-9100-d9d2fc0d53fa", "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "['computer-vision', 'other', 'natural-language-processing', 'mlops']" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Unique labels\n", "tags = train_df.tag.unique().tolist()\n", "tags" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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": null, "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 } ================================================ FILE: notebooks/clear_cell_nums.py ================================================ from pathlib import Path import nbformat def clear_execution_numbers(nb_path): with open(nb_path, "r", encoding="utf-8") as f: nb = nbformat.read(f, as_version=4) for cell in nb["cells"]: if cell["cell_type"] == "code": cell["execution_count"] = None for output in cell["outputs"]: if "execution_count" in output: output["execution_count"] = None with open(nb_path, "w", encoding="utf-8") as f: nbformat.write(nb, f) if __name__ == "__main__": NOTEBOOK_DIR = Path(__file__).parent notebook_fps = list(NOTEBOOK_DIR.glob("**/*.ipynb")) for fp in notebook_fps: clear_execution_numbers(fp) ================================================ FILE: notebooks/madewithml.ipynb ================================================ { "cells": [ { "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", "
" ] }, { "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." ] }, { "cell_type": "markdown", "metadata": { "id": "XTNsIiUrqoJW" }, "source": [ "
\n", " \n", " \n", "\"Open\n", "
" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "# 🛠️ Setup" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import os\n", "import ray" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import sys; sys.path.append(\"..\")\n", "import warnings; warnings.filterwarnings(\"ignore\")\n", "from dotenv import load_dotenv; load_dotenv()\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-12-07 11:26:30,445\tINFO worker.py:1633 -- Started a local Ray instance. View the dashboard at \u001b[1m\u001b[32m127.0.0.1:8265 \u001b[39m\u001b[22m\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "afcfdccd644b41d0b7af7f86f68dbdf3", "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.11
Ray version:2.7.0
Dashboard:http://127.0.0.1:8265
\n", "\n", "
\n", "
\n" ], "text/plain": [ "RayContext(dashboard_url='127.0.0.1:8265', python_version='3.10.11', ray_version='2.7.0', ray_commit='b4bba4717f5ba04ee25580fe8f88eed63ef0c5dc', protocol_version=None)" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Initialize Ray\n", "if ray.is_initialized():\n", " ray.shutdown()\n", "ray.init()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'memory': 30507458560.0,\n", " 'CPU': 12.0,\n", " 'node:__internal_head__': 1.0,\n", " 'node:127.0.0.1': 1.0,\n", " 'object_store_memory': 2147483648.0}" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ray.cluster_resources()" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "# Workers (1 g4dn.xlarge)\n", "num_workers = 1\n", "resources_per_worker={\"CPU\": 3, \"GPU\": 1}" ] }, { "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", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "/efs/shared_storage/madewithml/GokuMohandas\n" ] } ], "source": [ "# Storage\n", "EFS_DIR = f\"/efs/shared_storage/madewithml/{os.environ['GITHUB_USERNAME']}\"\n", "print (EFS_DIR)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Data" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## 🔢 Data ingestion" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import pandas as pd" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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()" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## ✂️ Data splitting" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from sklearn.model_selection import train_test_split" ] }, { "cell_type": "code", "execution_count": null, "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": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Value counts\n", "df.tag.value_counts()" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Train value counts\n", "train_df.tag.value_counts()" ] }, { "cell_type": "code", "execution_count": null, "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": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Validation (adjusted) value counts\n", "val_df.tag.value_counts() * int((1-test_size) / test_size)" ] }, { "cell_type": "markdown", "metadata": { "id": "WuCrsbxbNkSV" }, "source": [ "## 🔍 Exploratory Data Analysis (EDA)" ] }, { "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": null, "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": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "[('natural-language-processing', 310),\n", " ('computer-vision', 285),\n", " ('other', 106),\n", " ('mlops', 63)]" ] }, "execution_count": null, "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": null, "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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rEBwcDCAV/diBQUFISIiAgcPHsS1a9cwYsQI2NvbIyAgwMB7R0REREREJUWR6S4IAHPnzsWcOXMwYsQIpKWlwdvbG2vXrkXFihUBAD/99BPCwsLQvn17lC9fHmPGjEH79u3F5YcNG4bs7GxMmDABGRkZ8PHxwfLly2FsbGyoXSIiIiIiohJGIgiCYOgiirKcHBWePn2ul3UZGUlhZVUK477fhbsPU/SyTqK8VK1khfD/fYaUlOe8J4uIiIhID6ytS2k98EWR6S5IRERERET0IWDIIiIiIiIi0qMidU8WEX34pFIJpFKJocugEkClEqBSsUc8EREVPoYsIio0UqkEVlZmkEplhi6FSgCVKgcpKekMWkREVOgYsoio0Ly6iiXDnZ0/Iv3JY0OXQx8wM5sKcGz9NaRSCUMWEREVOoYsIip06U8eIz3hnqHLICIiInovOPAFERERERGRHjFkERERERER6RFDFhERERERkR4xZBEREREREekRQxYREREREZEeMWQRERERERHpEUMWERERERGRHjFkERERERER6RFDFhERERERkR4xZBEREREREekRQxYREREREZEeMWQRERERERHpEUMWERERERGRHjFkERERERER6RFDFhERERERkR4xZBEREREREekRQxYREREREZEeMWQRERERERHpUZEKWampqZg0aRL8/Pzg5eWFrl274ty5c+L03r17w9nZWeO/7t27i9MzMzMxZcoUNGjQAJ6enhg1ahSePn1qiF0hIiIiIqISysjQBbxu5MiRSEpKwty5c2FjY4PVq1ejb9++2LJlC6pVq4a///4b3377LZo3by4uY2xsLP7722+/xblz57Bw4ULI5XJMnjwZw4YNw5o1awyxO0REREREVAIVmZAVFxeH48ePY926dahbty4AYOLEiTh69Ch27NiBoKAgPHnyBO7u7ihfvnyu5RMSErB161YsWbIE3t7eAIC5c+eiVatWuHDhAjw9PQt1f4iIiIiIqGQqMiHLysoKy5YtQ506dcQ2iUQCiUQCpVKJv//+GxKJBI6Ojnkuf/78eQBA/fr1xTZHR0fY2dnh7Nmz7xSyjIz006tSJitSvTOpBChqx1xRq4c+fDzmiIjIEIpMyLK0tESTJk002vbu3Yu4uDiMGzcO169fh4WFBaZOnYrjx4/D3NwcrVq1wqBBgyCXy5GQkAAr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WPdp06YhPDwcQ4YMAQD4+fm9071hREREREREBaVTyFIoFDh8+DCCgoJyTcvJycFvv/2GGjVqFGidAwYMwIABA/5zHj8/P/j5+eU73dzcHNOnT8f06dMLtG0iIiIiIiJ90am7YFBQEI4fP47p06fj1q1bAIAXL17g0qVLGDBgAGJjY/HFF1/otVAiIiIiIqLiQKcrWYGBgbh27RqWL1+OtWvXAoDYRU8QBHTq1AmdOnXSX5VERERERETFhM73ZH3zzTdo2bIldu7cibt370KlUqFy5cpo2bKlxn1SREREREREJYnOIQsA3Nzc4Obmpq9aiIiIiIiIij2tQtb9+/dRrlw5mJmZiY+1IZFIUKpUKVhZWeleIRERERERUTGiVcgKCAjArFmzEBgYCABo0aIFJBKJ1hupVKkS5s2bhzp16uhWJRERERERUTGhVchq164dHBwcNB5rE7IEQYBSqcSJEycwefJkREdH614pERERERFRMaBVyJoxY4bG45kzZxZoI/PmzcOqVasKtAwREREREVFx9E4DXwiCgJiYGDx48AByuRwVK1ZEzZo1c83n5eWFxMTEd9kUERERERFRsaBzyPrzzz8RGhqKe/fuabQ7ODggLCwM3t7eYluTJk3QpEkT3askIiIiIiIqJnQKWbdu3ULfvn3x8uVLtGvXDjVq1EBOTg5u3LiBXbt24euvv0Z0dDQcHR31XS8REREREVGRplPIWrRoEaRSKaKjo6FQKDSm9evXD126dMHSpUsLfO8WERERERFRcSfVZaGTJ0+ia9euuQIWACgUCnTt2hUnTpx45+KIiIiIiIiKG51CllKpROXKlfOdXqVKFaSkpOhcFBERERERUXGlU8iyt7fHpUuX8p3+119/wdbWVueiiIiIiIiIiiudQlbz5s2xdetWbNmyJde0zZs3Y9u2bfD393/n4oiIiIiIiIobnQa+GDRoEA4ePIhx48Zh8eLFqFatGoBXow4+ePAAFSpUwKBBg/RaKBERERERUXGg05UsS0tLbNiwAe3bt0dKSgqOHDmCI0eOICUlBe3atcOmTZtgZWWl71qJiIiIiIiKPJ2uZB04cAA+Pj4IDw9HWFgYUlJSIAgCrK2tIZFI9F0jERERERFRsaHTlazx48dj2bJlAACJRAJra2vY2NgwYBERERERUYmnU8jKyspClSpV9F0LERERERFRsadTyOrYsSPWrFmDhw8f6rseIiIiIiKiYk2ne7KysrLw6NEjNG/eHJUrV4aNjQ1kMpnGPBKJBGvWrNFLkURERERERMWFTiFr06ZN4r/v37+P+/fv55rnXe/PWrp0KY4dO4bVq1eLbRMmTMAvv/yiMV+lSpVw6NAhAIBKpUJkZCR++eUXpKWlwcfHB5MmTWLXRiIiIiIiKjQ6haxr167puw4Na9euxfz58+Ht7a3R/vfff2PAgAEICgoS216/grZo0SKsW7cOM2fOhL29PWbPno1+/fphx44dkMvl77VmIiIiIiIiQMd7st6XhIQEDBgwABEREahatarGNEEQcPPmTdSuXRvly5cX/7O2tgbwqgtjVFQUhg0bhqZNm8LFxQXz5s1DfHw89u3bZ4C9ISIiIiKikkjnkPX8+XMsWLAArVu3hru7O7y8vNCxY0esWLEC2dnZOq3zypUrMDY2xvbt2+Hu7q4x7d69e3jx4gWqVauW57LXrl3D8+fP0aBBA7HN0tISrq6uOHv2rE71EBERERERFZRO3QWfPn2Krl27Ii4uDhYWFnByckJ2djbu3LmD7777Dnv27MGqVasK3EXP398f/v7+eU67fv06AGD16tX4448/IJVK4efnhxEjRsDCwgLx8fEAgAoVKmgsZ2trK07TlZGRfi74yWRF6sIhlQBF7ZgravXQh4/HHBERGYJOIWv+/Pm4d+8exo0bh6+++gpGRq9Wk5WVhRUrVmDu3LlYvHgx/ve//+mt0OvXr0MqlcLW1hZLlizBvXv3MGvWLNy4cQMrV65Eeno6AOQKdiYmJnj27JnO25VKJbCyKvVOtRMZiqWlmaFLIDIongNERGQIOoWsw4cPo3PnzujRo4dGu1wuR//+/XH79m3s2LFDryFr4MCB+Oqrr2BlZQUAUCgUKF++PL744gtcvnwZpqamAF4FPfW/ASAzMxNmZrp/yKpUApTKF+9W/P+TyaT8wKdCpVSmIydHZegyRDwHqLAVtXOAiIiKL0tLM617SOgUstLS0uDi4pLvdHd3d+zevVuXVedLKpWKAUutRo0aAID4+Hixm2BiYiIcHBzEeRITE+Hs7PxO287O5gc0FU85OSoev1Si8RwgIiJD0Kmzeq1atfDHH3/kO/3ChQv/GcJ0MWbMGPTq1Uuj7fLlywCA6tWrw8XFBaVLl8bp06fF6UqlErGxsfDx8dFrLURERERERPnRKWSNHz8e58+fx+TJk/HkyROxPT09HQsXLsT+/fsxceJEqFQqjf/eRcuWLXHy5ElERkbi3r17+P333zFu3Di0bt0aTk5OkMvlCAoKQkREBA4ePIhr165hxIgRsLe3R0BAwDttm4iIiIiISFs6dRccPnw4JBIJNm3ahE2bNsHKygpyuRxJSUlQqVQQBAGdO3fWWEYikSA2NlbnQj/55BPMnz8fy5Ytw48//ggLCwsEBgZi+PDh4jzDhg1DdnY2JkyYgIyMDPj4+GD58uUwNjbWebtEREREREQFoVPIsrOzg52dXa72KlWqvHNBajNnzszV9umnn+LTTz/NdxmZTIZvvvkG33zzjd7qICIiIiIiKgidQtbq1av1XQcREREREdEHgb/SSEREREREpEcMWURERERERHrEkEVERERERKRHDFlERERERER6pFXIio+Pf991EBERERERfRC0ClkdOnTAxo0bxceRkZG4fv36eyuKiIiIiIiouNIqZKWlpSEzM1N8HBkZib///vu9FUVERERERFRcafU7WVWqVMHixYvx+PFjlCpVCgCwf/9+xMXF5buMRCLB4MGD9VMlERERERFRMaFVyBoxYgRGjRqFn3/+GcCrALVv3z7s27cv32UYsoiIiIiIqCTSKmS1aNECv//+O27duoWsrCz06dMHwcHBqF+//vuuj4iIiIiIqFjRKmQBgJWVFby9vQEAPj4+qF+/Pho0aPDeCiMiIiIiIiqOtA5Zr1u9ejUAQBAExMTE4MGDB5DL5ahYsSJq1qyp1wKJiIiIiIiKE51CFgD8+eefCA0Nxb179zTaHRwcEBYWJl71IiIiIiIiKkl0Clm3bt1C37598fLlS7Rr1w41atRATk4Obty4gV27duHrr79GdHQ0HB0d9V0vERERERFRkaZTyFq0aBGkUimio6OhUCg0pvXr1w9dunTB0qVLMXPmTL0USUREREREVFxo9WPEbzp58iS6du2aK2ABgEKhQNeuXXHixIl3Lo6IiIiIiKi40SlkKZVKVK5cOd/pVapUQUpKis5FERERERERFVc6hSx7e3tcunQp3+l//fUXbG1tdS6KiIiIiIiouNIpZDVv3hxbt27Fli1bck3bvHkztm3bBn9//3cujoiIiIiIqLjRaeCLQYMG4eDBgxg3bhwWL16MatWqAXg16uCDBw9QoUIFDBo0SK+FEhERERERFQc6XcmytLTEhg0b0L59e6SkpODIkSM4cuQIUlJS0K5dO2zatAlWVlb6rpWIiIiIiKjI0/nHiG1sbBAeHo6wsDCkpKRAEARYW1tDIpHosz4iIiIiIqJiReeQpSaRSGBtba2PWoiIiIiIiIq9dw5Z78vSpUtx7NgxrF69Wmy7evUqwsLCEBMTA2tra/Tq1Qs9evQQp6tUKkRGRuKXX35BWloafHx8MGnSJFSpUsUQu0BERJQnqVQCqZQ9P+j9U6kEqFSCocsgKnGKZMhau3Yt5s+fD29vb7EtJSUFvXv3hr+/P6ZMmYKLFy9iypQpKFWqFDp27AgAWLRoEdatW4eZM2fC3t4es2fPRr9+/bBjxw7I5XJD7Q4REZFIKpWgrJUZZFKZoUuhEiBHlYPUlHQGLaJCVqRCVkJCAiZPnozTp0+jatWqGtM2bdoEY2NjTJ06FUZGRnByckJcXByWLVuGjh07IisrC1FRURg9ejSaNm0KAJg3bx4aN26Mffv2oXXr1oW/Q0RERG+QSiWQSWVY+vsqPHqWYOhy6ANWsYwdgpv0gFQqYcgiKmRFKmRduXIFxsbG2L59O3744Qc8fPhQnHbu3Dn4+vrCyOjfkuvXr4+lS5ciOTkZjx49wvPnz9GgQQNxuqWlJVxdXXH27FmGLCIiKlIePUtA3JMHhi6DiIjeA51CVmhoKLp06QJ3d3cAwIsXLzBt2jT069cPTk5OOhfj7++f748Yx8fHQ6FQaLTZ2toCAB4/foz4+HgAQIUKFXLNo56mKyMjnUa6z0Um0896iLRV1I65olYPffiK4jFXFGuiDxuPOaLCp1XIGjBgAGrXrg03NzfUrl0bW7ZsQcOGDcWQlZmZia1bt6JNmzbvFLL+S0ZGRq77qkxMTMTtp6enA0Ce8zx79kzn7UqlElhZldJ5eSJDsrQ0M3QJRAbFc4CI5wGRIWgVsrKysrB69Wo8e/YMEokEEokE69evx+PHj1G7dm1UrFgRgvB++/qampoiKytLoy0zMxMAYG5uDlNTU7FW9b/V85iZ6f7molIJUCpf6Lz862QyKd/oqFAplenIyVEZugwRzwEqbEXtHAB4HlDhK4rnAVFxZGlppvWVYa1CVlRUFADg3r17uHTpEkaPHo34+HgsWrQI6enpYvCKiorC7du34eHhARcXF8hk+hs5yd7eHomJiRpt6sd2dnbIzs4W2xwcHDTmcXZ2fqdtZ2fzjYmKp5wcFY9fKtF4DhDxPCAyhAJ10nVwcBAHkBg+fDj+/PNP7Ny5ExMnToQgCLh79y5mzpyJjh07agy/rg8+Pj44f/48cnJyxLZTp07B0dERNjY2cHFxQenSpXH69GlxulKpRGxsLHx8fPRaCxERERERUX60ClknTpyAUqnM1S6RSFC9enV8+umnAICpU6fi/PnzWL9+PYYPH67XQjt27Ih//vkH48ePx82bNxEdHY0VK1YgODgYwKt7sYKCghAREYGDBw/i2rVrGDFiBOzt7REQEKDXWoiIiIiIiPKjVXfBPn36QCKRoHLlyqhduzYkEgkePXqE9PT0XPc7yeVyeHp6wtPTU6+F2tjY4KeffkJYWBjat2+P8uXLY8yYMWjfvr04z7Bhw5CdnY0JEyYgIyMDPj4+WL58OYyNjfVaCxERERERUX60Cll79uzB5cuXxf8EQcD8+fOxYMECVK1aFU5OTpBIJLh37x68vb31EmpmzpyZq83NzQ0bN27MdxmZTIZvvvkG33zzzTtvn4iIiIiISBdahayqVauiatWqCAwMBAC4uLhg8ODBqFChAmJjY8Xg9e233yIsLAyurq7w8PBASEjIey2eiIiIiIioqNHpx4gB4KOPPkJgYCA6duyIp0+f4uOPP8b48eMhlUpx4cIFHD58mCGLiIiIiIhKHJ1Clo+PD8qVKyc+lsvl8PHxgZeXF1xdXfHVV1/prUAiIiIiIqLiRKeQtXr1ao3HpUuXztVGRERERERUEhXod7KIiIiIiIjovzFkERERERER6RFDFhERERERkR4xZBEREREREekRQxYREREREZEeMWQRERERERHpEUMWERERERGRHjFkERERERER6RFDFhERERERkR4xZBEREREREekRQxYREREREZEeMWQRERERERHpEUMWERERERGRHjFkERERERER6ZGRoQsgIiIiopJHKpVAKpUYugwqAVQqASqVUKjbZMgiIiIiokIllUpgVdYMUpnM0KVQCaDKyUFKanqhBi2GLCIiIiIqVFKpBFKZDBcXL8U/jx4buhz6gJWuWAEeA4MhlUoYsoiIiIjow/fPo8dQxsUZugwivePAF0RERERERHpU7EJWQkICnJ2dc/0XHR0NALh69SqCgoLg4eEB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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()" ] }, { "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": null, "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": null, "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)" ] }, { "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." ] }, { "cell_type": "markdown", "metadata": { "id": "HFifXKl_eKsN" }, "source": [ "## ✨ Data Preprocessing" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import json\n", "import nltk\n", "from nltk.corpus import stopwords\n", "from nltk.stem import PorterStemmer\n", "import re" ] }, { "cell_type": "markdown", "metadata": { "id": "6VgTwEQboTGc" }, "source": [ "### Feature engineering" ] }, { "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": null, "metadata": { "id": "3x1ldAFQNkSU", "tags": [] }, "outputs": [], "source": [ "# Feature engineering\n", "df[\"text\"] = df.title + \" \" + df.description" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Clean text" ] }, { "cell_type": "code", "execution_count": null, "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 /Users/goku/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": null, "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": null, "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]}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Clean DataFrame" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Label encoding" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'mlops': 0,\n", " 'natural-language-processing': 1,\n", " 'computer-vision': 2,\n", " 'other': 3}" ] }, "execution_count": null, "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": null, "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": null, "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": null, "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": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "['computer-vision', 'computer-vision', 'other', 'other', 'other']" ] }, "execution_count": null, "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)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Tokenizer" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import numpy as np\n", "from transformers import BertTokenizer" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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": null, "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": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Tokenization\n", "tokenize(df.head(1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll combine all of our preprocessing steps into function:" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Apply\n", "preprocess(df=train_df, class_to_index=class_to_index)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Distributed preprocessing" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from madewithml.data import stratify_split\n", "ray.data.DatasetContext.get_current().execution_options.preserve_order = True" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-12-07 11:26:57,951\tINFO read_api.py:406 -- To satisfy the requested parallelism of 24, each read task output is split into 24 smaller blocks.\n", "2023-12-07 11:26:57,959\tINFO dataset.py:2380 -- Tip: Use `take_batch()` instead of `take() / show()` to return records in pandas or numpy batch format.\n", "2023-12-07 11:26:57,960\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", "2023-12-07 11:26:57,961\tINFO streaming_executor.py:94 -- 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-12-07 11:26:57,961\tINFO streaming_executor.py:96 -- 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/576 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", "2023-12-07 11:26:59,974\tINFO streaming_executor.py:94 -- 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-12-07 11:26:59,974\tINFO streaming_executor.py:96 -- 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/576 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", "2023-12-07 11:27:00,813\tINFO streaming_executor.py:94 -- 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-12-07 11:27:00,814\tINFO streaming_executor.py:96 -- 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/576 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/576 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", "2023-12-07 11:27:01,561\tINFO streaming_executor.py:94 -- 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-12-07 11:27:01,562\tINFO streaming_executor.py:96 -- 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/576 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/576 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)] -> LimitOperator[limit=1]\n", "2023-12-07 11:27:02,546\tINFO streaming_executor.py:94 -- 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-12-07 11:27:02,546\tINFO streaming_executor.py:96 -- 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/576 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/576 [00:00\n", "\u001b[2m\u001b[36m(MapBatches(preprocess) pid=21398)\u001b[0m Traceback (most recent call last):\n", "\u001b[2m\u001b[36m(MapBatches(preprocess) pid=21398)\u001b[0m File \"/Users/goku/Documents/tobias/venv/lib/python3.10/site-packages/ray/data/dataset.py\", line 5222, in __del__\n", "\u001b[2m\u001b[36m(MapBatches(preprocess) pid=21398)\u001b[0m if self._current_executor and ray is not None and ray.is_initialized():\n", "\u001b[2m\u001b[36m(MapBatches(preprocess) pid=21398)\u001b[0m KeyboardInterrupt: \n" ] } ], "source": [ "# Distributed preprocessing\n", "sample_ds = train_ds.map_batches(preprocess, fn_kwargs={\"class_to_index\": class_to_index}, batch_format=\"pandas\")\n", "sample_ds.show(1)" ] }, { "cell_type": "markdown", "metadata": { "id": "lGvI2YuuNkSX", "tags": [] }, "source": [ "# Training" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When developing models, it's always a best practice to start with the simplest models and slowly motivate more complex models. For example our baseline model progression would be: \n", "\n", "1. random model (predict labels randomly)\n", "2. rule-based model (pattern match labels in input text)\n", "3. logistic regression (td-idf vectors from text)\n", "4. CNN (apply character filters over text)\n", "5. Fine-tune LLM (this notebook)\n", "\n", "We cover all of these methods in our [other lessons](https://madewithml.com/#foundations) but since our focus here in on MLOps, we will skip directly to fine-tuning an LLM for our task." ] }, { "cell_type": "markdown", "metadata": { "id": "K9CfUuNh2YLE" }, "source": [ "We'll first set up some functions that will help us achieve complete reproducibility." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "86sFERmsuPQl", "tags": [] }, "outputs": [], "source": [ "import os\n", "import random\n", "import torch\n", "from ray.data.preprocessor import Preprocessor" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "NXd8flJuNkSY", "tags": [] }, "outputs": [], "source": [ "def set_seeds(seed=42):\n", " \"\"\"Set seeds for reproducibility.\"\"\"\n", " np.random.seed(seed)\n", " random.seed(seed)\n", " torch.manual_seed(seed)\n", " torch.cuda.manual_seed(seed)\n", " eval(\"setattr(torch.backends.cudnn, 'deterministic', True)\")\n", " eval(\"setattr(torch.backends.cudnn, 'benchmark', False)\")\n", " os.environ[\"PYTHONHASHSEED\"] = str(seed)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "def load_data(num_samples=None):\n", " ds = ray.data.read_csv(DATASET_LOC)\n", " ds = ds.random_shuffle(seed=1234)\n", " ds = ray.data.from_items(ds.take(num_samples)) if num_samples else ds\n", " return ds" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "class CustomPreprocessor():\n", " \"\"\"Custom preprocessor class.\"\"\"\n", " def __init__(self, class_to_index={}):\n", " self.class_to_index = class_to_index or {} # mutable defaults\n", " self.index_to_class = {v: k for k, v in self.class_to_index.items()}\n", " \n", " def fit(self, ds):\n", " tags = ds.unique(column=\"tag\")\n", " self.class_to_index = {tag: i for i, tag in enumerate(tags)}\n", " self.index_to_class = {v:k for k, v in self.class_to_index.items()}\n", " return self\n", " \n", " def transform(self, ds):\n", " return ds.map_batches(\n", " preprocess, \n", " fn_kwargs={\"class_to_index\": self.class_to_index}, \n", " batch_format=\"pandas\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 🤖 Model" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "import torch.nn as nn\n", "from transformers import BertModel" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Some weights of the model checkpoint at allenai/scibert_scivocab_uncased were not used when initializing BertModel: ['cls.predictions.decoder.weight', 'cls.predictions.transform.dense.bias', 'cls.predictions.bias', 'cls.seq_relationship.weight', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.dense.weight', 'cls.predictions.decoder.bias']\n", "- 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", "- 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" ] } ], "source": [ "# Pretrained LLM\n", "llm = BertModel.from_pretrained(\"allenai/scibert_scivocab_uncased\", return_dict=False)\n", "embedding_dim = llm.config.hidden_size" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "(torch.Size([1, 10, 768]), torch.Size([1, 768]))" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Sample\n", "text = \"Transfer learning with transformers for text classification.\"\n", "batch = tokenizer([text], return_tensors=\"np\", padding=\"longest\")\n", "batch = {k:torch.tensor(v) for k,v in batch.items()} # convert to torch tensors\n", "seq, pool = llm(input_ids=batch[\"input_ids\"], attention_mask=batch[\"attention_mask\"])\n", "np.shape(seq), np.shape(pool)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "class FinetunedLLM(nn.Module):\n", " def __init__(self, llm, dropout_p, embedding_dim, num_classes):\n", " super(FinetunedLLM, self).__init__()\n", " self.llm = llm\n", " self.dropout_p = dropout_p\n", " self.embedding_dim = embedding_dim\n", " self.num_classes = num_classes\n", " self.dropout = torch.nn.Dropout(dropout_p)\n", " self.fc1 = torch.nn.Linear(embedding_dim, num_classes)\n", "\n", " def forward(self, batch):\n", " ids, masks = batch[\"ids\"], batch[\"masks\"]\n", " seq, pool = self.llm(input_ids=ids, attention_mask=masks)\n", " z = self.dropout(pool)\n", " z = self.fc1(z)\n", " return z\n", " \n", " @torch.inference_mode()\n", " def predict(self, batch):\n", " self.eval()\n", " z = self(batch)\n", " y_pred = torch.argmax(z, dim=1).cpu().numpy()\n", " return y_pred\n", " \n", " @torch.inference_mode()\n", " def predict_proba(self, batch):\n", " self.eval()\n", " z = self(batch)\n", " y_probs = F.softmax(z, dim=1).cpu().numpy()\n", " return y_probs\n", " \n", " def save(self, dp):\n", " with open(Path(dp, \"args.json\"), \"w\") as fp:\n", " contents = {\n", " \"dropout_p\": self.dropout_p,\n", " \"embedding_dim\": self.embedding_dim,\n", " \"num_classes\": self.num_classes,\n", " }\n", " json.dump(contents, fp, indent=4, sort_keys=False)\n", " torch.save(self.state_dict(), os.path.join(dp, \"model.pt\"))\n", "\n", " @classmethod\n", " def load(cls, args_fp, state_dict_fp):\n", " with open(args_fp, \"r\") as fp:\n", " kwargs = json.load(fp=fp)\n", " llm = BertModel.from_pretrained(\"allenai/scibert_scivocab_uncased\", return_dict=False)\n", " model = cls(llm=llm, **kwargs)\n", " model.load_state_dict(torch.load(state_dict_fp, map_location=torch.device(\"cpu\")))\n", " return model" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\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)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 📦 Batching" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created a temporary directory at /var/folders/x8/ffj4btjx0cv6r653rgfnffsc0000gn/T/tmpfieao6lq\n", "Writing /var/folders/x8/ffj4btjx0cv6r653rgfnffsc0000gn/T/tmpfieao6lq/_remote_module_non_scriptable.py\n" ] } ], "source": [ "from ray.train.torch import get_device" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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" ] }, { "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": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-12-07 11:27:34,483\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(24)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)] -> LimitOperator[limit=128]\n", "2023-12-07 11:27:34,484\tINFO streaming_executor.py:94 -- 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-12-07 11:27:34,484\tINFO streaming_executor.py:96 -- 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/576 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/576 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", "2023-09-18 21:57:50,565\tINFO streaming_executor.py:94 -- 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-09-18 21:57:50,566\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", "2023-09-18 21:57:51,012\tINFO streaming_executor.py:94 -- 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-09-18 21:57:51,012\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", "2023-09-18 21:57:53,337\tINFO streaming_executor.py:94 -- 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-09-18 21:57:53,338\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", "2023-09-18 21:57:54,977\tINFO streaming_executor.py:94 -- 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-09-18 21:57:54,977\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", "2023-09-18 21:57:56,897\tINFO streaming_executor.py:94 -- 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-09-18 21:57:56,898\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00\n", "
\n", "
\n", "

Tune Status

\n", " \n", "\n", "\n", "\n", "\n", "\n", "
Current time:2023-09-18 21:59:12
Running for: 00:01:13.39
Memory: 22.2/62.1 GiB
\n", "
\n", "
\n", "
\n", "

System Info

\n", " Using FIFO scheduling algorithm.
Logical resource usage: 4.0/32 CPUs, 1.0/2 GPUs (0.0/2.0 accelerator_type:A10G)\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_1a81f_00000TERMINATED10.0.34.101:727773 10 68.3685 90.0001 0.0525064
\n", "
\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[2m\u001b[36m(TorchTrainer pid=727773, ip=10.0.34.101)\u001b[0m Starting distributed worker processes: ['727834 (10.0.34.101)']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=727834, ip=10.0.34.101)\u001b[0m Setting up process group for: env:// [rank=0, world_size=1]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Auto configuring locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=727834, ip=10.0.34.101)\u001b[0m Moving model to device: cuda:0\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Executing DAG InputDataBuffer[Input] -> OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=727900, ip=10.0.34.101)\u001b[0m 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": [ "(pid=727900, ip=10.0.34.101) Running 0: 0%| | 0/64 [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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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_losstimestampshould_checkpointdonetraining_iterationtrial_iddate...time_since_restoreiterations_since_restorecheckpoint_dir_nameconfig/train_loop_config/dropout_pconfig/train_loop_config/lrconfig/train_loop_config/lr_factorconfig/train_loop_config/lr_patienceconfig/train_loop_config/num_epochsconfig/train_loop_config/batch_sizeconfig/train_loop_config/num_classes
000.00010.5770600.4994631695099495TrueFalse11a81f_000002023-09-18_21-58-15...12.8838821checkpoint_0000000.50.00010.83102564
110.00010.4977960.4546311695099501TrueFalse21a81f_000002023-09-18_21-58-21...18.9866892checkpoint_0000010.50.00010.83102564
220.00010.4324760.3242191695099507TrueFalse31a81f_000002023-09-18_21-58-27...25.0888693checkpoint_0000020.50.00010.83102564
330.00010.3196990.2500691695099513TrueFalse41a81f_000002023-09-18_21-58-33...31.1925354checkpoint_0000030.50.00010.83102564
440.00010.2438720.2089181695099519TrueFalse51a81f_000002023-09-18_21-58-39...37.3382415checkpoint_0000040.50.00010.83102564
550.00010.1888710.1830511695099525TrueFalse61a81f_000002023-09-18_21-58-45...43.4585406checkpoint_0000050.50.00010.83102564
660.00010.1453480.1396731695099532TrueFalse71a81f_000002023-09-18_21-58-52...49.5594157checkpoint_0000060.50.00010.83102564
770.00010.1029190.1266151695099538TrueFalse81a81f_000002023-09-18_21-58-58...56.1167728checkpoint_0000070.50.00010.83102564
880.00010.0740930.1357461695099544TrueFalse91a81f_000002023-09-18_21-59-04...62.2195639checkpoint_0000080.50.00010.83102564
990.00010.0525060.1135681695099550TrueFalse101a81f_000002023-09-18_21-59-10...68.36852610checkpoint_0000090.50.00010.83102564
\n", "

10 rows × 25 columns

\n", "" ], "text/plain": [ " epoch lr train_loss val_loss timestamp should_checkpoint done \\\n", "0 0 0.0001 0.577060 0.499463 1695099495 True False \n", "1 1 0.0001 0.497796 0.454631 1695099501 True False \n", "2 2 0.0001 0.432476 0.324219 1695099507 True False \n", "3 3 0.0001 0.319699 0.250069 1695099513 True False \n", "4 4 0.0001 0.243872 0.208918 1695099519 True False \n", "5 5 0.0001 0.188871 0.183051 1695099525 True False \n", "6 6 0.0001 0.145348 0.139673 1695099532 True False \n", "7 7 0.0001 0.102919 0.126615 1695099538 True False \n", "8 8 0.0001 0.074093 0.135746 1695099544 True False \n", "9 9 0.0001 0.052506 0.113568 1695099550 True False \n", "\n", " training_iteration trial_id date ... \\\n", "0 1 1a81f_00000 2023-09-18_21-58-15 ... \n", "1 2 1a81f_00000 2023-09-18_21-58-21 ... \n", "2 3 1a81f_00000 2023-09-18_21-58-27 ... \n", "3 4 1a81f_00000 2023-09-18_21-58-33 ... \n", "4 5 1a81f_00000 2023-09-18_21-58-39 ... \n", "5 6 1a81f_00000 2023-09-18_21-58-45 ... \n", "6 7 1a81f_00000 2023-09-18_21-58-52 ... \n", "7 8 1a81f_00000 2023-09-18_21-58-58 ... \n", "8 9 1a81f_00000 2023-09-18_21-59-04 ... \n", "9 10 1a81f_00000 2023-09-18_21-59-10 ... \n", "\n", " time_since_restore iterations_since_restore checkpoint_dir_name \\\n", "0 12.883882 1 checkpoint_000000 \n", "1 18.986689 2 checkpoint_000001 \n", "2 25.088869 3 checkpoint_000002 \n", "3 31.192535 4 checkpoint_000003 \n", "4 37.338241 5 checkpoint_000004 \n", "5 43.458540 6 checkpoint_000005 \n", "6 49.559415 7 checkpoint_000006 \n", "7 56.116772 8 checkpoint_000007 \n", "8 62.219563 9 checkpoint_000008 \n", "9 68.368526 10 checkpoint_000009 \n", "\n", " config/train_loop_config/dropout_p config/train_loop_config/lr \\\n", "0 0.5 0.0001 \n", "1 0.5 0.0001 \n", "2 0.5 0.0001 \n", "3 0.5 0.0001 \n", "4 0.5 0.0001 \n", "5 0.5 0.0001 \n", "6 0.5 0.0001 \n", "7 0.5 0.0001 \n", "8 0.5 0.0001 \n", "9 0.5 0.0001 \n", "\n", " config/train_loop_config/lr_factor config/train_loop_config/lr_patience \\\n", "0 0.8 3 \n", "1 0.8 3 \n", "2 0.8 3 \n", "3 0.8 3 \n", "4 0.8 3 \n", "5 0.8 3 \n", "6 0.8 3 \n", "7 0.8 3 \n", "8 0.8 3 \n", "9 0.8 3 \n", "\n", " config/train_loop_config/num_epochs config/train_loop_config/batch_size \\\n", "0 10 256 \n", "1 10 256 \n", "2 10 256 \n", "3 10 256 \n", "4 10 256 \n", "5 10 256 \n", "6 10 256 \n", "7 10 256 \n", "8 10 256 \n", "9 10 256 \n", "\n", " config/train_loop_config/num_classes \n", "0 4 \n", "1 4 \n", "2 4 \n", "3 4 \n", "4 4 \n", "5 4 \n", "6 4 \n", "7 4 \n", "8 4 \n", "9 4 \n", "\n", "[10 rows x 25 columns]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Metrics per epoch\n", "results.metrics_dataframe" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "[(Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/llm/TorchTrainer_e2941_00000_0_2023-09-17_22-40-33/checkpoint_000009),\n", " {'epoch': 9,\n", " 'lr': 0.0001,\n", " 'train_loss': 0.052506402134895325,\n", " 'val_loss': 0.11356845498085022,\n", " 'timestamp': 1695015703,\n", " 'should_checkpoint': True,\n", " 'done': False,\n", " 'training_iteration': 10,\n", " 'trial_id': 'e2941_00000',\n", " 'date': '2023-09-17_22-41-43',\n", " 'time_this_iter_s': 6.128554105758667,\n", " 'time_total_s': 66.49748063087463,\n", " 'pid': 842775,\n", " 'hostname': 'ip-10-0-35-174',\n", " 'node_ip': '10.0.35.174',\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': 66.49748063087463,\n", " 'iterations_since_restore': 10})]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Best checkpoints\n", "results.best_checkpoints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Evaluation" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from sklearn.metrics import precision_recall_fscore_support" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "class TorchPredictor:\n", " def __init__(self, preprocessor, model):\n", " self.preprocessor = preprocessor\n", " self.model = model\n", " self.model.eval()\n", " \n", " def __call__(self, batch):\n", " results = self.model.predict(collate_fn(batch))\n", " return {\"output\": results}\n", "\n", " def predict_proba(self, batch):\n", " results = self.model.predict_proba(collate_fn(batch))\n", " return {\"output\": results}\n", " \n", " def get_preprocessor(self):\n", " return self.preprocessor\n", " \n", " @classmethod\n", " def from_checkpoint(cls, checkpoint):\n", " metadata = checkpoint.get_metadata()\n", " preprocessor = CustomPreprocessor(class_to_index=metadata[\"class_to_index\"])\n", " model = FinetunedLLM.load(Path(checkpoint.path, \"args.json\"), Path(checkpoint.path, \"model.pt\"))\n", " return cls(preprocessor=preprocessor, model=model)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "# Artifacts\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": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-09-17 22:41:46,264\tINFO read_api.py:406 -- To satisfy the requested parallelism of 64, each read task output is split into 64 smaller blocks.\n", "2023-09-17 22:41:46,268\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)] -> LimitOperator[limit=1]\n", "2023-09-17 22:41:46,268\tINFO streaming_executor.py:94 -- 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-09-17 22:41:46,269\tINFO streaming_executor.py:96 -- 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/1 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches()]\n", "2023-09-17 22:41:46,831\tINFO streaming_executor.py:94 -- 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-09-17 22:41:46,832\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor)]\n", "2023-09-17 22:41:47,785\tINFO streaming_executor.py:94 -- 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-09-17 22:41:47,786\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(TorchPredictor) pid=348532, ip=10.0.34.101)\u001b[0m /tmp/ipykernel_841208/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" ] } ], "source": [ "# y_pred\n", "predictions = preprocessed_ds.map_batches(predictor).take_all()\n", "y_pred = np.array([d[\"output\"] for d in predictions])" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'precision': 0.9138952286238713,\n", " 'recall': 0.9109947643979057,\n", " 'f1': 0.9114851103432928}" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Evaluate\n", "metrics = precision_recall_fscore_support(y_true, y_pred, average=\"weighted\")\n", "{\"precision\": metrics[0], \"recall\": metrics[1], \"f1\": metrics[2]}" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "def evaluate(ds, predictor):\n", " # y_true\n", " preprocessor = predictor.get_preprocessor()\n", " preprocessed_ds = preprocessor.transform(ds)\n", " values = preprocessed_ds.select_columns(cols=[\"targets\"]).take_all()\n", " y_true = np.stack([item[\"targets\"] for item in values])\n", " \n", " # y_pred\n", " predictions = preprocessed_ds.map_batches(predictor).take_all()\n", " y_pred = np.array([d[\"output\"] for d in predictions])\n", "\n", " # Evaluate\n", " metrics = precision_recall_fscore_support(y_true, y_pred, average=\"weighted\")\n", " performance = {\"precision\": metrics[0], \"recall\": metrics[1], \"f1\": metrics[2]}\n", " return performance" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-09-17 22:41:54,734\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches()]\n", "2023-09-17 22:41:54,734\tINFO streaming_executor.py:94 -- 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-09-17 22:41:54,735\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor)]\n", "2023-09-17 22:41:55,456\tINFO streaming_executor.py:94 -- 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-09-17 22:41:55,456\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor.predict_proba)]\n", "2023-09-17 22:42:00,134\tINFO streaming_executor.py:94 -- 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-09-17 22:42:00,134\tINFO streaming_executor.py:96 -- 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/1 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", "2023-09-17 22:42:01,337\tINFO streaming_executor.py:94 -- 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-09-17 22:42:01,338\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", "2023-09-17 22:42:01,795\tINFO streaming_executor.py:94 -- 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-09-17 22:42:01,796\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", "2023-09-17 22:42:03,340\tINFO streaming_executor.py:94 -- 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-09-17 22:42:03,340\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", "2023-09-17 22:42:05,079\tINFO streaming_executor.py:94 -- 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-09-17 22:42:05,079\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", "2023-09-17 22:42:07,293\tINFO streaming_executor.py:94 -- 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-09-17 22:42:07,293\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00\n", "
\n", "
\n", "

Tune Status

\n", " \n", "\n", "\n", "\n", "\n", "\n", "
Current time:2023-09-17 22:43:31
Running for: 00:01:21.68
Memory: 20.8/62.1 GiB
\n", "
\n", "
\n", "
\n", "

System Info

\n", " Using FIFO scheduling algorithm.
Logical resource usage: 4.0/32 CPUs, 1.0/2 GPUs (0.0/2.0 accelerator_type:A10G)\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_1bd07_00000TERMINATED10.0.35.174:844750 10 63.6994 90.0001 0.0421994
\n", "
\n", "\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[2m\u001b[36m(TorchTrainer pid=844750)\u001b[0m Starting distributed worker processes: ['844833 (10.0.35.174)']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Setting up process group for: env:// [rank=0, world_size=1]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Auto configuring locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Moving model to device: cuda:0\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m /tmp/ipykernel_841208/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", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000000)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000001)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000002)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000003)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000004)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000005)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000006)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "2023-09-17 22:43:01,995\tWARNING worker.py:2012 -- [tqdm_ray] Failed to decode {\"__magic_token__\": \"__ray_tqdm_magic_token__\", \"x\": 47, \"pos\": 0, \"desc\": \"Running: 0.0/32.0 CPU, 0.0/2.0 GPU, 0.28 MiB/8.95 GiB object_store_memory\", \"total\": 64, \"ip\": \"10.0.35.174\", \"pid\": 844909, \"uuid\": \"54df93474628434c, this may be due to logging too fast. This warning will not be printed again.\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m 8d2fe8f67788261f\", \"closed\": false}\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000007)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000008)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=844909) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=844909)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=844833)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-42-09/TorchTrainer_1bd07_00000_0_2023-09-17_22-42-09/checkpoint_000009)\n", "2023-09-17 22:43:31,004\tINFO tune.py:1143 -- Total run time: 81.76 seconds (81.66 seconds for the tuning loop).\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 1.23 s, sys: 1.31 s, total: 2.53 s\n", "Wall time: 1min 21s\n" ] } ], "source": [ "%%time\n", "# Train\n", "results = trainer.fit()" ] }, { "cell_type": "code", "execution_count": null, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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_losstimestampshould_checkpointdonetraining_iterationtrial_iddate...time_since_restoreiterations_since_restorecheckpoint_dir_nameconfig/train_loop_config/dropout_pconfig/train_loop_config/lrconfig/train_loop_config/lr_factorconfig/train_loop_config/lr_patienceconfig/train_loop_config/num_epochsconfig/train_loop_config/batch_sizeconfig/train_loop_config/num_classes
000.00010.5777800.4931021695015745TrueFalse11bd07_000002023-09-17_22-42-25...11.8825751checkpoint_0000000.50.00010.83102564
110.00010.4896530.4319581695015751TrueFalse21bd07_000002023-09-17_22-42-31...17.6544352checkpoint_0000010.50.00010.83102564
220.00010.3988240.3062011695015757TrueFalse31bd07_000002023-09-17_22-42-37...23.3537523checkpoint_0000020.50.00010.83102564
330.00010.3005130.2388031695015763TrueFalse41bd07_000002023-09-17_22-42-43...29.1189924checkpoint_0000030.50.00010.83102564
440.00010.2206080.1744111695015769TrueFalse51bd07_000002023-09-17_22-42-49...34.8974855checkpoint_0000040.50.00010.83102564
550.00010.1514990.1586481695015775TrueFalse61bd07_000002023-09-17_22-42-55...40.6453846checkpoint_0000050.50.00010.83102564
660.00010.1050870.1128291695015781TrueFalse71bd07_000002023-09-17_22-43-01...46.3875687checkpoint_0000060.50.00010.83102564
770.00010.0773850.0919221695015788TrueFalse81bd07_000002023-09-17_22-43-08...52.1533438checkpoint_0000070.50.00010.83102564
880.00010.0538570.1098101695015794TrueFalse91bd07_000002023-09-17_22-43-14...57.9010849checkpoint_0000080.50.00010.83102564
990.00010.0421990.1211221695015800TrueFalse101bd07_000002023-09-17_22-43-20...63.69944410checkpoint_0000090.50.00010.83102564
\n", "

10 rows × 25 columns

\n", "
" ], "text/plain": [ " epoch lr train_loss val_loss timestamp should_checkpoint done \\\n", "0 0 0.0001 0.577780 0.493102 1695015745 True False \n", "1 1 0.0001 0.489653 0.431958 1695015751 True False \n", "2 2 0.0001 0.398824 0.306201 1695015757 True False \n", "3 3 0.0001 0.300513 0.238803 1695015763 True False \n", "4 4 0.0001 0.220608 0.174411 1695015769 True False \n", "5 5 0.0001 0.151499 0.158648 1695015775 True False \n", "6 6 0.0001 0.105087 0.112829 1695015781 True False \n", "7 7 0.0001 0.077385 0.091922 1695015788 True False \n", "8 8 0.0001 0.053857 0.109810 1695015794 True False \n", "9 9 0.0001 0.042199 0.121122 1695015800 True False \n", "\n", " training_iteration trial_id date ... \\\n", "0 1 1bd07_00000 2023-09-17_22-42-25 ... \n", "1 2 1bd07_00000 2023-09-17_22-42-31 ... \n", "2 3 1bd07_00000 2023-09-17_22-42-37 ... \n", "3 4 1bd07_00000 2023-09-17_22-42-43 ... \n", "4 5 1bd07_00000 2023-09-17_22-42-49 ... \n", "5 6 1bd07_00000 2023-09-17_22-42-55 ... \n", "6 7 1bd07_00000 2023-09-17_22-43-01 ... \n", "7 8 1bd07_00000 2023-09-17_22-43-08 ... \n", "8 9 1bd07_00000 2023-09-17_22-43-14 ... \n", "9 10 1bd07_00000 2023-09-17_22-43-20 ... \n", "\n", " time_since_restore iterations_since_restore checkpoint_dir_name \\\n", "0 11.882575 1 checkpoint_000000 \n", "1 17.654435 2 checkpoint_000001 \n", "2 23.353752 3 checkpoint_000002 \n", "3 29.118992 4 checkpoint_000003 \n", "4 34.897485 5 checkpoint_000004 \n", "5 40.645384 6 checkpoint_000005 \n", "6 46.387568 7 checkpoint_000006 \n", "7 52.153343 8 checkpoint_000007 \n", "8 57.901084 9 checkpoint_000008 \n", "9 63.699444 10 checkpoint_000009 \n", "\n", " config/train_loop_config/dropout_p config/train_loop_config/lr \\\n", "0 0.5 0.0001 \n", "1 0.5 0.0001 \n", "2 0.5 0.0001 \n", "3 0.5 0.0001 \n", "4 0.5 0.0001 \n", "5 0.5 0.0001 \n", "6 0.5 0.0001 \n", "7 0.5 0.0001 \n", "8 0.5 0.0001 \n", "9 0.5 0.0001 \n", "\n", " config/train_loop_config/lr_factor config/train_loop_config/lr_patience \\\n", "0 0.8 3 \n", "1 0.8 3 \n", "2 0.8 3 \n", "3 0.8 3 \n", "4 0.8 3 \n", "5 0.8 3 \n", "6 0.8 3 \n", "7 0.8 3 \n", "8 0.8 3 \n", "9 0.8 3 \n", "\n", " config/train_loop_config/num_epochs config/train_loop_config/batch_size \\\n", "0 10 256 \n", "1 10 256 \n", "2 10 256 \n", "3 10 256 \n", "4 10 256 \n", "5 10 256 \n", "6 10 256 \n", "7 10 256 \n", "8 10 256 \n", "9 10 256 \n", "\n", " config/train_loop_config/num_classes \n", "0 4 \n", "1 4 \n", "2 4 \n", "3 4 \n", "4 4 \n", "5 4 \n", "6 4 \n", "7 4 \n", "8 4 \n", "9 4 \n", "\n", "[10 rows x 25 columns]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results.metrics_dataframe" ] }, { "cell_type": "code", "execution_count": null, "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.config/train_loop_config/lr_patiencemetrics.time_total_smetrics.time_since_restoremetrics.config/train_loop_config/num_epochs...metrics.epochparams.train_loop_config/num_epochsparams.train_loop_config/lr_patienceparams.train_loop_config/batch_sizeparams.train_loop_config/lrparams.train_loop_config/lr_factorparams.train_loop_config/num_classesparams.train_loop_config/dropout_ptags.trial_nametags.mlflow.runName
0a67f6ec4e10b49a7845b91db61efc7e0703905858072772764FINISHEDfile:///efs/shared_storage/madewithml/GokuMoha...2023-09-18 05:42:12.863000+00:002023-09-18 05:43:30.925000+00:003.063.69944463.69944410.0...9.01032560.00010.840.5TorchTrainer_1bd07_00000TorchTrainer_1bd07_00000
\n", "

1 rows × 35 columns

\n", "
" ], "text/plain": [ " run_id experiment_id status \\\n", "0 a67f6ec4e10b49a7845b91db61efc7e0 703905858072772764 FINISHED \n", "\n", " artifact_uri \\\n", "0 file:///efs/shared_storage/madewithml/GokuMoha... \n", "\n", " start_time end_time \\\n", "0 2023-09-18 05:42:12.863000+00:00 2023-09-18 05:43:30.925000+00:00 \n", "\n", " metrics.config/train_loop_config/lr_patience metrics.time_total_s \\\n", "0 3.0 63.699444 \n", "\n", " metrics.time_since_restore metrics.config/train_loop_config/num_epochs \\\n", "0 63.699444 10.0 \n", "\n", " ... metrics.epoch params.train_loop_config/num_epochs \\\n", "0 ... 9.0 10 \n", "\n", " params.train_loop_config/lr_patience params.train_loop_config/batch_size \\\n", "0 3 256 \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/num_classes params.train_loop_config/dropout_p \\\n", "0 4 0.5 \n", "\n", " tags.trial_name tags.mlflow.runName \n", "0 TorchTrainer_1bd07_00000 TorchTrainer_1bd07_00000 \n", "\n", "[1 rows x 35 columns]" ] }, "execution_count": null, "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": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "run_id a67f6ec4e10b49a7845b91db61efc7e0\n", "experiment_id 703905858072772764\n", "status FINISHED\n", "artifact_uri file:///efs/shared_storage/madewithml/GokuMoha...\n", "start_time 2023-09-18 05:42:12.863000+00:00\n", "end_time 2023-09-18 05:43:30.925000+00:00\n", "metrics.config/train_loop_config/lr_patience 3.0\n", "metrics.time_total_s 63.699444\n", "metrics.time_since_restore 63.699444\n", "metrics.config/train_loop_config/num_epochs 10.0\n", "metrics.iterations_since_restore 10.0\n", "metrics.config/train_loop_config/batch_size 256.0\n", "metrics.pid 844750.0\n", "metrics.should_checkpoint 1.0\n", "metrics.timestamp 1695015800.0\n", "metrics.config/train_loop_config/num_classes 4.0\n", "metrics.done 0.0\n", "metrics.time_this_iter_s 5.79836\n", "metrics.train_loss 0.042199\n", "metrics.config/train_loop_config/lr 0.0001\n", "metrics.lr 0.0001\n", "metrics.val_loss 0.121122\n", "metrics.config/train_loop_config/dropout_p 0.5\n", "metrics.training_iteration 10.0\n", "metrics.config/train_loop_config/lr_factor 0.8\n", "metrics.epoch 9.0\n", "params.train_loop_config/num_epochs 10\n", "params.train_loop_config/lr_patience 3\n", "params.train_loop_config/batch_size 256\n", "params.train_loop_config/lr 0.0001\n", "params.train_loop_config/lr_factor 0.8\n", "params.train_loop_config/num_classes 4\n", "params.train_loop_config/dropout_p 0.5\n", "tags.trial_name TorchTrainer_1bd07_00000\n", "tags.mlflow.runName TorchTrainer_1bd07_00000\n", "Name: 0, dtype: object" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Best run\n", "best_run = sorted_runs.iloc[0]\n", "best_run" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dashboard" ] }, { "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 $EFS_DIR/mlflow\n", "```" ] }, { "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" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Loading" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "from ray.train import Result\n", "from urllib.parse import urlparse" ] }, { "cell_type": "code", "execution_count": null, "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": null, "metadata": {}, "outputs": [], "source": [ "# Artifacts\n", "best_checkpoint = get_best_checkpoint(run_id=best_run.run_id)\n", "predictor = TorchPredictor.from_checkpoint(best_checkpoint)\n", "preprocessor = predictor.get_preprocessor()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-09-17 22:43:36,691\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches()]\n", "2023-09-17 22:43:36,692\tINFO streaming_executor.py:94 -- 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-09-17 22:43:36,692\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor)]\n", "2023-09-17 22:43:37,552\tINFO streaming_executor.py:94 -- 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-09-17 22:43:37,553\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(TorchPredictor) pid=845827)\u001b[0m /tmp/ipykernel_841208/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": [ "{\n", " \"precision\": 0.9168092951711627,\n", " \"recall\": 0.9109947643979057,\n", " \"f1\": 0.9105512639658029\n", "}\n" ] } ], "source": [ "# Evaluate on test split\n", "performance = evaluate(ds=test_ds, predictor=predictor)\n", "print (json.dumps(performance, indent=2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-09-17 22:43:43,282\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor.predict_proba)]\n", "2023-09-17 22:43:43,282\tINFO streaming_executor.py:94 -- 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-09-17 22:43:43,283\tINFO streaming_executor.py:96 -- 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/1 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> LimitOperator[limit=1]\n", "2023-09-17 22:43:44,427\tINFO streaming_executor.py:94 -- 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-09-17 22:43:44,427\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> LimitOperator[limit=1]\n", "2023-09-17 22:43:44,886\tINFO streaming_executor.py:94 -- 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-09-17 22:43:44,887\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> AllToAllOperator[Aggregate] -> TaskPoolMapOperator[MapBatches()]\n", "2023-09-17 22:43:46,123\tINFO streaming_executor.py:94 -- 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-09-17 22:43:46,123\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", "2023-09-17 22:43:47,914\tINFO streaming_executor.py:94 -- 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-09-17 22:43:47,914\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> AllToAllOperator[RandomShuffle] -> AllToAllOperator[Sort] -> AllToAllOperator[MapBatches(group_fn)->MapBatches(_filter_split)->RandomShuffle] -> TaskPoolMapOperator[MapBatches(preprocess)]\n", "2023-09-17 22:43:50,092\tINFO streaming_executor.py:94 -- 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-09-17 22:43:50,093\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(_filter_split)->RandomShuffle 8: 0%| | 0/4096 [00:00) per trial\n", " grace_period=5, # min epoch () per trial\n", ")" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/html": [ "
\n", "
\n", "
\n", "

Tune Status

\n", " \n", "\n", "\n", "\n", "\n", "\n", "
Current time:2023-09-17 22:45:41
Running for: 00:01:49.07
Memory: 21.8/62.1 GiB
\n", "
\n", "
\n", "
\n", "

System Info

\n", " Using AsyncHyperBand: num_stopped=2
Bracket: Iter 5.000: -0.2372603341937065
Logical resource usage: 4.0/32 CPUs, 1.0/2 GPUs (0.0/2.0 accelerator_type:A10G)\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_639d7776TERMINATED10.0.35.174:8467050.5 0.0001 0.8 3 10 68.3885 90.0001 0.0520358
TorchTrainer_145c1bc2TERMINATED10.0.34.101:3497160.841192 5.18042e-050.7586272.25374 5 30.7297 45.18042e-05 0.392521
\n", "
\n", "
\n", "\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[2m\u001b[36m(TorchTrainer pid=846705)\u001b[0m Starting distributed worker processes: ['846788 (10.0.35.174)']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m Setting up process group for: env:// [rank=0, world_size=1]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Auto configuring locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m Moving model to device: cuda:0\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m /tmp/ipykernel_841208/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", "\u001b[2m\u001b[36m(TorchTrainer pid=349716, ip=10.0.34.101)\u001b[0m Starting distributed worker processes: ['349780 (10.0.34.101)']\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=349780, ip=10.0.34.101)\u001b[0m Setting up process group for: env:// [rank=0, world_size=1]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Auto configuring locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b']\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=349841, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=349780, ip=10.0.34.101)\u001b[0m /tmp/ipykernel_841208/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" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m 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": [ "(pid=349841, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m 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": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "2023-09-17 22:44:16,982\tWARNING util.py:315 -- The `callbacks.on_trial_result` operation took 3.185 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:16,983\tWARNING util.py:315 -- The `process_trial_result` operation took 3.187 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:16,984\tWARNING util.py:315 -- Processing trial results took 3.188 s, which may be a performance bottleneck. Please consider reporting results less frequently to Ray Tune.\n", "2023-09-17 22:44:16,984\tWARNING util.py:315 -- The `process_trial_result` operation took 3.188 s, which may be a performance bottleneck.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=349841, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m 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": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "2023-09-17 22:44:25,141\tWARNING util.py:315 -- The `callbacks.on_trial_result` operation took 3.025 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:25,143\tWARNING util.py:315 -- The `process_trial_result` operation took 3.028 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:25,144\tWARNING util.py:315 -- Processing trial results took 3.028 s, which may be a performance bottleneck. Please consider reporting results less frequently to Ray Tune.\n", "2023-09-17 22:44:25,144\tWARNING util.py:315 -- The `process_trial_result` operation took 3.029 s, which may be a performance bottleneck.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=349841, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m 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": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "2023-09-17 22:44:33,395\tWARNING util.py:315 -- The `callbacks.on_trial_result` operation took 3.181 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:33,397\tWARNING util.py:315 -- The `process_trial_result` operation took 3.183 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:33,398\tWARNING util.py:315 -- Processing trial results took 3.184 s, which may be a performance bottleneck. Please consider reporting results less frequently to Ray Tune.\n", "2023-09-17 22:44:33,398\tWARNING util.py:315 -- The `process_trial_result` operation took 3.184 s, which may be a performance bottleneck.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=349841, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m 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": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "2023-09-17 22:44:41,574\tWARNING util.py:315 -- The `callbacks.on_trial_result` operation took 3.101 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:41,576\tWARNING util.py:315 -- The `process_trial_result` operation took 3.102 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:41,576\tWARNING util.py:315 -- Processing trial results took 3.103 s, which may be a performance bottleneck. Please consider reporting results less frequently to Ray Tune.\n", "2023-09-17 22:44:41,577\tWARNING util.py:315 -- The `process_trial_result` operation took 3.104 s, which may be a performance bottleneck.\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=349841, ip=10.0.34.101) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['860a06117a62bfc12416a8163d19974a865e594674344a920da1e53b'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=349841, ip=10.0.34.101)\u001b[0m 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": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "2023-09-17 22:44:49,825\tWARNING util.py:315 -- The `callbacks.on_trial_result` operation took 3.286 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:49,828\tWARNING util.py:315 -- The `process_trial_result` operation took 3.289 s, which may be a performance bottleneck.\n", "2023-09-17 22:44:49,828\tWARNING util.py:315 -- Processing trial results took 3.289 s, which may be a performance bottleneck. Please consider reporting results less frequently to Ray Tune.\n", "2023-09-17 22:44:49,828\tWARNING util.py:315 -- The `process_trial_result` operation took 3.289 s, which may be a performance bottleneck.\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=349780, ip=10.0.34.101)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-43-52/TorchTrainer_145c1bc2_2_dropout_p=0.8412,lr=0.0001,lr_factor=0.7586,lr_patience=2.2537_2023-09-17_22-43-55/checkpoint_000005)\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-43-52/TorchTrainer_639d7776_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-09-17_22-43-52/checkpoint_000006)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-43-52/TorchTrainer_639d7776_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-09-17_22-43-52/checkpoint_000007)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-43-52/TorchTrainer_639d7776_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-09-17_22-43-52/checkpoint_000008)\n" ] }, { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "", "version_major": 2, "version_minor": 0 }, "text/plain": [ "(pid=846864) Running 0: 0%| | 0/64 [00:00 OutputSplitter[split(1, equal=True)]\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Execution config: ExecutionOptions(resource_limits=ExecutionResources(cpu=None, gpu=None, object_store_memory=None), locality_with_output=['c268d87a05f14889a7bdc3c259e78ced37c574c65ab440657e85be5a'], preserve_order=True, actor_locality_enabled=True, verbose_progress=False)\n", "\u001b[2m\u001b[36m(SplitCoordinator pid=846864)\u001b[0m Tip: For detailed progress reporting, run `ray.data.DataContext.get_current().execution_options.verbose_progress = True`\n", "\u001b[2m\u001b[36m(RayTrainWorker pid=846788)\u001b[0m Checkpoint successfully created at: Checkpoint(filesystem=local, path=/efs/shared_storage/madewithml/GokuMohandas/TorchTrainer_2023-09-17_22-43-52/TorchTrainer_639d7776_1_dropout_p=0.5000,lr=0.0001,lr_factor=0.8000,lr_patience=3.0000_2023-09-17_22-43-52/checkpoint_000009)\n", "2023-09-17 22:45:41,369\tINFO tune.py:1143 -- Total run time: 109.13 seconds (109.03 seconds for the tuning loop).\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 1.67 s, sys: 1.85 s, total: 3.52 s\n", "Wall time: 1min 49s\n" ] } ], "source": [ "%%time\n", "# Tune\n", "results = tuner.fit()" ] }, { "cell_type": "code", "execution_count": null, "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_losstimestampshould_checkpointdonetraining_iterationtrial_iddate...hostnamenode_iptime_since_restoreiterations_since_restorecheckpoint_dir_nameconfig/train_loop_config/dropout_pconfig/train_loop_config/lrconfig/train_loop_config/lr_factorconfig/train_loop_config/lr_patiencelogdir
090.0001000.0520360.0963911695015936TrueTrue10639d77762023-09-17_22-45-36...ip-10-0-35-17410.0.35.17468.38852410checkpoint_0000090.5000000.0001000.8000003.000000639d7776
140.0000520.3925210.3263201695015885TrueTrue5145c1bc22023-09-17_22-44-46...ip-10-0-34-10110.0.34.10130.7297465checkpoint_0000040.8411920.0000520.7586272.253736145c1bc2
\n", "

2 rows × 23 columns

\n", "
" ], "text/plain": [ " epoch lr train_loss val_loss timestamp should_checkpoint done \\\n", "0 9 0.000100 0.052036 0.096391 1695015936 True True \n", "1 4 0.000052 0.392521 0.326320 1695015885 True True \n", "\n", " training_iteration trial_id date ... hostname \\\n", "0 10 639d7776 2023-09-17_22-45-36 ... ip-10-0-35-174 \n", "1 5 145c1bc2 2023-09-17_22-44-46 ... ip-10-0-34-101 \n", "\n", " node_ip time_since_restore iterations_since_restore \\\n", "0 10.0.35.174 68.388524 10 \n", "1 10.0.34.101 30.729746 5 \n", "\n", " checkpoint_dir_name config/train_loop_config/dropout_p \\\n", "0 checkpoint_000009 0.500000 \n", "1 checkpoint_000004 0.841192 \n", "\n", " config/train_loop_config/lr config/train_loop_config/lr_factor \\\n", "0 0.000100 0.800000 \n", "1 0.000052 0.758627 \n", "\n", " config/train_loop_config/lr_patience logdir \n", "0 3.000000 639d7776 \n", "1 2.253736 145c1bc2 \n", "\n", "[2 rows x 23 columns]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# All trials in experiment\n", "results.get_dataframe()" ] }, { "cell_type": "code", "execution_count": null, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \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_losstimestampshould_checkpointdonetraining_iterationtrial_iddate...pidhostnamenode_iptime_since_restoreiterations_since_restorecheckpoint_dir_nameconfig/train_loop_config/dropout_pconfig/train_loop_config/lrconfig/train_loop_config/lr_factorconfig/train_loop_config/lr_patience
000.00010.5778600.4922271695015848TrueFalse1639d77762023-09-17_22-44-08...846705ip-10-0-35-17410.0.35.17412.8284651checkpoint_0000000.50.00010.83.0
110.00010.4757430.3871871695015856TrueFalse2639d77762023-09-17_22-44-16...846705ip-10-0-35-17410.0.35.17420.6512862checkpoint_0000010.50.00010.83.0
220.00010.4023740.3723901695015864TrueFalse3639d77762023-09-17_22-44-24...846705ip-10-0-35-17410.0.35.17428.2356283checkpoint_0000020.50.00010.83.0
330.00010.3490680.2977041695015873TrueFalse4639d77762023-09-17_22-44-33...846705ip-10-0-35-17410.0.35.17435.8737924checkpoint_0000030.50.00010.83.0
440.00010.2568880.2075741695015881TrueFalse5639d77762023-09-17_22-44-41...846705ip-10-0-35-17410.0.35.17443.4876125checkpoint_0000040.50.00010.83.0
550.00010.2042790.1612831695015889TrueFalse6639d77762023-09-17_22-44-49...846705ip-10-0-35-17410.0.35.17451.1135386checkpoint_0000050.50.00010.83.0
660.00010.1427160.1385461695015897TrueFalse7639d77762023-09-17_22-45-18...846705ip-10-0-35-17410.0.35.17451.1156707checkpoint_0000060.50.00010.83.0
770.00010.0976150.1080341695015924TrueFalse8639d77762023-09-17_22-45-24...846705ip-10-0-35-17410.0.35.17456.7815268checkpoint_0000070.50.00010.83.0
880.00010.0700970.1022921695015930TrueFalse9639d77762023-09-17_22-45-30...846705ip-10-0-35-17410.0.35.17462.6071849checkpoint_0000080.50.00010.83.0
990.00010.0520360.0963911695015936TrueTrue10639d77762023-09-17_22-45-36...846705ip-10-0-35-17410.0.35.17468.38852410checkpoint_0000090.50.00010.83.0
\n", "

10 rows × 22 columns

\n", "
" ], "text/plain": [ " epoch lr train_loss val_loss timestamp should_checkpoint done \\\n", "0 0 0.0001 0.577860 0.492227 1695015848 True False \n", "1 1 0.0001 0.475743 0.387187 1695015856 True False \n", "2 2 0.0001 0.402374 0.372390 1695015864 True False \n", "3 3 0.0001 0.349068 0.297704 1695015873 True False \n", "4 4 0.0001 0.256888 0.207574 1695015881 True False \n", "5 5 0.0001 0.204279 0.161283 1695015889 True False \n", "6 6 0.0001 0.142716 0.138546 1695015897 True False \n", "7 7 0.0001 0.097615 0.108034 1695015924 True False \n", "8 8 0.0001 0.070097 0.102292 1695015930 True False \n", "9 9 0.0001 0.052036 0.096391 1695015936 True True \n", "\n", " training_iteration trial_id date ... pid \\\n", "0 1 639d7776 2023-09-17_22-44-08 ... 846705 \n", "1 2 639d7776 2023-09-17_22-44-16 ... 846705 \n", "2 3 639d7776 2023-09-17_22-44-24 ... 846705 \n", "3 4 639d7776 2023-09-17_22-44-33 ... 846705 \n", "4 5 639d7776 2023-09-17_22-44-41 ... 846705 \n", "5 6 639d7776 2023-09-17_22-44-49 ... 846705 \n", "6 7 639d7776 2023-09-17_22-45-18 ... 846705 \n", "7 8 639d7776 2023-09-17_22-45-24 ... 846705 \n", "8 9 639d7776 2023-09-17_22-45-30 ... 846705 \n", "9 10 639d7776 2023-09-17_22-45-36 ... 846705 \n", "\n", " hostname node_ip time_since_restore iterations_since_restore \\\n", "0 ip-10-0-35-174 10.0.35.174 12.828465 1 \n", "1 ip-10-0-35-174 10.0.35.174 20.651286 2 \n", "2 ip-10-0-35-174 10.0.35.174 28.235628 3 \n", "3 ip-10-0-35-174 10.0.35.174 35.873792 4 \n", "4 ip-10-0-35-174 10.0.35.174 43.487612 5 \n", "5 ip-10-0-35-174 10.0.35.174 51.113538 6 \n", "6 ip-10-0-35-174 10.0.35.174 51.115670 7 \n", "7 ip-10-0-35-174 10.0.35.174 56.781526 8 \n", "8 ip-10-0-35-174 10.0.35.174 62.607184 9 \n", "9 ip-10-0-35-174 10.0.35.174 68.388524 10 \n", "\n", " checkpoint_dir_name config/train_loop_config/dropout_p \\\n", "0 checkpoint_000000 0.5 \n", "1 checkpoint_000001 0.5 \n", "2 checkpoint_000002 0.5 \n", "3 checkpoint_000003 0.5 \n", "4 checkpoint_000004 0.5 \n", "5 checkpoint_000005 0.5 \n", "6 checkpoint_000006 0.5 \n", "7 checkpoint_000007 0.5 \n", "8 checkpoint_000008 0.5 \n", "9 checkpoint_000009 0.5 \n", "\n", " config/train_loop_config/lr config/train_loop_config/lr_factor \\\n", "0 0.0001 0.8 \n", "1 0.0001 0.8 \n", "2 0.0001 0.8 \n", "3 0.0001 0.8 \n", "4 0.0001 0.8 \n", "5 0.0001 0.8 \n", "6 0.0001 0.8 \n", "7 0.0001 0.8 \n", "8 0.0001 0.8 \n", "9 0.0001 0.8 \n", "\n", " config/train_loop_config/lr_patience \n", "0 3.0 \n", "1 3.0 \n", "2 3.0 \n", "3 3.0 \n", "4 3.0 \n", "5 3.0 \n", "6 3.0 \n", "7 3.0 \n", "8 3.0 \n", "9 3.0 \n", "\n", "[10 rows x 22 columns]" ] }, "execution_count": null, "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": null, "metadata": { "tags": [] }, "outputs": [ { "data": { "text/plain": [ "{'dropout_p': 0.5, 'lr': 0.0001, 'lr_factor': 0.8, 'lr_patience': 3.0}" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Best trial's hyperparameters\n", "best_trial.config[\"train_loop_config\"]" ] }, { "cell_type": "code", "execution_count": null, "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_total_smetrics.config/train_loop_config/lr_patiencemetrics.time_since_restoremetrics.iterations_since_restore...metrics.config/train_loop_config/num_epochsparams.train_loop_config/lrparams.train_loop_config/lr_patienceparams.train_loop_config/dropout_pparams.train_loop_config/lr_factorparams.train_loop_config/num_classesparams.train_loop_config/num_epochsparams.train_loop_config/batch_sizetags.trial_nametags.mlflow.runName
0ebc5576cd02e4430bbe949612a25bd45703905858072772764FINISHEDfile:///efs/shared_storage/madewithml/GokuMoha...2023-09-18 05:43:55.499000+00:002023-09-18 05:45:41.257000+00:0068.3885243.00000068.38852410.0...NaN0.00013.00.50.8NoneNoneNoneTorchTrainer_639d7776TorchTrainer_639d7776
1a67f6ec4e10b49a7845b91db61efc7e0703905858072772764FINISHEDfile:///efs/shared_storage/madewithml/GokuMoha...2023-09-18 05:42:12.863000+00:002023-09-18 05:43:30.925000+00:0063.6994443.00000063.69944410.0...10.00.000130.50.8410256TorchTrainer_1bd07_00000TorchTrainer_1bd07_00000
20d8a50554ecf498cb6f1471b58aedb9d703905858072772764FINISHEDfile:///efs/shared_storage/madewithml/GokuMoha...2023-09-18 05:43:59.010000+00:002023-09-18 05:45:17.549000+00:0030.7297462.25373630.7297465.0...NaN5.1804178109970566e-052.2537356446691870.84119201160730330.7586266131367906NoneNoneNoneTorchTrainer_145c1bc2TorchTrainer_145c1bc2
\n", "

3 rows × 35 columns

\n", "
" ], "text/plain": [ " run_id experiment_id status \\\n", "0 ebc5576cd02e4430bbe949612a25bd45 703905858072772764 FINISHED \n", "1 a67f6ec4e10b49a7845b91db61efc7e0 703905858072772764 FINISHED \n", "2 0d8a50554ecf498cb6f1471b58aedb9d 703905858072772764 FINISHED \n", "\n", " artifact_uri \\\n", "0 file:///efs/shared_storage/madewithml/GokuMoha... \n", "1 file:///efs/shared_storage/madewithml/GokuMoha... \n", "2 file:///efs/shared_storage/madewithml/GokuMoha... \n", "\n", " start_time end_time \\\n", "0 2023-09-18 05:43:55.499000+00:00 2023-09-18 05:45:41.257000+00:00 \n", "1 2023-09-18 05:42:12.863000+00:00 2023-09-18 05:43:30.925000+00:00 \n", "2 2023-09-18 05:43:59.010000+00:00 2023-09-18 05:45:17.549000+00:00 \n", "\n", " metrics.time_total_s metrics.config/train_loop_config/lr_patience \\\n", "0 68.388524 3.000000 \n", "1 63.699444 3.000000 \n", "2 30.729746 2.253736 \n", "\n", " metrics.time_since_restore metrics.iterations_since_restore ... \\\n", "0 68.388524 10.0 ... \n", "1 63.699444 10.0 ... \n", "2 30.729746 5.0 ... \n", "\n", " metrics.config/train_loop_config/num_epochs params.train_loop_config/lr \\\n", "0 NaN 0.0001 \n", "1 10.0 0.0001 \n", "2 NaN 5.1804178109970566e-05 \n", "\n", " params.train_loop_config/lr_patience params.train_loop_config/dropout_p \\\n", "0 3.0 0.5 \n", "1 3 0.5 \n", "2 2.253735644669187 0.8411920116073033 \n", "\n", " params.train_loop_config/lr_factor params.train_loop_config/num_classes \\\n", "0 0.8 None \n", "1 0.8 4 \n", "2 0.7586266131367906 None \n", "\n", " params.train_loop_config/num_epochs params.train_loop_config/batch_size \\\n", "0 None None \n", "1 10 256 \n", "2 None None \n", "\n", " tags.trial_name tags.mlflow.runName \n", "0 TorchTrainer_639d7776 TorchTrainer_639d7776 \n", "1 TorchTrainer_1bd07_00000 TorchTrainer_1bd07_00000 \n", "2 TorchTrainer_145c1bc2 TorchTrainer_145c1bc2 \n", "\n", "[3 rows x 35 columns]" ] }, "execution_count": null, "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": null, "metadata": {}, "outputs": [], "source": [ "# Artifacts\n", "best_checkpoint = get_best_checkpoint(run_id=best_run.run_id)\n", "predictor = TorchPredictor.from_checkpoint(best_checkpoint)\n", "preprocessor = predictor.get_preprocessor()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-09-17 22:45:42,824\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches()]\n", "2023-09-17 22:45:42,824\tINFO streaming_executor.py:94 -- 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-09-17 22:45:42,825\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor)]\n", "2023-09-17 22:45:43,741\tINFO streaming_executor.py:94 -- 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-09-17 22:45:43,742\tINFO streaming_executor.py:96 -- 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/4096 [00:00MapBatches(TorchPredictor) pid=350325, ip=10.0.34.101)\u001b[0m /tmp/ipykernel_841208/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": [ "{\n", " \"precision\": 0.9168092951711627,\n", " \"recall\": 0.9109947643979057,\n", " \"f1\": 0.9105512639658029\n", "}\n" ] } ], "source": [ "# Evaluate on test split\n", "performance = evaluate(ds=test_ds, predictor=predictor)\n", "print (json.dumps(performance, indent=2))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2023-09-17 22:45:49,875\tINFO streaming_executor.py:93 -- Executing DAG InputDataBuffer[Input] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor.predict_proba)]\n", "2023-09-17 22:45:49,875\tINFO streaming_executor.py:94 -- 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-09-17 22:45:49,876\tINFO streaming_executor.py:96 -- 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/1 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches()]\n", "2023-09-17 22:45:52,091\tINFO streaming_executor.py:94 -- 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-09-17 22:45:52,091\tINFO streaming_executor.py:96 -- 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/4096 [00:00 TaskPoolMapOperator[ReadCSV->SplitBlocks(64)] -> TaskPoolMapOperator[MapBatches(preprocess)->MapBatches(TorchPredictor.predict_proba)]\n", "2023-09-17 22:45:52,988\tINFO streaming_executor.py:94 -- 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-09-17 22:45:52,988\tINFO streaming_executor.py:96 -- 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/4096 [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\\nThis repo contains ...natural-language-processingMention Classifier Category prediction model\\n...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\\nThis repo contains ... \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\\n... \n", "\n", " prediction \n", "0 computer-vision \n", "1 other \n", "2 other \n", "3 computer-vision \n", "4 natural-language-processing " ] }, "execution_count": null, "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()" ] }, { "cell_type": "markdown", "metadata": { "id": "TiXcls5JoNA8" }, "source": [ "### Coarse-grained metrics" ] }, { "cell_type": "code", "execution_count": null, "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.9138952286238713,\n", " \"recall\": 0.9109947643979057,\n", " \"f1\": 0.9114851103432928,\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))" ] }, { "cell_type": "markdown", "metadata": { "id": "zl3xSuXRutKG" }, "source": [ "### Fine-grained metrics" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "id": "jqetm3ybN9C1", "tags": [] }, "outputs": [], "source": [ "from collections import OrderedDict" ] }, { "cell_type": "code", "execution_count": null, "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": null, "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.9146341463414634,\n", " \"recall\": 0.9615384615384616,\n", " \"f1\": 0.9375000000000001,\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": null, "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", " \"other\",\n", " {\n", " \"precision\": 0.96,\n", " \"recall\": 0.9230769230769231,\n", " \"f1\": 0.9411764705882353,\n", " \"num_samples\": 26.0\n", " }\n", "]\n", "[\n", " \"natural-language-processing\",\n", " {\n", " \"precision\": 0.9146341463414634,\n", " \"recall\": 0.9615384615384616,\n", " \"f1\": 0.9375000000000001,\n", " \"num_samples\": 78.0\n", " }\n", "]\n", "[\n", " \"computer-vision\",\n", " {\n", " \"precision\": 0.9393939393939394,\n", " \"recall\": 0.8732394366197183,\n", " \"f1\": 0.9051094890510948,\n", " \"num_samples\": 71.0\n", " }\n", "]\n", "[\n", " \"mlops\",\n", " {\n", " \"precision\": 0.7222222222222222,\n", " \"recall\": 0.8125,\n", " \"f1\": 0.7647058823529411,\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))" ] }, { "cell_type": "markdown", "metadata": { "id": "f-juex26zvBF" }, "source": [ "### Confusion matrix" ] }, { "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": null, "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": null, "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, 17, 19, 23, 25, 26, 29, 30, 31, 32, 33, 34, 42, 47, 49, 50, 54, 56, 65, 66, 68, 71, 75, 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", "[41, 61, 102, 104, 154, 165, 188]\n", "[16, 76, 112]\n" ] } ], "source": [ "print (tp)\n", "print (fp)\n", "print (fn)" ] }, { "cell_type": "code", "execution_count": null, "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", "How Docker Can Help You Become A More Effective Data Scientist A look at Docker from the perspective of a data scientist.\n", " true: mlops\n", " pred: natural-language-processing\n", "\n", "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.\n", " true: computer-vision\n", " pred: natural-language-processing\n", "\n", "EfficientDet (PyTorch) A PyTorch implementation of EfficientDet faithful to the original Google implementation with ported weights.\n", " true: computer-vision\n", " pred: natural-language-processing\n", "\n", "\n", "=== False negatives ===\n", "The Unreasonable Effectiveness of Recurrent Neural Networks A close look at how RNNs are able to perform so well.\n", " true: natural-language-processing\n", " pred: computer-vision\n", "\n", "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.\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: mlops\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\")" ] }, { "cell_type": "markdown", "metadata": { "id": "6S5LZdP2Myjh" }, "source": [ "### Confidence learning" ] }, { "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" ] }, { "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": null, "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": null, "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": null, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "7DnkXhXFFMv_", "outputId": "c93cd01b-8ad1-4e63-8254-79f885534ffb", "tags": [] }, "outputs": [ { "data": { "text/plain": [ "[{'text': 'The Unreasonable Effectiveness of Recurrent Neural Networks A close look at how RNNs are able to perform so well.',\n", " 'true': 'natural-language-processing',\n", " 'pred': 'computer-vision',\n", " 'prob': 0.008757317},\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': 'mlops',\n", " 'prob': 0.020190474}]" ] }, "execution_count": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "low_confidence[0:3]" ] }, { "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": null, "metadata": { "id": "XX3cORGPPXXM", "tags": [] }, "outputs": [], "source": [ "import cleanlab\n", "from cleanlab.filter import find_label_issues" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "*** SIGTERM received at time=1695015958 on cpu 1 ***\n", "PC: @ 0x4edd8a (unknown) _PyEval_MakeFrameVector\n", " @ 0x7fe3ff0e9420 514711536 (unknown)\n", " @ 0x72c720 (unknown) (unknown)\n", "[2023-09-17 22:45:58,798 E 848689 841208] logging.cc:361: *** SIGTERM received at time=1695015958 on cpu 1 ***\n", "[2023-09-17 22:45:58,799 E 848689 841208] logging.cc:361: PC: @ 0x4edd8a (unknown) _PyEval_MakeFrameVector\n", "[2023-09-17 22:45:58,803 E 848689 841208] logging.cc:361: @ 0x7fe3ff0e9420 514711536 (unknown)\n", "[2023-09-17 22:45:58,808 E 848689 841208] 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
10314592020-06-16 03:06:10SuperGlue: Learning Feature Matching with Grap...SuperGlue, a neural network that matches two s...othercomputer-vision
10214512020-06-16 01:21:09EfficientDet (PyTorch)A PyTorch implementation of EfficientDet faith...computer-visionnatural-language-processing
16521372020-08-13 02:10:03Unpopular Opinion - Data Scientists Should Be ...I believe data scientists can be more effectiv...mlopsnatural-language-processing
617102020-05-05 04:01:24Differential Subspace Search in High-Dimension...Differential subspace search to allow efficien...computer-visionnatural-language-processing
162642020-04-06 21:33:32The Unreasonable Effectiveness of Recurrent Ne...A close look at how RNNs are able to perform s...natural-language-processingcomputer-vision
\n", "
" ], "text/plain": [ " id created_on \\\n", "103 1459 2020-06-16 03:06:10 \n", "102 1451 2020-06-16 01:21:09 \n", "165 2137 2020-08-13 02:10:03 \n", "61 710 2020-05-05 04:01:24 \n", "16 264 2020-04-06 21:33:32 \n", "\n", " title \\\n", "103 SuperGlue: Learning Feature Matching with Grap... \n", "102 EfficientDet (PyTorch) \n", "165 Unpopular Opinion - Data Scientists Should Be ... \n", "61 Differential Subspace Search in High-Dimension... \n", "16 The Unreasonable Effectiveness of Recurrent Ne... \n", "\n", " description \\\n", "103 SuperGlue, a neural network that matches two s... \n", "102 A PyTorch implementation of EfficientDet faith... \n", "165 I believe data scientists can be more effectiv... \n", "61 Differential subspace search to allow efficien... \n", "16 A close look at how RNNs are able to perform s... \n", "\n", " tag prediction \n", "103 other computer-vision \n", "102 computer-vision natural-language-processing \n", "165 mlops natural-language-processing \n", "61 computer-vision natural-language-processing \n", "16 natural-language-processing computer-vision " ] }, "execution_count": null, "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()" ] }, { "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)." ] }, { "cell_type": "markdown", "metadata": { "id": "dvS3UpusXP_R" }, "source": [ "### Slice metrics" ] }, { "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": null, "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": null, "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": null, "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" ] }, { "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": null, "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, 32805.57it/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": null, "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": null, "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, 64413.61it/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": null, "metadata": {}, "output_type": "execute_result" } ], "source": [ "short_text_df = slice_dataframe(test_df, short_text)\n", "short_text_df[[\"text\", \"tag\"]].head()" ] }, { "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": null, "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, 27137.02it/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', '