Skip to main content

Python binding to Omikuji, an efficient implementation of Partioned Label Trees and its variations for extreme multi-label classification

Project description

Omikuji

Build Status Crate version PyPI version

An efficient implementation of Partitioned Label Trees (Prabhu et al., 2018) and its variations for extreme multi-label classification, written in Rust🦀 with love💖.

Features & Performance

Omikuji has has been tested on datasets from the Extreme Classification Repository. All tests below are run on a quad-core Intel® Core™ i7-6700 CPU, and we allowed as many cores to be utilized as possible. We measured training time, and calculated precisions at 1, 3, and 5. (Note that, due to randomness, results might vary from run to run, especially for smaller datasets.)

Parabel, better parallelized

Omikuji provides a more parallelized implementation of Parabel (Prabhu et al., 2018) that trains faster when more CPU cores are available. Compared to the original implementation written in C++, which can only utilize the same number of CPU cores as the number of trees (3 by default), Omikuji maintains the same level of precision but trains 1.3x to 1.7x faster on our quad-core machine. Further speed-up is possible if more CPU cores are available.

Dataset Metric Parabel Omikuji
(balanced,
cluster.k=2)
EURLex-4K P@1 82.2 82.1
P@3 68.8 68.8
P@5 57.6 57.7
Train Time 18s 14s
Amazon-670K P@1 44.9 44.8
P@3 39.8 39.8
P@5 36.0 36.0
Train Time 404s 234s
WikiLSHTC-325K P@1 65.0 64.8
P@3 43.2 43.1
P@5 32.0 32.1
Train Time 959s 659s

Regular k-means for shallow trees

Following Bonsai (Khandagale et al., 2019), Omikuji supports using regular k-means instead of balanced 2-means clustering for tree construction, which results in wider, shallower and unbalanced trees that train slower but have better precision. Comparing to the original Bonsai implementation, Omikuji also achieves the same precisions while training 2.6x to 4.6x faster on our quad-core machine. (Similarly, further speed-up is possible if more CPU cores are available.)

Dataset Metric Bonsai Omikuji
(unbalanced,
cluster.k=100,
max_depth=3)
EURLex-4K P@1 82.8 83.0
P@3 69.4 69.5
P@5 58.1 58.3
Train Time 87s 19s
Amazon-670K P@1 45.5* 45.6
P@3 40.3* 40.4
P@5 36.5* 36.6
Train Time 5,759s 1,753s
WikiLSHTC-325K P@1 66.6* 66.6
P@3 44.5* 44.4
P@5 33.0* 33.0
Train Time 11,156s 4,259s

*Precision numbers as reported in the paper; our machine doesn't have enough memory to run the full prediction with their implementation.

Balanced k-means for balanced shallow trees

Sometimes it's desirable to have shallow and wide trees that are also balanced, in which case Omikuji supports the balanced k-means algorithm used by HOMER (Tsoumakas et al., 2008) for clustering as well.

Dataset Metric Omikuji
(balanced,
cluster.k=100)
EURLex-4K P@1 82.1
P@3 69.4
P@5 58.1
Train Time 19s
Amazon-670K P@1 45.4
P@3 40.3
P@5 36.5
Train Time 1,153s
WikiLSHTC-325K P@1 65.6
P@3 43.6
P@5 32.5
Train Time 3,028s

Layer collapsing for balanced shallow trees

An alternative way for building balanced, shallow and wide trees is to collapse adjacent layers, similar to the tree compression step used in AttentionXML (You et al., 2019): intermediate layers are removed, and their children replace them as the children of their parents. For example, with balanced 2-means clustering, if we collapse 5 layers after each layer, we can increase the tree arity from 2 to 2⁵⁺¹ = 64.

Dataset Metric Omikuji
(balanced,
cluster.k=2,
collapse 5 layers)
EURLex-4K P@1 82.4
P@3 69.3
P@5 58.0
Train Time 16s
Amazon-670K P@1 45.3
P@3 40.2
P@5 36.4
Train Time 460s
WikiLSHTC-325K P@1 64.9
P@3 43.3
P@5 32.3
Train Time 1,649s

Build & Install

Omikuji can be easily built & installed with Cargo as a CLI app:

cargo install omikuji --features cli

Or install from the latest source:

cargo install --git https://github.com/tomtung/omikuji.git --features cli

The CLI app will be available as omikuji. For example, to reproduce the results on the EURLex-4K dataset:

