scikit-learn suggests使用pickle进行模型持久化。但是,他们注意到在使用不同版本的scikit-learn或python时,pickle的局限性。 (另请参见this stackoverflow question)

在许多机器学习方法中,仅从大型数据集中学习了很少的参数。这些估计的参数存储在带有trailing underscore的属性中,例如coef_
现在我的问题是:
是否可以通过持久保存估计的属性并在以后分配给它们来实现模型持久性?
对于scikit-learn中所有估算器来说,这种方法是否安全?在某些估算器的情况下,是否存在潜在的副作用(例如必须设置的私有(private)变量)?

如以下示例所示,它似乎适用于逻辑回归:

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() 使用私有(private)属性_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 Persistence and JSON Serialization

不幸的是,这无法安全地将估算器带到新版本的scikit-learn。私有(private)属性本质上是一个实现细节,可以在版本之间随时更改。

关于python - 我可以在scikit-learn中安全地分配给 `coef_`和其他估计的参数吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46316031/

10-12 23:18