计算文本中单个单词的TDIDF

2024-10-02 00:33:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用Textacy来计算标准语料库中单个单词的TF-IDF分数,但是我对得到的结果有点不清楚。在

我希望有一个单独的浮点数来表示这个词在语料库中的出现频率。为什么我会收到一份名单共7个结果?在

“accler”实际上是一个法语单词,所以我们期望从英语语料库中得到0。在

word = 'acculer'
vectorizer = textacy.Vectorizer(tf_type='linear', apply_idf=True, idf_type='smooth')
tf_idf = vectorizer.fit_transform(word)
logger.info("tf_idf:")
logger.info(tfidf)

输出

^{pr2}$

问题的第二部分是如何为文本学中的TF-IDF功能提供自己的语料库,特别是在另一种语言中的功能?在

编辑

如@Vishal所述,我使用以下行记录输出:

logger.info(vectorizer.vocabulary_terms)

提供的单词acculer似乎已被拆分为字符。在

{'a': 0, 'c': 1, 'u': 5, 'l': 3, 'e': 2, 'r': 4}

(1)如何根据语料库(而不是每个字符)获取该单词的TF-IDF?在

(2)如何提供自己的语料库并将其作为param指向?在

(3)TF-IDF能否用于句子层面?这个句子中的术语相对于语料库的相对频率是多少。在


Tags: 功能infotftypelogger字符单词word
2条回答

你可以用TF-IDF来查语料库。在

docs = ['this is me','this was not that you thought', 'lets test them'] ## create a list of documents
from sklearn.feature_extraction.text import TfidfVectorizer

vec = TfidfVectorizer()
vec.fit(docs) ##fit your documents

print(vec.vocabulary_) #print vocabulary, don't run for 2.5 million documents

Output:包含每个单词的idf,并在输出中为其分配一个唯一的索引

^{pr2}$

输出:打印每个词汇表单词的idf值

[ 1.69314718  1.69314718  1.69314718  1.69314718  1.69314718  1.69314718 1.69314718  1.28768207  1.69314718  1.69314718  1.69314718]

现在根据你的问题,假设你想找tf-idf,那么你可以得到:

word = 'thought' #example    
index = vec.vocabulary_[word] 
>8
print(vec.idf_[index]) #prints idf value
>1.6931471805599454

参考文献: 1prepare-text

现在对文本进行同样的操作

import spacy
nlp = spacy.load('en') ## install it by python -m spacy download en (run as administrator)

doc_strings = [
    'this is me','this was not that you thought', 'lets test them'
]
docs = [nlp(string.lower()) for string in doc_strings]
corpus = textacy.Corpus(nlp,docs =docs)
vectorizer = textacy.Vectorizer(tf_type='linear', apply_idf=True, idf_type='smooth')
doc_term_matrix = vectorizer.fit_transform((doc.to_terms_list(ngrams=1, normalize='lower',as_strings=True,filter_stops=False) for doc in corpus))

print(vectorizer.terms_list)
print(doc_term_matrix.toarray())

输出

['is', 'lets', 'me', 'not', 'test', 'that', 'them', 'this', 'thought','was', 'you']


[[1.69314718 0.         1.69314718 0.         0.         0.
  0.         1.28768207 0.         0.         0.        ]
 [0.         0.         0.         1.69314718 0.         1.69314718
  0.         1.28768207 1.69314718 1.69314718 1.69314718]
 [0.         1.69314718 0.         0.         1.69314718 0.
  1.69314718 0.         0.         0.         0.        ]]

参考号:link

基本原理

在研究实际问题之前,让我们先弄清楚定义。在

假设我们的语料库包含3个文档(分别是d1、d2和d3):

corpus = ["this is a red apple", "this is a green apple", "this is a cat"]

术语频率(tf)

tf(单词的)定义为单词在文档中出现的次数。在

^{pr2}$

tf是在文档级别为单词定义的。在

tf('a',d1)     = 1      tf('a',d2)     = 1      tf('a',d3)     = 1
tf('apple',d1) = 1      tf('apple',d2) = 1      tf('apple',d3) = 0
tf('cat',d1)   = 0      tf('cat',d2)   = 0      tf('cat',d3)   = 1
tf('green',d1) = 0      tf('green',d2) = 1      tf('green',d3) = 0
tf('is',d1)    = 1      tf('is',d2)    = 1      tf('is',d3)    = 1
tf('red',d1)   = 1      tf('red',d2)   = 0      tf('red',d3)   = 0
tf('this',d1)  = 1      tf('this',d2)  = 1      tf('this',d3)  = 1