omikuji train eurlex_train.txt --model_path ./model
omikuji test ./model eurlex_test.txt --out_path predictions.txt

Python Binding

A simple Python binding is also available for training and prediction. It can be install via pip:

pip install omikuji

Note that you might still need to install Cargo should compilation become necessary.

You can also install from the latest source:

pip install git+https://github.com/tomtung/omikuji.git -v

The following script demonstrates how to use the Python binding to train a model and make predictions:

import omikuji

# Train
hyper_param = omikuji.Model.default_hyper_param()
# Adjust hyper-parameters as needed
hyper_param.n_trees = 5
model = omikuji.Model.train_on_data("./eurlex_train.txt", hyper_param)

# Serialize & de-serialize
model.save("./model")
model = omikuji.Model.load("./model")
# Optionally densify model weights to trade off between prediction speed and memory usage
model.densify_weights(0.05)

# Predict
feature_value_pairs = [
    (0, 0.101468),
    (1, 0.554374),
    (2, 0.235760),
    (3, 0.065255),
    (8, 0.152305),
    (10, 0.155051),
    # ...
]
label_score_pairs =  model.predict(feature_value_pairs)

Usage

$ omikuji train --help
omikuji-train
Train a new model

USAGE:
    omikuji train [FLAGS] [OPTIONS] <TRAINING_DATA_PATH>

FLAGS:
        --cluster.unbalanced     Perform regular k-means clustering instead of balanced k-means clustering
    -h, --help                   Prints help information
        --train_trees_1_by_1     Finish training each tree before start training the next; limits initial
                                 parallelization but saves memory
        --tree_structure_only    Build the trees without training classifiers; useful when a downstream user needs the
                                 tree structures only
    -V, --version                Prints version information

OPTIONS:
        --centroid_threshold <THRESHOLD>         Threshold for pruning label centroid vectors [default: 0]
        --cluster.eps <EPS>                      Epsilon value for determining clustering convergence [default: 0.0001]
        --cluster.k <K>                          Number of clusters [default: 2]
        --cluster.min_size <SIZE>
            Labels in clusters with sizes smaller than this threshold are reassigned to other clusters instead [default:
            2]
        --collapse_every_n_layers <N>
            Number of adjacent layers to collapse, which increases tree arity and decreases tree depth [default: 0]

        --linear.c <C>                           Cost co-efficient for regularizing linear classifiers [default: 1]
        --linear.eps <EPS>
            Epsilon value for determining linear classifier convergence [default: 0.1]

        --linear.loss <LOSS>
            Loss function used by linear classifiers [default: hinge]  [possible values: hinge, log]

        --linear.max_iter <M>
            Max number of iterations for training each linear classifier [default: 20]

        --linear.weight_threshold <THRESHOLD>
            Threshold for pruning weight vectors of linear classifiers [default: 0.1]

        --max_depth <DEPTH>                      Maximum tree depth [default: 20]
        --min_branch_size <SIZE>
            Number of labels below which no further clustering & branching is done [default: 100]

        --model_path <PATH>
            Optional path of the directory where the trained model will be saved if provided; if an model with
            compatible settings is already saved in the given directory, the newly trained trees will be added to the
            existing model
        --n_threads <T>
            Number of worker threads. If 0, the number is selected automatically [default: 0]

        --n_trees <N>                            Number of trees [default: 3]

ARGS:
    <TRAINING_DATA_PATH>    Path to training dataset file (in the format of the Extreme Classification Repository)
$ omikuji test --help
omikuji-test
Test an existing model

USAGE:
    omikuji test [OPTIONS] <MODEL_PATH> <TEST_DATA_PATH>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --beam_size <beam_size>           Beam size for beam search [default: 10]
        --k_top <K>                       Number of top predictions to write out for each test example [default: 5]
        --max_sparse_density <DENSITY>    Density threshold above which sparse weight vectors are converted to dense
                                          format. Lower values speed up prediction at the cost of more memory usage
                                          [default: 0.1]
        --n_threads <T>                   Number of worker threads. If 0, the number is selected automatically [default:
                                          0]
        --out_path <PATH>                 Path to the which predictions will be written, if provided

ARGS:
    <MODEL_PATH>        Path of the directory where the trained model is saved
    <TEST_DATA_PATH>    Path to test dataset file (in the format of the Extreme Classification Repository)

Data format

