将提取的向量加载到 TfidfVectorizer

Posted

技术标签:

【中文标题】将提取的向量加载到 TfidfVectorizer【英文标题】:Load extracted vectors to TfidfVectorizer 【发布时间】:2017-01-26 21:12:35 【问题描述】:

我正在寻找一种方法来加载我之前使用 scikit-learn 的 TfidfVectorizer 生成的向量。总的来说,我希望更好地了解 TfidfVectorizer 的数据持久性。

例如,到目前为止我所做的是:

vectorizer = TfidfVectorizer(stop_words=stop)
vect_train = vectorizer.fit_transform(corpus)

然后我编写了 2 个函数以便能够保存和加载我的矢量化器:

def save_model(model,name):
    '''
    Function that enables us to save a trained model

    '''
    joblib.dump(model, '.pkl'.format(name)) 


def load_model(name):
    '''
    Function that enables us to load a saved model

    '''
    return joblib.load('.pkl'.format(name))

我检查了类似下面的帖子,但我仍然无法理解。

How do I store a TfidfVectorizer for future use in scikit-learn?

我最终希望能够进行培训,然后加载这组生成的向量,根据这些向量转换一些新的文本输入,并使用旧向量和基于它们生成的新向量执行 cosine_similarity。

我希望这样做的原因之一是因为在如此大的数据集中进行向量化大约需要 10 分钟,我希望这样做一次,而不是每次有新查询进入。

我想我应该保存的是 vect_train 对吧?但是,首先保存它然后将其加载到新创建的 TfidfVectorizer 实例中的正确方法是什么?

我第一次尝试使用 joblib 保存 vect_train,因为 scikit-learn 中的好心人建议这样做,我得到了 4 个文件:tfidf.pkl、tfidf.pkl_01.npy、tfidf.pkl_02.npy、tfidf.pkl_03.npy。如果我知道这些到底是什么以及如何将它们加载到一个新的

实例中,那就太好了
vectorizer = TfidfVectorizer(stop_words=stop)

在不同的脚本中创建。

提前谢谢你。

【问题讨论】:

为了澄清,你有一个“训练”集,你想将其转换为 tf-idf 向量矩阵。然后你想保存那个m x n 矩阵。稍后,在新会话中,您想重新加载该矩阵并使用它来计算查询的余弦距离?在写答案之前确保我理解 是的,这就是我想做的!详细说明一下,我的最终目标是进行一次耗时的培训课程,该课程将返回您提到的矩阵,然后通过加载该矩阵来转换“看不见的”查询。我不确定是否只需保存矢量化器就可以重新加载它并使用它来初始化具有先前提取的矢量的新实例。 你应该已经准备好了已经写好的答案。保存矢量化器并保存vect_train。重新加载 vect_train 以便您拥有 tf-idf 矩阵。然后重新加载向量器并使用它将新查询转换为相同的m x n 空间。从那里,您可以使用任意数量的方法来计算余弦距离/相似度。 【参考方案1】:

vect_train = vectorizer.fit_transform(corpus) 的结果是双重的:(i) 矢量化器适合您的数据,即它学习语料库词汇和每个术语的 idf,并且 (ii) vect_train 用你的语料库的向量实例化。

您建议的save_modelload_model 函数持久化并加载矢量化器,即它已经学习的内部参数,例如词汇表和idfs。加载矢量化器后,获取矢量所需要做的就是用数据转换一个列表。它可以是看不见的数据,也可以是您在fit_transform 期间使用的原始数据。因此,您只需要:

vectorizer = load_model(name)
vect_train = vectorizer.transform(corpus) # (1) or any unseen data

此时,您拥有保存之前的所有内容,但转换调用 (1) 将需要一些时间,具体取决于您的语料库。如果您想跳过这个,您还需要保存vect_train 的内容,正如您在问题中所想的那样。这是一个稀疏矩阵,可以使用 scipy 保存/加载,例如,您可以在 question 中找到信息。复制该问题,以实际保存您还需要的 csr 矩阵:

def save_sparse_csr(filename,array):
    np.savez(filename,data = array.data ,indices=array.indices,
             indptr =array.indptr, shape=array.shape )

def load_sparse_csr(filename):
    loader = np.load(filename)
    return csr_matrix((  loader['data'], loader['indices'], loader['indptr']),
                         shape = loader['shape'])

总之,上述函数可用于保存/加载您的vec_train,而您提供的用于保存/加载转换器以矢量化新数据的函数。

【讨论】:

我会试试这个,希望它能奏效!愚蠢的后续问题:正如我在保存vect_train 时提到的,我得到4 个文件,即tfidf.pkl, tfidf.pkl_01.npy, tfidf.pkl_02.npy, tfidf.pkl_03.npy。加载回来时,我想我应该使用tfidf.pkl,并且每个相关文件也会被加载,或者我应该找到一种方法将它们全部加载到新的矢量化器中?干杯! 只是 tdidf.pkl。当要序列化的数据量大时,拆分成多个文件。 如果还在纠结,下次保存vect_train,tf-idf矩阵,用save_sparse_csr保存为.npz文件。然后使用load_sparse_csr 将其恢复。您仍然可以将保存/加载用于矢量化器。

以上是关于将提取的向量加载到 TfidfVectorizer的主要内容,如果未能解决你的问题,请参考以下文章

scikit-learn 中的 TfidfVectorizer:ValueError:np.nan 是无效文档

使用 Sklearn 的 TfidfVectorizer 变换

了解python scikit-learn中的文本特征提取TfidfVectorizer

在 SVC(kernel='linear') 模型的 tfidfvectorizer 中提取 ngram 的特征重要性

sklearn文本特征提取——TfidfVectorizer

在实践中如何使用 TfidfVectorizer 和元数据进行分类?