如何使用Joblib或Pickle保存通过Pipeline和GridSearchCV创建的模型?

56

在使用pipelineGridSearchCV确定最佳参数后,我如何使用pickle/joblib将此过程保存以便以后重复使用?当它是单个分类器时,我知道如何做到这一点...

from sklearn.externals import joblib
joblib.dump(clf, 'filename.pkl') 

在执行并完成gridsearch后,我该如何保存带有最佳参数的整个pipeline呢?

我尝试了以下方式:

  • joblib.dump(grid, 'output.pkl') - 但这会导出每次尝试的结果(很多文件)
  • joblib.dump(pipeline, 'output.pkl') - 但我不认为其中包含最佳参数

X_train = df['Keyword']
y_train = df['Ad Group']

pipeline = Pipeline([
  ('tfidf', TfidfVectorizer()),
  ('sgd', SGDClassifier())
  ])

parameters = {'tfidf__ngram_range': [(1, 1), (1, 2)],
              'tfidf__use_idf': (True, False),
              'tfidf__max_df': [0.25, 0.5, 0.75, 1.0],
              'tfidf__max_features': [10, 50, 100, 250, 500, 1000, None],
              'tfidf__stop_words': ('english', None),
              'tfidf__smooth_idf': (True, False),
              'tfidf__norm': ('l1', 'l2', None),
              }

grid = GridSearchCV(pipeline, parameters, cv=2, verbose=1)
grid.fit(X_train, y_train)

#These were the best combination of tuning parameters discovered
##best_params = {'tfidf__max_features': None, 'tfidf__use_idf': False,
##               'tfidf__smooth_idf': False, 'tfidf__ngram_range': (1, 2),
##               'tfidf__max_df': 1.0, 'tfidf__stop_words': 'english',
##               'tfidf__norm': 'l2'}
2个回答

67
import joblib
joblib.dump(grid.best_estimator_, 'filename.pkl')

如果您想将对象转储到一个文件中,请使用:

joblib.dump(grid.best_estimator_, 'filename.pkl', compress = 1)

12
作为最佳实践,一旦选择了最佳模型,应该在整个数据集上重新训练它。为此,应该将同一个管道对象应用于整个数据集(从而应用相同的数据处理),然后部署该对象吗?还是应该重新创建一个新模型? - Odisseo
2
@Odisseo - 我的意见是你从头开始重新训练一个新模型。你仍然可以使用管道,但是将你的网格分类器更改为最终分类器(比如随机森林)。将该分类器添加到管道中,使用所有数据进行重新训练。保存最终模型。- 最终结果是你的整个数据集都在所需的完整管道内进行了训练。这可能会导致稍微不同的预处理,但应该更加健壮。实际上,这意味着你调用pipeline.fit()并保存管道。 - brian_ds
20
@Odisseo 我有点晚了,但是... GridSearchCV 会自动在整个数据集上重新训练模型,除非你明确要求它不这样做。因此,当你训练 GridSearchCV 模型时,用于预测的模型(换句话说,best_estimator_)已经在整个数据集上重新训练过了。 - Federico Dorato

0
我只想指出,就磁盘上的大小而言,保存GridSearchCV或其最佳估计器并没有太大区别(对于我的个人项目来说,1865 KB与1801 KB之间),但压缩却有天壤之别。换句话说,传递compress=True(或介于1和9之间的整数)非常重要。
在下面的示例中,case1.pkl的磁盘大小要比case2.pkl和case3.pkl小得多,而case2.pkl和case3.pkl的大小则非常相似。
import joblib
joblib.dump(grid, 'case1.pkl', compress=True)     # <--- good

joblib.dump(grid, 'case2.pkl')
joblib.dump(grid.best_estimator_, 'case3.pkl')

如果你想使用pickle而不是joblib,你可以将它与内置的gzip结合起来进行压缩:
import pickle
import gzip

with gzip.open('case4.pkl', 'wb') as f:
    pickle.dump(grid, f)

顺便提一下,当你加载腌制的模型时,请确保 joblib 版本至少与最初用于转储模型的 joblib 版本一样新。否则,可能会引发 KeyError 异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接