Giter Site home page Giter Site logo

motiwari / banditpam Goto Github PK

View Code? Open in Web Editor NEW
645.0 9.0 37.0 75.42 MB

BanditPAM C++ implementation and Python package

License: MIT License

CMake 1.02% Dockerfile 0.58% Shell 1.68% C++ 71.96% Python 17.88% R 4.26% M4 0.72% JavaScript 1.47% C 0.32% TeX 0.11%
python clustering machine-learning

banditpam's Introduction

BanditPAM: Almost Linear-Time $k$-Medoids Clustering

Linux - build package and run tests Linux - build source distribution and wheels MacOS - build package and run tests MacOS - build wheels Run CMake build on MacOS Run style checks

This repo contains a high-performance implementation of BanditPAM from BanditPAM: Almost Linear-Time k-Medoids Clustering. The code can be called directly from Python, R, or C++.

If you use this software, please cite:

Mo Tiwari, Martin Jinye Zhang, James Mayclin, Sebastian Thrun, Chris Piech, Ilan Shomorony. "BanditPAM: Almost Linear Time k-medoids Clustering via Multi-Armed Bandits" Advances in Neural Information Processing Systems (NeurIPS) 2020.

@inproceedings{BanditPAM,
  title={BanditPAM: Almost Linear Time k-medoids Clustering via Multi-Armed Bandits},
  author={Tiwari, Mo and Zhang, Martin J and Mayclin, James and Thrun, Sebastian and Piech, Chris and Shomorony, Ilan},
  booktitle={Advances in Neural Information Processing Systems},
  pages={368--374},
  year={2020}
}

Requirements

TL;DR run python -m pip install banditpam or install.packages(banditpam) and jump to the examples.

If you have any difficulties, please see the platform-specific guides and file a Github issue if you have additional trouble.

Further Reading

Python Quickstart

Install the repo and its dependencies:

This can be done either through PyPI (recommended)

/BanditPAM/: python -m pip install -r requirements.txt
/BanditPAM/: python -m pip install banditpam

OR through the source code via

/BanditPAM/: git submodule update --init --recursive
/BanditPAM/: cd headers/carma
/BanditPAM/: mkdir build && cd build && cmake -DCARMA_INSTALL_LIB=ON .. && sudo cmake --build . --config Release --target install
/BanditPAM/: cd ../../..
/BanditPAM/: python -m pip install -r requirements.txt
/BanditPAM/: sudo python -m pip install .

Example 1: Synthetic data from a Gaussian Mixture Model

from banditpam import KMedoids
import numpy as np
import matplotlib.pyplot as plt

# Generate data from a Gaussian Mixture Model with the given means:
np.random.seed(0)
n_per_cluster = 40
means = np.array([[0,0], [-5,5], [5,5]])
X = np.vstack([np.random.randn(n_per_cluster, 2) + mu for mu in means])

# Fit the data with BanditPAM:
kmed = KMedoids(n_medoids=3, algorithm="BanditPAM")
kmed.fit(X, 'L2')

print(kmed.average_loss)  # prints 1.2482391595840454
print(kmed.labels)  # prints cluster assignments [0] * 40 + [1] * 40 + [2] * 40

# Visualize the data and the medoids:
for p_idx, point in enumerate(X):
    if p_idx in map(int, kmed.medoids):
        plt.scatter(X[p_idx, 0], X[p_idx, 1], color='red', s = 40)
    else:
        plt.scatter(X[p_idx, 0], X[p_idx, 1], color='blue', s = 10)

plt.show()

png

Example 2: MNIST and its medoids visualized via t-SNE

# Start in the repository root directory, i.e. '/BanditPAM/'.
from banditpam import KMedoids
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.manifold import TSNE

# Load the 1000-point subset of MNIST and calculate its t-SNE embeddings for visualization:
X = pd.read_csv('data/MNIST_1k.csv', sep=' ', header=None).to_numpy()
X_tsne = TSNE(n_components=2).fit_transform(X)

# Fit the data with BanditPAM:
kmed = KMedoids(n_medoids=10, algorithm="BanditPAM")
kmed.fit(X, 'L2')

