基于TF-IDF的关键词提取的实现

一.TF-IDF的简单介绍

TF-IDF(Term Frequency-Inverse Document Frequency)是一种用于信息检索与文本挖掘的常用加权技术,用于评估一个词在文档集合中的重要性。它结合了词频和逆文档频率的概念。

以下是TF-IDF的简单介绍:

词频(TF - Term Frequency):
    表示一个词在文档中出现的频率。通常,词频越高,说明该词在文档中越重要。
    
公式:
	TF(t,d)=词t在文档D中出现的次数 / 文档D中所有词的总数
	
逆文档频率(IDF - Inverse Document Frequency):
    表示一个词在整个文档集合中的普遍程度。如果一个词在很多文档中都出现,它的逆文档频率就较低。

公式:
	IDF(t,D)=log⁡(文档集合D中的文档总数包含词t的文档数+1)
	+1是为了避免分母为零的情况。

TF-IDF加权:
    将词频和逆文档频率结合,得到一个词在文档中的重要性。

公式:
	TF-IDF(t,d,D)=TF(t,d)×IDF(t,D)TF-IDF(t,d,D)=TF(t,d)×IDF(t,D)

TF-IDF的思想是,对于一个词,它在当前文档中的重要性越高(TF越高),并且在整个文档集合中出现越少(IDF越高),其TF-IDF值就越大。因此,TF-IDF能够在文档集合中区分不同词的重要性,用于信息检索、文本分类等任务。TF-IDF(Term Frequency-Inverse Document Frequency)是一种常用的文本特征表示方法,具有一些优点和缺点,以下是它们的简要介绍:

优点:
1.简单直观:TF-IDF的计算过程相对简单,易于理解和实现。不涉及复杂的数学模型,适用于快速的文本处理任务。
2.有效降低常见词重要性:通过逆文档频率的引入,TF-IDF能够有效地降低在整个文档集合中频繁出现的常见词的权重,使得这些词在特征表示中占据较小的比重,更注重区分性较强的词语。
3.适用于短文本:在处理短文本或者特定领域的文本时,TF-IDF能够较好地捕捉关键信息,因为它考虑了词语在文档中的频率和在整个文档集合中的分布。
4.不依赖领域知识:TF-IDF不需要领域专业知识的先验信息,是一种通用的文本特征表示方法,适用于不同领域和主题的文本处理任务。

缺点:
1.忽略语义信息:TF-IDF主要基于词频和文档频率的统计信息,忽略了词语之间的语义关系。在一些文本处理任务中,语义信息可能对模型性能有重要影响,而TF-IDF无法捕捉这种信息。
2.稀疏性问题:由于文本中通常只有少数几个词汇的TF-IDF值较大,导致文本的表示是稀疏的。这可能对某些机器学习算法产生负面影响,特别是在样本量较小的情况下。
3.无法处理词序信息:TF-IDF只关注词汇的出现频率,而没有考虑词汇的顺序。对于某些文本任务,如文本分类、情感分析等,词汇的顺序信息可能是重要的。
4.依赖文档集合:TF-IDF的计算依赖于整个文档集合,如果文档集合变化较大,需要重新计算TF-IDF值。这可能在实时更新的文本数据中存在一定的不便之处。

在实际应用中,根据任务需求和文本特性,选择合适的文本特征表示方法是重要的。在一些场景下,TF-IDF作为一种简单而有效的方法仍然被广泛使用。

二.基于TF-IDF关键词提取的步骤

基于TF-IDF的关键词提取通常包括以下步骤:

1.文本预处理:清洗文本数据,去除无关字符、标点符号、停用词等。进行分词,将文本划分为单独的词语。
2.构建文档-词频矩阵:统计每个文档中每个词的出现次数,构建文档-词频矩阵。这个矩阵表示了文档集合中词语的分布情况。
3.计算词频(TF):计算每个词在每个文档中的词频。通常使用的词频计算方法是将一个词在文档中出现的次数除以文档中所有词的总数。
4.TF(t,d)=词t在文档D中出现的次数/文档D中所有词的总数
5.计算逆文档频率(IDF):计算每个词的逆文档频率。逆文档频率衡量了一个词在整个文档集合中的普遍程度,可以通过以下公式计算:
IDF(t,D)=log⁡(文档集合D中的文档总数包含词t的文档数+1)
+1 是为了避免分母为零的情况。
6.计算TF-IDF值:将词频和逆文档频率相乘,得到TF-IDF值。这一步强调了一个词在当前文档中的重要性,并考虑了它在整个文档集合中的分布情况。
TF-IDF(t,d,D)=TF(t,d)×IDF(t,D)
7.排序和提取关键词:对于每个文档,按照TF-IDF值进行排序,选择排名靠前的词作为关键词。可以根据需求选择提取的关键词数量。

