Skip to content

Commit

Permalink
Merge pull request #78 from online-ml/rename_deep_river
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxHalford authored Dec 23, 2022
2 parents 61f73f0 + ad452fa commit ea7f777
Show file tree
Hide file tree
Showing 50 changed files with 1,242 additions and 752 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@ jobs:
run: python -c "from river import datasets; datasets.CreditCard().download(); datasets.Elec2().download(); datasets.Keystroke().download()"

- name: pytest
run: pytest --cov=river_torch -m "not datasets"
run: pytest --cov=deep_river -m "not datasets"
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v2
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
files: river_torch
files: deep_river
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
Expand Down
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,46 @@
<p align="center">
<img height="150px" src="https://raw.githubusercontent.com/online-ml/river-torch/master/docs/img/logo.png" alt="incremental dl logo">
<img height="150px" src="https://raw.githubusercontent.com/online-ml/deep-river/master/docs/img/logo.png" alt="incremental dl logo">
</p>
<p align="center">
<img alt="PyPI" src="https://img.shields.io/pypi/v/river-torch">
<a href="https://codecov.io/gh/online-ml/river-torch" >
<img src="https://codecov.io/gh/online-ml/river-torch/branch/master/graph/badge.svg?token=ZKUIISZAYA"/>
<img alt="PyPI" src="https://img.shields.io/pypi/v/deep-river">
<a href="https://codecov.io/gh/online-ml/deep-river" >
<img src="https://codecov.io/gh/online-ml/deep-river/branch/master/graph/badge.svg?token=ZKUIISZAYA"/>
</a>
<img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dw/river-torch">
<img alt="GitHub" src="https://img.shields.io/github/license/online-ml/river-torch">
<img alt="PyPI - Downloads" src="https://img.shields.io/pypi/dw/deep-river">
<img alt="GitHub" src="https://img.shields.io/github/license/online-ml/deep-river">
</p>
<p align="center">
river-torch is a Python library for online deep learning.
River-torch's ambition is to enable <a href="https://www.wikiwand.com/en/Online_machine_learning">online machine learning</a> for neural networks.
deep-river is a Python library for online deep learning.
deep-river's ambition is to enable <a href="https://www.wikiwand.com/en/Online_machine_learning">online machine learning</a> for neural networks.
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>.
</p>

## 💈 Installation

```shell
pip install river-torch
pip install deep-river
```
or
```shell
pip install "river[torch]"
pip install "river[deep]"
```
You can install the latest development version from GitHub as so:

```shell
pip install https://github.com/online-ml/river-torch/archive/refs/heads/master.zip
pip install https://github.com/online-ml/deep-river/archive/refs/heads/master.zip
```

## 🍫 Quickstart

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.
The following example creates a simple MLP architecture based on PyTorch and incrementally predicts and trains on the website phishing dataset.
For further examples check out the <a href="https://online-ml.github.io/river-torch">Documentation</a>.
For further examples check out the <a href="https://online-ml.github.io/deep-river">Documentation</a>.

### Classification

```python
>>> from river import metrics, datasets, preprocessing, compose
>>> from river_torch import classification
>>> from deep_river import classification
>>> from torch import nn
>>> from torch import optim
>>> from torch import manual_seed
Expand Down Expand Up @@ -72,7 +72,7 @@ For further examples check out the <a href="https://online-ml.github.io/river-to
>>> for x, y in dataset:
... y_pred = model_pipeline.predict_one(x) # make a prediction
... metric = metric.update(y, y_pred) # update the metric
... model_pipeline = model_pipeline.learn_one(x,y) # make the model learn
... model_pipeline = model_pipeline.learn_one(x, y) # make the model learn
>>> print(f"Accuracy: {metric.get():.4f}")
Accuracy: 0.6728

Expand All @@ -81,7 +81,7 @@ Accuracy: 0.6728
### Anomaly Detection

```python
>>> from river_torch.anomaly import Autoencoder
>>> from deep_river.anomaly import Autoencoder
>>> from river import metrics
>>> from river.datasets import CreditCard
>>> from torch import nn
Expand Down Expand Up @@ -111,9 +111,9 @@ Accuracy: 0.6728
>>> model = Pipeline(scaler, ae)

>>> for x, y in dataset:
... score = model.score_one(x)
... model = model.learn_one(x=x)
... metric = metric.update(y, score)
... score = model.score_one(x)
... model = model.learn_one(x=x)
... metric = metric.update(y, score)
...
>>> print(f"ROCAUC: {metric.get():.4f}")
ROCAUC: 0.7447
Expand Down
128 changes: 0 additions & 128 deletions check.ipynb

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
8 changes: 4 additions & 4 deletions river_torch/anomaly/ae.py → deep_river/anomaly/ae.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from river.anomaly.base import AnomalyDetector
from torch import nn

