deep-river 0.3.0__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. deep_river-0.3.2/PKG-INFO +324 -0
  2. deep_river-0.3.2/README.md +257 -0
  3. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/__version__.py +1 -1
  4. deep_river-0.3.2/deep_river/anomaly/__init__.py +17 -0
  5. deep_river-0.3.2/deep_river/anomaly/ae.py +192 -0
  6. deep_river-0.3.2/deep_river/anomaly/probability_weighted_ae.py +97 -0
  7. deep_river-0.3.2/deep_river/anomaly/rolling_ae.py +243 -0
  8. deep_river-0.3.2/deep_river/base.py +763 -0
  9. deep_river-0.3.2/deep_river/classification/__init__.py +22 -0
  10. deep_river-0.3.2/deep_river/classification/classifier.py +341 -0
  11. deep_river-0.3.2/deep_river/classification/rolling_classifier.py +205 -0
  12. deep_river-0.3.2/deep_river/classification/zoo.py +545 -0
  13. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/regression/__init__.py +11 -6
  14. deep_river-0.3.2/deep_river/regression/multioutput.py +343 -0
  15. deep_river-0.3.2/deep_river/regression/regressor.py +156 -0
  16. deep_river-0.3.2/deep_river/regression/rolling_regressor.py +255 -0
  17. deep_river-0.3.2/deep_river/regression/zoo.py +489 -0
  18. deep_river-0.3.2/deep_river/utils/estimator_checks.py +320 -0
  19. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/inspect.py +1 -1
  20. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/tensor_conversion.py +83 -57
  21. deep_river-0.3.2/deep_river.egg-info/PKG-INFO +324 -0
  22. deep_river-0.3.2/deep_river.egg-info/SOURCES.txt +34 -0
  23. deep_river-0.3.2/deep_river.egg-info/dependency_links.txt +1 -0
  24. deep_river-0.3.2/deep_river.egg-info/requires.txt +46 -0
  25. deep_river-0.3.2/deep_river.egg-info/top_level.txt +1 -0
  26. deep_river-0.3.2/pyproject.toml +122 -0
  27. deep_river-0.3.2/setup.cfg +9 -0
  28. deep_river-0.3.0/PKG-INFO +0 -230
  29. deep_river-0.3.0/README.md +0 -197
  30. deep_river-0.3.0/deep_river/anomaly/__init__.py +0 -23
  31. deep_river-0.3.0/deep_river/anomaly/ae.py +0 -452
  32. deep_river-0.3.0/deep_river/anomaly/probability_weighted_ae.py +0 -276
  33. deep_river-0.3.0/deep_river/anomaly/rolling_ae.py +0 -352
  34. deep_river-0.3.0/deep_river/base.py +0 -700
  35. deep_river-0.3.0/deep_river/classification/__init__.py +0 -23
  36. deep_river-0.3.0/deep_river/classification/classifier.py +0 -598
  37. deep_river-0.3.0/deep_river/classification/rolling_classifier.py +0 -470
  38. deep_river-0.3.0/deep_river/classification/zoo.py +0 -277
  39. deep_river-0.3.0/deep_river/regression/multioutput.py +0 -306
  40. deep_river-0.3.0/deep_river/regression/regressor.py +0 -345
  41. deep_river-0.3.0/deep_river/regression/rolling_regressor.py +0 -436
  42. deep_river-0.3.0/deep_river/regression/zoo.py +0 -234
  43. deep_river-0.3.0/deep_river/utils/estimator_checks.py +0 -70
  44. deep_river-0.3.0/deep_river/utils/layer_adaptation.py +0 -239
  45. deep_river-0.3.0/deep_river/utils/test_layer_adaptation.py +0 -179
  46. deep_river-0.3.0/pyproject.toml +0 -83
  47. {deep_river-0.3.0 → deep_river-0.3.2}/LICENSE +0 -0
  48. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/__init__.py +0 -0
  49. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/anomaly/scaler.py +0 -0
  50. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/__init__.py +0 -0
  51. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/hooks.py +0 -0
  52. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/params.py +0 -0
  53. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/test_estimators.py +0 -0
  54. {deep_river-0.3.0 → deep_river-0.3.2}/deep_river/utils/test_tensor_conversion.py +0 -0
