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.4.tar.gz (46.6 kB view details)

Uploaded Source

Built Distributions

omikuji-0.3.4-cp39-cp39-win_amd64.whl (374.9 kB view details)

Uploaded CPython 3.9 Windows x86-64

omikuji-0.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.3 MB view details)

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

omikuji-0.3.4-cp39-cp39-macosx_10_14_x86_64.whl (513.5 kB view details)

Uploaded CPython 3.9 macOS 10.14+ x86-64

omikuji-0.3.4-cp38-cp38-win_amd64.whl (374.9 kB view details)

Uploaded CPython 3.8 Windows x86-64

omikuji-0.3.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.3 MB view details)

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

omikuji-0.3.4-cp38-cp38-macosx_10_14_x86_64.whl (513.5 kB view details)

Uploaded CPython 3.8 macOS 10.14+ x86-64

omikuji-0.3.4-cp37-cp37m-win_amd64.whl (374.9 kB view details)

Uploaded CPython 3.7m Windows x86-64

omikuji-0.3.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.3 MB view details)

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

omikuji-0.3.4-cp37-cp37m-macosx_10_14_x86_64.whl (513.5 kB view details)

Uploaded CPython 3.7m macOS 10.14+ x86-64

omikuji-0.3.4-cp36-cp36m-win_amd64.whl (374.9 kB view details)

Uploaded CPython 3.6m Windows x86-64

omikuji-0.3.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (1.3 MB view details)

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

omikuji-0.3.4-cp36-cp36m-macosx_10_14_x86_64.whl (513.5 kB view details)

Uploaded CPython 3.6m macOS 10.14+ x86-64

File details

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

File metadata

  • Download URL: omikuji-0.3.4.tar.gz
  • Upload date:
  • Size: 46.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4.tar.gz
Algorithm Hash digest
SHA256 9acfd88c8e97f5bb3ecb97038f9210ec5d677b4f134a4f4497839a061dcf319f
MD5 64f0865a2b7ee2df665e15d3e7d30589
BLAKE2b-256 5cd65d5da8b2601723a0f7acaa50c8c2ada54fd50ee80e88495eb41da9b10224

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 374.9 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 8f42b81c6a08a9be676c8ac47833fd30c974b4f6d0ae247c84386cb1f39fd2c8
MD5 ca323e0b2a21812edc3abee966cf9595
BLAKE2b-256 ca107b7b7cc42eeb165af7521fa88a951ee4f684f4fc12ab86579642d73392d5

See more details on using hashes here.

File details

Details for the file omikuji-0.3.4-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.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 452d9b31ce8c54af9f51e17a634a07df3a474f3d4783fc70f56bc743bdf1a4ee
MD5 abf7a11b27b8d43dd6880e81801cf499
BLAKE2b-256 4531f69288ef9784e9eea6b54832b9f7e4ae4e1d6d03d85b19a03731bacf3500

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp39-cp39-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 513.5 kB
  • Tags: CPython 3.9, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp39-cp39-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 34c0b4f9313099fcb42bcd992e15435807ba03a16e62988ddbef6e70114d6f57
MD5 7a66032903e038e9e80ca8815334217a
BLAKE2b-256 39fce19da1079e1dc3ddfef518de107eaa6d632d5a8b89aa1f95a95b00bc7797

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 374.9 kB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 31035f1c1ee59a2a9c98ba02498b4944da9f0ac35f13719b60d94a8d211989ce
MD5 a34140196be5089e50a5f5fd3e7c8cd9
BLAKE2b-256 3cbce40e2df37381fa2011ec69b4ea399bef83e5dcc98d985a7bd5334cd28649

See more details on using hashes here.

File details

Details for the file omikuji-0.3.4-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.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 06345b34015ce6ff908828391d141680e9508887648cfd73b4cfd7fbb3dfa606
MD5 ff1e747c58757faa73b54f63fe8af47c
BLAKE2b-256 936bdafb4213bbe2335da6d6283534a00c6a78098da7de7b6f06a8e79face38a

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp38-cp38-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 513.5 kB
  • Tags: CPython 3.8, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp38-cp38-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 4fef6380da1f45c8b5d054e67f170f9c82ccd5cde8fca81d8e8ddd7293153446
MD5 7a6999c62a1b8f4b4ba84aec2571ebe1
BLAKE2b-256 0016fef7f2f53ed85a9f8e925f4adf33655a8e86c75dde1eba312b4b5088127d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 374.9 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 b8de2c0b01e139da09f65357c4fd4f941c6463d5bfe87102a946e6eb78aedb8c
MD5 231c48e89aadea779b3823eab44b4097
BLAKE2b-256 f721eb105b12faa6061d2c7f1bc7d85e3b7fd6c4a191de780cb6f4b868ed871b

See more details on using hashes here.

File details

Details for the file omikuji-0.3.4-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.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 c7f705f6a02d736242f3fd799f0d8aad3c063ea922d40ca7bdc3c00ac48896de
MD5 794ce17206e55ed2bc721a3d6f3e960a
BLAKE2b-256 541be9e1b7ddbac321af228e0d75c19b882ff626986c67bd767b8d89881c334f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp37-cp37m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 513.5 kB
  • Tags: CPython 3.7m, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp37-cp37m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 94bd1995c7cd85373aee2c47c8399d8f85c5c8bd215380611dc1b143aa6bf543
MD5 738618db2a46d66c4b9e38cf5eebf5ee
BLAKE2b-256 5387a325fadf00a801b13b35d0e57df2ab547ab6105cbcc42833d708c60cd3af

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp36-cp36m-win_amd64.whl
  • Upload date:
  • Size: 374.9 kB
  • Tags: CPython 3.6m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 9b830fec4f1800e1cf227bbc22719bbdec5576c0a304dd1888afa4cad7e11a95
MD5 0f2f1e0360248c55abd81e2230c123e2
BLAKE2b-256 aff4694148faa740a89f4d2992e7da2471d0a3da00241afa60798db1727bd955

See more details on using hashes here.

File details

Details for the file omikuji-0.3.4-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.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
Algorithm Hash digest
SHA256 0679e464c0b423b35eb69c4b65809f29e676c1accfc46a76b98fd246cacd8f1c
MD5 f90ee0440f1a88913a4db78a0c0886a3
BLAKE2b-256 550d76e843114f772445f2db9fa4afc298c1f77653a02f120de4baee5c3bb96e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: omikuji-0.3.4-cp36-cp36m-macosx_10_14_x86_64.whl
  • Upload date:
  • Size: 513.5 kB
  • Tags: CPython 3.6m, macOS 10.14+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.8.2 requests/2.22.0 setuptools/45.2.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10

File hashes

Hashes for omikuji-0.3.4-cp36-cp36m-macosx_10_14_x86_64.whl
Algorithm Hash digest
SHA256 b89e1b1cd35a83c32cc47f1fe1f31c08826fb620ecafd1ce5c84cc66b43ceefd
MD5 e3c145cc0f2635e2825341a3761eea0f
BLAKE2b-256 d0f1a15ee96e68867032897092db35f000c05d5ca7bd6d2c83f0e87d7a0a3890

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