# Visualize the data and the medoids via t-SNE:
for p_idx, point in enumerate(X):
    if p_idx in map(int, kmed.medoids):
        plt.scatter(X_tsne[p_idx, 0], X_tsne[p_idx, 1], color='red', s = 40)
    else:
        plt.scatter(X_tsne[p_idx, 0], X_tsne[p_idx, 1], color='blue', s = 5)

plt.show()

R Examples

Please see here.

Documentation

Documentation for BanditPAM can be found on read the docs.

Building the C++ executable from source

Please note that it is NOT necessary to build the C++ executable from source to use the Python code above. However, if you would like to use the C++ executable directly, follow the instructions below.

Option 1: Building with Docker

We highly recommend building using Docker. One can download and install Docker by following instructions at the Docker install page. Once you have Docker installed and the Docker Daemon is running, run the following commands:

/BanditPAM/scripts/docker$ chmod +x env_setup.sh
/BanditPAM/scripts/docker$ ./env_setup.sh
/BanditPAM/scripts/docker$ ./run_docker.sh

which will start a Docker instance with the necessary dependencies. Then:

/BanditPAM$ mkdir build && cd build
/BanditPAM/build$ cmake .. && make

This will create an executable named BanditPAM in BanditPAM/build/src.

Option 2: Installing requirements and building directly

Building this repository requires four external requirements:

  • CMake >= 3.17
  • Armadillo >= 10.5.3
  • OpenMP >= 2.5 (OpenMP is supported by default on most Linux platforms, and can be downloaded through homebrew on MacOS)
  • CARMA >= 0.6.2

If installing these requirements from source, one can generally use the following procedure to install each requirement from the library's root folder (with armadillo used as an example here):

/armadillo$ mkdir build && cd build
/armadillo/build$ cmake .. && make && sudo make install

Note that CARMA has different installation instructions; see its instructions.

Platform-specific installation guides

Further installation information for MacOS, Linux, and Windows is available in the docs folder. Ensure all the requirements above are installed and then run:

/BanditPAM$ mkdir build && cd build
/BanditPAM/build$ cmake .. && make

This will create an executable named BanditPAM in BanditPAM/build/src.

C++ Usage

Once the executable has been built, it can be invoked with:

/BanditPAM/build/src/BanditPAM -f [path/to/input.csv] -k [number of clusters]
  • -f is mandatory and specifies the path to the dataset
  • -k is mandatory and specifies the number of clusters with which to fit the data

For example, if you ran ./env_setup.sh and downloaded the MNIST dataset, you could run:

/BanditPAM/build/src/BanditPAM -f ../data/MNIST_1k.csv -k 10

The expected output in the command line will be:

Medoids: 694,168,306,714,324,959,527,251,800,737

Implementing a custom distance metric

One of the advantages of $k$-medoids is that it works with arbitrary distance metrics; in fact, your "metric" need not even be a real metric -- it can be negative, asymmetric, and/or not satisfy the triangle inequality or homogeneity. Any pairwise dissimilarity function works with $k$-medoids.

This also allows for clustering of "exotic" objects like trees, graphs, natural language, and more -- settings where running $k$-means wouldn't even make sense. We talk about one such setting in the full paper.

The package currently supports a number of distance metrics, including all $L_p$ losses and cosine distance.

If you're willing to write a little C++, you only need to add a few lines to kmedoids_algorithm.cpp and kmedoids_algorithm.hpp to implement your distance metric / pairwise dissimilarity!

Then, be sure to re-install the repository with a python -m pip install . (note the trailing .).

The maintainers of this repository are working on permitting arbitrary dissimilarity metrics that users write in Python, as well; see #4.

Testing

To run the full suite of tests, run in the root directory:

/BanditPAM$ python -m unittest discover -s tests

Alternatively, to run a "smaller" set of tests, from the main repo folder run python tests/test_smaller.py or python tests/test_larger.py to run a set of longer, more intensive tests.

Credits

Mo Tiwari wrote the original Python implementation of BanditPAM and many features of the C++ implementation. Mo and Adarsh Kumarappan now maintain the implementations.

James Mayclin developed the initial C++ implementation of BanditPAM.

The original BanditPAM paper was published by Mo Tiwari, Martin Jinye Zhang, James Mayclin, Sebastian Thrun, Chris Piech, and Ilan Shomorony.

We would like to thank Jerry Quinn, David Durst, Geet Sethi, and Max Horton for helpful guidance regarding the C++ implementation.