使用原始计数有一个问题:与较短的文档相比,较长文档中单词的tf值具有较高的值。这个问题可以通过将原始计数值除以文档长度(相应文档中的字数)来规范化来解决。这称为l1规范化。文档d1现在可以用tf vector来表示,其中包含语料库中所有单词的所有tf值。还有一种称为l2的规范化方法,它使文档的tf向量的l2范数等于1。在

tf(word, document, normalize='l1') = count(word, document)/|document|
tf(word, document, normalize='l2') = count(word, document)/l2_norm(document)
|d1| = 5, |d2| = 5, |d3| = 4
l2_norm(d1) = 0.447, l2_norm(d2) = 0.447, l2_norm(d3) = 0.5, 

代码:tf

corpus = ["this is a red apple", "this is a green apple", "this is a cat"]
# Convert docs to textacy format
textacy_docs = [textacy.Doc(doc) for doc in corpus]

for norm in [None, 'l1', 'l2']:
    # tokenize the documents
    tokenized_docs = [
    doc.to_terms_list(ngrams=1, named_entities=True, as_strings=True, filter_stops=False, normalize='lower')
    for doc in textacy_docs]

    # Fit the tf matrix 
    vectorizer = textacy.Vectorizer(apply_idf=False, norm=norm)
    doc_term_matrix = vectorizer.fit_transform(tokenized_docs)

    print ("\nVocabulary: ", vectorizer.vocabulary_terms)
    print ("TF with {0} normalize".format(norm))
    print (doc_term_matrix.toarray())

输出:

Vocabulary:  {'this': 6, 'is': 4, 'a': 0, 'red': 5, 'apple': 1, 'green': 3, 'cat': 2}
TF with None normalize
[[1 1 0 0 1 1 1]
 [1 1 0 1 1 0 1]
 [1 0 1 0 1 0 1]]

Vocabulary:  {'this': 6, 'is': 4, 'a': 0, 'red': 5, 'apple': 1, 'green': 3, 'cat': 2}
TF with l1 normalize
[[0.2  0.2  0.   0.   0.2  0.2  0.2 ]
 [0.2  0.2  0.   0.2  0.2  0.   0.2 ]
 [0.25 0.   0.25 0.   0.25 0.   0.25]]

Vocabulary:  {'this': 6, 'is': 4, 'a': 0, 'red': 5, 'apple': 1, 'green': 3, 'cat': 2}
TF with l2 normalize
[[0.4472136 0.4472136 0.        0.        0.4472136 0.4472136 0.4472136]
 [0.4472136 0.4472136 0.        0.4472136 0.4472136 0.        0.4472136]
 [0.5       0.        0.5       0.        0.5       0.        0.5      ]]

tf矩阵中的行对应于文档(因此我们的语料库有3行),列对应于词汇表中的每个单词(词汇词典中显示的单词索引)

反向文件频率(idf)

有些词传达的信息比其他词少。例如像,a,an,this这样的词是非常常见的,它们传达的信息非常少。国防军是衡量这个词重要性的尺度。我们认为出现在许多文档中的单词比出现在少数文档中的单词信息量少。在

idf(word, corpus) = log(|corpus| / No:of documents containing word) + 1  # standard idf

对于我们的语料库来说idf(apple, corpus) < idf(cat,corpus)

idf('apple', corpus) = log(3/2) + 1 = 1.405 
idf('cat', corpus) = log(3/1) + 1 = 2.098
idf('this', corpus) = log(3/3) + 1 = 1.0

代码:idf

textacy_docs = [textacy.Doc(doc) for doc in corpus]    
tokenized_docs = [
    doc.to_terms_list(ngrams=1, named_entities=True, as_strings=True, filter_stops=False, normalize='lower')
    for doc in textacy_docs]

vectorizer = textacy.Vectorizer(apply_idf=False, norm=None)
doc_term_matrix = vectorizer.fit_transform(tokenized_docs)