from river_torch.base import DeepEstimator
from river_torch.utils import dict2tensor
from river_torch.utils.tensor_conversion import df2tensor
from deep_river.base import DeepEstimator
from deep_river.utils import dict2tensor
from deep_river.utils.tensor_conversion import df2tensor


class _TestAutoencoder(torch.nn.Module):
Expand Down Expand Up @@ -58,7 +58,7 @@ class Autoencoder(DeepEstimator, AnomalyDetector):
Examples
--------
>>> from river_torch.anomaly import Autoencoder
>>> from deep_river.anomaly import Autoencoder
>>> from river import metrics
>>> from river.datasets import CreditCard
>>> from torch import nn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from river import stats, utils
from scipy.special import ndtr

from river_torch.anomaly import ae
from river_torch.utils import dict2tensor
from deep_river.anomaly import ae
from deep_river.utils import dict2tensor


class ProbabilityWeightedAutoencoder(ae.Autoencoder):
Expand Down Expand Up @@ -51,7 +51,7 @@ class ProbabilityWeightedAutoencoder(ae.Autoencoder):
Examples
--------
>>> from river_torch.anomaly import ProbabilityWeightedAutoencoder
>>> from deep_river.anomaly import ProbabilityWeightedAutoencoder
>>> from river import metrics
>>> from river.datasets import CreditCard
>>> from torch import nn, manual_seed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from river import anomaly
from torch import nn

from river_torch.base import RollingDeepEstimator
from river_torch.utils.tensor_conversion import deque2rolling_tensor
from deep_river.base import RollingDeepEstimator
from deep_river.utils.tensor_conversion import deque2rolling_tensor


class _TestLSTMAutoencoder(nn.Module):
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion river_torch/base.py → deep_river/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import torch
from river import base

from river_torch.utils import get_loss_fn, get_optim_fn
from deep_river.utils import get_loss_fn, get_optim_fn

try:
from graphviz import Digraph
Expand Down
7 changes: 7 additions & 0 deletions deep_river/classification/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from deep_river.classification.classifier import Classifier
from deep_river.classification.rolling_classifier import RollingClassifier

__all__ = [
"Classifier",
"RollingClassifier",
]
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
from torch import nn
from torch.utils.hooks import RemovableHandle