banditpam's People

Contributors

adarsh321123 avatar ben-h3 avatar bnaras avatar dhaval737 avatar esfrankel avatar jmayclin avatar lukeleeai avatar motiwari avatar prasoon911 avatar ying1123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

banditpam's Issues

Lots of errors with env_setup.sh

Ensure that the script env_setup.sh can be run.

A while ago, I had a significant number of errors, which seeemed to be because the default docker image is too small. To fix, follow: kaldi-asr/kaldi#3781 (comment). If this is always necessary, we should update the script/README.

I may have also had to do the following after installing docker-machine and virtualbox on Mac: https://docs.docker.com/machine/install-machine/ and https://www.virtualbox.org/wiki/Downloads. If this is always necessary, please update the script/README

Throw error if no file is passed to the BanditPAM executable

Right now, if no file is passed to the BanditPAM executable, it throws a misleading error (below) about sampling more than N points.

Instead, if no file is passed, we should surface an error expressing this. Please choose a good error type (or create your own) to surface, in this case.

@"HDF5-DIAG: Error detected in HDF5 (1.12.0) thread 0:\r\n"
@"  #000: H5Fdeprec.c line 159 in H5Fis_hdf5(): no file name specified\r\n"
@"    major: Invalid arguments to routine\r\n"
@"    minor: Out of range\r\n"
@"\r\n"
@"warning: Mat::load(): cannot open file \r\n"
@"\r\n"
@"error: randperm(): 'M' must be less than or equal to 'N'\r\n"
@"libc++abi.dylib: terminating with uncaught exception of type std::logic_error: randperm(): 'M' must be less than or equal to 'N'\r\n"
The program '/Users/motiwari/Desktop/BanditPAM/src/main' has exited with code 0 (0x00000000).

Restructure `kmedoids_ucb.cpp` and corresponding header

kmedoids_ucb.cpp is not a good name for the file or its corresponding header, because:

  • We shouldn't call the algorithm "UCB"; instead, we should call it BanditPAM
  • It also contains the code for naive PAM as well

Instead, we should split the code into 2 (or 3) new files, and their corresponding headers, which contain the code for their respective algorithms, e.g. banditpam.cpp, pam.cpp, etc.. The two algorithms (BanditPAM and Naive) could implement a common interface, kmedoids_algorithm.cpp.

In the future, we will also add a third algorithm (FastPAM -- fastpam.cpp); keep this in mind when modularizing

Create suite of automated tests

Right now, every time a PR is put up, the author needs to manually run an example test as in #51 to ensure that nothing broke and there are no performance degradations.

Instead, we should automatically run these tests when a PR is submitted. There are ways to do this automatically with Github so that when a PR is put up, the tests will automatically run and notify everyone if they fail.

Having these tests allows everyone to contribute more quickly, and also allows external collaborators to contribute.

I believe we have some tests in https://github.com/ThrunGroup/BanditPAM/blob/main/tests/test_commit.py, but they may be broken. If so, please fix them.

Relevant documentation for automated testing: https://coderefinery.github.io/testing/continuous-integration/. It will probably help to find an example repo that does this.

Python bindings do not catch interrupts

Right now, if we run the code from Python and try to interrupt it with Ctrl+C, nothing happens -- the script continues running, or only kills after a very long time.

Instead, we should modify the code to pass this interrupt / kill signal to the C++ code and kill the computation, so users don't have to wait a long time after pressing Ctrl+C.

Duplication of code on loss function

Loss parsing is done on the main function in main.cpp:
https://github.com/ThrunGroup/BanditPAM/blob/c3f2c77c2891c064b0d71a4628c1846c18714e08/src/main.cpp#L58-L62

as well as in setLossFn function in kmedoids_ucb.cpp:
https://github.com/ThrunGroup/BanditPAM/blob/c3f2c77c2891c064b0d71a4628c1846c18714e08/src/kmedoids_ucb.cpp#L110-L113

The reason for duplicating the code is because when we call the Python, the main is not called -- we actually create a binding that calls setLossFn directly. To avoid duplication, we should have main call setLossFn function to set the loss function.

Move `carma` to a submodule

We copied all of carma's files from the unstable branch into this repo, which is obviously suboptimal. We should move it to a git submodule, but one that tracks the unstable branch.

Ref: #32

Use of globals should be removed

