自然语言处理容易混淆知识点(一)c-TF-IDF和TF-IDF的区别

c-TF-IDF 和 TF-IDF

    • [什么是 c-TF-IDF?](#什么是 c-TF-IDF?)
      • [传统 TF-IDF](#传统 TF-IDF)
      • [c-TF-IDF(基于类的 TF-IDF)](#c-TF-IDF(基于类的 TF-IDF))
    • [c-TF-IDF 的计算公式](#c-TF-IDF 的计算公式)
    • 直观理解
    • [在 BERTopic 中的工作流程](#在 BERTopic 中的工作流程)
    • [代码示例:使用 c-TF-IDF](#代码示例:使用 c-TF-IDF)
    • [与传统 TF-IDF 对比](#与传统 TF-IDF 对比)
    • [c-TF-IDF 的优势](#c-TF-IDF 的优势)
    • [自定义 c-TF-IDF 参数](#自定义 c-TF-IDF 参数)
    • [可视化 c-TF-IDF 权重](#可视化 c-TF-IDF 权重)
    • 总结

BERTopic 中一个 非常核心的概念 ------ c-TF-IDF (class-based TF-IDF)。这是 BERTopic 区别于其他主题模型的关键创新点。

什么是 c-TF-IDF?

传统 TF-IDF

  • TF(词频):一个词在单个文档中出现的频率
  • IDF(逆文档频率):衡量一个词在所有文档中的普遍性
  • 应用对象:单个文档

c-TF-IDF(基于类的 TF-IDF)

  • 每个主题视为一个"文档类"
  • 计算时:一个主题(类) vs 所有其他主题(类)
  • 应用对象:整个主题/类别

c-TF-IDF 的计算公式

复制代码
c-TF-IDF(w, c) = tf(w, c) × log(1 + N / df(w))
  • tf(w, c):词 w 在主题 c 的所有文档中出现的总次数
  • N:主题总数
  • df(w):包含词 w 的主题数量

词出现在越少的文档中,其 IDF 值越大,对区分文档的贡献越大。

直观理解

假设我们有 3 个主题:科技、体育、政治

科技主题 体育主题 政治主题 是否适合做主题词
"算法" 高频 几乎无 偶尔出现 ✅ 优秀(区分度高)
"比赛" 低频 高频 低频 ✅ 优秀
"政策" 低频 低频 高频 ✅ 优秀
"非常" 中频 中频 高频 ❌ 差(普遍性高)
"重要" 高频 高频 高频 ❌ 差(无区分度)

在 BERTopic 中的工作流程

python 复制代码
from bertopic import BERTopic
from bertopic.vectorizers import ClassTfidfTransformer

# 1. 文档聚类(使用嵌入和聚类算法)
# docs → 文档嵌入 → 聚类 → 得到主题标签

# 2. 为每个主题创建词袋表示
# 同一主题的所有文档合并 → 统计词频

# 3. 应用 c-TF-IDF
ctfidf_model = ClassTfidfTransformer(
    reduce_frequent_words=True,  # 降低过于频繁的词的权重
    bm25_weighting=True,         # 使用 BM25 风格的权重(可选)
)

# 4. 得到每个主题的 top N 关键词
topic_keywords = ctfidf_model.transform(topic_word_frequencies)

代码示例:使用 c-TF-IDF

python 复制代码
from bertopic import BERTopic
from bertopic.vectorizers import ClassTfidfTransformer
import numpy as np

# 示例文档
docs = [
    "机器学习算法需要大量数据",
    "深度学习是机器学习的一个分支",
    "篮球比赛需要团队合作",
    "足球运动员需要良好的体能",
    "政府发布了新的经济政策",
    "外交关系对国家发展很重要"
]

# 1. 创建 BERTopic 模型,自定义 c-TF-IDF 参数
ctfidf_model = ClassTfidfTransformer(
    bm25_weighting=True,        # 使用 BM25 而非传统 TF-IDF
    reduce_frequent_words=True, # 降低常见词的权重
    diversity=0.5               # 增加多样性(可选)
)

topic_model = BERTopic(
    ctfidf_model=ctfidf_model,  # 使用自定义的 c-TF-IDF
    min_topic_size=2,           # 每个主题最少文档数
    verbose=True
)

# 2. 训练模型
topics, probabilities = topic_model.fit_transform(docs)

# 3. 查看主题关键词(基于 c-TF-IDF 排序)
print("主题和关键词:")
for topic_num in set(topics):
    if topic_num != -1:  # 跳过异常值(-1 表示未聚类)
        topic_info = topic_model.get_topic(topic_num)
        print(f"\n主题 {topic_num}:")
        for word, score in topic_info[:5]:  # 前5个关键词
            print(f"  {word}: {score:.4f}")

# 4. 查看 c-TF-IDF 矩阵
print("\n=== c-TF-IDF 矩阵形状 ===")
if hasattr(topic_model, 'c_tf_idf_'):
    print(f"矩阵形状: {topic_model.c_tf_idf_.shape}")
    print(f"(主题数 × 词汇表大小)")

与传统 TF-IDF 对比

python 复制代码
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd

# 传统 TF-IDF(文档级别)
vectorizer = TfidfVectorizer()
X_tfidf = vectorizer.fit_transform(docs)
print("传统 TF-IDF 矩阵形状:", X_tfidf.shape)  # (6个文档 × 词汇表大小)

# c-TF-IDF(主题级别)
# 假设我们已经有主题标签:[0, 0, 1, 1, 2, 2]
# BERTopic 内部会合并同一主题的文档
# 得到矩阵形状: (3个主题 × 词汇表大小)

c-TF-IDF 的优势

  1. 主题导向:为整个主题选择最具代表性的词
  2. 去噪能力:自动降低常见词(如"的"、"是")和停用词的权重
  3. 可解释性:每个主题的关键词都是基于统计的,容易理解
  4. 效率高:只在主题级别计算,而非文档级别

自定义 c-TF-IDF 参数

python 复制代码
from bertopic.vectorizers import ClassTfidfTransformer

# 配置选项
ctfidf_config = {
    # BM25 参数
    "bm25_weighting": True,      # 使用 BM25(更好的长文档处理)
    "k1": 1.2,                   # BM25 k1 参数(控制词频饱和度)
    "b": 0.75,                   # BM25 b 参数(控制文档长度归一化)
    
    # 传统 TF-IDF 参数
    "reduce_frequent_words": True,  # 降低过于频繁的词的权重
    "diversity": None,              # 可选:0-1,增加关键词多样性
}

ctfidf_model = ClassTfidfTransformer(**ctfidf_config)

# 或者在创建 BERTopic 时直接传递
topic_model = BERTopic(
    ctfidf_model=ctfidf_model,
    # ... 其他参数
)

可视化 c-TF-IDF 权重

python 复制代码
import matplotlib.pyplot as plt

# 获取特定主题的关键词和权重
topic_num = 0
topic_words = topic_model.get_topic(topic_num)

# 提取词和权重
words = [word for word, score in topic_words[:10]]
scores = [score for word, score in topic_words[:10]]

# 绘制条形图
plt.figure(figsize=(10, 6))
plt.barh(words, scores)
plt.xlabel('c-TF-IDF 权重')
plt.title(f'主题 {topic_num} 的关键词权重')
plt.gca().invert_yaxis()  # 最高权重在顶部
plt.show()

总结

c-TF-IDF 是 BERTopic 的"大脑",它:

  • 将传统 TF-IDF 从文档级别 提升到主题级别
  • 自动识别每个主题最具有区分度的关键词
  • 配合嵌入模型,既考虑语义相似度,又考虑统计显著性
  • 使得生成的主题标签既准确又可解释

这就是为什么 BERTopic 既能处理海量文档,又能生成高质量、易理解的主题!

相关推荐
wa的一声哭了6 小时前
拉格朗日插值
人工智能·线性代数·算法·机器学习·计算机视觉·自然语言处理·矩阵
deng-c-f7 小时前
C/C++内置库函数(2):智能指针
java·c语言·c++
yuhaiqun19897 小时前
新手练 C++ HTTP 服务实操:从 “拆请求头” 到 “发 HTML 响应”
c语言·c++·程序人生·http·html·学习方法·改行学it
野生风长7 小时前
从零开始的C语言: 指针深入理解从入门到实践(中)指针与数组的结合
c语言·数据结构·算法
无妄无望7 小时前
大语言模型是零样本推理器 Large Language Models are Zero-Shot Reasoners
人工智能·语言模型·自然语言处理
暴风鱼划水7 小时前
大型语言模型(入门篇)A
人工智能·语言模型·自然语言处理·大模型·llm
EXtreme357 小时前
【数据结构】建堆操作:向上调整与向下调整的数学推导与性能对比
c语言·数据结构··时间复杂度·topk问题·算法分析
星川皆无恙8 小时前
基于ARIMA 算法模型和NLP:社交媒体舆情分析在涉众型经济犯罪情报挖掘中的应用研究
人工智能·爬虫·python·算法·机器学习·自然语言处理·数据分析
zore_c8 小时前
【C语言】Win 32 API——一部分内容详解!!!
c语言·开发语言·c++·经验分享·笔记