使用Scikit for Python保留TFIDF结果以预测新内容

lol*_*Wen 19 python machine-learning tf-idf scikit-learn

我在Python上使用sklearn来做一些聚类.我已经训练了200,000个数据,下面的代码效果很好.

corpus = open("token_from_xml.txt")
vectorizer = CountVectorizer(decode_error="replace")
transformer = TfidfTransformer()
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))
km = KMeans(30)
kmresult = km.fit(tfidf).predict(tfidf)
Run Code Online (Sandbox Code Playgroud)

但是当我有新的测试内容时,我想将它集中到我训练过的现有集群中.所以我想知道如何保存IDF结果,这样我就可以为新的测试内容做TFIDF,并确保新测试内容的结果具有相同的数组长度.

提前致谢.

UPDATE

我可能需要将"transformer"或"tfidf"变量保存到文件(txt或其他),如果其中一个包含经过训练的IDF结果.

UPDATE

例如.我有训练数据:

["a", "b", "c"]
["a", "b", "d"]
Run Code Online (Sandbox Code Playgroud)

并且做TFIDF,结果将包含4个特征(a,b,c,d)

当我测试时:

["a", "c", "d"]
Run Code Online (Sandbox Code Playgroud)

查看它所属的集群(已由k-means制作).TFIDF只会给出3个特征(a,c,d)的结果,因此k-means中的聚类将会下降.(如果我测试["a", "b", "e"],可能还有其他问题.)

那么如何存储用于测试数据的功能列表(甚至更多,将其存储在文件中)?

UPDATE

解决了,见下面的答案.

lol*_*Wen 19

我通过保存vectorizer.vocabulary_和重用来成功保存了功能列表CountVectorizer(decode_error="replace",vocabulary=vectorizer.vocabulary_)

代码如下:

corpus = np.array(["aaa bbb ccc", "aaa bbb ddd"])
vectorizer = CountVectorizer(decode_error="replace")
vec_train = vectorizer.fit_transform(corpus)
#Save vectorizer.vocabulary_
pickle.dump(vectorizer.vocabulary_,open("feature.pkl","wb"))

#Load it later
transformer = TfidfTransformer()
loaded_vec = CountVectorizer(decode_error="replace",vocabulary=pickle.load(open("feature.pkl", "rb")))
tfidf = transformer.fit_transform(loaded_vec.fit_transform(np.array(["aaa ccc eee"])))
Run Code Online (Sandbox Code Playgroud)

这样可行.tfidf将具有与训练数据相同的特征长度.

  • 以后加载它是错误的!! ..为什么它是fit_transform ..从技术上讲,如果你正在改变新的/看不见的数据,它应该只是转换. (11认同)
  • 如果有人对此感兴趣,请听@MANU所说的解释:“fit()”方法计算转换的参数。另一方面,“transform()”方法只是根据“fit()”方法中计算的参数来转换数据集。同样,“fit_transform()”只是以优化的方式一个接一个地执行它。但在机器学习中,我们根据训练集来计算参数。在测试时,我们不计算任何新参数,而是仅应用从训练集计算出的参数来转换测试数据。因此,在测试时我们应该只使用“transform()”。 (2认同)

Arj*_*hra 15

可以直接使用 tfidfvectorizer 的词汇表,而不是使用 CountVectorizer 来存储词汇表。

训练阶段:

from sklearn.feature_extraction.text import TfidfVectorizer

# tf-idf based vectors
tf = TfidfVectorizer(analyzer='word', ngram_range=(1,2), stop_words = "english", lowercase = True, max_features = 500000)

# Fit the model
tf_transformer = tf.fit(corpus)

# Dump the file
pickle.dump(tf_transformer, open("tfidf1.pkl", "wb"))


# Testing phase
tf1 = pickle.load(open("tfidf1.pkl", 'rb'))

# Create new tfidfVectorizer with old vocabulary
tf1_new = TfidfVectorizer(analyzer='word', ngram_range=(1,2), stop_words = "english", lowercase = True,
                          max_features = 500000, vocabulary = tf1.vocabulary_)
X_tf1 = tf1_new.fit_transform(new_corpus)
Run Code Online (Sandbox Code Playgroud)

fit_transform 在这里工作,因为我们使用的是旧词汇。如果您不存储 tfidf,您将只对测试数据使用转换。即使您在那里进行转换,来自测试数据的新文档也正在“适合”火车矢量化器的词汇表。这正是我们在这里所做的。我们唯一可以为 tfidf 向量化器存储和重用的东西就是词汇表。


use*_*123 7

如果要存储用于测试数据的功能列表以供将来使用,可以执行以下操作:

tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))

#store the content
with open("x_result.pkl", 'wb') as handle:
                    pickle.dump(tfidf, handle)
#load the content
tfidf = pickle.load(open("x_result.pkl", "rb" ) )
Run Code Online (Sandbox Code Playgroud)

  • `tfidf`不包含功能列表,我已成功保存功能列表以供重用,并自行回答.谢谢你鼓舞我. (2认同)

小智 6

一个更简单的解决方案,只需使用 joblib 库,如文档所述:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.externals import joblib

vectorizer = CountVectorizer()
X = vectorizer.fit_transform(texts)
feature_name = vectorizer.get_feature_names()
tfidf = TfidfTransformer()
tfidf.fit(X)

# save your model in disk
joblib.dump(tfidf, 'tfidf.pkl') 

# load your model
tfidf = joblib.load('tfidf.pkl') 
Run Code Online (Sandbox Code Playgroud)