scikit-learn suggests使用pickle进行模型持久化。然而,他们注意到不同版本的scikit-learn或python时pickle的局限性。 (另见this stackoverflow question)
在许多机器学习方法中,从大数据集中只学习了很少的参数。这些估算参数存储在trailing underscore的属性中,例如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
答案 0 :(得分:5)
单独设置估计属性是不够的 - 至少在所有估算器的一般情况下。
我至少知道一个会失败的例子。
LinearDiscriminantAnalysis.transform()
使用私有属性_max_components
:
def transform(self, X):
# ... code omitted
return X_new[:, :self._max_components]
但是,它可能适用于某些估算工具。如果您只需要针对特定估算器,最佳方法是查看估算器源代码并保存__init__()
和.fit()
方法中设置的所有属性。
更通用的方法可能是保存估算工具.__dict__
中的所有项目。 E.g:
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。私有属性本质上是一个实现细节,可以在不同版本之间随时更改。