TF-IDF和TextRank算法可以结合使用来提高关键词提取的准确性和完整性。

一、实现步骤

具体来说,可以按照以下步骤进行:

  1. 用TF-IDF算法提取文本中的关键词,并根据词频和文本频率计算每个词的TF-IDF值。
  2. 使用TextRank算法对文本中的关键词进行排序,将得分最高的词作为关键词。
  3. 将TF-IDF值和TextRank得分相结合,例如可以计算两个得分的平均值,以此作为关键词的权重。
  4. 根据权重对关键词进行排序,得到最终的关键词列表。

需要注意的是,TF-IDF算法和TextRank算法的权重值范围不同,需要进行归一化处理。此外,对于一些过于常见或者过于稀有的词汇,可以进行过滤或者加权处理,以避免对结果产生过大或过小的影响。

二、怎样进行归一化处理

归一化处理是将不同量级的数值统一到相同的范围内,以便于综合比较。

在TF-IDF算法和TextRank算法结合时,可以使用以下方法进行归一化处理:

1、对TF-IDF值进行归一化处理,

可以使用线性缩放方法,将TF-IDF值映射到[0,1]的范围内。

具体而言,可以使用以下公式进行归一化处理:

TF-IDF_normalized = (TF-IDF - min_TF-IDF) / (max_TF-IDF - min_TF-IDF)

其中,min_TF-IDF和max_TF-IDF分别为文本中所有词的TF-IDF值的最小值和最大值。

2. 对TextRank得分进行归一化处理,

可以使用softmax方法,将TextRank得分映射到[0,1]的范围内。

具体而言,可以使用以下公式进行归一化处理:

TextRank_normalized = exp(TextRank) / sum(exp(TextRank))

其中,TextRank是TextRank算法计算出的得分,sum(exp(TextRank))是所有关键词得分的指数和。

3. 对TF-IDF值和TextRank得分进行加权和,

可以使用以下公式计算关键词的综合得分:

Score = TF-IDF_weight * TF-IDF_normalized + TextRank_weight * TextRank_normalized

其中,TF-IDF_weight和TextRank_weight分别是TF-IDF和TextRank的权重值,可以根据实际情况进行调整。

通过归一化处理,可以将不同算法得到的权重值映射到相同的范围内,从而方便进行综合排序。

三、归一化处理的示例代码-使用python实现

在Python中,实现TF-IDF算法和TextRank算法可以使用第三方库,例如:

TF-IDF算法:可以使用scikit-learn库中的TfidfVectorizer类或者gensim库中的TfidfModel类来计算TF-IDF值;
TextRank算法:可以使用gensim库中的summarization模块的textrank函数来实现。

归一化处理可以使用scikit-learn库中的MinMaxScaler类,它可以对数据进行最大最小值缩放,将数据限制在0和1之间。

import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from gensim.summarization import keywords as textrank_keywords
from sklearn.preprocessing import MinMaxScaler
 
# 示例文本
text = "中国足球队在世界杯预选赛中战胜了日本队,这是中国足球历史上的一次伟大胜利。"
 
# 计算TF-IDF值
vectorizer = TfidfVectorizer()
tfidf = vectorizer.fit_transform([text])
feature_names = vectorizer.get_feature_names()
 
# 使用TextRank算法提取关键词
tr_keywords = textrank_keywords(text, split=True)
 
# 合并关键词
keywords = set(feature_names + tr_keywords)
 
# 构建关键词向量
keyword_vectors = np.zeros((len(keywords), len(feature_names)))
for i, keyword in enumerate(keywords):
    if keyword in feature_names:
        keyword_vectors[i, feature_names.index(keyword)] = tfidf[0, feature_names.index(keyword)]
    if keyword in tr_keywords:
        keyword_vectors[i, feature_names.index(keyword)] = 1.0
 
# 归一化处理
scaler = MinMaxScaler()
normalized_vectors = scaler.fit_transform(keyword_vectors)
 
# 输出关键词和对应的向量
for i, keyword in enumerate(keywords):
    print(keyword, normalized_vectors[i])

