Code and data for the EMNLP 2021 paper "Just Say No: Analyzing the Stance of Neural Dialogue Generation in Offensive Contexts". Coming soon!

Related tags

Deep LearningToxiChat
Overview

ToxiChat

Code and data for the EMNLP 2021 paper "Just Say No: Analyzing the Stance of Neural Dialogue Generation in Offensive Contexts".

Install dependencies

conda env create -f environment.yml

Data

The train, dev, test split of the data are given in data/OC_S_post_thread/ folder

Offensive and Stance Classification models

Single instance Offensive Classification

NBOW model

We will train NBOW single sentence classification model initialized with GloVe embedding
To train NBOW model, you'd need to download and extract GloVe vectors into data/GloVe/ dir and then run python convert_glove_text_vectors_to_pkl.py from within the directory

  • Training offensive classifier on OC_S_post_thread data
    python experiments/train_and_evaluate_NBOW_offensive_classifier.py -g data/GloVe/glove.6B.300d.pkl -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/NBOW_OC_S_offensive_e30 -o results/OC_S_post_thread/NBOW_OC_S_offensive_e30 -e 30 -dv 1 -t

BERT large cased model

  • Training offensive classifier on OC_S_post_thread data
    python experiments/train_and_evaluate_BERT_offensive_classifier.py -e 8 -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/BERT_large_OC_S_offensive_e8 -o results/OC_S_post_thread/BERT_large_OC_S_offensive_e8 -t

Full Sequence Offensive Classification (DGPT)

We will train a DGPT model offensive classifier for the entire comment thread with EOS tokens used for sentence representations.

  • Training offensive classifier on OC_S_post_thread data
    python experiments/train_and_evaluate_DGPT_offensive_classifier.py -e 12 -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/DGPT_medium_OC_S_offensive_e12 -o results/OC_S_post_thread/DGPT_medium_OC_S_offensive_e12 -t
  • Training offensive classifier on OC_S_post_thread + SBF data
    python experiments/train_and_evaluate_DGPT_offensive_classifier.py -e 3 -td "{'OC_S':'data/OC_S_post_thread/', 'SBF':'data/SBF'}" -s saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e3 -o results/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e3 -t -dv 4

Stance Classification

Pairwise Stance Classification

NBOW model

We will train NBOW Sentence Pair classification model initialized with GloVe embedding

  • Training Stance classifier on OC_S_post_thread_data (cross entropy)
    python experiments/train_and_evaluate_NBOW_pairwise_stance_classifier.py -g data/GloVe/glove.6B.300d.pkl -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/NBOW_OC_S_pairwise_stance_e30 -o results/OC_S_post_thread/NBOW_OC_S_pairwise_stance_e30 -e 30 -dv 1 -t

BERT large cased model

We will train Bert Sentence Pair classification model

  • Training Stance classifier on OC_S_post_thread_data (cross entropy)
    python experiments/train_and_evaluate_BERT_pairwise_stance_classifier.py -e 8 -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/BERT_large_OC_S_pairwise_stance_e8 -o results/OC_S_post_thread/BERT_large_OC_S_pairwise_stance_e8 -t

Full Sequence Stance Classification

We will train a DGPT model stance classifier for the entire comment thread with EOS tokens used for sentence representations.

  • Training Stance classifier on OC_S_post_thread_data (cross entropy)
    python experiments/train_and_evaluate_DGPT_stance_classifier.py -e 12 -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e12 -o results/OC_S_post_thread/DGPT_medium_OC_S_stance_e12 -t
  • Training Stance classifier on OC_S_post_thread_data (Focal Loss)
    python experiments/train_and_evaluate_DGPT_stance_classifier.py -e 16 -td "{'OC_S':'data/OC_S_post_thread/'}" -s saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -o results/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -foc -lr 5e-5 -t

To download pretrained DGPT offensive and Stance (Focal) classifiers use the following link

Mitigating Offensive language using Controlled Text Generation

Dataset Preparation

