river bridge: how do I use a Dense-Armor classifier in a river loop, and a river model after a Dense-Armor scaler?¶
river and Dense-Armor both learn one sample at a time, and both name the same methods: learn_one, predict_one, predict_proba_one. Because the interfaces match, the bridge does not convert anything: to_river(est) and from_river(est) return the object they receive. The two functions exist to say, in the code, which side the object is used from, and to raise a clear error when river is not installed.
The two steps below use a synthetic stream of 60 samples: 30 of class 0 with a near 0 to 3, and 30 of class 1 with a near 5 to 8.
1. A Dense-Armor classifier inside a river loop¶
to_river hands a Dense-Armor classifier to river code. The loop is the prequential one of river: predict first, then learn.
from river import metrics
from dense_armor.bridges.river import to_river
from dense_armor.utility.online.learn.online_classifiers import OnlineGaussianNB
s = [({"a": 0.1 * i, "b": 1.0}, 0) for i in range(30)]
s += [({"a": 5 + 0.1 * i, "b": 1.0}, 1) for i in range(30)]
m = to_river(OnlineGaussianNB())
acc = metrics.Accuracy()
for x, y in s:
p = m.predict_one(x)
if p is not None:
acc.update(y, p)
m.learn_one(x, y)
print(round(acc.get(), 4), m.predict_one({"a": 5.5, "b": 1.0}), m.predict_one({"a": 0.2, "b": 1.0}))
The first sample has no prediction (the classifier has seen nothing), so the accuracy counts the other 59. After the stream, a point at a = 5.5 is class 1 and a point at a = 0.2 is class 0.
2. A river classifier after a Dense-Armor scaler¶
from_river hands a river model to Dense-Armor code. The | operator of Dense-Armor chains a scaler and the river classifier in one pipeline.
from river import linear_model
from dense_armor.bridges.river import from_river
from dense_armor.utility.signals.preprocessing.scale import StandardScaler
s = [({"a": 0.1 * i, "b": 1.0}, False) for i in range(30)]
s += [({"a": 5 + 0.1 * i, "b": 1.0}, True) for i in range(30)]
pipe = StandardScaler() | from_river(linear_model.LogisticRegression())
for x, y in s:
pipe.learn_one(x, y)
print(pipe.predict_one({"a": 5.5, "b": 1.0}), pipe.predict_one({"a": 0.2, "b": 1.0}))
The river logistic regression is binary and takes True and False as labels. The scaler of Dense-Armor standardises each feature before it reaches the river model.
Details¶
References¶
- river documentation, the
learn_oneandpredict_onemethods of its classifiers. Not read for this page: the two blocks above are the check that the interfaces match, on the installed version.
Choices stated explicitly¶
- The bridge is the identity. No wrapper class is written, because the objects already have the other side's methods. A wrapper would add a layer where the two interfaces are equal.
- The extra.
pip install dense-armor[river]installsriver>=0.26on Python 3.11 or newer, aspyproject.tomldeclares. Importingdense_armor.bridges.riverwithout river raises aModuleNotFoundErrorthat names the extra.
Measured cost¶
Not measured: the functions return their argument.
Not covered¶
River estimators that need a method Dense-Armor classifiers do not have, and Dense-Armor classifiers that need a method river does not call. The two blocks above run on river 0.26.1.