"""Definitions of interfaces for data science objects expected by :mod:`porter.services`."""
import abc
from porter.loading import load_file
from porter import utils
[docs]
class BaseModel(abc.ABC):
"""Class defining the model interface required by
:meth:`porter.services.ModelApp.add_service`."""
[docs]
@abc.abstractmethod
def predict(self, X):
"""Return predictions corresponding to the data in ``X``."""
[docs]
class BasePreProcessor(abc.ABC):
"""Class defining the preprocessor interface required by
:meth:`porter.services.ModelApp.add_service`."""
[docs]
@abc.abstractmethod
def process(self, X_input):
"""Process and return ``X_input``.
Args:
X_input (``pandas.DataFrame``): The raw input from a POST request
converted to a ``pandas.DataFrame``.
Returns:
``X_input`` processed as desired.
"""
[docs]
class BasePostProcessor(abc.ABC):
"""Class defining the postprocessor interface required by
:meth:`porter.services.ModelApp.add_service`."""
[docs]
@abc.abstractmethod
def process(self, X_input, X_preprocessed, predictions):
"""Process and return ``predictions``.
Args:
X_input (``pandas.DataFrame``): The raw input from a POST request
converted to a ``pandas.DataFrame``.
X_preprocessed: The POST request data with preprocessing applied.
predictions: The output of an instance of :class:`BaseModel`.
Returns:
``predictions`` processed as desired.
Note: ``X_input`` and ``X_preprocessed`` are included to provide additional
context for postprocessing predictions if necessary.
"""
[docs]
class WrappedModel(BaseModel):
"""A convenience class that exposes a model persisted to disk with the
:class:`BaseModel` interface.
Args:
model: An object with a scikit-learn-compatible ``.predict()`` method.
"""
def __init__(self, model):
if not hasattr(model, 'predict') or not callable(model.predict):
raise TypeError('model must have a .predict() method:\n{}'
.format(model))
self.model = model
super(WrappedModel, self).__init__()
[docs]
def predict(self, X):
return self.model.predict(X)
[docs]
@classmethod
def from_file(cls, path, *args, s3_access_key_id=None,
s3_secret_access_key=None, **kwargs):
model = load_file(path, s3_access_key_id, s3_secret_access_key)
return cls(model, *args, **kwargs)