模拟估算器:scikit-learn Estimator
scikit-learn机器学习模型通常嵌入在数据管道中,以便对通过管道传递的数据进行预测。对于任何生产管道,需要对机器学习模型进行历史数据训练,以提供准确的预测。但是,在某些情况下,使用不考虑任何先前数据的简单规则来处理管道数据是有意义的。一些有用的案例是:
Pipeline MVP
当一个数据科学项目刚刚开始时,关键是要尽可能快地走向一个最小可行的产品(MVP)。这个MVP将包含最终数据产品的所有组件,但只具有最低限度的功能。在项目达到这一点之后,迭代和改进已经存在的Pipeline将会更快。由于一个经过训练的机器学习模型需要花费大量的时间和精力来创建,因此在数据管道中放置一个模拟模型将允许数据工程师在数据科学家完成最终模型的训练之前开始他们的工作。
性能Baseline
模拟模型有用的另一种情况是确定机器学习模型有价值所需的最低性能。例如,如果模型试图预测哪些客户将离开以及哪些客户将留下,那么一个天真的模型可能预测所有客户将留下。它的精度会很差。任何可行的模型都需要击败天真模型的表现。拥有遵循简单规则并可插入相同分析代码的模拟模型将允许数据科学家以他们为真实模型测量它的确切方式来衡量其性能。
模拟估算器
现在我们知道创建模拟模型背后的目的,让我们看看如何在实践中完成它。以下Python代码创建MockBinaryClassifier充当二元预测模型的类。该模型遵循以下简单规则:如果第一个特征的值小于或等于0,则返回0级,如果第一个特征大于0则返回1级。Python代码如下:
import numpy as np from sklearn.base import BaseEstimator from sklearn.pipeline import Pipeline from sklearn.preprocessing import MinMaxScaler class MockBinaryClassifier(BaseEstimator): """Class to emulate a predictive model using a simple heuristic.""" def __init__(self): """Set the classes for binary classification""" self.n_classes_ = 2 self.classes_ = np.array([0, 1]) def fit( self, features: np.ndarray, target: np.ndarray, sample_weight: np.ndarray = None ): """ Mocks out the fit function for a standard scikit-learn estimator. Since the heuristic doesn't rely on any previous data, the function simply returns self. :param features: Ignored. :param target: Ignored. :param sample_weight: Ignored. :return: Returns the estimator without any changes. """ return self def predict(self, features: np.ndarray) -> np.ndarray: """ Emulate a machine learning model's behavior. This function will return the most probable class for each instance. It only uses the first feature of the `features` array. If the feature value is less than or equal to 0, it will return a class 0. If feature value is greater than zero, it will return a class 1. :param features: Ndarray that corresponds to features used in a classification model. :return: Predicted class for all instances of `features`. """ return np.where(features[:, 0] > 0, 1, 0)
代码格式:
关于MockBinaryClassifier有一些需要注意。第一个是类继承自sklearn.base.BaseEstimator。这意味着它可以在任何使用scikit-learn estimator 的地方使用。另一个是,fit函数本质上是一个无操作。既然我们知道如何对实例进行分类,就不需要考虑任何历史数据。
示范
下面是Python示例代码,用于显示实际运行中的MockBinaryClassifier:
model = MockBinaryClassifier() test_feature = np.array([[0], [0.5], [3], [-1]]) predictions = model.predict(test_feature) print(predictions)
[0 1 1 0]
该示例显示了对一组单特征实例打分的预测值函数。您可能会反对说,这并不能证明类可以像其他任何scikit-learn estimator 一样被使用,因为Python代码即使不从sklearn.base.BaseEstimator继承也能工作。下面的Python代码展示了MockBinaryClassifier如何在scikit-learn pipeline中工作:
train_feature = np.zeros_like(test_feature) train_target = np.zeros_like(test_feature) pipe = Pipeline([ ('scale', MinMaxScaler(feature_range=(0, 1))), ('mock', MockBinaryClassifier()) ]) pipe_predictions = pipe.fit(train_feature, train_target).predict(test_feature) print(pipe_predictions)
[0 1 1 0]
MockBinaryClassifier可以在任意复杂的数据管道中作为scikit-learn estimator 的替代。惟一可能需要的更改是实现额外的函数,如predict_proba等。
需要注意的一点是,如果数据管道包括使用pickle从持久存储加载模型,那么需要在加载环境中导入MockBinaryClassifier。
结论
使用启发式方法创建模拟模型是在开发周期中消除瓶颈的一种极好的方法。它允许数据工程师和数据科学家并行工作,而不需要工程师等待真正的机器学习模型被建立。它还允许数据科学家使用他们将用于构建真实模型的精确代码来设置基准性能标准。