该代码中首先使用TF-IDF算法计算文本的TF-IDF值,并使用TextRank算法提取关键词。然后,将两种算法提取出来的关键词合并,并构建关键词向量。最后,使用MinMaxScaler类对关键词向量进行归一化处理,并输出关键词和对应的向量。

四、过滤或者加权处理过于常见或稀有的词汇

对于过于常见的词汇(如停用词)和过于稀有的词汇(如低频词),在关键词提取过程中需要进行过滤或加权处理,以提高关键词提取的准确度。以下是一些常见的方法:

1、停用词过滤:

停用词是指在文本中出现频率非常高但在语义上无实际意义的词汇,如“的”、“是”、“在”等。可以将这些停用词从文本中删除,以减小干扰。在Python中,可以使用NLTK库提供的停用词列表进行过滤。

2. 低频词过滤:

对于出现频率较低的词汇,可以将其过滤掉或进行加权处理。可以根据词频或者TF-IDF值来设定阈值,将低频词过滤掉,或者对其进行加权处理,以提高关键词提取的准确度。

3. 关键词加权:

在TextRank等算法中,可以通过对关键词进行加权来提高其重要性。例如,可以根据词性、词频、词义等因素对关键词进行加权处理。

在Python中,可以使用NLTK、Scikit-learn、gensim等库进行停用词过滤、低频词过滤和关键词加权等处理。例如,可以使用NLTK库提供的stopwords列表进行停用词过滤,使用Scikit-learn库中的CountVectorizer或TfidfVectorizer来计算词频或TF-IDF值,使用gensim库中的Word2Vec或FastText来计算词向量并对关键词进行加权处理。

五、过滤或者加权处理过于常见或稀有的词汇的示例代码-使用python实现

(1)过于常见的词汇使用停用词表进行过滤

在Python中,对于过于常见的词汇可以使用停用词表进行过滤。一些常用的中文停用词表如中科院计算所停用词表、哈工大停用词表等,可以在GitHub等网站上进行下载。

1、以中科院计算所停用词表为例

import jieba
# 加载停用词表
stopwords = [line.strip() for line in open('stopwords.txt', 'r', encoding='utf-8').readlines()]
 
# 读取中科院计算所停用词表 使用 codecs 模块打开中科院计算所停用词表文件
# import codecs
# with codecs.open('cn_stopwords.txt', 'r', encoding='utf-8') as f:
#     stopwords = [line.strip() for line in f]
 
 
# 进行分词并过滤停用词
text = "体育新闻内容……"
words = jieba.lcut(text)
# words = jieba.cut(text)
words_filtered = [word for word in words if word not in stopwords]
print(words_filtered)

2、以哈工大停用词表为例

在这个示例中,我们首先读入了停用词表,并将停用词保存在一个Python的集合(set)中。然后,我们使用jieba库进行分词,得到分词后的结果。最后,我们遍历分词结果,将不在停用词表中的词加入到一个列表中。最终,我们打印出了过滤停用词后的词列表。

import jieba
 
# 读入停用词表
stopwords = set()
with open('stopwords.txt', 'r', encoding='utf-8') as f:
    for line in f:
        stopwords.add(line.strip())
 
# 进行分词
text = "我喜欢打篮球,不喜欢踢足球。"
words = jieba.cut(text)
 
# 过滤停用词
filtered_words = []
for word in words:
    if word not in stopwords:
        filtered_words.append(word)
 
print(filtered_words)

(2)过于稀有的词汇使用基于词频的加权方法进行处理

对于过于稀有的词汇,可以考虑使用基于词频的加权方法进行处理。该方法主要是通过给予稀有词汇更高的权重来强化它们在关键词提取中的重要性。比如设定一个词汇出现频率的阈值,将频率低于该阈值的词汇进行加权处理。

1、以TF-IDF算法为例①

对于每个词汇,计算它在文本中出现的频率f(w),即该词汇在文本中出现的次数除以文本总词数。
对于每个词汇,计算它的权重weight(w),可以使用如下公式: weight(w) = a / (a + f(w)) 其中,a为平滑参数,一般取值为1。
对于每个文本,将其中所有词汇的权重相加,得到该文本的权重总和。
对于每个词汇,将它在所有文本中的权重总和作为该词汇的最终权重。

