scikit-learn建议将泡菜用于模型持久性。但是,他们注意到泡菜的局限性在Scikit-Learn或Python的不同版本方面的局限性。(另请参阅此堆叠问题)
在许多机器学习方法中,只有很少的参数从大型数据集中学到。这些估计的参数存储在属性下,例如尾随下划线,例如coef_
现在我的问题是:可以通过持续估计属性并稍后分配给它们来实现模型持久性?在Scikit-learn中,该方法对是否有安全的副作用(例如,必须设置的私有变量)在某些估计器中? 如下所示,它似乎适用于逻辑回归:from sklearn import datasets
from sklearn.linear_model import LogisticRegression
try:
from sklearn.model_selection import train_test_split
except ImportError:
from sklearn.cross_validation import train_test_split
iris = datasets.load_iris()
tt_split = train_test_split(iris.data, iris.target, test_size=0.4)
X_train, X_test, y_train, y_test = tt_split
# Here we train the logistic regression
lr = LogisticRegression(class_weight='balanced')
lr.fit(X_train, y_train)
print(lr.score(X_test, y_test)) # prints 0.95
# Persisting
params = lr.get_params()
coef = lr.coef_
intercept = lr.intercept_
# classes_ is not documented as public member,
# but not explicitely private (not starting with underscore)
classes = lr.classes_
lr.n_iter_ #This is meta-data. No need to persist
# Now we try to load the Classifier
lr2 = LogisticRegression()
lr2.set_params(**params)
lr2.coef_ = coef
lr2.intercept_ = intercept
lr2.classes_ = classes
print(lr2.score(X_test, y_test)) #Prints the same: 0.95
设置单独的估计属性是不够的 - 至少在的一般情况下,所有估计器。
。我至少知道一个示例会失败。 LinearDiscriminantAnalysis.transform()
使用私有属性_max_components
:
def transform(self, X):
# ... code omitted
return X_new[:, :self._max_components]
但是,它可能适用于某些估计器。如果您只需要特定的估算器,则最佳方法是查看估算器源代码并保存在__init__()
和.fit()
方法中设置的所有属性。
一种更通用的方法可能是保存估算器.__dict__
中的所有项目。例如:
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
lda = LDA().fit([[1, 2, 3], [1, 2, 1], [4, 5, 6], [9, 9, 9]], [1, 2, 1, 2])
lda.__dict__
# {'_max_components': 1,
# 'classes_': array([1, 2]),
# 'coef_': array([[ -9.55555556, 21.55555556, -9.55555556]]),
# 'explained_variance_ratio_': array([ 1.]),
# 'intercept_': array([-15.77777778]),
# 'means_': array([[ 2.5, 3.5, 4.5],
# [ 5. , 5.5, 5. ]]),
# 'n_components': None,
# 'priors': None,
# 'priors_': array([ 0.5, 0.5]),
# 'scalings_': array([[-2.51423299],
# [ 5.67164186],
# [-2.51423299]]),
# 'shrinkage': None,
# 'solver': 'svd',
# 'store_covariance': False,
# 'tol': 0.0001,
# 'xbar_': array([ 3.75, 4.5 , 4.75])}
对于包含更复杂数据的估计器,例如包含多个估计器的集合,这不会是微不足道的。有关更多详细信息,请参见博客文章Scikit-Learn Pipeline持久性和JSON序列化。
不幸的是,这不会安全地将估计器带到Scikit-Learn的新版本。私有属性本质上是一个实现细节,可以在发行版之间随时改变。