科普:CountVectorizer、TF、TF-IDF,三者层层递进

  1. CountVectorizer

    Count Vectorizer

    计数向量化器

  2. 词频

    TF = Term Frequency

    词条频率

  3. TF-IDF

    Term Frequency -- Inverse Document Frequency

    词条频率 - 逆文档频率

    ountVectorizer、TF、TF-IDF本来是给 NLP(自然语言)用的,但常被借用来处理「多值离散字段」,即把「多值离散字段」当成文本来用!

一、三者层层递进关系

先看一业务场景

我们有一个离散字段 merchant_type(用户交易活动的商户类型),每个用户的交易记录如下:

card_id merchant_type(商户类型)
user1 餐饮, 餐饮, 超市, 餐饮
user2 超市, 超市, 便利店
user3 餐饮, 便利店, 餐饮, 超市

我们把每个用户的交易记录,看成一段"文本"(伪文本):

  • user1 的"文本":餐饮 餐饮 超市 餐饮
  • user2 的"文本":超市 超市 便利店
  • user3 的"文本":餐饮 便利店 餐饮 超市

第一层:CountVectorizer(计数向量化)

CountVectorizer(计数向量化)是一个工具,作用是:把文本/类别数据,转换成一个由「词频」组成的矩阵。

它的工作分两步:

  1. 构建词表:把所有出现过的"词"(这里就是所有商户类型)收集起来,形成一个固定的词汇表。
  2. 计数:对每一段文本,统计词表中每个词出现的次数。

举例:对我们的交易数据

  1. 构建词表
    ["餐饮", "超市", "便利店"]
  2. 计数:对每个用户的"文本"统计词频。

结果矩阵:

card_id 餐饮 超市 便利店
user1 3 1 0
user2 0 2 1
user3 2 1 1

第二层:词频(Term Frequency, TF)

词频,就是某个词在单条文本/单个用户 中出现的次数。

它是 CountVectorizer 的直接计算的结果,也是构建更复杂特征(如 TF-IDF)的基础。

在我们的例子里,表格里的每一个数字,都是一个"词频":

  • user1餐饮 词频是 3
  • user2便利店 词频是 1

词频的优缺点

  • 优点 :直接反映用户的行为频次,和数值情况用 groupby 做的 count 统计逻辑完全一致,非常直观。
  • 缺点:它不考虑词的"重要性"。比如"超市"这个词,所有用户都用,词频很高,但它无法区分用户的独特偏好。

第三层:TF-IDF(Term Frequency -- Inverse Document Frequency,词频-逆文档频率)

它是在"词频(TF)"的基础上,为克服其缺点,引入了"逆文档频率(IDF)"来衡量词的稀有度,从而给不同的词赋予不同的权重。

公式:
TF-IDF=词频(TF)×逆文档频率(IDF) \text{TF-IDF} = \text{词频(TF)} \times \text{逆文档频率(IDF)} TF-IDF=词频(TF)×逆文档频率(IDF)

  • TF(词频):就是第二层我们讲的,词在当前文本中出现的次数。
  • IDF(逆文档频率) :衡量这个词在所有文本/所有用户中的稀有程度。词越稀有,IDF值越高。

举例:对我们的交易数据

第一步:计算 IDF(稀有度)

总共有 3 个用户(文本)。

  • 餐饮:出现在 2 个用户中 → 不算太普遍
  • 超市:出现在 3 个用户中 → 非常普遍
  • 便利店:出现在 2 个用户中 → 不算太普遍

IDF 的简化计算:
IDF(词)=log⁡(总用户数出现该词的用户数) \text{IDF}(词) = \log(\frac{\text{总用户数}}{\text{出现该词的用户数}}) IDF(词)=log(出现该词的用户数总用户数)

  • IDF(餐饮)=log⁡(3/2)≈0.405\text{IDF(餐饮)} = \log(3/2) ≈ 0.405IDF(餐饮)=log(3/2)≈0.405
  • IDF(超市)=log⁡(3/3)=0\text{IDF(超市)} = \log(3/3) = 0IDF(超市)=log(3/3)=0
  • IDF(便利店)=log⁡(3/2)≈0.405\text{IDF(便利店)} = \log(3/2) ≈ 0.405IDF(便利店)=log(3/2)≈0.405
第二步:计算 TF-IDF

user1 为例:

  • 餐饮:TF=3×IDF=0.405≈1.215TF=3 \times IDF=0.405 ≈ 1.215TF=3×IDF=0.405≈1.215
  • 超市:TF=1×IDF=0=0TF=1 \times IDF=0 = 0TF=1×IDF=0=0
  • 便利店:TF=0×IDF=0.405=0TF=0 \times IDF=0.405 = 0TF=0×IDF=0.405=0