通过这种方法,可以有效地提高稀有词汇在关键词提取中的权重,使其更容易成为关键词。

下面是一个基于词频加权的关键词提取的Python示例代码:

import jieba
import math
from collections import defaultdict
 
def get_keywords(text, topK=10, withWeight=False):
    # 加载停用词表
    stop_words = set()
    with open('stopwords.txt', 'r', encoding='utf-8') as f:
        for line in f:
            stop_words.add(line.strip())
 
    # 分词
    words = [w for w in jieba.cut(text) if w not in stop_words]
 
    # 统计词频
    freq = defaultdict(int)
    for w in words:
        freq[w] += 1
 
    # 计算权重
    a = 1
    weights = {}
    for w in freq:
        weights[w] = a / (a + freq[w] / len(words))
 
    # 计算文本权重
    total_weight = sum(weights.values())
 
    # 计算词汇最终权重
    max_weight = {}
    for w in weights:
        max_weight[w] = weights[w] * total_weight
 
    # 按最终权重排序
    keywords = sorted(max_weight.items(), key=lambda x: x[1], reverse=True)
 
    if withWeight:
        return keywords[:topK]
    else:
        return [w[0] for w in keywords[:topK]]

在这个示例中,我们首先加载了一个停用词表,并使用结巴分词库对输入的文本进行分词。然后,我们计算了每个词汇在文本中出现的频率,并使用基于词频的加权方法计算了每个词汇的权重。接着,我们计算了文本的权重总和以及每个词汇在所有文本中的权重总和,并按照最终权重进行排序,最后返回前topK个关键词。

2、以TF-IDF算法为例②

以TF-IDF算法为例,在计算TF-IDF权重时,可以将低频词汇的TF值进行加权,如将TF值乘以一个小于1的系数,使得低频词汇的权重相对于高频词汇更小。

在TF-IDF算法中,我们可以使用一个TF-IDF加权公式来进行加权处理。假设某个词汇在文档中出现的次数为tf,它在整个语料库中出现的文档频率(即含有该词汇的文档数)为df,则该词汇的TF-IDF权重为tf-idf = tf * log(N/df),其中N为语料库的文档总数。

对于过于稀有的词汇,可以通过将其出现次数进行加权来调整其TF值,使其权重适当提高。比如,可以设置一个阈值,只对出现次数超过该阈值的词汇进行加权处理。

以下是一个基于TF-IDF算法加权的python代码示例:

import jieba.analyse
 
# 原始文本
text = "这是一篇体育新闻,介绍了一场精彩的足球比赛。"
 
# 加载停用词表
stopwords_path = "stopwords.txt"
stopwords = [line.strip() for line in open(stopwords_path, "r", encoding="utf-8").readlines()]
 
# 分词并去除停用词
words = jieba.cut(text)
words = [word for word in words if word not in stopwords]
 
# 计算词频
word_freq = {}
for word in words:
    if word not in word_freq:
        word_freq[word] = 1
    else:
        word_freq[word] += 1
 
# 计算TF-IDF权重
total_docs = 1000 # 假设语料库共有1000篇文档
for word in word_freq:
    tf = word_freq[word]
    df = get_df(word) # 获取文档频率,即包含该词汇的文档数
    idf = log(total_docs / df)
    tf_idf = tf * idf
    if tf < threshold: # 对出现次数过少的词汇进行加权
        tf_idf *= 2 # 将权重乘以2
    word_freq[word] = tf_idf
 
# 按权重排序并输出
sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)
for word, weight in sorted_words:
    print(word, weight)

在代码中,我们使用了jieba库进行分词,并加载了一个停用词表进行去除停用词的操作。然后,我们统计了每个词汇在文本中出现的次数,并计算了它们的TF-IDF权重。对于出现次数过少的词汇,我们将其权重乘以2以进行加权处理。最后,我们将关键词按照权重进行排序并输出。