@@ -0,0 +1,324 @@
1
+ Metadata-Version: 2.4
2
+ Name: deep_river
3
+ Version: 0.3.2
4
+ Summary: Online Deep Learning for river
5
+ Author-email: Cedric Kulbach <cedric.kulbach@googlemail.com>, Lucas Cazzonelli <Cazzonelli@fzi.de>, Hoang-Anh Ngo <hoang-anh.ngo@alumni.polytechnique.org>, Max Halford <maxhalford25@gmail.com>, Saulo Martiello Mastelini <saulomastelini@gmail.com>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/online-ml/deep-river
8
+ Project-URL: Repository, https://github.com/online-ml/deep-river
9
+ Project-URL: Documentation, https://github.com/online-ml/deep-river
10
+ Keywords: online-learning,deep-learning,data-streams
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: Implementation :: CPython
17
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
18
+ Requires-Python: <3.13,>=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: scikit-learn~=1.5.0
22
+ Requires-Dist: torch==2.2.2
23
+ Requires-Dist: pandas~=2.2.2
24
+ Requires-Dist: numpy~=1.26.4
25
+ Requires-Dist: river
26
+ Requires-Dist: tqdm~=4.66.5
27
+ Requires-Dist: torchviz~=0.0.2
28
+ Requires-Dist: mkdocstrings[python]>=0.19.0
29
+ Requires-Dist: pytkdocs[numpy-style]>=0.5.0
30
+ Requires-Dist: sortedcontainers>=2.4.0
31
+ Provides-Extra: dev
32
+ Requires-Dist: graphviz>=0.20.3; extra == "dev"
33
+ Requires-Dist: matplotlib>=3.9.2; extra == "dev"
34
+ Requires-Dist: mypy>=1.11.1; extra == "dev"
35
+ Requires-Dist: codecov>=2.1.13; extra == "dev"
36
+ Requires-Dist: pre-commit>=3.8.0; extra == "dev"
37
+ Requires-Dist: pytest>=8.3.2; extra == "dev"
38
+ Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
39
+ Requires-Dist: black>=24.8.0; extra == "dev"
40
+ Requires-Dist: flake8>=7.1.1; extra == "dev"
41
+ Requires-Dist: isort>=5.13.2; extra == "dev"
42
+ Requires-Dist: jupyter>=1.0.0; extra == "dev"
43
+ Requires-Dist: pyupgrade==3.17.0; extra == "dev"
44
+ Requires-Dist: flask>=3.0.2; extra == "dev"
45
+ Requires-Dist: ipykernel>=6.9.0; extra == "dev"
46
+ Requires-Dist: mike>=0.5.3; extra == "dev"
47
+ Requires-Dist: mkdocs>=1.2.3; extra == "dev"
48
+ Requires-Dist: mkdocs-awesome-pages-plugin>=2.7.0; extra == "dev"
49
+ Requires-Dist: mkdocs-gen-files>=0.3.5; extra == "dev"
50
+ Requires-Dist: mkdocs-charts-plugin>=0.0.8; extra == "dev"
51
+ Requires-Dist: mkdocs-literate-nav>=0.4.1; extra == "dev"
52
+ Requires-Dist: mkdocs-material>=8.1.11; extra == "dev"
53
+ Requires-Dist: ipython_genutils>=0.1.0; extra == "dev"
54
+ Requires-Dist: mkdocs-jupyter>=0.20.0; extra == "dev"
55
+ Requires-Dist: nbconvert>=6.4.2; extra == "dev"
56
+ Requires-Dist: jupyter_contrib_nbextensions==0.7.0; extra == "dev"
57
+ Requires-Dist: numpydoc>=1.2; extra == "dev"
58
+ Requires-Dist: notebook==6.4.3; extra == "dev"
59
+ Requires-Dist: spacy>=3.2.2; extra == "dev"
60
+ Requires-Dist: jinja2>=3.0.3; extra == "dev"
61
+ Requires-Dist: dominate; extra == "dev"
62
+ Requires-Dist: jupyter-client; extra == "dev"
63
+ Requires-Dist: python-slugify; extra == "dev"
64
+ Requires-Dist: watermark==2.3.1; extra == "dev"
65
+ Requires-Dist: plotly>=5.0.0; extra == "dev"
66
+ Dynamic: license-file
67
+
68
+ <p align="center">
69
+ <img height="150px" src="https://raw.githubusercontent.com/online-ml/deep-river/master/docs/img/logo.png" alt="incremental dl logo">
70
+ </p>
71
+ <p align="center">
72
+ <img alt="PyPI" src="https://img.shields.io/pypi/v/deep-river">
73
+ <!-- Single Coverage Badge (Shields.io) -->
74
+ <a href="https://app.codecov.io/gh/online-ml/deep-river" >
75
+ <img alt="Coverage" src="https://img.shields.io/codecov/c/github/online-ml/deep-river?branch=master&logo=codecov&label=coverage" />
76
+ </a>
77
+ <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/deep-river">
78
+ <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/deep-river">
79
+ <img alt="GitHub" src="https://img.shields.io/github/license/online-ml/deep-river">
80
+ <a href="https://joss.theoj.org/papers/6a76784f55e8b041d71a7fa776eb386a"><img src="https://joss.theoj.org/papers/6a76784f55e8b041d71a7fa776eb386a/status.svg"></a>
81
+ <a href="https://doi.org/10.5281/zenodo.14601980"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.14601980.svg" alt="DOI"></a>
82
+ </p>
83
+ <p align="center">
84
+ deep-river is a Python library for online deep learning.
85
+ deep-river's ambition is to enable <a href="https://www.wikiwand.com/en/Online_machine_learning">online machine learning</a> for neural networks.
86
+ It combines the <a href="https://www.riverml.xyz">river</a> API with the capabilities of designing neural networks based on <a href="https://pytorch.org">PyTorch</a>.
87
+ </p>
88
+
89
+ ## 📚 [Documentation](https://online-ml.github.io/deep-river/)
90
+ The [documentation](https://online-ml.github.io/deep-river/) contains an overview of all features of this repository as well as the repository's full features list.
91
+ In each of these, the git repo reference is listed in a section that shows [examples](https://github.com/online-ml/deep-river/blob/master/docs/examples) of the features and functionality.
92
+ As we are always looking for further use cases and examples, feel free to contribute to the documentation or the repository itself via a pull request
93
+
94
+ ## 💈 Installation
95
+
96
+ ```shell
97
+ pip install deep-river
98
+ ```
99
+ or
100
+ ```shell
101
+ pip install "river[deep]"
102
+ ```
103
+ You can install the latest development version from GitHub as so:
104
+
105
+ ```shell
106
+ pip install https://github.com/online-ml/deep-river/archive/refs/heads/master.zip
107
+ ```
108
+
109
+ ### Development Environment
110
+
111
+ For contributing to deep-river, we recommend using [uv](https://docs.astral.sh/uv/) for fast dependency management and environment setup:
112
+
113
+ ```shell
114
+ # Install uv if you haven't already
115
+ curl -LsSf https://astral.sh/uv/install.sh | sh
116
+
117
+ # Clone the repository
118
+ git clone https://github.com/online-ml/deep-river.git
119
+ cd deep-river
120
+
121
+ # Install all dependencies (including dev dependencies)
122
+ uv sync --extra dev
123
+
124
+ # Run tests
125
+ make test
126
+
127
+ # Format code
128
+ make format
129
+
130
+ # Build documentation
131
+ make doc
132
+ ```
133
+
134
+ ## 🍫 Quickstart
135
+
136
+ We build the development of neural networks on top of the <a href="https://www.riverml.xyz">river API</a> and refer to the rivers design principles.
137
+ The following example creates a simple MLP architecture based on PyTorch and incrementally predicts and trains on the website phishing dataset.
138
+ For further examples check out the <a href="https://online-ml.github.io/deep-river">Documentation</a>.
139
+
140
+
141
+ ### Classification
142
+
143
+ ```python
144
+ >>> import random, numpy as np
145
+ >>> from river import metrics, datasets, preprocessing, compose
146
+ >>> from deep_river.classification import Classifier
147
+ >>> from torch import nn, manual_seed
148
+ >>> _ = manual_seed(42); random.seed(42); np.random.seed(42)
149
+ >>> first_x, _ = next(iter(datasets.Phishing()))
150
+ >>> n_features = len(first_x)
151
+ >>> class MyModule(nn.Module):
152
+ ... def __init__(self, n_features):
153
+ ... super().__init__()
154
+ ... self.net = nn.Sequential(
155
+ ... nn.Linear(n_features, 16),
156
+ ... nn.ReLU(),
157
+ ... nn.Linear(16, 2)
158
+ ... )
159
+ ... def forward(self, x):
160
+ ... return self.net(x)
161
+ >>> model = compose.Pipeline(
162
+ ... preprocessing.StandardScaler(),
163
+ ... Classifier(
164
+ ... module=MyModule(n_features),
165
+ ... loss_fn='cross_entropy',
166
+ ... optimizer_fn='adam',
167
+ ... lr=1e-3,
168
+ ... is_class_incremental=True
169
+ ... )
170
+ ... )
171
+ >>> metric = metrics.Accuracy()
172
+ >>> for i, (x, y) in enumerate(datasets.Phishing().take(200)):
173
+ ... if i > 0:
174
+ ... y_pred = model.predict_one(x)
175
+ ... metric.update(y, y_pred)
176
+ ... model.learn_one(x, y)
177
+ >>> assert 0.5 <= metric.get() <= 1.0
178
+ >>> print(f"Accuracy: {metric.get():.4f}") # doctest: +ELLIPSIS
179
+ Accuracy: ...
180
+
181
+ ```
182
+
183
+ ### Multi Target Regression
184
+
185
+ ```python
186
+ >>> import random, numpy as np
187
+ >>> from river import stream, metrics, preprocessing, compose
188
+ >>> from sklearn import datasets as sk_datasets
189
+ >>> from deep_river.regression import MultiTargetRegressor
190
+ >>> from torch import nn, manual_seed
191
+ >>> _ = manual_seed(42); random.seed(42); np.random.seed(42)
192
+ >>> linnerud_stream = stream.iter_sklearn_dataset(sk_datasets.load_linnerud(), shuffle=True, seed=42)
193
+ >>> first_x, first_y = next(iter(linnerud_stream))
194
+ >>> n_features, n_outputs = len(first_x), len(first_y)
195
+ >>> class TinyNet(nn.Module):
196
+ ... def __init__(self, n_features, n_outputs):
197
+ ... super().__init__()
198
+ ... self.net = nn.Sequential(
199
+ ... nn.Linear(n_features, 16),
200
+ ... nn.ReLU(),
201
+ ... nn.Linear(16, n_outputs)
202
+ ... )
203
+ ... def forward(self, x):
204
+ ... return self.net(x)
205
+ >>> model = compose.Pipeline(
206
+ ... preprocessing.StandardScaler(), # feature scaling stabilizes training
207
+ ... MultiTargetRegressor(
208
+ ... module=TinyNet(n_features, n_outputs),
209
+ ... loss_fn='mse', optimizer_fn='adam', lr=5e-3,
210
+ ... is_feature_incremental=False, is_target_incremental=False,
211
+ ... gradient_clip_value=1.0,
212
+ ... )
213
+ ... )
214
+ >>> mae_micro = metrics.multioutput.MicroAverage(metrics.MAE())
215
+ >>> mae_macro = metrics.multioutput.MacroAverage(metrics.MAE())
216
+ >>> rmse_micro = metrics.multioutput.MicroAverage(metrics.RMSE())
217
+ >>> # Recreate the iterator (the first sample was consumed to infer shapes)
218
+ >>> linnerud_stream = stream.iter_sklearn_dataset(sk_datasets.load_linnerud(), shuffle=True, seed=42)
219
+ >>> for i, (x, y_dict) in enumerate(linnerud_stream):
220
+ ... if i > 0:
221
+ ... y_pred = model.predict_one(x)
222
+ ... mae_micro.update(y_dict, y_pred)
223
+ ... mae_macro.update(y_dict, y_pred)
224
+ ... rmse_micro.update(y_dict, y_pred)
225
+ ... model.learn_one(x, y_dict)
226
+ >>> assert 0.0 <= mae_micro.get() < 300.0
227
+ >>> assert 0.0 <= mae_macro.get() < 300.0
228
+ >>> assert 0.0 <= rmse_micro.get() < 400.0
229
+ >>> print({
230
+ ... 'MAE_micro': round(mae_micro.get(), 4),
231
+ ... 'MAE_macro': round(mae_macro.get(), 4),
232
+ ... 'RMSE_micro': round(rmse_micro.get(), 4)
233
+ ... }) # doctest: +ELLIPSIS
234
+ {'MAE_micro': ..., 'MAE_macro': ..., 'RMSE_micro': ...}
235
+
236
+ ```
237
+
238
+ ### Anomaly Detection
239
+
240
+ ```python
241
+ >>> import random, numpy as np
242
+ >>> from torch import nn, manual_seed
243
+ >>> from river import metrics
244
+ >>> from deep_river.anomaly import Autoencoder
245
+ >>> _ = manual_seed(42); random.seed(42); np.random.seed(42)
246
+ >>> # Create a deterministic synthetic stream: normals (y=0) vs. anomalies (y=1)
247
+ >>> def synthetic_stream(n_norm=2000, n_anom=200, n_features=8, seed=42):
248
+ ... rng = np.random.default_rng(seed)
249
+ ... # Normals around 0, anomalies shifted
250
+ ... X_norm = rng.normal(loc=0.0, scale=1.0, size=(n_norm, n_features))
251
+ ... y_norm = np.zeros(n_norm, dtype=int)
252
+ ... X_anom = rng.normal(loc=5.0, scale=1.0, size=(n_anom, n_features))
253
+ ... y_anom = np.ones(n_anom, dtype=int)
254
+ ... # Interleave anomalies every k steps to keep streaming flavour
255
+ ... k = max(1, n_norm // n_anom)
256
+ ... X, Y = [], []
257
+ ... i_norm = i_anom = 0
258
+ ... for t in range(n_norm + n_anom):
259
+ ... take_anom = (t % k == 0) and (i_anom < n_anom)
260
+ ... if take_anom:
261
+ ... X.append(X_anom[i_anom]); Y.append(y_anom[i_anom]); i_anom += 1
262
+ ... else:
263
+ ... if i_norm < n_norm:
264
+ ... X.append(X_norm[i_norm]); Y.append(y_norm[i_norm]); i_norm += 1
265
+ ... elif i_anom < n_anom:
266
+ ... X.append(X_anom[i_anom]); Y.append(y_anom[i_anom]); i_anom += 1
267
+ ... for row, label in zip(X, Y):
268
+ ... yield {f"f{i}": float(v) for i, v in enumerate(row)}, int(label)
269
+ >>> n_features = 8
270
+ >>> class MyAutoEncoder(nn.Module):
271
+ ... def __init__(self, n_features, latent_dim=4):
272
+ ... super().__init__()
273
+ ... self.encoder = nn.Sequential(
274
+ ... nn.Linear(n_features, latent_dim),
275
+ ... nn.LeakyReLU()
276
+ ... )
277
+ ... self.decoder = nn.Sequential(
278
+ ... nn.Linear(latent_dim, n_features),
279
+ ... nn.Sigmoid()
280
+ ... )
281
+ ... def forward(self, x):
282
+ ... z = self.encoder(x)
283
+ ... return self.decoder(z)
284
+ >>> ae = Autoencoder(module=MyAutoEncoder(n_features), lr=5e-3, optimizer_fn='adam')
285
+ >>> metric = metrics.ROCAUC()
286
+ >>> # Train only on normal samples to keep the model focused on the normal manifold
287
+ >>> for x, y in synthetic_stream(n_norm=2000, n_anom=200, n_features=n_features, seed=42):
288
+ ... score = ae.score_one(x)
289
+ ... if y == 0:
290
+ ... ae.learn_one(x)
291
+ ... metric.update(y, score)
292
+ >>> print(f"ROCAUC: {metric.get():.4f}") # doctest: +ELLIPSIS
293
+ ROCAUC: ...
294
+
295
+ ```
296
+
297
+ ## 💬 Citation
298
+
299
+ To acknowledge the use of the `DeepRiver` library in your research, please refer to our [paper](https://joss.theoj.org/papers/10.21105/joss.07226) published on Journal of Open Source Software (JOSS):
300
+
301
+ ```bibtex
302
+ @article{Kulbach2025,
303
+ doi = {10.21105/joss.07226},
304
+ url = {https://doi.org/10.21105/joss.07226},
305
+ year = {2025},
306
+ publisher = {The Open Journal},
307
+ volume = {10},
308
+ number = {105},
309
+ pages = {7226},
310
+ author = {Cedric Kulbach and Lucas Cazzonelli and Hoang-Anh Ngo and Max Halford and Saulo Martiello Mastelini},
311
+ title = {DeepRiver: A Deep Learning Library for Data Streams},
312
+ journal = {Journal of Open Source Software}
313
+ }
314
+ ```
315
+
316
+ ## 🏫 Affiliations
317
+
318
+ <p align="center">
319
+ <img src="https://upload.wikimedia.org/wikipedia/de/thumb/4/44/Fzi_logo.svg/1200px-Fzi_logo.svg.png?raw=true" alt="FZI Logo" height="200"/>
320
+ </p>
321
+
322
+ <p align="center">
323
+ <img src="https://lieferbotnet.de/wp-content/uploads/2022/09/LieferBotNet-Logo.png?raw=true" alt="Lieferbot net" height="200"/>
324
+ </p>
@@ -0,0 +1,257 @@
1
+ <p align="center">
2
+ <img height="150px" src="https://raw.githubusercontent.com/online-ml/deep-river/master/docs/img/logo.png" alt="incremental dl logo">
3
+ </p>
4
+ <p align="center">
5
+ <img alt="PyPI" src="https://img.shields.io/pypi/v/deep-river">
6
+ <!-- Single Coverage Badge (Shields.io) -->
7
+ <a href="https://app.codecov.io/gh/online-ml/deep-river" >
8
+ <img alt="Coverage" src="https://img.shields.io/codecov/c/github/online-ml/deep-river?branch=master&logo=codecov&label=coverage" />
9
+ </a>
10
+ <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/deep-river">
11
+ <img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dm/deep-river">
12
+ <img alt="GitHub" src="https://img.shields.io/github/license/online-ml/deep-river">
13
+ <a href="https://joss.theoj.org/papers/6a76784f55e8b041d71a7fa776eb386a"><img src="https://joss.theoj.org/papers/6a76784f55e8b041d71a7fa776eb386a/status.svg"></a>
14
+ <a href="https://doi.org/10.5281/zenodo.14601980"><img src="https://zenodo.org/badge/DOI/10.5281/zenodo.14601980.svg" alt="DOI"></a>
15
+ </p>
16
+ <p align="center">
17
+ deep-river is a Python library for online deep learning.
18
+ deep-river's ambition is to enable <a href="https://www.wikiwand.com/en/Online_machine_learning">online machine learning</a> for neural networks.
19
+ It combines the <a href="https://www.riverml.xyz">river</a> API with the capabilities of designing neural networks based on <a href="https://pytorch.org">PyTorch</a>.
20
+ </p>
21
+
22
+ ## 📚 [Documentation](https://online-ml.github.io/deep-river/)
23
+ The [documentation](https://online-ml.github.io/deep-river/) contains an overview of all features of this repository as well as the repository's full features list.
24
+ In each of these, the git repo reference is listed in a section that shows [examples](https://github.com/online-ml/deep-river/blob/master/docs/examples) of the features and functionality.
25
+ As we are always looking for further use cases and examples, feel free to contribute to the documentation or the repository itself via a pull request
26
+
27
+ ## 💈 Installation
28
+
29
+ ```shell
30
+ pip install deep-river
31
+ ```
32
+ or
33
+ ```shell
34
+ pip install "river[deep]"
35
+ ```
36
+ You can install the latest development version from GitHub as so:
37
+
38
+ ```shell
39
+ pip install https://github.com/online-ml/deep-river/archive/refs/heads/master.zip
40
+ ```
41
+
42
+ ### Development Environment
43
+
44
+ For contributing to deep-river, we recommend using [uv](https://docs.astral.sh/uv/) for fast dependency management and environment setup:
45
+
46
+ ```shell
47
+ # Install uv if you haven't already
48
+ curl -LsSf https://astral.sh/uv/install.sh | sh
49
+
50
+ # Clone the repository
51
+ git clone https://github.com/online-ml/deep-river.git
52
+ cd deep-river
53
+
54
+ # Install all dependencies (including dev dependencies)
55
+ uv sync --extra dev
56
+
57
+ # Run tests
58
+ make test
59
+
60
+ # Format code
61
+ make format
62
+
63
+ # Build documentation
64
+ make doc
65
+ ```
66
+
67
+ ## 🍫 Quickstart
68
+
69
+ We build the development of neural networks on top of the <a href="https://www.riverml.xyz">river API</a> and refer to the rivers design principles.
70
+ The following example creates a simple MLP architecture based on PyTorch and incrementally predicts and trains on the website phishing dataset.
71
+ For further examples check out the <a href="https://online-ml.github.io/deep-river">Documentation</a>.
72
+
73
+
74
+ ### Classification
75
+
76
+ ```python
77
+ >>> import random, numpy as np
78
+ >>> from river import metrics, datasets, preprocessing, compose
79
+ >>> from deep_river.classification import Classifier
80
+ >>> from torch import nn, manual_seed
81
+ >>> _ = manual_seed(42); random.seed(42); np.random.seed(42)
82
+ >>> first_x, _ = next(iter(datasets.Phishing()))
83
+ >>> n_features = len(first_x)
84
+ >>> class MyModule(nn.Module):
85
+ ... def __init__(self, n_features):
86
+ ... super().__init__()
87
+ ... self.net = nn.Sequential(
88
+ ... nn.Linear(n_features, 16),
89
+ ... nn.ReLU(),
90
+ ... nn.Linear(16, 2)
91
+ ... )
92
+ ... def forward(self, x):
93
+ ... return self.net(x)
94
+ >>> model = compose.Pipeline(
95
+ ... preprocessing.StandardScaler(),
96
+ ... Classifier(
97
+ ... module=MyModule(n_features),
98
+ ... loss_fn='cross_entropy',
99
+ ... optimizer_fn='adam',
100
+ ... lr=1e-3,
101
+ ... is_class_incremental=True
102
+ ... )
103
+ ... )
104
+ >>> metric = metrics.Accuracy()
105
+ >>> for i, (x, y) in enumerate(datasets.Phishing().take(200)):
106
+ ... if i > 0:
107
+ ... y_pred = model.predict_one(x)
108
+ ... metric.update(y, y_pred)
109
+ ... model.learn_one(x, y)
110
+ >>> assert 0.5 <= metric.get() <= 1.0
111
+ >>> print(f"Accuracy: {metric.get():.4f}") # doctest: +ELLIPSIS
112
+ Accuracy: ...
113
+
114
+ ```
115
+
116
+ ### Multi Target Regression
117
+
118
+ ```python
119
+ >>> import random, numpy as np
120
+ >>> from river import stream, metrics, preprocessing, compose
121
+ >>> from sklearn import datasets as sk_datasets
122
+ >>> from deep_river.regression import MultiTargetRegressor
123
+ >>> from torch import nn, manual_seed
124
+ >>> _ = manual_seed(42); random.seed(42); np.random.seed(42)
125
+ >>> linnerud_stream = stream.iter_sklearn_dataset(sk_datasets.load_linnerud(), shuffle=True, seed=42)
126
+ >>> first_x, first_y = next(iter(linnerud_stream))
127
+ >>> n_features, n_outputs = len(first_x), len(first_y)
128
+ >>> class TinyNet(nn.Module):
129
+ ... def __init__(self, n_features, n_outputs):
130
+ ... super().__init__()
131
+ ... self.net = nn.Sequential(
132
+ ... nn.Linear(n_features, 16),
133
+ ... nn.ReLU(),
134
+ ... nn.Linear(16, n_outputs)
135
+ ... )
136
+ ... def forward(self, x):
137
+ ... return self.net(x)
138
+ >>> model = compose.Pipeline(
139
+ ... preprocessing.StandardScaler(), # feature scaling stabilizes training
140
+ ... MultiTargetRegressor(
141
+ ... module=TinyNet(n_features, n_outputs),
142
+ ... loss_fn='mse', optimizer_fn='adam', lr=5e-3,
143
+ ... is_feature_incremental=False, is_target_incremental=False,
144
+ ... gradient_clip_value=1.0,
145
+ ... )
146
+ ... )
147
+ >>> mae_micro = metrics.multioutput.MicroAverage(metrics.MAE())
148
+ >>> mae_macro = metrics.multioutput.MacroAverage(metrics.MAE())
149
+ >>> rmse_micro = metrics.multioutput.MicroAverage(metrics.RMSE())
150
+ >>> # Recreate the iterator (the first sample was consumed to infer shapes)
151
+ >>> linnerud_stream = stream.iter_sklearn_dataset(sk_datasets.load_linnerud(), shuffle=True, seed=42)
152
+ >>> for i, (x, y_dict) in enumerate(linnerud_stream):
153
+ ... if i > 0:
154
+ ... y_pred = model.predict_one(x)
155
+ ... mae_micro.update(y_dict, y_pred)
156
+ ... mae_macro.update(y_dict, y_pred)
157
+ ... rmse_micro.update(y_dict, y_pred)
158
+ ... model.learn_one(x, y_dict)
159
+ >>> assert 0.0 <= mae_micro.get() < 300.0
160
+ >>> assert 0.0 <= mae_macro.get() < 300.0
161
+ >>> assert 0.0 <= rmse_micro.get() < 400.0
162
+ >>> print({
163
+ ... 'MAE_micro': round(mae_micro.get(), 4),
164
+ ... 'MAE_macro': round(mae_macro.get(), 4),
165
+ ... 'RMSE_micro': round(rmse_micro.get(), 4)
166
+ ... }) # doctest: +ELLIPSIS
167
+ {'MAE_micro': ..., 'MAE_macro': ..., 'RMSE_micro': ...}
168
+
169
+ ```
170
+
171
+ ### Anomaly Detection
172
+
173
+ ```python
174
+ >>> import random, numpy as np
175
+ >>> from torch import nn, manual_seed
176
+ >>> from river import metrics
177
+ >>> from deep_river.anomaly import Autoencoder
178
+ >>> _ = manual_seed(42); random.seed(42); np.random.seed(42)
179
+ >>> # Create a deterministic synthetic stream: normals (y=0) vs. anomalies (y=1)
180
+ >>> def synthetic_stream(n_norm=2000, n_anom=200, n_features=8, seed=42):
181
+ ... rng = np.random.default_rng(seed)
182
+ ... # Normals around 0, anomalies shifted
183
+ ... X_norm = rng.normal(loc=0.0, scale=1.0, size=(n_norm, n_features))
184
+ ... y_norm = np.zeros(n_norm, dtype=int)
185
+ ... X_anom = rng.normal(loc=5.0, scale=1.0, size=(n_anom, n_features))
186
+ ... y_anom = np.ones(n_anom, dtype=int)
187
+ ... # Interleave anomalies every k steps to keep streaming flavour
188
+ ... k = max(1, n_norm // n_anom)
189
+ ... X, Y = [], []
190
+ ... i_norm = i_anom = 0
191
+ ... for t in range(n_norm + n_anom):
192
+ ... take_anom = (t % k == 0) and (i_anom < n_anom)
193
+ ... if take_anom:
194
+ ... X.append(X_anom[i_anom]); Y.append(y_anom[i_anom]); i_anom += 1
195
+ ... else:
196
+ ... if i_norm < n_norm:
197
+ ... X.append(X_norm[i_norm]); Y.append(y_norm[i_norm]); i_norm += 1
198
+ ... elif i_anom < n_anom:
199
+ ... X.append(X_anom[i_anom]); Y.append(y_anom[i_anom]); i_anom += 1
200
+ ... for row, label in zip(X, Y):
201
+ ... yield {f"f{i}": float(v) for i, v in enumerate(row)}, int(label)
202
+ >>> n_features = 8
203
+ >>> class MyAutoEncoder(nn.Module):
204
+ ... def __init__(self, n_features, latent_dim=4):
205
+ ... super().__init__()
206
+ ... self.encoder = nn.Sequential(
207
+ ... nn.Linear(n_features, latent_dim),
208
+ ... nn.LeakyReLU()
209
+ ... )
210
+ ... self.decoder = nn.Sequential(
211
+ ... nn.Linear(latent_dim, n_features),
212
+ ... nn.Sigmoid()
213
+ ... )
214
+ ... def forward(self, x):
215
+ ... z = self.encoder(x)
216
+ ... return self.decoder(z)
217
+ >>> ae = Autoencoder(module=MyAutoEncoder(n_features), lr=5e-3, optimizer_fn='adam')
218
+ >>> metric = metrics.ROCAUC()
219
+ >>> # Train only on normal samples to keep the model focused on the normal manifold
220
+ >>> for x, y in synthetic_stream(n_norm=2000, n_anom=200, n_features=n_features, seed=42):
221
+ ... score = ae.score_one(x)
222
+ ... if y == 0:
223
+ ... ae.learn_one(x)
224
+ ... metric.update(y, score)
225
+ >>> print(f"ROCAUC: {metric.get():.4f}") # doctest: +ELLIPSIS
226
+ ROCAUC: ...
227
+
228
+ ```
229
+
230
+ ## 💬 Citation
231
+
232
+ To acknowledge the use of the `DeepRiver` library in your research, please refer to our [paper](https://joss.theoj.org/papers/10.21105/joss.07226) published on Journal of Open Source Software (JOSS):
233
+
234
+ ```bibtex
235
+ @article{Kulbach2025,
236
+ doi = {10.21105/joss.07226},
237
+ url = {https://doi.org/10.21105/joss.07226},
238
+ year = {2025},
239
+ publisher = {The Open Journal},
240
+ volume = {10},
241
+ number = {105},
242
+ pages = {7226},
243
+ author = {Cedric Kulbach and Lucas Cazzonelli and Hoang-Anh Ngo and Max Halford and Saulo Martiello Mastelini},
244
+ title = {DeepRiver: A Deep Learning Library for Data Streams},
245
+ journal = {Journal of Open Source Software}
246
+ }
247
+ ```
248
+
249
+ ## 🏫 Affiliations
250
+
251
+ <p align="center">
252
+ <img src="https://upload.wikimedia.org/wikipedia/de/thumb/4/44/Fzi_logo.svg/1200px-Fzi_logo.svg.png?raw=true" alt="FZI Logo" height="200"/>
253
+ </p>
254
+
255
+ <p align="center">
256
+ <img src="https://lieferbotnet.de/wp-content/uploads/2022/09/LieferBotNet-Logo.png?raw=true" alt="Lieferbot net" height="200"/>
257
+ </p>
@@ -1,3 +1,3 @@
1
- VERSION = (0, 3, 0)
1
+ VERSION = (0, 3, 2)
2
2
 
3
3
  __version__ = ".".join(map(str, VERSION)) # noqa: F401
@@ -0,0 +1,17 @@
1
+ from .ae import Autoencoder
2
+ from .probability_weighted_ae import ProbabilityWeightedAutoencoder
3
+ from .rolling_ae import RollingAutoencoder
4
+ from .scaler import AnomalyMeanScaler, AnomalyMinMaxScaler, AnomalyStandardScaler
5
+
6
+ """
7
+ This module contains the anomaly detection algorithms for the
8
+ deep_river package.
9
+ """
10
+ __all__ = [
11
+ "AnomalyStandardScaler",
12
+ "AnomalyMeanScaler",
13
+ "AnomalyMinMaxScaler",
14
+ "Autoencoder",
15
+ "ProbabilityWeightedAutoencoder",
16
+ "RollingAutoencoder",
17
+ ]