保留 TFIDF 结果以使用 Scikit for Python 预测新内容
Posted
技术标签:
【中文标题】保留 TFIDF 结果以使用 Scikit for Python 预测新内容【英文标题】:Keep TFIDF result for predicting new content using Scikit for Python 【发布时间】:2015-06-29 13:10:48 【问题描述】:我在 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)
但是当我有新的测试内容时,我想将它聚集到我训练过的现有集群中。所以我想知道如何保存 IDF 结果,以便我可以为新的测试内容做 TFIDF 并确保新测试内容的结果具有相同的数组长度。
提前致谢。
更新
如果其中一个包含经过训练的 IDF 结果,我可能需要将“transformer”或“tfidf”变量保存到文件(txt 或其他)中。
更新
例如。我有训练数据:
["a", "b", "c"]
["a", "b", "d"]
再做 TFIDF,结果会包含 4 个特征(a,b,c,d)
当我测试:
["a", "c", "d"]
查看它属于哪个集群(已经由 k-means 制作)。 TFIDF 只会给出 3 个特征(a,c,d)的结果,因此 k-means 中的聚类会下降。 (如果我测试["a", "b", "e"]
,可能还有其他问题。)
那么如何存储测试数据的特征列表(更甚者,存储在文件中)?
更新
已解决,请参阅下面的答案。
【问题讨论】:
新内容是什么意思?新的测试内容或培训内容? 新测试内容@user123 我猜您可能无法将新的培训内容附加到以前培训的内容中。你必须用整个训练数据至少训练一次,然后你可以腌制那些训练过的数据,以后可以用它来消除训练延迟。但是当你获得新内容时,你必须至少训练一次 @user123 感谢您的回复。我更新了我的问题。我不会将新的训练内容附加到之前训练的内容中,而是要测试新内容以查看它属于哪个集群,这可能吗? 【参考方案1】:我通过保存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"])))
这行得通。 tfidf
将具有与训练数据相同的特征长度。
【讨论】:
这会保存 tfidf 训练的模型以及生成的 tfidf 矩阵吗? 稍后加载部分是错误的! .. 为什么它是 fit_transform.. 从技术上讲,如果您要转换新的/看不见的数据,它应该只是转换。 如果有人对这里感兴趣是@MANU 所说的解释:fit()
方法计算转换的参数。另一方面,transform()
方法只是根据fit()
方法中计算的参数转换数据集。同样fit_transform()
只是以优化的方式一个接一个地进行。但是在机器学习中,我们根据训练集计算参数。在测试时,我们不计算任何新参数,而是应用从训练集计算的参数来转换测试数据。因此,在测试时我们应该只使用transform()
。
我尝试了这个例子,因为他们删除了我的一个明显相似的问题,但我总是得到“TF-IDF 矢量化器未安装”
@hafiz031 如果你替换 fit_tranform 这个代码不起作用【参考方案2】:
不用CountVectorizer来存储词汇,直接使用tfidfvectorizer的词汇即可。
训练阶段:
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)
fit_transform 在这里工作,因为我们使用的是旧词汇。如果您没有存储 tfidf,那么您只需对测试数据使用转换。即使您在那里进行转换,来自测试数据的新文档也正在“适合”火车矢量化器的词汇表。这正是我们在这里所做的。对于 tfidf 矢量化器,我们唯一可以存储和重复使用的是词汇表。
【讨论】:
为什么这里有人说不需要最终的 fit_tranform 并且有人发布代码正在使用它? 顺便说一句,这是唯一有效的方法【参考方案3】:如果您想存储特征列表以供将来使用的测试数据,您可以这样做:
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" ) )
【讨论】:
tfidf
不包含功能列表,我已成功保存功能列表以供重复使用,并自己回答了这个问题。谢谢你给了我灵感。【参考方案4】:
一个更简单的解决方案,就像document所说的那样使用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')
【讨论】:
【参考方案5】:您可以在一个阶段完成矢量化和 tfidf 转换:
vec =TfidfVectorizer()
然后对训练数据进行拟合和转换
tfidf = vec.fit_transform(training_data)
并使用tfidf模型进行改造
unseen_tfidf = vec.transform(unseen_data)
km = KMeans(30)
kmresult = km.fit(tfidf).predict(unseen_tfid)
【讨论】:
谢谢。但我想将 tfidf 结果保存到文件(txt 或其他文件)中,稍后再加载。你的意思是重用“vec”变量,但是可以保存吗? 这是 TfidfVectorizer 的标准用法。OP 需要保存和重新加载矢量化器。虽然听起来可能很奇怪,但它对于使用 Amazon Sagemaker 等服务的人很有用,在这些服务中,训练和预测在单独的 ec2 实例上运行。以上是关于保留 TFIDF 结果以使用 Scikit for Python 预测新内容的主要内容,如果未能解决你的问题,请参考以下文章
如何在 scikit-learn 中的 tfidf 之后查看术语文档矩阵的前 n 个条目
scikit-learn - HashingVectorizer 上的 Tfidf