我想编写一个使用字典来获取tf:idf(比例?)的脚本。
我们的想法是让脚本使用os.walk查找目录及其子目录中的所有.txt文件:
files = []
for root, dirnames, filenames in os.walk(directory):
for filename in fnmatch.filter(filenames, '*.txt'):
files.append(os.path.join(root, filename))
然后使用该列表查找所有单词以及它们出现的次数:
def word_sort(filename3):
with open(filename3) as f3:
passage = f3.read()
stop_words = "THE OF A TO AND IS IN YOU THAT IT THIS YOUR AS AN BUT FOR".split()
words = re.findall(r'\w+', passage)
cap_words = [word.upper() for word in words if word.upper() not in stop_words]
word_sort = Counter(cap_words)
return word_sort
term_freq_per_file = {}
for file in files:
term_freq_per_file[file] = (word_sort(file))
最终会出现如下字典:
'/home/seb/Learning/ex15_sample.txt': Counter({'LOTS': 2, 'STUFF': 2, 'HAVE': 1,
'I': 1, 'TYPED': 1, 'INTO': 1, 'HERE': 1,
'FILE': 1, 'FUN': 1, 'COOL': 1,'REALLY': 1}),
在我看来,这给了我每个文件的单词频率。
如何找到实际的tf?
我怎么能找到idf?
我指的是术语频率,它是一个单词(术语)出现在文档中的次数
TF(t)=(术语t出现在文档中的次数)/(文档中的术语总数)。
而idf我的意思是逆文档频率,其中文档频率是单词出现的文档数量
IDF(t)= log_e(文件总数/含有期限t的文件数量)。
为了澄清,我的问题是如何提取这些值并将它们放入公式中,我知道它们在那里,但我不知道如何撤回它们并进一步使用它们。
我决定制作另一个字典,其中包含使用该字的文件,如下所示:
{word : (file1, file2, file3)}
通过这样迭代第一个字典:
for file in tfDic:
word = tfDic[file][Counter]
for word in tfDic:
if word not in dfDic.keys():
dfDic.setdefault(word,[]).append(file)
if word in dfDic.keys():
dfDic[word].append(file)
问题在于这一行:
word = tfDic[file][Counter]
我认为它会“导航”到单词,但是我注意到单词是计数器字典中的键,它是tfDic(文件)的值。
我的问题是,如何告诉它迭代单词('Counter'字典的键)?
答案 0 :(得分:0)
如果您想坚持使用当前的数据结构,则必须深入研究每个单词的每个文件的整个结构,以便计算其idf
。
# assume the term you are looking for is in the variable term
df = 0
for file in files:
if term in term_freq_per_file[file]:
df += 1
idf = math.log(len(files)/df)
此答案的早期版本包含替代数据结构的草图,但这可能已经足够了。
答案 1 :(得分:0)
(最终)
我决定回去改变我的字数公式,以便代替:
word_sort = Counter(cap_words)
我已经遍历列表中的单词,并根据它们出现的次数创建了自己的字典:
word_sort = {}
for term in cap_words:
word_sort[term] = cap_words.count(term)
所以我不是每次都有一个子字典(Counter),而是以tfDic结束这个:
'/home/seb/Learning/ex17output.txt': {'COOL': 1,
'FILE': 1,
'FUN': 1,
'HAVE': 1,
'HERE': 1,
'I': 1,
'INTO': 1,
'LOTS': 2,
'REALLY': 1,
'STUFF': 2,
'TYPED': 1},
然后我遍历tfDic [file]的键来创建另一个Dictionary,其中包含已使用给定单词的文件中的信息:
for file in tfDic:
word = tfDic[file].keys()
for word in tfDic[file]:
if word not in dfDic.keys():
dfDic.setdefault(word,[]).append(file)
if word in dfDic.keys():
dfDic[word].append(file)
,最终结果如下:
'HERE': ['/home/seb/Learning/ex15_sample.txt',
'/home/seb/Learning/ex15_sample.txt',
'/home/seb/Learning/ex17output.txt'],
现在我计划提取'价值并将它们放入我之前提到的公式中。
答案 2 :(得分:0)
除非这是关于tf-idf如何运作的学习练习,否则我建议使用内置的scikit-learn类来完成此任务。
首先,为每个文件创建一个计数字典数组。然后将计数字典数组输入DictVectorizer,然后将输出稀疏矩阵输入TfidfTransformer
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
dv = DictVectorizer()
D = [{'foo': 1, 'bar': 2}, {'foo': 3, 'baz': 1}]
X = dv.fit_transform(D)
tv = TfidfTransformer()
tfidf = tv.fit_transform(X)
print(tfidf.to_array())