{"id":18345990,"url":"https://github.com/infineon/streamgen","last_synced_at":"2025-06-24T00:31:49.234Z","repository":{"id":253772964,"uuid":"841294493","full_name":"Infineon/StreamGen","owner":"Infineon","description":" Python framework for generating streams of labeled data.","archived":false,"fork":false,"pushed_at":"2025-01-08T13:23:50.000Z","size":67490,"stargazers_count":12,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-05T04:47:47.894Z","etag":null,"topics":["continual-learning","data-generation","data-streams","data-structures","function-composition","python"],"latest_commit_sha":null,"homepage":"https://infineon.github.io/StreamGen/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Infineon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":"codemeta.json","zenodo":null}},"created_at":"2024-08-12T05:50:37.000Z","updated_at":"2025-04-19T16:01:07.000Z","dependencies_parsed_at":"2024-09-11T12:16:36.213Z","dependency_job_id":"971103d2-17ef-4e97-a189-48e60dea6f8b","html_url":"https://github.com/Infineon/StreamGen","commit_stats":null,"previous_names":["infineon/streamgen"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/Infineon/StreamGen","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2FStreamGen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2FStreamGen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2FStreamGen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2FStreamGen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Infineon","download_url":"https://codeload.github.com/Infineon/StreamGen/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2FStreamGen/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260081562,"owners_count":22956134,"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","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":["continual-learning","data-generation","data-streams","data-structures","function-composition","python"],"created_at":"2024-11-05T21:10:09.028Z","updated_at":"2025-06-24T00:31:49.210Z","avatar_url":"https://github.com/Infineon.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/artwork/crystal_cascades_by_th3dutchzombi3_dgmp8d5-pre.jpg?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n    🌌 StreamGen\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\na 🐍 Python framework for generating streams of labelled data\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://pypi.org/project/streamgen/\"\u003e\u003cimg alt=\"PyPI - Version\" src=\"https://img.shields.io/pypi/v/streamgen?label=%F0%9F%93%A6%20PyPi\"\u003e\n\u003c/a\u003e\n    \u003ca href=\"https://www.repostatus.org/#active\"\u003e\u003cimg src=\"https://www.repostatus.org/badges/latest/active.svg\" alt=\"Project Status: Active – The project has reached a stable, usable state and is being actively developed.\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/Infineon/StreamGen/actions/workflows/python-package-ubuntu.yaml\"\u003e\u003cimg alt=\"🐍 Python package\" src=\"https://github.com/Infineon/StreamGen/actions/workflows/python-package-ubuntu.yaml/badge.svg\"\u003e\u003c/a\u003e\n    \u003cimg alt=\"Static Badge\" src=\"https://img.shields.io/badge/Coverage-85%25-yellow?logo=codecov\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://www.python.org/\"\u003e\u003cimg alt=\"Python\" src=\"https://img.shields.io/badge/Python-3.11|3.12-yellow?logo=python\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://python-poetry.org/\"\u003e\u003cimg alt=\"Poetry\" src=\"https://img.shields.io/badge/Poetry-2.0.0-blue?logo=Poetry\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://joss.theoj.org/papers/4b6bac90bd1eb54700f8afb9f32caebe\"\u003e\u003cimg src=\"https://joss.theoj.org/papers/4b6bac90bd1eb54700f8afb9f32caebe/status.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://zenodo.org/records/14273611\"\u003e\u003cimg src=\"https://zenodo.org/badge/DOI/10.5281/zenodo.14273611.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/astral-sh/ruff\"\u003e\u003cimg alt=\"Ruff\" src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\"\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/beartype/beartype\"\u003e\u003cimg alt=\"Beartype\" src=\"https://raw.githubusercontent.com/beartype/beartype-assets/main/badge/bear-ified.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/Infineon/StreamGen?tab=readme-ov-file#%EF%B8%8F-motivation\"\u003e⚗️ Motivation\u003c/a\u003e •\n  \u003ca href=\"https://github.com/Infineon/StreamGen?tab=readme-ov-file#-idea\"\u003e💡 Idea\u003c/a\u003e •\n  \u003ca href=\"https://github.com/Infineon/StreamGen?tab=readme-ov-file#-installation\"\u003e📦 Installation\u003c/a\u003e •\n  \u003ca href=\"https://github.com/Infineon/StreamGen?tab=readme-ov-file#-examples\"\u003e👀 Examples\u003c/a\u003e •\n  \u003ca href=\"https://github.com/Infineon/StreamGen?tab=readme-ov-file#-documentation\"\u003e📖 Documentation\u003c/a\u003e •\n  \u003ca href=\"https://github.com/Infineon/StreamGen?tab=readme-ov-file#-acknowledgement\"\u003e🙏 Acknowledgement\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## ⚗️ Motivation\n\nMost machine learning systems rely on *stationary, labeled, balanced and large-scale* datasets.\n**Incremental learning** (IL), also referred to as **lifelong learning** (LL) or **continual learning** (CL), extends the traditional paradigm to work in dynamic and evolving environments.\nThis requires such systems to acquire and preserve knowledge continually.\n\nExisting CL frameworks like [avalanche](https://github.com/ContinualAI/avalanche)[^1] or [continuum](https://github.com/Continvvm/continuum)[^2] construct data streams by *splitting* large datasets into multiple *experiences*, which has a few disadvantages:\n\n- results in unrealistic scenarios\n- offers limited insight into distributions and their evolution\n- not extendable to scenarios with fewer constraints on the stream properties\n\nTo answer different research questions in the field of CL, researchers need knowledge and control over:\n\n- class distributions\n- novelties and outliers\n- complexity and evolution of the background domain\n- semantics of the unlabeled parts of a domain\n- class dependencies\n- class composition (for multi-label modelling)\n\nA more economical alternative to collecting and labelling streams with desired properties is the **generation** of synthetic streams[^6].\nSome mentionable efforts in that direction include augmentation based dataset generation like [ImageNet-C](https://github.com/hendrycks/robustness)[^3] or simulation-based approaches like the [EndlessCLSim](https://arxiv.org/abs/2106.02585)[^4], where semantically labeled street-view images are generated (and labeled) by a game engine, that procedurally generates the city environment and simulates drift by modifying parameters (like the weather and illumination conditions) over time.\n\n\u003cdetails\u003e\n\u003csummary\u003eImageNet-C [3]\u003c/summary\u003e\n\u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/imagenet-c.png?raw=true\"\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eEndlessCLSim [4]\u003c/summary\u003e\n\u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/endless_cl_sim.png?raw=true\"\u003e\n\u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/endless_cl_sim_model.png?raw=true\"\u003e\n\u003c/details\u003e\n\nThis project builds on these ideas and presents a general framework for generating streams of labeled samples.\n\n## 💡 Idea\n\nThis section introduces the main ideas and building blocks of the `streamgen` framework.\n\n### 🎲 Building complex Distributions through random Transformations\n\nThere exists only a limited number of distributions one can directly sample from (e.g.: a gaussian distribution).\n\nInstead of generating samples directly from a distribution, researchers often work with collected sets of samples.\nA common practice to increase the variability of such datasets is the use of **stochastic transformations** in a sequential augmentation pipeline:\n\n```python\nfrom torchvision.transforms import v2\n\ntransforms = v2.Compose([\n    v2.RandomResizedCrop(size=(224, 224), antialias=True),\n    v2.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n    # ...\n])\n\nwhile generating_data:\n    # option 1 - sample from a dataset\n    sample = np.random.choice(dataset)\n    # option 2 - sample from a distribution\n    sample = np.random.randn(...)\n\n    augmented_sample = transforms(sample)\n```\n\nCombined with an initial sampler, that either samples from a data set or directly from a distribution, these chained transformations can represent complex distributions.\n\n\u003cdetails\u003e\n    \u003csummary\u003eFunction Composition Details \u003c/summary\u003e\n\nTwo (or more) functions f: X → X, g: X → X having the same domain and codomain are often called **transformations**. One can form chains of transformations composed together, such as f ∘ f ∘ g ∘ f (which is the same as f(f(g(f(x)))) given some input x). Such chains have the algebraic structure of a **monoid**, called a transformation monoid or (much more seldom) a composition monoid. [^7]\n\nA lot of programming languages offer native support for such transformation monoids.\n\nJulia uses `|\u003e` or `∘` for function chaining:\n```julia\ndistribution = sample |\u003e filter |\u003e augment\ndistribution = augment ∘ filter ∘ sample\n```\n\nR uses the chain operator `%\u003e%`:\n```R\ndistribution \u003c- sample %\u003e%\n    filter() %\u003e%\n    augment()\n```\n\nIn python, you can use `functools.reduce` to create simple monoids:\n```python\nfrom functools import reduce\nfrom typing import Callable\n\ndef compose(*funcs) -\u003e Callable[[int], int]:\n    \"\"\"Compose a group of functions (f(g(h(...)))) into a single composite func.\"\"\"\n    return reduce(lambda f, g: lambda x: f(g(x)), funcs)\n\ndistribution = compose(sample, filter, augment)\n```\n\n\u003e 🤚 StreamGen is not trying to implement general (and optimized) function composition in Python. It rather offers a very opinionated implementation, that is optimal for the data generation use-case.\n\n\u003c/details\u003e\n\n### 🌳 Sampling Trees\n\nOne shortcoming of this approach is that one can only generate samples from a single distribution -\u003e different class distributions are not representable.\n\nOne solution to this problem is the use of a [tree](https://en.wikipedia.org/wiki/Tree_(data_structure)) (or other directed acyclic graph (DAG)) data structure to store the transformations.\n\n- samples are transformed during the traversal of the tree from the root to the leaves.\n- each path through the tree represents its own class-conditional distribution.\n- each branching point represents a categorical distribution which determines the path to take for a sample during the tree traversal.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/sampling_tree.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n### ⚙️ Parameter Schedules\n\nIf we want to model evolving distributions (streams), we either need to change the **parameters** of the stochastic transformations or the **topology** of the tree over time.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/parameter_schedule.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nCurrently, `streamgen` does not support scheduling topological changes (like adding branches and nodes), but by **unrolling** these changes over time into one static tree, topological changes can be modelled purely with branch probabilities.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/data_drifts_by_topology_changes.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/unrolled_static_tree.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003e 💡 the directed acyclic graph above is not a tree anymore due to the *merging* of certain branches. Because these merges are very convenient in certain scenarios, `streamgen` support the definition of such trees by copying the paths below the merge to every branch before the merge. For an example of this, have a look at `examples/time series classification/04-multi-label-generation.ipynb`.\n\n### 📈 Data Drift Scenarios\n\nThe proposed tree structure can model all three common data drift scenarios by scheduling the parameters of the transformations at specific nodes.\n\n#### 📉 Covariate shift\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/covariate_shift.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n#### 📊 Prior probability shift\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/prior_probability_shift.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n#### 🏷️ Concept shift\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/images/concept_shift.png?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## 📦 Installation\n\nThe graph visualizations require [Graphviz](https://www.graphviz.org/download/) to be installed on your system. Depending on your operating system and package manager, you might try one of the following options:\n\n- ubuntu: `sudo apt-get install graphviz`\n- windows: `choco install graphviz`\n- macOs: `brew install graphviz`\n\nThe basic version of the package can be installed from [PyPi](https://pypi.org/project/streamgen/) with:\n```sh\npip install streamgen\n```\n\n`streamgen` provides a few (pip) extras:\n\n| extras group | needed for                                                                 | additional dependencies      |\n| ------------ | -------------------------------------------------------------------------- | ---------------------------- |\n| **examples** | running the example notebooks with their application specific dependencies | `perlin-numpy`, `polars`     |\n| **cl**       | continual learning frameworks                                              | `continuum`                  |\n| **all**      | shortcut for installing every extra                                        | *                            |\n\nTo install the package with specific extras execute:\n\n```sh\npip install streamgen[\u003cname_of_extra\u003e]\n```\n\n\u003e 🧑‍💻 to install a development environment (which you need if you want to work on the package, instead of just using the package), `cd` into the project's root directory and call:\n```bash\npoetry install --sync --compile --all-extras\n```\n\n## 👀 Examples\n\nThere are example notebooks 🪐📓 showcasing and explaining `streamgen` features:\n\n+ 📈 time series\n    + [🎲 sampling from static distributions](https://github.com/Infineon/StreamGen/blob/main/examples/time%20series%20classification/01-static-distributions.ipynb)\n    + [🌌 creating data streams](https://github.com/Infineon/StreamGen/blob/main/examples/time%20series%20classification/02-data-streams.ipynb)\n    + [📊 data drift scenarios](https://github.com/Infineon/StreamGen/blob/main/examples/time%20series%20classification/03-drift-scenarios.ipynb)\n    + [🏷️ multi-label generation](https://github.com/Infineon/StreamGen/blob/main/examples/time%20series%20classification/04-multi-label-generation.ipynb)\n+ 🖼️ analog wafer map streams based on the [wm811k dataset](https://www.kaggle.com/datasets/qingyi/wm811k-wafer-map)[^5] in [🌐 wafer map generation](https://github.com/Infineon/StreamGen/blob/main/examples/wafer_map_generation.ipynb)\n\nHere is a preview of what we will create in the time series examples:\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://github.com/Infineon/StreamGen/blob/main/docs/videos/time_series_tree_svg.gif?raw=true\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## 📖 Documentation\n\nThe [documentation](https://infineon.github.io/StreamGen/) is hosted through github pages.\n\nTo locally build and view it, call `poe docs_local`.\n\n## 🙏 Acknowledgement\n\nMade with ❤️ and ☕ by Laurenz Farthofer.\n\nThis work was funded by the Austrian Research Promotion Agency (FFG, Project No. 905107).\n\nSpecial thanks to Benjamin Steinwender, Marius Birkenbach and Nikolaus Neugebauer for their valuable feedback.\n\nI want to thank Infineon and KAI for letting me work on and publish this project.\n\nFinally, I want to thank my university supervisors Thomas Pock and Marc Masana for their guidance.\n\n---\n\n## 🖼️ ©️ Banner Artwork Attribution\n\n\u003ca rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-nd/3.0/\"\u003e\u003cimg alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-nd/3.0/88x31.png\" /\u003e\u003c/a\u003e\u003cbr /\u003eThe art in the banner of this README is licensed under a [Creative Commons Attribution-NonCommercial-No Derivatives Works 3.0 License](https://creativecommons.org/licenses/by-nc-nd/3.0/). It was made by [th3dutchzombi3](https://www.deviantart.com/th3dutchzombi3). Check out his beautiful artwork ❤️\n\n---\n\n## 📄 References\n\n[^1]: V. Lomonaco et al., “Avalanche: an End-to-End Library for Continual Learning,” in 2021 IEEE/CVF Conference on Computer Vision and Pattern Recognition Workshops (CVPRW), Nashville, TN, USA: IEEE, Jun. 2021, pp. 3595–3605. doi: 10.1109/CVPRW53098.2021.00399.\n[^2]: A. Douillard and T. Lesort, “Continuum: Simple Management of Complex Continual Learning Scenarios.” arXiv, Feb. 11, 2021. doi: 10.48550/arXiv.2102.06253.\n[^3]: D. Hendrycks and T. Dietterich, “Benchmarking Neural Network Robustness to Common Corruptions and Perturbations.” arXiv, Mar. 28, 2019. doi: 10.48550/arXiv.1903.12261.\n[^4]: T. Hess, M. Mundt, I. Pliushch, and V. Ramesh, “A Procedural World Generation Framework for Systematic Evaluation of Continual Learning.” arXiv, Dec. 13, 2021. doi: 10.48550/arXiv.2106.02585.\n[^5]: Wu, Ming-Ju, Jyh-Shing R. Jang, and Jui-Long Chen. “Wafer Map Failure Pattern Recognition and Similarity Ranking for Large-Scale Data Sets.” IEEE Transactions on Semiconductor Manufacturing 28, no. 1 (February 2015): 1–12.\n[^6]: J. Lu, A. Liu, F. Dong, F. Gu, J. Gama, and G. Zhang, “Learning under Concept Drift: A Review” IEEE Trans. Knowl. Data Eng., pp. 1–1, 2018, doi: 10.1109/TKDE.2018.2876857.\n[^7]: “Function composition,” Wikipedia. Feb. 16, 2024. Accessed: Apr. 17, 2024. [Online]. Available: https://en.wikipedia.org/w/index.php?title=Function_composition\u0026oldid=1207989326\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfineon%2Fstreamgen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finfineon%2Fstreamgen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfineon%2Fstreamgen/lists"}