Our implementation takes dataset files formatted as those provided in the Extreme Classification Repository. A data file starts with a header line with three space-separated integers: total number of examples, number of features, and number of labels. Following the header line, there is one line per each example, starting with comma-separated labels, followed by space-separated feature:value pairs:

label1,label2,...labelk ft1:ft1_val ft2:ft2_val ft3:ft3_val .. ftd:ftd_val

Trivia

The project name comes from o-mikuji (御神籤), which are predictions about one's future written on strips of paper (labels?) at jinjas and temples in Japan, often tied to branches of pine trees after they are read.

References

  • Y. Prabhu, A. Kag, S. Harsola, R. Agrawal, and M. Varma, “Parabel: Partitioned Label Trees for Extreme Classification with Application to Dynamic Search Advertising,” in Proceedings of the 2018 World Wide Web Conference, 2018, pp. 993–1002.
  • S. Khandagale, H. Xiao, and R. Babbar, “Bonsai - Diverse and Shallow Trees for Extreme Multi-label Classification,” Apr. 2019.
  • G. Tsoumakas, I. Katakis, and I. Vlahavas, “Effective and efficient multilabel classification in domains with large number of labels,” ECML, 2008.
  • R. You, S. Dai, Z. Zhang, H. Mamitsuka, and S. Zhu, “AttentionXML: Extreme Multi-Label Text Classification with Multi-Label Attention Based Recurrent Neural Networks,” Jun. 2019.

License

Omikuji is licensed under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

omikuji-0.3.2.tar.gz (46.8 kB view details)

Uploaded Source

Built Distributions

omikuji-0.3.2-cp39-cp39-win_amd64.whl (386.6 kB view details)

Uploaded CPython 3.9 Windows x86-64

omikuji-0.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.12+ x86-64 manylinux: glibc 2.5+ x86-64

omikuji-0.3.2-cp39-cp39-macosx_10_14_x86_64.whl (521.2 kB view details)

Uploaded CPython 3.9 macOS 10.14+ x86-64

omikuji-0.3.2-cp38-cp38-win_amd64.whl (387.7 kB view details)

Uploaded CPython 3.8 Windows x86-64

omikuji-0.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.12+ x86-64 manylinux: glibc 2.5+ x86-64

omikuji-0.3.2-cp38-cp38-macosx_10_14_x86_64.whl (524.0 kB view details)

Uploaded CPython 3.8 macOS 10.14+ x86-64

omikuji-0.3.2-cp37-cp37m-win_amd64.whl (387.8 kB view details)

Uploaded CPython 3.7m Windows x86-64

omikuji-0.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.12+ x86-64 manylinux: glibc 2.5+ x86-64

omikuji-0.3.2-cp37-cp37m-macosx_10_14_x86_64.whl (522.3 kB view details)

Uploaded CPython 3.7m macOS 10.14+ x86-64

omikuji-0.3.2-cp36-cp36m-win_amd64.whl (387.9 kB view details)

Uploaded CPython 3.6m Windows x86-64

omikuji-0.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.6m manylinux: glibc 2.12+ x86-64 manylinux: glibc 2.5+ x86-64

omikuji-0.3.2-cp36-cp36m-macosx_10_14_x86_64.whl (525.9 kB view details)

Uploaded CPython 3.6m macOS 10.14+ x86-64

File details

Details for the file omikuji-0.3.2.tar.gz.

File metadata

  • Download URL: omikuji-0.3.2.tar.gz
  • Upload date:
  • Size: 46.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2.tar.gz
Algorithm Hash digest
SHA256 509add0cf641dd3bef1ed83cf0a95caa22e97d9970da2e498fe7a38cf831fb78
MD5 053bb8b8fa35bbf665c79942d1268025
BLAKE2b-256 c3cb15cacb91a7b85c974b159345610d779d3af59a24162d798af25efa4796db

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 386.6 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 f38979a7a23f54473971bd5992dfbc64a8d8f1803dd0b753e26a35a87b05ec08
MD5 81b5ee8430f565ed149b2c6ef23cffc0
BLAKE2b-256 5566549633317689ee85da566b7ca85352964f34a6dfb4226247b8e1c18945ef

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for omikuji-0.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 1738b1ac224f48ef6a916b31772e349e3e7f82f58b4ca686717e3214ca1a429d
MD5 0298711b0e7c15c0c57f0d371e7a77d1
BLAKE2b-256 122bdc1b364cd392d39965d76c2f82886ed88be1955c58cd98a84190031522cf

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp39-cp39-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp39-cp39-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 521.2 kB
  • Tags: CPython 3.9, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp39-cp39-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 af03b6d75e56d1eeb48bba18f835c0aba1b486a20d12fd8f69a6188ee9fc932e