这些步骤是基于TF-IDF的关键词提取的一般流程。在实际应用中,可以根据任务需求和文本特点进行适当的调整。例如,可能需要考虑加入其他的特征、调整逆文档频率的计算方式等。

三.基于TF-IDF关键词提取的代码实现

import math
from collections import Counter

# 示例文本
text = "TF-IDF is a common technique for keyword extraction. It is widely used in natural language processing and information retrieval."

# 分词
def tokenize(text):
    return text.lower().split()

# 计算词频(TF)
def calculate_tf(tokens):
    tf = Counter(tokens)
    total_words = len(tokens)
    tf_normalized = {word: count / total_words for word, count in tf.items()}
    return tf_normalized

# 计算逆文档频率(IDF)
def calculate_idf(documents, term):
    document_count = sum(1 for doc in documents if term in doc)
    idf = math.log(len(documents) / (document_count + 1))
    return idf

# 计算TF-IDF
def calculate_tfidf(tf, idf):
    tfidf = {word: tf[word] * idf[word] for word in tf.keys() & idf.keys()}
    return tfidf

# 获取关键词
def get_keywords(text, documents):
    tokens = tokenize(text)
    tf = calculate_tf(tokens)
    
    idf = {}
    for token in set(tokens):
        idf[token] = calculate_idf(documents, token)
    
    tfidf = calculate_tfidf(tf, idf)
    sorted_tfidf = sorted(tfidf.items(), key=lambda x: x[1], reverse=True)
    keywords = [word[0] for word in sorted_tfidf]
    return keywords

# 示例文档集合
documents = [
    "TF-IDF is a technique used in information retrieval.",
    "Information retrieval is a field of study in natural language processing.",
    "Natural language processing involves the interaction between computers and humans using natural language.",
]

# 获取关键词
keywords = get_keywords(text, documents)
print("Keywords:", keywords)

这个简单的实现包括了分词、计算词频(TF)、计算逆文档频率(IDF)以及计算TF-IDF的步骤。这只是一个基础版本,实际应用中可能需要考虑更多的优化和细节。当然,你可以使用机器学习库函数中的sklearn封装好的算法,直接调用即可,但是个人觉得还是应该自己手动复现一边基本的代码,理解的才会更加深刻。

四.案例分析

综合案例中使用人民网上的新闻数据,该数据集包括558个文件,每个文件的内容均为标题和摘要。
关键词提取综合案例的实现流程如下:
1.将原始数据集处理成result.csv文本、具体包括编号、标题、摘要。
2.获取每行记录的标题和摘要字段,并拼接这两个字段。
3.加载自定义停用词表stopWord.txt,然后拼接的文本进行数据预处理操作,包括分词、去除停用词、空格分割文本等。
4.编写相应的TF-IDF算法提取关键词。
5.将最终结果写入文件并进行保存。

1.数据预处理

# 1.导入工具包
import os
import csv
# 2.文本合并文件
def text_combine(path):
    # 1.获取文件列表
    files = []
    for file in os.listdir(path):
        if file.endswith(".txt"):
            files.append(path + "/" + file)
    # 2.创建text.txt文件,保存结果
    all_text = []
    with open('/home/visionx/mt/learn_pytorch/自然语言处理应用与实战/第3章/3.3.2-关键词提取综合案例/keywords_extracts/data/all.csv', 'w', newline='',encoding='utf-8') as csvfile:
        writera = csv.writer(csvfile)
        writera.writerow(['id', 'title', 'abstract'])

        for file_name in files:
            numbers = (file_name.split('/')[-1]).split('_')[0]
            title, text = '', ''
            count = 0
            # 4.读取标题和内容
            with open(file_name, encoding='UTF-8') as f:
                for line in f:
                    if count == 0:
                        title += line.strip()
                    else:
                        text += line.strip()
                    count += 1
            res = [numbers, title, text]
            all_text.append(res)
        writera.writerows(all_text)