We will first create a dataset of posts and comments from all of the reddit. Then we will create comment trees from these posts and comments and label them with our stance and offensive classifiers

Downloading the reddit posts and comments dumps

  1. Download the reddit comments and submissions dumps from August(08) to October(10), 2019 in the data folder
    mkdir -p data/reddit_dumps/comments_compressed
    cd data/reddit_dumps/comments_compressed
    wget -nc https://files.pushshift.io/reddit/comments/RC_2019-10.zst
    wget -nc https://files.pushshift.io/reddit/comments/RC_2019-09.zst
    wget -nc https://files.pushshift.io/reddit/comments/RC_2019-08.zst
    wget -nc https://files.pushshift.io/reddit/comments/RC_2019-07.zst
    wget -nc https://files.pushshift.io/reddit/comments/RC_2019-06.zst
    wget -nc https://files.pushshift.io/reddit/comments/RC_2019-05.zst
    cd ..
    mkdir posts_compressed
    cd posts_compressed
    wget -nc https://files.pushshift.io/reddit/submissions/RS_2019-10.zst
    wget -nc https://files.pushshift.io/reddit/submissions/RS_2019-09.zst
    wget -nc https://files.pushshift.io/reddit/submissions/RS_2019-08.zst
    wget -nc https://files.pushshift.io/reddit/submissions/RS_2019-07.zst
    wget -nc https://files.pushshift.io/reddit/submissions/RS_2019-06.zst
    wget -nc https://files.pushshift.io/reddit/submissions/RS_2019-05.zst
    cd ../../
    

Create posts and comments sample

  • python extract_reddit_posts.py -f data/reddit_dumps/posts_compressed/RS_2019-10.zst data/reddit_dumps/posts_compressed/RS_2019-09.zst data/reddit_dumps/posts_compressed/RS_2019-08.zst data/reddit_dumps/posts_compressed/RS_2019-07.zst data/reddit_dumps/posts_compressed/RS_2019-06.zst data/reddit_dumps/posts_compressed/RS_2019-05.zst -p 0.8 -o data/reddit_dumps/posts/all_mitigating_sample/
  • python extract_reddit_comments_for_posts.py -f data/reddit_dumps/comments_compressed/RC_2019-05.zst data/reddit_dumps/comments_compressed/RC_2019-06.zst data/reddit_dumps/comments_compressed/RC_2019-07.zst data/reddit_dumps/comments_compressed/RC_2019-08.zst data/reddit_dumps/comments_compressed/RC_2019-09.zst data/reddit_dumps/comments_compressed/RC_2019-10.zst -p data/reddit_dumps/posts/all_mitigating_sample/all_subreddit_posts.jsonl -o data/reddit_dumps/comments/all_mitigating_sample/

Create threads from posts and comments sample

python create_post_comment_trees_from_all_reddit_sample.py -ip data/reddit_dumps/posts/all_mitigating_sample/all_subreddit_posts.jsonl -ic data/reddit_dumps/comments/all_mitigating_sample/all_subreddit_post_related_comments.jsonl -mc 3 -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/

Split the post comment threads into 4 splits

python split_threads_into_files.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/all_reddit_post_and_comments_3_threads.pkl -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/ -n 4

Predict separately for each split

  • python predict_DGPT_stance_on_post_comment_trees.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/split_0.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/ -s data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/split_0_preds.pkl
  • python predict_DGPT_stance_on_post_comment_trees.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/split_1.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/ -s data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/split_1_preds.pkl
  • python predict_DGPT_stance_on_post_comment_trees.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/split_2.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/ -s data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/split_2_preds.pkl
  • python predict_DGPT_stance_on_post_comment_trees.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/split_3.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/ -s data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/split_3_preds.pkl

Merge predictions

python merge_Off_Stance_predictions.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/ -n 4 -o data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/merged_split_predictions.pkl

Create CTG fine-tuning dataset from post_comment threads with stance and offensive labels

