{"id":34094231,"url":"https://github.com/smeznar/snore","last_synced_at":"2026-04-02T01:01:24.819Z","repository":{"id":57468948,"uuid":"282386365","full_name":"smeznar/SNoRe","owner":"smeznar","description":"SNoRe: Scalable Unsupervised Learning of Symbolic Node Representations","archived":false,"fork":false,"pushed_at":"2023-09-26T18:32:14.000Z","size":5110,"stargazers_count":11,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-06T15:48:46.185Z","etag":null,"topics":["graph-embedding","graph-learning","interpretable-machine-learning","node-prediction","unsupervised-graph-embedding","unsupervised-learning"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smeznar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-25T06:33:32.000Z","updated_at":"2024-11-19T07:50:24.000Z","dependencies_parsed_at":"2022-09-19T10:10:17.460Z","dependency_job_id":null,"html_url":"https://github.com/smeznar/SNoRe","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/smeznar/SNoRe","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smeznar%2FSNoRe","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smeznar%2FSNoRe/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smeznar%2FSNoRe/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smeznar%2FSNoRe/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smeznar","download_url":"https://codeload.github.com/smeznar/SNoRe/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smeznar%2FSNoRe/sbom","scorecard":{"id":833280,"data":{"date":"2025-08-11","repo":{"name":"github.com/smeznar/SNoRe","commit":"c1d7a50c74948b3f1b207dea4f3198ef2a5592d6"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/22 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/pylint.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pylint.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/smeznar/SNoRe/pylint.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pylint.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/smeznar/SNoRe/pylint.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/pylint.yml:19","Warn: pipCommand not pinned by hash: .github/workflows/pylint.yml:20","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"13 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2018-34 / GHSA-2fc2-6r4j-p65h","Warn: Project is vulnerable to: PYSEC-2021-856 / GHSA-5545-2q6w-2gh6","Warn: Project is vulnerable to: PYSEC-2019-108 / GHSA-9fq2-x9r6-wfmf","Warn: Project is vulnerable to: PYSEC-2018-33 / GHSA-cw6w-4rcx-xphc","Warn: Project is vulnerable to: PYSEC-2021-857 / GHSA-f7c7-j99h-c22f","Warn: Project is vulnerable to: GHSA-fpfv-jqm9-f5jm","Warn: Project is vulnerable to: PYSEC-2017-1 / GHSA-frgw-fgh6-9g52","Warn: Project is vulnerable to: PYSEC-2020-107 / GHSA-jjw5-xxj6-pcv5","Warn: Project is vulnerable to: PYSEC-2024-110 / GHSA-jw8x-6495-233v","Warn: Project is vulnerable to: PYSEC-2020-108","Warn: Project is vulnerable to: PYSEC-2019-156 / GHSA-xp76-357g-9wqq","Warn: Project is vulnerable to: PYSEC-2023-102","Warn: Project is vulnerable to: PYSEC-2023-114"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T18:18:26.879Z","repository_id":57468948,"created_at":"2025-08-23T18:18:26.880Z","updated_at":"2025-08-23T18:18:26.880Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31293631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graph-embedding","graph-learning","interpretable-machine-learning","node-prediction","unsupervised-graph-embedding","unsupervised-learning"],"created_at":"2025-12-14T15:01:42.732Z","updated_at":"2026-04-02T01:01:24.781Z","avatar_url":"https://github.com/smeznar.png","language":"Python","readme":"# SNoRe: Scalable Unsupervised Learning of Symbolic Node Representations\nThis repository contains the implementation of SNoRe algorithm from SNoRe paper\nfound [here](https://ieeexplore.ieee.org/document/9265235):\n\n```\n@ARTICLE{meznar2020snore,\n         author={S. {Me\\v{z}nar} and N. {Lavra\\v{c}} and B. {\\v{S}krlj}},\n         journal={IEEE Access}, \n         title={SNoRe: Scalable Unsupervised Learning of Symbolic Node Representations},\n         year={2020},\n         volume={8},\n         number={}, \n         pages={212568-212588},\n         doi={10.1109/ACCESS.2020.3039541}}\n```\n\nAn overview of the algorithm is presented in the image below.\n\n![algorithm overview](https://github.com/smeznar/SNoRe/blob/master/images/algorithm_overview.png)\n\n## Installing SNoRe\n```\npython setup.py install\n```\n\nor\n\n```\npip install snore-embedding\n```\n\n## Using SNoRe\nA simple use-case is shown below.\nFirst, we import the necessary libraries and load the dataset and its labels.\n\n```\nfrom snore import SNoRe\nfrom scipy.io import loadmat\nfrom sklearn.utils import shuffle\nfrom catboost import CatBoost\nimport pandas as pd\nfrom sklearn.metrics import f1_score\nimport numpy as np\n\n# Load adjacency matrix and labels\ndataset = loadmat(\"data/cora.mat\")\nnetwork_adj = dataset[\"network\"]\nlabels = dataset[\"group\"]\n```\n\nWe then create the SNoRe model and embed the network. \nIn code, the default parameters are shown.\n\n```\n# Create the model\nmodel = SNoRe(dimension=256, num_walks=1024, max_walk_length=5,\n              inclusion=0.005, fixed_dimension=False, metric=\"cosine\",\n              num_bins=256)\n\n# Embed the network\nembedding = model.embed(network_adj)\n```\n\nFinally, we train the classifier and test on the remaining data.\n\n```\n# Train the classifier\nnodes = shuffle([i for i in range(network_adj.shape[0])])\ntrain_mask = nodes[:int(network_adj.shape[0]*0.8)]\ntest_mask = nodes[int(network_adj.shape[0]*0.8):]\nclassifier = CatBoost(params={'loss_function': 'MultiRMSE', 'iterations': 500})\ndf = pd.DataFrame.sparse.from_spmatrix(embedding)\nclassifier.fit(df.iloc[train_mask], labels[train_mask])\n\n# Test prediction\npredictions = classifier.predict(df.iloc[test_mask])\nprint(\"Micro score:\",\n      f1_score(np.argmax(labels[test_mask], axis=1),\n               np.argmax(predictions, axis=1),\n               average='micro'))\n\n```\n\nFurther examples of evaluation and embedding explainability can be found in the examples folder.\n\n## Hyperparameter explanation\n\nSNoRe uses the following hyperparameters and their default values:\n\n| Hyperparameter  | Description                                                                                                                                                                                                                                | Default Value |\n|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|\n| dimension       | The number of features if fixed number of features are used, otherwise the number of features that make up space equivalent to \u0026#124;N\u0026#124;*dimensions                                                                                    | 256           |\n| num_walks       | The number of random walks for every node                                                                                                                                                                                                  | 1024          |\n| max_walk_length | The length of the longest random walk                                                                                                                                                                                                      | 5             |\n| inclusion       | Inclusion threshold. Node needs to be encountered with frequency inclusion to appear in the hash representation                                                                                                                            | 0.005         |\n| fixed_dimension | If True, fixed number of features are used, otherwise space equivalent to \u0026#124;N\u0026#124;*dimensions is used                                                                                                                                 | False         |\n| metric          | Metric used for similarity calculation. Metrics 'cosine','HPI','HDI','euclidean', 'jaccard', 'seuclidean', and 'canberra' can be used when calculating the embedding of fixed dimensions, otherwise 'cosine', 'HPI', and 'HDI' can be used | 'cosine'      |\n| num_bins        | Number of bins used in SNoRe SDF to digitize the embedding and reduce it's size. The values are not digitized if None is chosen.                                                                                                           | 256           |\n\n## Results against other baselines\n\nIn the above mentioned paper we test SNoRe and it's extension SNoRe SDF against NetMF (SCD), Deepwalk, node2vec,\nLINE, PPRS, VGAE, Label Propagation, and the random baseline. The results can be seen on the image below.\n\n![micro f1 results](https://github.com/smeznar/SNoRe/blob/master/images/micro_plot_baseline.png)\n\nBy aggregating this results we get scores presented in the table below.\n\n![micro f1 table](https://github.com/smeznar/SNoRe/blob/master/images/f1_table.png)\n\n## Embedding interpretability with SHAP\n\nAn advantage of SNoRe is the ability to interpret why instances were predicted the way they were. We can do such\ninterpretation for a single instance as show in the image below.\n\n![micro f1 table](https://github.com/smeznar/SNoRe/blob/master/images/waterfall.png)\n\nWe can also see which features are the most important with the summary plot shown in the image below.\n\n![micro f1 table](https://github.com/smeznar/SNoRe/blob/master/images/Shap_pubmed.png)\n\nTo try the interpretation for yourself use code in the example *examples/explainability_example.py*. \n\n## Latent clustering with UMAP\n\nWe can use tools such as UMAP to cluster the embedding we create with SNoRe and see if nodes with similar labels\ncluster together. Such clusterings can be seen in the image below.\n\n![micro f1 results](https://github.com/smeznar/SNoRe/blob/master/images/umap.png)\n\nTo create such clustering you can start with code in *examples/umap_example.py*.\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmeznar%2Fsnore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmeznar%2Fsnore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmeznar%2Fsnore/lists"}