print ("\nVocabulary: ", vectorizer.vocabulary_terms)
print ("standard idf: ")
print (textacy.vsm.matrix_utils.get_inverse_doc_freqs(doc_term_matrix, type_='standard'))

输出:

Vocabulary:  {'this': 6, 'is': 4, 'a': 0, 'red': 5, 'apple': 1, 'green': 3, 'cat': 2}
standard idf: 
[1.     1.405       2.098       2.098       1.      2.098       1.]

术语频率-反向文档频率(tf-idf):tf-idf是一个衡量词在语料库中文档中的重要性的指标。单词的tf和它的id加权得到单词的tf-idf度量。在

tf-idf(word, document, corpus) = tf(word, docuemnt) * idf(word, corpus)
tf-idf('apple', 'd1', corpus) = tf('apple', 'd1') * idf('apple', corpus) = 1 * 1.405 = 1.405
tf-idf('cat', 'd3', corpus) = tf('cat', 'd3') * idf('cat', corpus) = 1 * 2.098 = 2.098

代码:tf idf

textacy_docs = [textacy.Doc(doc) for doc in corpus]

tokenized_docs = [
    doc.to_terms_list(ngrams=1, named_entities=True, as_strings=True, filter_stops=False, normalize='lower')
    for doc in textacy_docs]

print ("\nVocabulary: ", vectorizer.vocabulary_terms)
print ("tf-idf: ")

vectorizer = textacy.Vectorizer(apply_idf=True, norm=None, idf_type='standard')
doc_term_matrix = vectorizer.fit_transform(tokenized_docs)
print (doc_term_matrix.toarray())

输出:

Vocabulary:  {'this': 6, 'is': 4, 'a': 0, 'red': 5, 'apple': 1, 'green': 3, 'cat': 2}
tf-idf: 
[[1.         1.405   0.         0.         1.         2.098   1.        ]
 [1.         1.405   0.         2.098      1.         0.      1.        ]
 [1.         0.      2.098      0.         1.         0.      1.        ]]

现在来回答问题:

(1) How can I get the TF-IDF for this word against the corpus, rather than each character?

如上所述,没有独立定义的tf-idf,单词的tf-idf与语料库中的文档有关。在

(2) How can I provide my own corpus and point to it as a param?

如上述样品所示。在

  1. 使用将文本文档转换为文本文档文本文档美国石油学会
  2. Tokenzie公司文本文档正在使用tou-terms\u-list方法。(使用此方法,您可以使用在词汇表中添加unigram、bigram或trigram,过滤掉stop words sm noramalize text等)
  3. 使用文本。矢量器从标记化的文档创建术语矩阵。返回的矩阵项是
    • tf (raw counts): apply_idf=False, norm=None
    • tf (l1 normalized): apply_idf=False, norm='l1'
    • tf (l2 normalized): apply_idf=False, norm='l2'
    • tf-idf (standard): apply_idf=True, idf_type='standard'

(3) Can TF-IDF be used at a sentence level? ie: what is the relative frequency of this sentence's terms against the corpus.

是的,你可以,如果而且只有当你把每句话都当作一个单独的文件。在这种情况下,对应文档的tf-idf向量(整行)可以被视为文档的向量表示(在您的例子中是一个句子)。在

对于我们的语料库(事实上每个文档包含一个句子),d1和d2的向量表示应该与向量d1和d3更接近。让我们检查余弦相似度,看看:

cosine_similarity(doc_term_matrix)

输出

array([[1.        ,     0.53044716,     0.35999211],
       [0.53044716,     1.        ,     0.35999211],
       [0.35999211,     0.35999211,     1.        ]])

如你所见,余弦相似性(d1,d2)=0.53,余弦相似性(d1,d3)=0.35,因此d1和d2确实比d1和d3更相似(1表示完全相似,0表示不相似-正交向量)。在

一旦你训练了你的Vectorizer,你就可以把训练过的对象保存到磁盘上以备以后使用。在

结论

单词的tf位于文档级别,idf位于语料库级别,单词的{}相对于语料库位于文档级别。它们非常适合于文档(或者当文档由一句话)。如果您对单词的向量表示感兴趣,那么可以探索单词嵌入,比如(word2vec、fasttext、glow等)。在

相关问题 更多 >

    热门问题