python get_fine_tuning_subsets_from_label_predicted_convs.py -i data/reddit_dumps/post_comment_threads/all_mitigating_sample/splits/predictions_both/merged_split_predictions.pkl -o data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/

Fine-tune DGPT medium model for different CTG experiments

DAPT

CTG using DAPT i.e. simply training on the subset we care about

1. Off Control [SAFE] subset (DAPT - [S])

python experiments/CTG_DGPT_finetuner.py -so [SAFE] -t data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/off_control_train.pkl -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/off_control_dev.pkl -s saved_models/CTG/Off_control_DGPT_safe_subset -o results/CTG/Off_control_DGPT_safe_subset -e 3

2. Safe Stance Control [NO-STANCE] subset (DAPT - [S][N])

python experiments/CTG_DGPT_finetuner.py -so [NO-STANCE] -t data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/safe_stance_control_train.pkl -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/safe_stance_control_dev.pkl -s saved_models/CTG/safe_stance_control_DGPT_no_stance_subset -o results/CTG/safe_stance_control_DGPT_no_stance_subset -e 3

ATCON

CTG using control labels

1. Offensive Label Control (ATCON [S])

python experiments/CTG_DGPT_finetuner.py -t data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/off_control_train.pkl -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/off_control_dev.pkl -s saved_models/CTG/Off_control_DGPT -o results/CTG/Off_control_DGPT -e 3 -dv 100

2. Stance Label Control (Safe) (ATCON [N])

python experiments/CTG_DGPT_finetuner.py -t data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/safe_stance_control_train.pkl -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/safe_stance_control_dev.pkl -s saved_models/CTG/safe_stance_control_DGPT -o results/CTG/safe_stance_control_DGPT -e 3

3. Both Offensive and Stance Label Control (both) (ATCON [S][N])

python experiments/CTG_DGPT_finetuner.py -t data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/both_control_train.pkl -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/both_control_dev.pkl -s saved_models/CTG/both_control_DGPT -o results/CTG/both_control_DGPT -e 3

Generate Responses on test set using CTG models

Control labels [OFF]/[SAFE] and [AGREE]/[NO-STANCE]

  • Baseline No Control
    python generate_CTG_responses_and_make_off_and_stance_predictions.py -m microsoft/DialoGPT-medium -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/test_threads.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e3 -n 1 -bs 10 -o results/CTG/DGPT/test_threads_replies_and_off_stance_preds.pkl
  • DAPT Offensive Control Safe Subset (DAPT - [S])
    python generate_CTG_responses_and_make_off_and_stance_predictions.py -m saved_models/CTG/Off_control_DGPT_safe_subset -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/test_threads.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -n 1 -bs 10 -o results/CTG/Off_control_DGPT/DAPT_Off_control_safe_subset_test_threads_replies_and_off_stance_preds.pkl
  • DAPT Safe Stance Control No-Stance Subset (DAPT - [S][N])
    python generate_CTG_responses_and_make_off_and_stance_predictions.py -m saved_models/CTG/safe_stance_control_DGPT_no_stance_subset -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/test_threads.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -n 1 -bs 10 -o results/CTG/safe_stance_control_DGPT/DAPT_safe_stance_control_no_stance_subset_test_threads_replies_and_off_stance_preds.pkl
  • Offensive Control (ATCON - [S])
    python generate_CTG_responses_and_make_off_and_stance_predictions.py -m saved_models/CTG/Off_control_DGPT -p [SAFE] -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/test_threads.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -n 1 -bs 10 -o results/CTG/Off_control_DGPT/Off_control_test_threads_safe_replies_and_off_stance_preds.pkl
  • Stance Control (Safe) (ATCON - [N])
    python generate_CTG_responses_and_make_off_and_stance_predictions.py -m saved_models/CTG/safe_stance_control_DGPT -p [NO-STANCE] -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/test_threads.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -n 1 -bs 10 -o results/CTG/safe_stance_control_DGPT/safe_stance_control_test_threads_no_stance_replies_and_off_stance_preds.pkl
  • Both Control (ATCON - [S][N])
    python generate_CTG_responses_and_make_off_and_stance_predictions.py -m saved_models/CTG/both_control_DGPT -p [SAFE][NO-STANCE] -d data/reddit_dumps/post_comment_threads/CTG_experiments/all_mitigating_sample/final/test_threads.pkl -sm saved_models/OC_S_post_thread/DGPT_medium_OC_S_stance_e16_focal_lr5e_5 -om saved_models/OC_S_post_thread/DGPT_medium_OC_S_and_SBF_offensive_e2 -n 1 -bs 10 -o results/CTG/both_control_DGPT/both_control_test_threads_safe_no_stance_replies_and_off_stance_preds.pkl