MD5 629015e1b5e02d9f10791a75251c6213
BLAKE2b-256 2b517aafceffc66d2d0900d501ba234a26fb1ff1613f447f9b4c05194cbbfa6a

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 387.7 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 b8de66c3355cd7359129d9741ee01ab99d9d1e3a52108dbb034f41520c2c404c
MD5 0ef22a894bb986d9a996bdfe7ffeee0a
BLAKE2b-256 a0c31d2e3713434263514ea13b1b6d3ef876427f8043560ac52654a45343a9a4

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for omikuji-0.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 124628354a799a2dc77711944a9f1af0060b9e2f33f83f8104051e99c6638cff
MD5 6ffb0042f791698439cf8dae5606090a
BLAKE2b-256 5f240fb0a411e46403e5eddf29482f1ad14379dad9200ea16efbc2592aec1d22

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp38-cp38-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp38-cp38-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 524.0 kB
  • Tags: CPython 3.8, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp38-cp38-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 bcf4dc22ffd7541284408ce32d09f00b525b4deb2e6fb97b06e002bce2d09f5c
MD5 7237bed80a349bdb6f93eeabbedb1ee2
BLAKE2b-256 20942fa42290877fa17c797abc6f6fbe9c95cadb568828a18986d038a8127281

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 387.8 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 0ec0ae8c7a38621d1931e98062919dcfcabd9bdd795fe6a0ba0acd7c895baa8d
MD5 2f968061e398def9d1c9c50a14258d43
BLAKE2b-256 c7f990cb95a18a2ffd6818de1795b5ce0d202e679d4863cebd2ddacb3eead176

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for omikuji-0.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 6cbed545560581baa4aea0b29c0cdf182e0d7f535cacbb41f29624eb2f413328
MD5 8eee087830743ae2e91448aeb5ae890c
BLAKE2b-256 d5e085131dec93ed8fd5e8231d8d7595e30cc65c6525d4563d8304cb57b4173a

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp37-cp37m-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp37-cp37m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 522.3 kB
  • Tags: CPython 3.7m, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp37-cp37m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 5e6d948a7416ba484bbab5922736c8fc20d03a5ff7f874ad4e807a5bc740ec87
MD5 33721e41bf1ede8b7b5772ccaed43bf3
BLAKE2b-256 b9c1ca125f82322ecbe475ea9960622679302c0fa18a3aee39b78e6965cade41

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp36-cp36m-win_amd64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp36-cp36m-win_amd64.whl
  • Upload date:
  • Size: 387.9 kB
  • Tags: CPython 3.6m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 fff94fe171be6f2152a4002c329260a099c23e86e30ff5372d35977003f8b0c7
MD5 5b25386b94e98203ea5d69448b608105
BLAKE2b-256 a18ee1124b26437d09ad9aa6989f152e64104820f1d822f4cca6bed0a4d97484

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl.

File metadata

File hashes

Hashes for omikuji-0.3.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 beea9a338ed7cd2fe4c9caa4c77221a38ae758bcaf740326fd7cea6a32eb79b9
MD5 fe366f087361eee20dfbd251f80263f3
BLAKE2b-256 ffd00e278490e2fa8fe68da7d55b3393eaf553345b809f8e1cf53030dd80d5de

See more details on using hashes here.

File details

Details for the file omikuji-0.3.2-cp36-cp36m-macosx_10_14_x86_64.whl.

File metadata

  • Download URL: omikuji-0.3.2-cp36-cp36m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 525.9 kB
  • Tags: CPython 3.6m, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.22.0 setuptools/42.0.2 requests-toolbelt/0.9.1 tqdm/4.34.0 CPython/3.6.9

File hashes

Hashes for omikuji-0.3.2-cp36-cp36m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 b3fc92ae6abc8928402ca074d8d4e74e991585fd8fc5a6f838d5ee4f0d7699e6
MD5 9296f2a5c80cc03dd8b446774bc8da43
BLAKE2b-256 e05d98ac36d1bda416adb8e9281db6c0691a9a0b0946a64ce5b952517a7c5cd1

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page