最终 TF-IDF 矩阵:

card_id 餐饮_tfidf 超市_tfidf 便利店_tfidf
user1 1.215 0 0
user2 0 0 0.405
user3 0.81 0 0.405

TF-IDF 完美解决了"词频"的缺点:

  • 高频普遍词被削弱:所有用户都爱去的"超市",IDF为0,权重被压低,无法区分用户。
  • 低频独特词被强化:用户的独特偏好(如 user1 高频的"餐饮"、user2 的"便利店")被放大,权重很高,能有效区分用户行为。

三者的递进关系总结

层级 核心概念 本质 作用
1️⃣ CountVectorizer 工具 把文本/类别列表转换成词频矩阵 从非数值数据中提取基础频次特征
2️⃣ 词频 (TF) 结果/基础特征 词在单条文本中的出现次数 反映用户的行为频次,是构建更复杂特征的基础
3️⃣ TF-IDF 进阶特征 词频 × 稀有度(IDF) 反映用户的独特行为偏好,是对词频特征的补充和优化

一句话串起来:
CountVectorizer 工具,产出了词频(TF);在词频的基础上,乘以逆文档频率(IDF),就得到了 TF-IDF。


二、TF-IDF 极简代码示例

用上述交易商户类型场景举例。

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

# 1. 构造数据(每个用户的商户类型行为)
data = {
    'card_id': ['user1', 'user2', 'user3'],
    'merchant_text': [
        '餐饮 餐饮 超市 餐饮',    # user1
        '超市 超市 便利店',      # user2
        '餐饮 便利店 餐饮 超市'  # user3
    ]
}

df = pd.DataFrame(data)

# 2. 初始化 TF-IDF 工具
tfidf = TfidfVectorizer()

# 3. 把文本转成 TF-IDF 特征矩阵
tfidf_matrix = tfidf.fit_transform(df['merchant_text'])

# 4. 转成 DataFrame 方便查看
tfidf_df = pd.DataFrame(
    tfidf_matrix.toarray(),
    columns=tfidf.get_feature_names_out()
)

# 5. 合并回原数据
result = pd.concat([df[['card_id']], tfidf_df], axis=1)
print(result)

运行结果

复制代码
  card_id      便利店        餐饮        超市
0   user1  0.000000  0.927743  0.372302
1   user2  0.720338  0.000000  0.693642
2   user3  0.542701  0.542701  0.643187

这个结果代表什么?

  • 数字越大 = 这个商户类型对这个用户越独特、越重要
  • 数字越小 = 越普通、越没有区分度

重点解读:

  1. user1 的 餐饮 分数最高(0.93)

    因为他经常去餐饮,且餐饮不是所有人都去 → 独特行为

  2. 超市 分数都不高

    因为大家都去超市 → 太普遍,不重要

  3. 便利店 只对 user2、user3 重要

    因为不是所有人都去 → 有区分度


1. TF-IDF 用于离散字段做特征

例如:

  • merchant_type(商户类型)
  • city(城市)
  • category(品类)
  • brand(品牌)

把每个用户的历史行为拼成一段文本,直接用 TF-IDF 生成强特征。

2. 作用:

  • 自动识别用户独特偏好
  • 自动降低大家都有的普遍行为权重
  • 给模型提供区分度极强的特征

相关推荐
qq_342295821 小时前
如何监控集群 interconnect_ping与traceroute验证心跳通畅
jvm·数据库·python
qq_342295822 小时前
Go语言错误处理如何做_Go语言error错误处理教程【实用】
jvm·数据库·python
qq_334563552 小时前
如何在phpMyAdmin中执行多条SQL语句_分号分隔与批量执行解析
jvm·数据库·python
2401_897190552 小时前
Golang如何做Clean Architecture_Golang整洁架构教程【详解】
jvm·数据库·python
qq_189807032 小时前
如何在网页中实现国际象棋棋子的拖拽与格点吸附功能
jvm·数据库·python
C系语言2 小时前
ONNX Runtime安装
人工智能·python·深度学习
2402_854808372 小时前
如何管理微服务下Oracle的数据库连接数_调整应用节点的MaxActive汇总以防止超processes
jvm·数据库·python
慕涯AI2 小时前
Agent 30 课程开发指南 - 第16课
人工智能·python
Shorasul2 小时前
如何修改数据库实例名_ORACLE_SID环境变量重命名实战
jvm·数据库·python