Automatic evalaution of CTG test predictions

python automatic_evaluation_of_CTG_test_predictions.py -mg "[('DGPT medium baseline', 'results/CTG/DGPT/test_threads_replies_and_off_stance_preds.pkl'), ('ATCON - [S]', 'results/CTG/Off_control_DGPT/Off_control_test_threads_safe_replies_and_off_stance_preds.pkl'), ('ATCON [N]', 'results/CTG/safe_stance_control_DGPT/safe_stance_control_test_threads_no_stance_replies_and_off_stance_preds.pkl'), ('ATCON [N][S]', 'results/CTG/both_control_DGPT/both_control_test_threads_safe_no_stance_replies_and_off_stance_preds.pkl'), ('DAPT [S]', 'results/CTG/Off_control_DGPT/DAPT_Off_control_safe_subset_test_threads_replies_and_off_stance_preds.pkl'), ('DAPT [S][N]', 'results/CTG/safe_stance_control_DGPT/DAPT_safe_stance_control_no_stance_subset_test_threads_replies_and_off_stance_preds.pkl')]" -o results/CTG/auto_eval/

Citation

@article{baheti2021just,
  title={Just Say No: Analyzing the Stance of Neural Dialogue Generation in Offensive Contexts},
  author={Baheti, Ashutosh and Sap, Maarten and Ritter, Alan and Riedl, Mark},
  journal={arXiv preprint arXiv:2108.11830},
  year={2021}
}
Owner
Ashutosh Baheti
I am a Computer Science PhD student working with Prof. Alan Ritter. I will be a graduate student at Georgia Tech starting from Fall 2020.
Ashutosh Baheti
Example Of Fine-Tuning BERT For Named-Entity Recognition Task And Preparing For Cloud Deployment Using Flask, React, And Docker

Example Of Fine-Tuning BERT For Named-Entity Recognition Task And Preparing For Cloud Deployment Using Flask, React, And Docker This repository contai

Nikita 12 Dec 14, 2022
Official code of CVPR 2021's PLOP: Learning without Forgetting for Continual Semantic Segmentation

PLOP: Learning without Forgetting for Continual Semantic Segmentation This repository contains all of our code. It is a modified version of Cermelli e

Arthur Douillard 116 Dec 14, 2022
Self-describing JSON-RPC services made easy

ReflectRPC Self-describing JSON-RPC services made easy Contents What is ReflectRPC? Installation Features Datatypes Custom Datatypes Returning Errors

Andreas Heck 31 Jul 16, 2022
Metric learning algorithms in Python

metric-learn: Metric Learning in Python metric-learn contains efficient Python implementations of several popular supervised and weakly-supervised met

1.3k Dec 28, 2022
Orthogonal Over-Parameterized Training

The inductive bias of a neural network is largely determined by the architecture and the training algorithm. To achieve good generalization, how to effectively train a neural network is of great impo

Weiyang Liu 11 Apr 18, 2022
AdaNet is a lightweight TensorFlow-based framework for automatically learning high-quality models with minimal expert intervention

AdaNet is a lightweight TensorFlow-based framework for automatically learning high-quality models with minimal expert intervention. AdaNet buil

3.4k Jan 07, 2023
A multilingual version of MS MARCO passage ranking dataset

mMARCO A multilingual version of MS MARCO passage ranking dataset This repository presents a neural machine translation-based method for translating t