if __name__ == "__main__":
    path = "/home/visionx/mt/learn_pytorch/自然语言处理应用与实战/第3章/3.3.2-关键词提取综合案例/words_extracts/text_file"
    text_combine(path)

2.tf-idf的实现

# coding=utf-8
import codecs
import pandas as pd
import numpy as np
# 导入jieba分词
import jieba.posseg
import jieba.analyse
# 导入文本向量化函数
from sklearn.feature_extraction.text import TfidfTransformer
# 导入词频统计函数
from sklearn.feature_extraction.text import CountVectorizer
# 读取text.csv文件:分词,去停用词,词性筛选
def data_read(text, stopkey):
    l = []
    pos = ['n', 'nz', 'v', 'vd', 'vn', 'l', 'a', 'd']  # 定义选取的词性
    seg = jieba.posseg.cut(text)  # 分词
    for i in seg:
        if i.word not in stopkey and i.flag in pos:  # 去停用词 + 词性筛选
            l.append(i.word)
    return l
# tf-idf获取文本top10关键词
def words_tfidf(data, stopkey, topK):
    idList, titleList, abstractList = \
        data['id'], data['title'], data['abstract']
    corpus = []  # 将所有文档输出到一个list中,一行就是一个文档
    for index in range(len(idList)):
        # 拼接标题和摘要
        text = '%s。%s' % (titleList[index], abstractList[index])
        text = data_read(text, stopkey)  # 文本预处理
        text = " ".join(text)  # 连接成字符串,空格分隔
        corpus.append(text)
    # 1、构建词频矩阵,将文本中的词语转换成词频矩阵
    vectorizer = CountVectorizer()
    # 词频矩阵,a[i][j]:表示j词在第i个文本中的词频
    X = vectorizer.fit_transform(corpus)
    # 2、统计每个词的tf-idf权值
    transformer = TfidfTransformer()
    tfidf = transformer.fit_transform(X)
    # 3、获取词袋模型中的关键词
    word = vectorizer.get_feature_names()
    # 4、获取tf-idf矩阵,a[i][j]表示j词在i篇文本中的tf-idf权重
    weight = tfidf.toarray()
    # 5、打印词语权重
    ids, titles, keys = [], [], []
    for i in range(len(weight)):
        print(u"-------这里输出第", i + 1, u"篇文本的词语tf-idf------")
        ids.append(idList[i])
        titles.append(titleList[i])
        df_word, df_weight = [], []  # 当前文章的所有词汇列表、词汇对应权重列表
        for j in range(len(word)):
            print(word[j], weight[i][j])
            df_word.append(word[j])
            df_weight.append(weight[i][j])
        df_word = pd.DataFrame(df_word, columns=['word'])
        df_weight = pd.DataFrame(df_weight, columns=['weight'])
        word_weight = pd.concat([df_word, df_weight], axis=1)  # 拼接词汇列表和权重列表
        word_weight = word_weight.sort_values(by="weight", ascending=False)  # 按照权重值降序排列
        keyword = np.array(word_weight['word'])  # 选择词汇列并转成数组格式
        word_split = [keyword[x] for x in range(0, topK)]  # 抽取前topK个词汇作为关键词
        word_split = " ".join(word_split)
        keys.append(word_split.encode("utf-8").decode("utf-8"))
    result = pd.DataFrame({"id": ids, "title": titles, "key": keys},
                          columns=['id', 'title', 'key'])
    return result
if __name__ == '__main__':
    # 读取数据集
    dataFile = 'data/text.csv'
    data = pd.read_csv(dataFile)
    # 停用词表
    stopkey = [w.strip() for w in codecs.open('data/stopWord.txt', 'r', encoding="utf-8").readlines()]
    # tf-idf关键词抽取
    result = words_tfidf(data, stopkey, 10)
    result.to_csv("result/tfidf.csv", index=False)



你可能感兴趣的:(自然语言处理,tf-idf,python,人工智能)