forml.pipeline.wrap¶
Decorators for creating operators and actors by wrapping generic (non-ForML) implementations.
Instead of creating ForML actors and/or operators by fully implementing their relevant base classes, they can (in special cases) be conveniently defined using the wrappers provided within this module.
Module Attributes
-
forml.pipeline.wrap.AUTO =
[AutoSklearnTransformer, AutoSklearnClassifier, AutoSklearnRegressor]
¶ The default list of
auto-wrapper
implementations to be used by thewrap.importer
context manager.
Functions
- forml.pipeline.wrap.importer(*wrappers: wrap.Auto) Iterable[None] [source]¶
Context manager capturing all direct imports and wrapping their matching entities using the explicit or default list of auto-wrappers.
The signature of the wrapped object is compatible with the original entity.
- Parameters:
- Returns:
Context manager under which the direct imports become subject to auto-wrapping.
Examples
All three possible import syntax alternatives are supported, although only the first one is recommended:
with wrap.importer(): # 1. auto-wrap just the explicit members (recommended): from sklearn.ensemble import GradientBoostingClassifier # 2. auto-wrap all members discovered in ensemble.* # (not recommended - unnecessarily heavy) from sklearn import ensemble # 3. similar but without the namespace # (even less recommended - heavy and dirty) from sklearn.ensemble import *
Example use-case importing the
sklearn.ensemble.GradientBoostingClassifier
classifier wrapped as a ForML operator that can be directly used within a pipeline composition expression:>>> from forml import flow >>> from forml.pipeline import wrap >>> >>> with wrap.importer(): ... from sklearn.ensemble import RandomForestClassifier ... >>> RFC = RandomForestClassifier(n_estimators=30, max_depth=10) >>> isinstance(RFC, flow.Operator) True >>> PIPELINE = preprocessing.Prepare() >> RFC
Classes
- class forml.pipeline.wrap.Actor(*args, **kwargs)[source]¶
Bases:
object
Central class providing decorators/wrappers for creating ForML Actors using a number of convenient ways not requiring to fully implement the
flow.Actor
base class from scratch.Decorator Methods
- apply(origin)[source]¶
Decorator for turning a given plain function into a stateless Actor.
- Parameters:
- origin¶
Decorated function.
The function must have one of the following signatures:
def foo(*features: flow.Features) -> flow.Result: def foo(features: flow.Features) -> flow.Result: def foo(*features: flow.Features, opt1, optN=None) -> flow.Result: def foo(features: flow.Features, *, opt1, optN=None) -> flow.Result: def foo(*features: flow.Features, opt1, **kwargs) -> flow.Result: def foo(features: flow.Features, /, *, opt1, **kwargs) -> flow.Result:
Attention
The optional arguments
opt1
,opt2
, and**kwargs
must all be keyword-only arguments.
- Returns:
A stateless Actor class with the given apply logic.
Examples
Simple stateless imputation actor using the provided value to fill the NaNs:
@wrap.Actor.apply def StaticImpute( df: pandas.DataFrame, *, column: str, value: float, ) -> pandas.DataFrame: df[column] = df[column].fillna(value) return df
- train(origin)[source]¶
Decorator for turning a given plain function into a follow-up apply function decorator.
Stateful actors need to have distinct implementations for their train vs apply modes. This wrapping facility achieves that by decorating two companion functions each implementing the relevant mode.
- Parameters:
- origin¶
Decorated train function.
The decorated train function must have one of the following signatures:
def foo(state: typing.Optional[State], features: flow.Features, labels: flow.Labels) -> State: def foo(state: typing.Optional[State], features: flow.Features, labels: flow.Labels, opt1, optN=None) -> State: def foo(state: typing.Optional[State], features: flow.Features, labels: flow.Labels, /, opt1,**kwargs) -> State:
The function will receive the previous state as the first parameter and is expected to provide the new state instance as its return value.
- Returns:
Follow-up decorator to be used for wrapping the companion apply function which eventually returns a stateful Actor class with the given train-apply logic.
The decorated apply function must have one of the following signatures:
def foo(state: State, features: flow.Features) -> flow.Result: def foo(state: State, features: flow.Features, opt1, optN=None) -> flow.Result: def foo(state: State, features: flow.Features, /, opt1, **kwargs) -> flow.Result:
The function will receive the current state as the first parameter and is expected to provide the apply-mode transformation result.
Examples
Simple stateful imputation actor using the trained mean value to fill the NaNs:
@wrap.Actor.train # starting with wrapping the train-mode function def MeanImpute( state: typing.Optional[float], # receving the previous state (not used) features: pandas.DataFrame, labels: pandas.Series, *, column: str, ) -> float: return features[column].mean() # returning the new state @MeanImpute.apply # continue with the follow-up apply-mode function decorator def MeanImpute( state: float, # receiving current state features: pandas.DataFrame, *, column: str ) -> pandas.DataFrame: features[column] = features[column].fillna(state) return features # apply-mode result
-
type(origin=
None
, /, *, apply=None
, train=None
, get_params=None
, set_params=None
)[source]¶ Wrapper for turning an external user class into a valid Actor.
This can be used either as a parameterless decorator or optionally with mapping of Actor methods to decorated user class implementation.
- Parameters:
- origin=
None
¶ Decorated class.
- apply=
None
¶ Target method name or decorator function implementing the actor
apply
logic.- train=
None
¶ Target method name or decorator function implementing the actor
train
logic.- get_params=
None
¶ Target method name or decorator function implementing the actor
get_params
logic.- set_params=
None
¶ Target method name or decorator function implementing the actor
set_params
logic.
- origin=
- Returns:
Actor class.
Examples
>>> RfcActor = wrap.Actor.type( ... sklearn.ensemble.RandomForestClassifier, ... train='fit', ... apply=lambda c, *a, **kw: c.predict_proba(*a, **kw).transpose()[-1], ... )
- class forml.pipeline.wrap.Auto[source]¶
-
Generic base class for auto-wrapper implementations.
If supplied to the
wrap.importer()
context manager when capturing the imports, each discovered entity within the imported namespace is checked against the auto-wrapper using itsmatch()
method and if compatible it gets wrapped in-place using itsapply()
method.Each auto-wrapper needs to implement the following methods:
-
class forml.pipeline.wrap.AutoSklearnTransformer(apply: str | Callable[[...], Any] =
'transform'
)[source]¶ Bases:
AutoClass
[type
[TransformerMixin
]]Auto-wrapper for turning Scikit-learn transformers into ForML operators.
Instances can be used with
wrap.importer
to auto-wrap Scikit-learn transformers upon importing.Hint
Supports not just the official Scikit-learn transformers but any
sklearn.base.TransformerMixin
subclasses including 3rd party implementations.
-
class forml.pipeline.wrap.AutoSklearnClassifier(apply: str | collections.abc.Callable[..., Any] =
predict_proba[-1]
)[source]¶ Bases:
AutoClass
[type
[ClassifierMixin
]]Auto-wrapper for turning Scikit-learn classifiers into ForML operators.
Instances can be used with
wrap.importer
to auto-wrap Scikit-learn classifiers upon importing.Hint
Supports not just the official Scikit-learn classifiers but any
sklearn.base.ClassifierMixin
subclasses including 3rd party implementations.- Parameters:
- apply: str | collections.abc.Callable[..., Any] =
predict_proba[-1]
¶ Customizable
mapping
for the apply-mode target endpoint. Defaults to a callback hitting the.predict_proba
and returning the last of its produced columns (conveniently the 1-class probability in case of binary classification; for multiclass this needs tweaking).
- apply: str | collections.abc.Callable[..., Any] =
-
class forml.pipeline.wrap.AutoSklearnRegressor(apply: str | Callable[[...], Any] =
'predict'
)[source]¶ Bases:
AutoClass
[type
[RegressorMixin
]]Auto-wrapper for turning Scikit-learn regressors into ForML operators.
Instances can be used with
wrap.importer
to auto-wrap Scikit-learn regressors upon importing.Hint
Supports not just the official Scikit-learn regressors but any
sklearn.base.RegressorMixin
subclasses including 3rd party implementations.
- class forml.pipeline.wrap.Operator(*args, **kwargs)[source]¶
Bases:
Operator
Special operator created via a decoration of particular actors.
This represents a convenient way of implementing ForML Operators without requiring to fully implement the
flow.Operator
base class from scratch.Attention
Instances are expected to be created via the decorator methods.
This approach is applicable only to a special case of simple operators implemented by at most one actor per each of the coherent appy/train/label segments corresponding to the relevant primitive decorators (
apply()
,train()
,label()
) supplying the particular actors.In addition to the primitive decorators, there is the combined
mapper()
decorator filling both the train/apply segments at once.Hint
The decorators can be chained together as well as applied in a split fashion onto separate actors for different builder:
@wrap.Operator.train @wrap.Operator.apply # can be chained if same actor is also to be used in another mode @wrap.Actor.apply def MyOperator(df, *, myarg=None): ... # stateless actor implementation used for train/apply segments @MyOperator.label # decorated operator can itself be used as decorator in split fashion @wrap.Actor.apply def MyOperator(df, *, myarg=None): ... # stateless actor implementation used for the label segment
Decorator Methods
Actor definitions for individual builder can be provided using the following decorator methods.
- train(actor)¶
Train segment actor decorator.
When used as a decorator, this method creates an operator engaging the wrapped actor in the train-mode. If stateful, the actor also gets normally trained first. Note it does not get applied to the apply-mode features unless also decorated with the
apply()
decorator (this is rarely desired - see themapper()
decorator for a more typical use case)!- Parameters:
- actor¶
Decorated actor.
- Returns:
An Operator class using the given actor.
Examples
Usage with a wrapped stateless actor:
@wrap.Operator.train @wrap.Actor.apply def TrainOnlyDropColumn( df: pandas.DataFrame, *, column: str ) -> pandas.DataFrame: return df.drop(columns=column) PIPELINE = AnotherOperator() >> TrainOnlyDropColumn(column='foo')
- apply(actor)¶
Apply segment actor decorator.
When used as a decorator, this method creates an operator engaging the wrapped actor in the apply-mode. If stateful, the actor also gets normally trained in train-mode (but does not get applied to the train-mode features unless also decorated with the
train()
decorator!).- Parameters:
- actor¶
Decorated actor.
- Returns:
An Operator class using the given actor.
Examples
Usage with a wrapped stateful actor:
@wrap.Actor.train def ApplyOnlyFillnaMean( state: typing.Optional[float], df: pandas.DataFrame, labels: pandas.Series, *, column: str, ) -> float: return df[column].mean() @wrap.Operator.apply @ApplyOnlyFillnaMean.apply def ApplyOnlyFillnaMean( state: float, df: pandas.DataFrame, *, column: str ) -> pandas.DataFrame: df[column] = df[column].fillna(state) return df PIPELINE = ( AnotherOperator() >> TrainOnlyDropColumn(column='foo') >> ApplyOnlyFillnaMean(column='bar') )
- label(actor)¶
Label segment actor decorator.
When used as a decorator, this method creates an operator engaging the wrapped actor in the train-mode as the label transformer. If stateful, the actor also gets normally trained first. The actor gets engaged prior to any other stateful actors potentially added to the same operator (using the
train()
orapply()
decorators).- Parameters:
- actor¶
Decorated actor.
- Returns:
An Operator class using the given actor.
Examples
Usage with a wrapped stateless actor:
@wrap.Operator.label @wrap.Actor.apply def LabelOnlyFillZero(labels: pandas.Series) -> pandas.Series: return labels.fillna(0) PIPELINE = ( anotheroperator() >> LabelOnlyFillZero() >> TrainOnlyDropColumn(column='foo') >> ApplyOnlyFillnaMean(column='bar') )
Alternatively, it could as well be just added to the existing
ApplyOnlyFillnaMean
:@ApplyOnlyFillnaMean.label @wrap.Actor.apply def ApplyFillnaMeanLabelFillZero(labels: pandas.Series) -> pandas.Series: return labels.fillna(0)
- mapper(actor)¶
Combined train-apply decorator.
Decorator representing the wrapping of the same actor using both the
train()
andapply()
decorators effectively engaging the actor in transforming the features in both the train-mode as well as the apply-mode.- Parameters:
- actor¶
Decorated actor.
- Returns:
An Operator class using the given actor.