75 Dec 27, 2022
Implementation of "Scaled-YOLOv4: Scaling Cross Stage Partial Network" using PyTorch framwork.

YOLOv4-large This is the implementation of "Scaled-YOLOv4: Scaling Cross Stage Partial Network" using PyTorch framwork. YOLOv4-CSP YOLOv4-tiny YOLOv4-

Kin-Yiu, Wong 2k Jan 02, 2023
KoΓ§ University deep learning framework.

Knet Knet (pronounced "kay-net") is the KoΓ§ University deep learning framework implemented in Julia by Deniz Yuret and collaborators. It supports GPU

1.4k Dec 31, 2022
Polynomial-time Meta-Interpretive Learning

Louise - polynomial-time Program Learning Getting help with Louise Louise's author can be reached by email at Stassa Patsantzis 64 Dec 26, 2022

A clean and scalable template to kickstart your deep learning project πŸš€ ⚑ πŸ”₯

Lightning-Hydra-Template A clean and scalable template to kickstart your deep learning project πŸš€ ⚑ πŸ”₯ Click on Use this template to initialize new re

Hyunsoo Cho 1 Dec 20, 2021
Tensorflow implementation of "Learning Deconvolution Network for Semantic Segmentation"

Tensorflow implementation of Learning Deconvolution Network for Semantic Segmentation. Install Instructions Works with tensorflow 1.11.0 and uses the

Fabian Bormann 224 Apr 15, 2022
Hierarchical User Intent Graph Network for Multimedia Recommendation

Hierarchical User Intent Graph Network for Multimedia Recommendation This is our Pytorch implementation for the paper: Hierarchical User Intent Graph

6 Jan 05, 2023
μ‹œκ° μž₯애인을 μœ„ν•œ 슀마트 μ§€νŒ‘μ΄μ— ν™œμš©λ  λ”₯λŸ¬λ‹ λͺ¨λΈ (DL Model Repo)

SmartCane-DL-Model Smart Cane using semantic segmentation μ°Έκ³ ν•œ Github repositoy πŸ”— https://github.com/JunHyeok96/Road-Segmentation.git 데이터셋 πŸ”— https://

λ°˜λ“œμ‹œ μ‘Έμ—…ν•œλ‹€ (Team Just Graduate) 4 Dec 03, 2021
Conformer: Local Features Coupling Global Representations for Visual Recognition

Conformer: Local Features Coupling Global Representations for Visual Recognition (arxiv) This repository is built upon DeiT and timm Usage First, inst

Zhiliang Peng 378 Jan 08, 2023
OptaPlanner wrappers for Python. Currently significantly slower than OptaPlanner in Java or Kotlin.

OptaPy is an AI constraint solver for Python to optimize the Vehicle Routing Problem, Employee Rostering, Maintenance Scheduling, Task Assignment, School Timetabling, Cloud Optimization, Conference S

OptaPy 211 Jan 02, 2023
Repo for the Tutorials of Day1-Day3 of the Nordic Probabilistic AI School 2021 (https://probabilistic.ai/)

ProbAI 2021 - Probabilistic Programming and Variational Inference Tutorial with Pryo Day 1 (June 14) Slides Notebook: students_PPLs_Intro Notebook: so

PGM-Lab 46 Nov 01, 2022
A tensorflow implementation of GCN-LPA

GCN-LPA This repository is the implementation of GCN-LPA (arXiv): Unifying Graph Convolutional Neural Networks and Label Propagation Hongwei Wang, Jur

Hongwei Wang 83 Nov 28, 2022
Learning to Draw: Emergent Communication through Sketching

Learning to Draw: Emergent Communication through Sketching This is the official code for the paper "Learning to Draw: Emergent Communication through S

19 Jul 22, 2022
Machine learning, in numpy

numpy-ml Ever wish you had an inefficient but somewhat legible collection of machine learning algorithms implemented exclusively in NumPy? No? Install

David Bourgin 11.6k Dec 30, 2022