from river_torch.base import DeepEstimator
from river_torch.utils.hooks import ForwardOrderTracker, apply_hooks
from river_torch.utils.tensor_conversion import (
from deep_river.base import DeepEstimator
from deep_river.utils.hooks import ForwardOrderTracker, apply_hooks
from deep_river.utils.tensor_conversion import (
df2tensor,
dict2tensor,
labels2onehot,
Expand All @@ -35,7 +35,7 @@ def forward(self, X, **kwargs):
return X


class Classifier(DeepEstimator, base.Classifier):
class Classifier(DeepEstimator, base.MiniBatchClassifier):
"""
Wrapper for PyTorch classification models that automatically handles
increases in the number of classes by adding output neurons in case
Expand Down Expand Up @@ -83,7 +83,7 @@ class Classifier(DeepEstimator, base.Classifier):
Examples
--------
>>> from river import metrics, preprocessing, compose, datasets
>>> from river_torch import classification
>>> from deep_river import classification
>>> from torch import nn
>>> from torch import manual_seed
Expand Down Expand Up @@ -258,7 +258,7 @@ def predict_proba_one(self, x: dict) -> Dict[ClfTarget, float]:
y_pred = self.module(x_t)
return output2proba(
y_pred, self.observed_classes, self.output_is_logit
)
)[0]

def learn_many(self, X: pd.DataFrame, y: pd.Series) -> "Classifier":
"""
Expand Down Expand Up @@ -286,7 +286,7 @@ def learn_many(self, X: pd.DataFrame, y: pd.Series) -> "Classifier":
if self.is_class_incremental:
self._adapt_output_dim()

return self._learn(x=X, y=y.tolist())
return self._learn(x=X, y=y)

def predict_proba_many(self, X: pd.DataFrame) -> pd.DataFrame:
"""
Expand All @@ -309,7 +309,7 @@ def predict_proba_many(self, X: pd.DataFrame) -> pd.DataFrame:
self.module.eval()
with torch.inference_mode():
y_preds = self.module(X_t)
return pd.Dataframe(output2proba(y_preds, self.observed_classes))
return pd.DataFrame(output2proba(y_preds, self.observed_classes))

def _adapt_output_dim(self):
out_features_target = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
from river.base.typing import ClfTarget
from torch import nn

from river_torch.base import RollingDeepEstimator
from river_torch.classification import Classifier
from river_torch.utils.tensor_conversion import (
from deep_river.base import RollingDeepEstimator
from deep_river.classification import Classifier
from deep_river.utils.tensor_conversion import (
deque2rolling_tensor,
output2proba,
)
Expand Down Expand Up @@ -80,7 +80,7 @@ class RollingClassifier(Classifier, RollingDeepEstimator):
Examples
--------
>>> from river_torch.classification import RollingClassifier
>>> from deep_river.classification import RollingClassifier
>>> from river import metrics, datasets, compose, preprocessing
>>> import torch
Expand Down Expand Up @@ -266,7 +266,7 @@ def predict_proba_one(self, x: dict) -> Dict[ClfTarget, float]:
if self.append_predict:
self._x_window.append(list(x.values()))

return proba
return proba[0]

def learn_many(self, X: pd.DataFrame, y: pd.Series) -> "RollingClassifier":
"""
Expand Down Expand Up @@ -333,7 +333,7 @@ def predict_proba_many(self, X: pd.DataFrame) -> pd.DataFrame:
probas = [default_proba] * len(X)
return pd.DataFrame(probas)

def _get_default_proba(self):
def _get_default_proba(self) -> List[Dict[ClfTarget, float]]:
if len(self.observed_classes) > 0:
mean_proba = (
1 / len(self.observed_classes)
Expand All @@ -343,7 +343,7 @@ def _get_default_proba(self):
proba = {c: mean_proba for c in self.observed_classes}
else:
proba = {c: 1.0 for c in self.observed_classes}
return proba
return [proba] if isinstance(proba, dict) else proba

def _adapt_output_dim(self):
out_features_target = (
Expand Down
7 changes: 7 additions & 0 deletions deep_river/regression/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from deep_river.regression.regressor import Regressor
from deep_river.regression.rolling_regressor import RollingRegressor

__all__ = [
"Regressor",
"RollingRegressor",
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
from river import base
from river.base.typing import RegTarget

from river_torch.base import DeepEstimator
from river_torch.utils.tensor_conversion import (
from deep_river.base import DeepEstimator
from deep_river.utils.tensor_conversion import (
df2tensor,
dict2tensor,
float2tensor,
Expand All @@ -32,7 +32,7 @@ def forward(self, X, **kwargs):
return X


class Regressor(DeepEstimator, base.Regressor):
class Regressor(DeepEstimator, base.MiniBatchRegressor):
"""
Wrapper for PyTorch regression models that enables
compatibility with River.
Expand Down Expand Up @@ -181,7 +181,7 @@ def predict_one(self, x: dict) -> RegTarget:
y_pred = self.module(x_t).item()
return y_pred

def learn_many(self, X: pd.DataFrame, y: List) -> "Regressor":
def learn_many(self, X: pd.DataFrame, y: pd.Series) -> "Regressor":
"""
Performs one step of training with a batch of examples.
Expand All @@ -201,7 +201,9 @@ def learn_many(self, X: pd.DataFrame, y: List) -> "Regressor":
self.kwargs["n_features"] = len(X.columns)
self.initialize_module(**self.kwargs)
X_t = df2tensor(X, device=self.device)
y_t = torch.tensor(y, device=self.device, dtype=torch.float32)
y_t = torch.tensor(
y, device=self.device, dtype=torch.float32
).unsqueeze(1)
self._learn(X_t, y_t)
return self

Expand All @@ -224,7 +226,6 @@ def predict_many(self, X: pd.DataFrame) -> List:
self.initialize_module(**self.kwargs)

X = df2tensor(X, device=self.device)
self.module.eval()
with torch.inference_mode():
y_preds = self.module(X).detach().tolist()
y_preds = self.module(X).detach().squeeze().tolist()
return y_preds
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
import torch
from river.base.typing import RegTarget

from river_torch.base import RollingDeepEstimator
from river_torch.regression import Regressor
from river_torch.utils.tensor_conversion import (
from deep_river.base import RollingDeepEstimator
from deep_river.regression import Regressor
from deep_river.utils.tensor_conversion import (
deque2rolling_tensor,
float2tensor,
)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Deque, Dict, Optional, Union
from typing import Deque, Dict, List, Optional, Union

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -146,7 +146,7 @@ def labels2onehot(

def output2proba(
preds: torch.Tensor, classes: OrderedSet, with_logits=False
) -> Dict[ClfTarget, float]:
) -> List[Dict[ClfTarget, float]]:
if with_logits:
if preds.shape[-1] >= 1:
preds = torch.softmax(preds, dim=-1)
Expand All @@ -168,4 +168,4 @@ def output2proba(
if preds_np.shape[0] == 1
else [dict(zip(classes, pred)) for pred in preds_np]
)
return dict(probas)
return [probas] if isinstance(probas, dict) else list(probas)
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
import pytest
import river

from river_torch import utils
from deep_river import utils


def iter_estimators():
for submodule in importlib.import_module("river_torch").__all__:
for submodule in importlib.import_module("deep_river").__all__:

def is_estimator(obj):
return inspect.isclass(obj) and issubclass(
obj, river.base.Estimator
)

for _, obj in inspect.getmembers(
importlib.import_module(f"river_torch.{submodule}"), is_estimator
importlib.import_module(f"deep_river.{submodule}"), is_estimator
):
yield obj

Expand Down
Loading

0 comments on commit ea7f777

Please sign in to comment.