{"id":22446121,"url":"https://github.com/henrikbostrom/xrf","last_synced_at":"2025-10-16T05:31:33.416Z","repository":{"id":265710901,"uuid":"896533006","full_name":"henrikbostrom/xrf","owner":"henrikbostrom","description":"xrf is a Python package that implements random forests with example attribution","archived":false,"fork":false,"pushed_at":"2025-06-25T12:55:19.000Z","size":372,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-30T03:48:15.494Z","etag":null,"topics":["classification","example-based-explanations","explainability","explainable-ai","explainable-artificial-intelligence","explainable-machine-learning","explainable-ml","machine-learning","random-forest","regression"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/henrikbostrom.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-30T16:07:06.000Z","updated_at":"2025-06-25T12:55:22.000Z","dependencies_parsed_at":"2025-02-01T15:43:13.268Z","dependency_job_id":"fa1f38f1-12c4-4b73-8d97-6981240a16b9","html_url":"https://github.com/henrikbostrom/xrf","commit_stats":null,"previous_names":["henrikbostrom/xrf"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/henrikbostrom/xrf","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrikbostrom%2Fxrf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrikbostrom%2Fxrf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrikbostrom%2Fxrf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrikbostrom%2Fxrf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/henrikbostrom","download_url":"https://codeload.github.com/henrikbostrom/xrf/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/henrikbostrom%2Fxrf/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279159536,"owners_count":26116492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-16T02:00:06.019Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["classification","example-based-explanations","explainability","explainable-ai","explainable-artificial-intelligence","explainable-machine-learning","explainable-ml","machine-learning","random-forest","regression"],"created_at":"2024-12-06T03:26:08.431Z","updated_at":"2025-10-16T05:31:33.410Z","avatar_url":"https://github.com/henrikbostrom.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\u003ca href=\"https://xrf.readthedocs.io\"\u003e\u003cimg alt=\"xrf\" src=\"https://github.com/henrikbostrom/xrf/blob/main/docs/xrf.png\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://pypi.org/project/xrf/\"\u003e\u003cimg src=\"https://img.shields.io/badge/pypi package-0.1.1-brightgreen\" alt=\"PyPI version\" height=20 align=\"center\"\u003e\u003c/a\u003e\n\u003ca href=\"https://anaconda.org/conda-forge/xrf\"\u003e\u003cimg src=\"https://img.shields.io/badge/conda--forge-0.1.1-orange\" alt=\"conda-forge version\" height=20 align=\"center\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pepy.tech/project/xrf\"\u003e\u003cimg src=\"https://static.pepy.tech/badge/xrf?dummy=unused\" alt=\"Downloads\" height=20 align=\"center\"\u003e\u003c/a\u003e\n\u003ca href=\"https://xrf.readthedocs.io/en/latest\"\u003e\u003cimg src=\"https://readthedocs.org/projects/xrf/badge/?version=latest\" alt=\"docs status\" height=20 align=\"center\"\u003e\u003c/a\u003e \n\u003ca href=\"https://github.com/henrikbostrom/xrf/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-BSD--3--clause-blue\" alt=\"License\" height=20 align=\"center\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/henrikbostrom/xrf/blob/main/CHANGELOG.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/release--date-Nov.%2030,%202024-darkgreen\" alt=\"Release date\" height=20 align=\"center\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n``xrf`` is a Python package that implements random forests with \nexample attribution, i.e., predictions are\nassociated with weight distributions over the training examples, where\neach prediction is the scalar product of the weights and targets of\nthe training examples. The examples that are used to form\npredictions can be constrained by their number or by their cumulative\nweight. When not constrained, the predictions are identical to what is\noutput by random forest classifiers and regressors as implemented in\n[scikit-learn](https://scikit-learn.org/).\n\n## Installation\n\nFrom [PyPI](https://pypi.org/project/xrf/)\n\n```bash\npip install xrf\n```\n\nFrom [conda-forge](https://anaconda.org/conda-forge/xrf)\n\n```bash\nconda install conda-forge::xrf\n```\n\n## Documentation\n\nFor the complete documentation, see [xrf.readthedocs.io](https://xrf.readthedocs.io/en/latest/).\n\n## Quickstart\n\n### Classification forests\n\nLet us start by importing the tic-tac-toe dataset from [openml.org](www.openml.org).\n\n```python\nfrom sklearn.datasets import fetch_openml\nfrom sklearn.preprocessing import OneHotEncoder\n\ndataset = fetch_openml(name=\"tic-tac-toe\", parser=\"auto\")\n\ny = dataset.target.values\n\nX = OneHotEncoder().fit_transform(dataset.data.values).toarray()\n```\n\nLet us split the dataset into a training and a test set.\n\n```python\nfrom sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.75)\n```\n\nLet us now fit an explainable random forest classifier; we can use the same parameters as for standard random forest classifiers as implemented in [scikit-learn](https://scikit-learn.org/).\n\n```python\nfrom xrf import XRandomForestClassifier\n\nrfx = XRandomForestClassifier(n_jobs=-1)\nrfx.fit(X_train, y_train)\n```\n\nWe get the predictions in the usual way, using either `predict` or `predict_proba`, here resulting in exactly the same output as the standard random forest classifiers in [scikit-learn](https://scikit-learn.org/). \n\n```python\nrfx.predict_proba(X_test)\n```\n\n```numpy\narray([[0.05, 0.95],\n       [0.56, 0.44],\n       [0.4 , 0.6 ],\n       ...,\n       [0.21, 0.79],\n       [0.17, 0.83],\n       [0.59, 0.41]])\n```\n\nWe may now limit the number of examples involved in a prediction, e.g., to at most 5.\n\n```python\nrfx.predict_proba(X_test, k=5)\n```\n\n```numpy\narray([[0.        , 1.        ],\n       [0.85416634, 0.14583366],\n       [0.34500622, 0.65499378],\n       ...,\n       [0.27464175, 0.72535825],\n       [0.12693503, 0.87306497],\n       [1.        , 0.        ]])\n```\n\nLet us also obtain the example attributions, by setting `return_examples` and `return_weights` to `True`.\n\n```python\npredictions, examples, weights = rfx.predict_proba(X_test, k=5, \n                                                   return_examples=True, \n                                                   return_weights=True)\n```\n\nLet us also take a look at the example attributions; `examples` will contain the indexes of the training objects involved in each prediction, while `weights` will contain the corresponding weights.\n\n```python\nexamples\n```\n\n```numpy\narray([[ 26, 131,  40, 193, 169],\n       [ 48, 121,  52, 164,   6],\n       [203, 176, 213, 110,  99],\n       ...,\n       [ 52, 167, 194, 175,  53],\n       [104,  71,  20,  35, 122],\n       [ 33,  47, 188, 228, 120]])\n```\n\n```python\nweights\n```\n\n```numpy\narray([[0.23050922, 0.21026052, 0.19812573, 0.18882078, 0.17228375],\n       [0.24554293, 0.20930998, 0.20651394, 0.19279949, 0.14583366],\n       [0.2935989 , 0.25979051, 0.21957101, 0.12543522, 0.10160437],\n       ...,\n       [0.27464175, 0.23320384, 0.19853987, 0.15467345, 0.13894108],\n       [0.32220957, 0.21056097, 0.20287181, 0.13742261, 0.12693503],\n       [0.26857466, 0.20863132, 0.20008477, 0.18560888, 0.13710037]])\n```\n\n### Regression forests\n\nLet us import the Miami housing dataset from [openml.org](www.openml.org).\n\n```python\nfrom sklearn.datasets import fetch_openml\nfrom sklearn.preprocessing import OneHotEncoder\n\ndataset = fetch_openml(name=\"miami_housing\", parser=\"auto\")\n\ny = dataset.target.values\nX = dataset.data.values\n```\n\nLet us split the dataset into a training and a test set.\n\n```python\nfrom sklearn.model_selection import train_test_split\n\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.75)\n```\n\nLet us generate and apply an explainable random forest regressor without constraining the number of training examples involved in the predictions.\n\n```python\nfrom xrf import XRandomForestRegressor\n\nrfx = XRandomForestRegressor(n_jobs=-1)\nrfx.fit(X_train, y_train)\nrfx.predict(X_test)\n```\n\n```numpy\narray([492859., 193170., 260507., ..., 330824., 416856., 241969.])\n```\n\nWe may now limit the number of examples involved in a prediction, e.g., to at most 5.\n\n```python\nrfx.predict(X_test, k=5)\n```\n\n```numpy\narray([541411.11111111, 196994.81865285, 210900.81300813, ...,\n       340516.66666667, 389410.25641026, 241550.27422303])\n```\n\nThe example attributions are obtained by setting `return_examples` and `return_weights` to `True`.\n\n```python\npredictions, examples, weights = rfx.predict(X_test, k=5,\n                                             return_examples=True,\n                                             return_weights=True)\n```\n\nWe may check that the predictions are the same as the weighted targets of the training examples.\n\n```python\nimport numpy as np\n\nweighted_predictions = np.sum([weights[i]*y_train[examples[i]] \n                               for i in range(len(weights))], axis=1)\n\nnp.allclose(predictions, weighted_predictions)\n```\n\n```python\nTrue\n```\n\n### More examples\n\nFor more examples, see this [Jupyter notebook](https://github.com/henrikbostrom/xrf/blob/main/docs/Examples.ipynb).\n\n## Citing xrf\n\nIf you use `xrf` for a scientific publication, you are kindly requested to cite the following paper:\n\nBoström, H., 2024. Example-Based Explanations of Random Forest Predictions. International Symposium on Intelligent Data Analysis, Springer, pp. 185-196 [Link](https://arxiv.org/pdf/2311.14581)\n\nBibtex entry:\n\n```bibtex\n@inproceedings{xrf,\n  title={Example-Based Explanations of Random Forest Predictions},\n  author={Bostr{\\\"o}m, Henrik},\n  booktitle={International Symposium on Intelligent Data Analysis},\n  pages={185--196},\n  year={2024},\n  organization={Springer}\n}\n```\n\n- - -\n\nAuthor: Henrik Boström (bostromh@kth.se)\nCopyright 2024 Henrik Boström\nLicense: BSD 3 clause\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrikbostrom%2Fxrf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhenrikbostrom%2Fxrf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhenrikbostrom%2Fxrf/lists"}