The current code uses a lot of global/class variables, and I'm not sure this is in the right way. An example is this line, which refers to data, which should either be a class variable or a parameter.

Please find all the instances of global use throughout, and correct them by making them class variables or parameters to their respective functions

Support arbitrary distance metrics

We should have an easy way for users to incorporate their own dissimilarity metrics. Users should be able to write their dissimilarity metric in Python, which is then called via the C++ code.

User feedback suggests allowing users to pass the reference to the function that will compute distances. Asking the user to supply the O(n^2) distance matrix is of course infeasible.

This is a several-step task, including:

  1. Making the Python function callable via the C++ (C++ bindings for the Python code); perhaps via some translation
  2. Updating the C++ code to use this custom function. Some relevant code

Need to change to `carma/carma` directory

image

The documentation above assumes that the user has already run cd carma from the repo's top-level directory before running those commands. Please make this more explicit

Update project description on PyPi

The project's description provides extremely general information about clustering. Instead, we should highlight the key contributions of our algorithm and why it's important. Likely the people viewing that documentation will already be familiar with clustering in general.

Issue with loading data from numpy array?

Hi,

as part of my thesis I have been implementing the algorithms from this repo from scratch, and I found a discrepancy in the results my code produced when compared to the reference (this repo's Python wrapper).

I debugged the issue for a bit and found that the data matrix doesn't match the passed numpy array. This can be seen by printing data.col(0) after the transpose on line 262. We would expect it to return the same point as X[0] (where X is the numpy array), but instead we get something else. Weirdly enough, the y-coordinate matches, but the x-coordinate is different (and does not appear anywhere in the input data).

To reproduce, insert the following after line 262:

printf("[C++   ] :: X[0] = [%f %f]\n", data.col(0)[0], data.col(0)[1]);

then recompile the BanditPAM dependency and run the following Python script:

import numpy as np
from math import dist
from BanditPAM import KMedoids

np.random.seed(0)

means = np.array([[0,0], [-5,5], [5,5]])
X = np.vstack([np.random.randn(2**7, 2) + µ for µ in means])

kmed = KMedoids(n_medoids=3, algorithm="naive", verbosity=0)
kmed.fit(X, "L2", 3, "")

print(f"[Python] :: X[0] = {X[0]}")

This gives the following output:

[C++   ] :: X[0] = [0.000000 0.400157]
[Python] :: X[0] = [1.76405235 0.40015721]

We would expect them to be equal, but they are not. I have not dug deep enough to figure out why this is, though I suspect it is an issue with the C++/Python interfacing libraries. Also possible is that my dependencies are somehow messed up, though that seems unlikely as the issue persists in the BanditPAM version from PyPI, as confirmed by the resulting medoids being identical.

Error installing BanditPAM armadillo not found

(base) thomascheung@Thomass-MacBook-Pro Desktop % sudo pip install BanditPAM
Password:
WARNING: The directory '/Users/thomascheung/Library/Caches/pip' or its parent directory is not owned or is not writable by the current user. The cache has been disabled. Check the permissions and owner of that directory. If executing pip with sudo, you may want sudo's -H flag.
Collecting BanditPAM
  Downloading BanditPAM-0.0.17.tar.gz (20 kB)
Building wheels for collected packages: BanditPAM
  Building wheel for BanditPAM (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /Users/thomascheung/miniforge3/bin/python3.9 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/setup.py'"'"'; __file__='"'"'/private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /private/tmp/pip-wheel-s4i6ztt_
       cwd: /private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/
  Complete output (17 lines):
  running bdist_wheel
  running build
  running build_ext
  creating tmp
  /usr/bin/gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -fwrapv -O2 -Wall -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -I/Users/thomascheung/miniforge3/include/python3.9 -c /tmp/tmp02cnd6gr.cpp -o tmp/tmp02cnd6gr.o -fvisibility=hidden
  building 'BanditPAM' extension
  creating build
  creating build/temp.macosx-11.0-arm64-3.9
  creating build/temp.macosx-11.0-arm64-3.9/src
  /usr/bin/gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -fwrapv -O2 -Wall -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -DVERSION_INFO="0.0.17" -I/Users/thomascheung/miniforge3/lib/python3.9/site-packages/pybind11/include -Iheaders -I/Users/thomascheung/miniforge3/include/python3.9 -c src/kmedoids_ucb.cpp -o build/temp.macosx-11.0-arm64-3.9/src/kmedoids_ucb.o -stdlib=libc++ -mmacosx-version-min=10.7 -Wno-register -std=c++14 -Xpreprocessor -fopenmp -fvisibility=hidden
  clang: warning: argument unused during compilation: '-Xpreprocessor -fopenmp' [-Wunused-command-line-argument]
  In file included from src/kmedoids_ucb.cpp:8:
  headers/kmedoids_ucb.hpp:4:10: fatal error: 'armadillo' file not found
  #include <armadillo>
           ^~~~~~~~~~~
  1 error generated.
  error: command '/usr/bin/gcc' failed with exit code 1
  ----------------------------------------
  ERROR: Failed building wheel for BanditPAM
  Running setup.py clean for BanditPAM
Failed to build BanditPAM
Installing collected packages: BanditPAM
    Running setup.py install for BanditPAM ... error
    ERROR: Command errored out with exit status 1:
     command: /Users/thomascheung/miniforge3/bin/python3.9 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/setup.py'"'"'; __file__='"'"'/private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/tmp/pip-record-njzr2ocz/install-record.txt --single-version-externally-managed --compile --install-headers /Users/thomascheung/miniforge3/include/python3.9/BanditPAM
         cwd: /private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/
    Complete output (16 lines):
    running install
    running build
    running build_ext
    /usr/bin/gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -fwrapv -O2 -Wall -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -I/Users/thomascheung/miniforge3/include/python3.9 -c /tmp/tmpq8k8m731.cpp -o tmp/tmpq8k8m731.o -fvisibility=hidden
    building 'BanditPAM' extension
    creating build
    creating build/temp.macosx-11.0-arm64-3.9
    creating build/temp.macosx-11.0-arm64-3.9/src
    /usr/bin/gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -fwrapv -O2 -Wall -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -fPIC -O2 -isystem /Users/thomascheung/miniforge3/include -arch arm64 -DVERSION_INFO="0.0.17" -I/Users/thomascheung/miniforge3/lib/python3.9/site-packages/pybind11/include -Iheaders -I/Users/thomascheung/miniforge3/include/python3.9 -c src/kmedoids_ucb.cpp -o build/temp.macosx-11.0-arm64-3.9/src/kmedoids_ucb.o -stdlib=libc++ -mmacosx-version-min=10.7 -Wno-register -std=c++14 -Xpreprocessor -fopenmp -fvisibility=hidden
    clang: warning: argument unused during compilation: '-Xpreprocessor -fopenmp' [-Wunused-command-line-argument]
    In file included from src/kmedoids_ucb.cpp:8:
    headers/kmedoids_ucb.hpp:4:10: fatal error: 'armadillo' file not found
    #include <armadillo>
             ^~~~~~~~~~~
    1 error generated.
    error: command '/usr/bin/gcc' failed with exit code 1
    ----------------------------------------
ERROR: Command errored out with exit status 1: /Users/thomascheung/miniforge3/bin/python3.9 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/setup.py'"'"'; __file__='"'"'/private/tmp/pip-install-4mou614m/banditpam_49ef6f2d25414032a94e5715288841f9/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/tmp/pip-record-njzr2ocz/install-record.txt --single-version-externally-managed --compile --install-headers /Users/thomascheung/miniforge3/include/python3.9/BanditPAM Check the logs for full command output.

Emitting log file causes Python kernel crashing

When testing the Python code on MNIST data with PAM algorithm, adding verbosity = 1 causes issue on the kernel. In particular, the following code causes kernel crashing.

X = pd.read_csv('data/MNIST-1k.csv', sep=' ', header=None).to_numpy()
X_tsne = TSNE(n_components = 2).fit_transform(X)

kmed = KMedoids(n_medoids = 10, algorithm = "naive", verbosity = 1)
kmed.fit(X, 'L2', 10, "naive_v1_mnist_log")

The above code runs properly if the verbosity = 1 is removed. If we change the algorithm to "BanditPAM", the verbosity = 1 does not cause any issue and the log file is generated properly.

OpenMP not being used in PyPi version?

OpenMP is not used by the Dockerfile or when building the distributions for PyPi. This likely means the PyPi releases are not using OpenMP and could be improved.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.