【问题标题】:How do I store a TfidfVectorizer for future use in scikit-learn?如何存储 TfidfVectorizer 以供将来在 scikit-learn 中使用?
【发布时间】:2015-12-22 06:31:02
【问题描述】:

我有一个TfidfVectorizer,它对文章集合进行矢量化,然后进行特征选择。

vectroizer = TfidfVectorizer()
X_train = vectroizer.fit_transform(corpus)
selector = SelectKBest(chi2, k = 5000 )
X_train_sel = selector.fit_transform(X_train, y_train)

现在,我想存储它并在其他程序中使用它。我不想在训练数据集上重新运行 TfidfVectorizer() 和特征选择器。我怎么做?我知道如何使用joblib 使模型持久化,但我想知道这是否与使模型持久化相同。

【问题讨论】:

  • joblib 似乎工作。但我想我必须独立转储矢量化器和特征选择器。
  • 当你得到一个可行的解决方案时,请发布你的方法和一些代码。
  • scikit-learn.org/stable/modules/model_persistence.html 有一些关于安全和版本管理的警告。

标签: python python-3.x scikit-learn tf-idf joblib


【解决方案1】:

这是我使用 joblib 的答案:

import joblib
joblib.dump(vectorizer, 'vectorizer.pkl')
joblib.dump(selector, 'selector.pkl')

稍后,我可以加载它并准备好了:

vectorizer = joblib.load('vectorizer.pkl')
selector = joblib.load('selector.pkl')

test = selector.trasnform(vectorizer.transform(['this is test']))

【讨论】:

  • vectorizer 上的一个小错字
【解决方案2】:

你可以简单地使用内置的pickle库:

import pickle
pickle.dump(vectorizer, open("vectorizer.pickle", "wb"))
pickle.dump(selector, open("selector.pickle", "wb"))

并加载它:

vectorizer = pickle.load(open("vectorizer.pickle", "rb"))
selector = pickle.load(open("selector.pickle", "rb"))

Pickle 会将对象序列化到磁盘并在您需要时再次将它们加载到内存中

pickle lib docs

【讨论】:

  • 所以基本上,在将您的解决方案与我的解决方案进行比较时,您将 joblib 替换为 pickle,对吧?
  • 我试过cPickle,我试过使用pickle的joblib。对于任何一种方法,我都会得到pickle.PicklingError: Can't pickle <type 'instancemethod'>: it's not found as __builtin__.instancemethod 这是如何工作的?我也在存储 TfIdfVectorizer 对象。
  • @user2161903 他还修正了您在“vectroizer”中的拼写错误;)。
【解决方案3】:

“使对象持久化”基本上意味着您要将存储在内存中的二进制代码转储到硬盘驱动器上的文件中,以便稍后在您的程序或任何其他程序中对象可以从硬盘驱动器中的文件重新加载到内存中。

包含joblib 的scikit-learn 或picklecPickle 的stdlib 都可以完成这项工作。 我更喜欢cPickle,因为它明显更快。使用ipython's %timeit command

>>> from sklearn.feature_extraction.text import TfidfVectorizer as TFIDF
>>> t = TFIDF()
>>> t.fit_transform(['hello world'], ['this is a test'])

# generic serializer - deserializer test
>>> def dump_load_test(tfidf, serializer):
...:    with open('vectorizer.bin', 'w') as f:
...:        serializer.dump(tfidf, f)
...:    with open('vectorizer.bin', 'r') as f:
...:        return serializer.load(f)

# joblib has a slightly different interface
>>> def joblib_test(tfidf):
...:    joblib.dump(tfidf, 'tfidf.bin')
...:    return joblib.load('tfidf.bin')

# Now, time it!
>>> %timeit joblib_test(t)
100 loops, best of 3: 3.09 ms per loop

>>> %timeit dump_load_test(t, pickle)
100 loops, best of 3: 2.16 ms per loop

>>> %timeit dump_load_test(t, cPickle)
1000 loops, best of 3: 879 µs per loop

现在,如果您想在一个文件中存储多个对象,您可以轻松地创建一个数据结构来存储它们,然后转储数据结构本身。这适用于tuplelistdict。 从您的问题示例中:

# train
vectorizer = TfidfVectorizer()
X_train = vectorizer.fit_transform(corpus)
selector = SelectKBest(chi2, k = 5000 )
X_train_sel = selector.fit_transform(X_train, y_train)

# dump as a dict
data_struct = {'vectorizer': vectorizer, 'selector': selector}
# use the 'with' keyword to automatically close the file after the dump
with open('storage.bin', 'wb') as f: 
    cPickle.dump(data_struct, f)

稍后或在另一个程序中,以下语句将带回程序内存中的数据结构:

# reload
with open('storage.bin', 'rb') as f:
    data_struct = cPickle.load(f)
    vectorizer, selector = data_struct['vectorizer'], data_struct['selector']

# do stuff...
vectors = vectorizer.transform(...)
vec_sel = selector.transform(vectors)

【讨论】:

  • 泡菜的速度好像提高了很多。我得到了%timeit dump_load_test(t, pickle) 433 µs ± 40.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)。另外,您需要将文件打开模式设置为'wb''rb'
猜你喜欢
  • 2019-04-27
  • 2018-01-23
  • 2015-08-30
  • 2014-08-22
  • 2016-08-16
  • 2017-05-26
  • 1970-01-01
  • 2014-11-12
相关资源
最近更新 更多