导航菜单

  • 1.vector
  • 2.milvus
  • 3.pymilvus
  • 4.rag
  • 5.rag_measure
  • 7.search
  • ragflow
  • heapq
  • HNSW
  • cosine_similarity
  • math
  • typing
  • etcd
  • minio
  • collections
  • jieba
  • random
  • beautifulsoup4
  • chromadb
  • sentence_transformers
  • numpy
  • lxml
  • openpyxl
  • PyMuPDF
  • python-docx
  • requests
  • python-pptx
  • text_splitter
  • all-MiniLM-L6-v2
  • openai
  • llm
  • BPETokenizer
  • Flask
  • RAGAS
  • BagofWords
  • langchain
  • Pydantic
  • abc
  • faiss
  • MMR
  • scikit-learn
  • 1. 什么是词袋模型?
    • 1.1 核心概念
    • 1.2 为什么叫"词袋"?
    • 1.3 简单类比
  • 2. 为什么需要词袋模型?
    • 2.1 计算机无法直接理解文字
    • 2.2 词袋模型的作用
    • 2.3 实际应用场景
  • 3. 词袋模型的工作原理
    • 3.1 三个核心步骤
      • 3.1.1 步骤1:构建词汇表
      • 3.1.2 步骤2:创建词到索引的映射
      • 3.1.3 步骤3:向量化
    • 3.2 可视化理解
  • 4. 实现词袋模型
    • 4.1 代码示例
    • 4.2 运行结果
  • 5. 词袋模型的优缺点
    • 5.1 优点
      • 5.1.1 简单直观
      • 5.1.2 计算高效
      • 5.1.3 适用范围广
      • 5.1.4 易于扩展
    • 5.2 缺点
      • 5.2.1 丢失词序信息
      • 5.2.2 丢失语义信息
      • 5.2.3 维度灾难
      • 5.2.4 无法处理新词
    • 5.3 适用场景

1. 什么是词袋模型? #

1.1 核心概念 #

词袋模型(Bag of Words,简称BoW)是一种将文本转换为数字向量的方法。想象一下,你把一篇文章的所有词都扔进一个袋子里,然后只统计每个词出现了多少次,完全不管这些词原来的顺序和位置。这就是"词袋"这个名字的由来。

1.2 为什么叫"词袋"? #

  • "词":指的是文本中的词汇
  • "袋":表示我们把这些词都装进一个袋子里,打乱顺序
  • "模型":这是一种将文本转换为计算机可以处理的数字的方法

1.3 简单类比 #

假设你有两个购物清单:

  • 清单1:苹果、香蕉、苹果、橙子
  • 清单2:香蕉、橙子、葡萄

用词袋模型表示,我们只关心:

  • 清单1:苹果(2次)、香蕉(1次)、橙子(1次)
  • 清单2:香蕉(1次)、橙子(1次)、葡萄(1次)

我们不在乎这些水果在清单上的顺序,只关心每种水果出现了几次。

2. 为什么需要词袋模型? #

2.1 计算机无法直接理解文字 #

计算机只能处理数字,不能直接理解文字。如果我们想让计算机分析文本(比如判断一篇文章是正面还是负面情感),就需要把文字转换成数字。

2.2 词袋模型的作用 #

词袋模型将文本转换成固定长度的数字向量,这样:

  1. 计算机可以处理:向量是数字,计算机可以计算
  2. 可以比较文本:通过比较向量,可以判断两段文本是否相似
  3. 可以用于机器学习:大多数机器学习算法需要数字输入

2.3 实际应用场景 #

  • 文本分类:判断邮件是垃圾邮件还是正常邮件
  • 情感分析:判断评论是正面还是负面
  • 文档相似度:找出相似的文档
  • 搜索引擎:匹配搜索关键词和网页内容

3. 词袋模型的工作原理 #

3.1 三个核心步骤 #

词袋模型的工作过程可以分为三个步骤:

3.1.1 步骤1:构建词汇表 #

收集所有文档中出现过的所有不重复的词,形成一个词汇表(也叫词典)。

例子: 假设我们有两句话:

  • 句子1:"我喜欢机器学习"
  • 句子2:"机器学习喜欢数据"

分词后:

  • 句子1:["我", "喜欢", "机器学习"]
  • 句子2:["机器学习", "喜欢", "数据"]

词汇表就是所有不重复的词:["我", "喜欢", "机器学习", "数据"]

3.1.2 步骤2:创建词到索引的映射 #

为了快速查找每个词在词汇表中的位置,我们创建一个字典,将每个词映射到一个数字索引。

例子:

"我" → 0
"喜欢" → 1
"机器学习" → 2
"数据" → 3

3.1.3 步骤3:向量化 #

对于每个文档,我们创建一个向量(一个数字列表)。向量的长度等于词汇表的长度,每个位置对应词汇表中的一个词,数值表示该词在文档中出现的次数。

例子:

  • 句子1:"我喜欢机器学习"

    • "我"出现1次 → 向量位置0的值是1
    • "喜欢"出现1次 → 向量位置1的值是1
    • "机器学习"出现1次 → 向量位置2的值是1
    • "数据"出现0次 → 向量位置3的值是0
    • 最终向量:[1, 1, 1, 0]
  • 句子2:"机器学习喜欢数据"

    • "我"出现0次 → 向量位置0的值是0
    • "喜欢"出现1次 → 向量位置1的值是1
    • "机器学习"出现1次 → 向量位置2的值是1
    • "数据"出现1次 → 向量位置3的值是1
    • 最终向量:[0, 1, 1, 1]

3.2 可视化理解 #

原始文本:
文档1: "我喜欢机器学习"
文档2: "机器学习喜欢数据"

         ↓ 分词

分词结果:
文档1: ["我", "喜欢", "机器学习"]
文档2: ["机器学习", "喜欢", "数据"]

         ↓ 构建词汇表

词汇表: ["我", "喜欢", "机器学习", "数据"]
索引:   [ 0,    1,       2,         3  ]

         ↓ 向量化

文档1向量: [1, 1, 1, 0]  ← "我"1次,"喜欢"1次,"机器学习"1次,"数据"0次
文档2向量: [0, 1, 1, 1]  ← "我"0次,"喜欢"1次,"机器学习"1次,"数据"1次

4. 实现词袋模型 #

4.1 代码示例 #

# 第一步:准备数据
# 我们准备三个已经分好词的文档作为示例
# 在实际应用中,这些文档可能是文章、评论、邮件等
documents = [
    ["我", "喜欢", "机器学习"],
    ["机器学习", "喜欢", "数据"],
    ["我", "爱", "编程"]
]

# 打印原始文档,方便查看
print("=" * 50)
print("原始文档:")
print("=" * 50)
for i, doc in enumerate(documents, 1):
    print(f"文档 {i}: {doc}")

# 第二步:构建词汇表
# 词汇表包含所有文档中出现过的所有不重复的词
print("\n" + "=" * 50)
print("第二步:构建词汇表")
print("=" * 50)

# 创建一个空集合,用来收集所有不重复的词
# 集合(set)的特点是自动去除重复元素
vocab_set = set()

# 遍历每个文档,将文档中的所有词添加到集合中
for doc in documents:
    # update()方法可以将列表中的所有元素添加到集合中
    vocab_set.update(doc)

# 将集合转换为排序后的列表
# sorted()确保词汇表的顺序是固定的,这样每次运行结果一致
vocabulary = sorted(list(vocab_set))

# 打印词汇表
print(f"词汇表(共{len(vocabulary)}个词): {vocabulary}")

# 第三步:创建词到索引的映射
# 这个字典帮助我们快速找到每个词在词汇表中的位置
print("\n" + "=" * 50)
print("第三步:创建词到索引的映射")
print("=" * 50)

# 使用字典推导式创建映射
# enumerate()返回索引和对应的值
# 例如:enumerate(['a', 'b']) → [(0, 'a'), (1, 'b')]
word_to_index = {word: idx for idx, word in enumerate(vocabulary)}

# 打印映射关系,方便理解
print("词 → 索引映射:")
for word, index in word_to_index.items():
    print(f"  '{word}' → {index}")

# 第四步:定义向量化函数
# 这个函数将一段分词后的文本转换为词袋向量
print("\n" + "=" * 50)
print("第四步:定义向量化函数")
print("=" * 50)

def bag_of_words(text, word_to_index):
    """
    将分词后的文本转换为词袋模型向量

    参数说明:
    - text: 分词后的文本,是一个词列表,例如 ["我", "喜欢", "编程"]
    - word_to_index: 词到索引的映射字典,例如 {"我": 0, "喜欢": 1, "编程": 2}

    返回值:
    - vector: 词袋向量,是一个整数列表,长度等于词汇表长度
    """
    # 创建一个全0向量,长度等于词汇表的长度
    # [0] * n 表示创建一个包含n个0的列表
    vector = [0] * len(word_to_index)

    # 遍历输入文本中的每个词
    for word in text:
        # 检查该词是否在词汇表中
        if word in word_to_index:
            # 获取该词在词汇表中的索引位置
            index = word_to_index[word]
            # 在对应位置计数加1
            vector[index] += 1

    # 返回生成的向量
    return vector

# 测试向量化函数
# 用一个简单的例子测试函数是否正常工作
test_text = ["我", "喜欢", "机器学习"]
test_vector = bag_of_words(test_text, word_to_index)
print(f"测试文本: {test_text}")
print(f"测试向量: {test_vector}")
print("(这个向量表示:'我'出现1次,'喜欢'出现1次,'机器学习'出现1次)")

# 第五步:将所有文档转换为向量
print("\n" + "=" * 50)
print("第五步:将所有文档转换为向量")
print("=" * 50)

# 创建一个列表来存储所有文档的向量
all_vectors = []

# 遍历每个文档
for i, doc in enumerate(documents, 1):
    # 将文档转换为向量
    vector = bag_of_words(doc, word_to_index)
    # 将向量添加到列表中
    all_vectors.append(vector)
    # 打印结果,方便查看
    print(f"文档 {i}: {doc}")
    print(f"  向量: {vector}")

    # 详细解释向量的含义
    print("  向量含义:")
    for j, count in enumerate(vector):
        if count > 0:  # 只显示出现次数大于0的词
            word = vocabulary[j]
            print(f"    '{word}' 出现 {count} 次")

# 打印最终结果汇总
print("\n" + "=" * 50)
print("最终结果汇总")
print("=" * 50)
print(f"词汇表: {vocabulary}")
print("\n所有文档的向量:")
for i, vector in enumerate(all_vectors, 1):
    print(f"文档 {i}: {vector}")

# 额外说明:向量可以用于计算文档相似度
print("\n" + "=" * 50)
print("应用示例:计算文档相似度")
print("=" * 50)
print("通过比较向量,我们可以判断文档的相似程度")
print("例如,文档1和文档2的向量:")
print(f"  文档1: {all_vectors[0]}")
print(f"  文档2: {all_vectors[1]}")
print("它们都有'喜欢'和'机器学习',所以比较相似")

4.2 运行结果 #

运行上述代码后,你会看到类似以下的输出:

==================================================
原始文档:
==================================================
文档 1: ['我', '喜欢', '机器学习']
文档 2: ['机器学习', '喜欢', '数据']
文档 3: ['我', '爱', '编程']

==================================================
第二步:构建词汇表
==================================================
词汇表(共6个词): ['数据', '我', '机器学习', '爱', '编程', '喜欢']

==================================================
第三步:创建词到索引的映射
==================================================
词 → 索引映射:
  '数据' → 0
  '我' → 1
  '机器学习' → 2
  '爱' → 3
  '编程' → 4
  '喜欢' → 5

==================================================
第四步:定义向量化函数
==================================================
测试文本: ['我', '喜欢', '机器学习']
测试向量: [0, 1, 1, 0, 0, 1]
(这个向量表示:'我'出现1次,'喜欢'出现1次,'机器学习'出现1次)

==================================================
第五步:将所有文档转换为向量
==================================================
文档 1: ['我', '喜欢', '机器学习']
  向量: [0, 1, 1, 0, 0, 1]
  向量含义:
    '我' 出现 1 次
    '机器学习' 出现 1 次
    '喜欢' 出现 1 次
文档 2: ['机器学习', '喜欢', '数据']
  向量: [1, 0, 1, 0, 0, 1]
  向量含义:
    '数据' 出现 1 次
    '机器学习' 出现 1 次
    '喜欢' 出现 1 次
文档 3: ['我', '爱', '编程']
  向量: [0, 1, 0, 1, 1, 0]
  向量含义:
    '我' 出现 1 次
    '爱' 出现 1 次
    '编程' 出现 1 次

==================================================
最终结果汇总
==================================================
词汇表: ['数据', '我', '机器学习', '爱', '编程', '喜欢']

所有文档的向量:
文档 1: [0, 1, 1, 0, 0, 1]
文档 2: [1, 0, 1, 0, 0, 1]
文档 3: [0, 1, 0, 1, 1, 0]

==================================================
应用示例:计算文档相似度
==================================================
通过比较向量,我们可以判断文档的相似程度
例如,文档1和文档2的向量:
  文档1: [0, 1, 1, 0, 0, 1]
  文档2: [1, 0, 1, 0, 0, 1]
它们都有'喜欢'和'机器学习',所以比较相似

5. 词袋模型的优缺点 #

5.1 优点 #

5.1.1 简单直观 #

词袋模型的原理非常简单,容易理解和实现。即使没有深厚的数学背景,也能快速掌握。

5.1.2 计算高效 #

将文本转换为向量后,计算机可以快速处理。向量之间的计算(如计算相似度)非常高效。

5.1.3 适用范围广 #

虽然简单,但在很多实际任务中效果不错,特别是:

  • 文本分类(如垃圾邮件检测)
  • 情感分析(判断评论是正面还是负面)
  • 文档检索(找到相似的文档)

5.1.4 易于扩展 #

可以在此基础上添加更多功能,比如:

  • 考虑词的重要性(TF-IDF)
  • 过滤停用词(如"的"、"了"等常见但无意义的词)
  • 处理N-gram(考虑词的组合)

5.2 缺点 #

5.2.1 丢失词序信息 #

词袋模型完全忽略了词的顺序,这会导致一些问题:

例子:

  • "狗咬人" 和 "人咬狗" 在词袋模型中是完全相同的向量
  • 但它们的含义完全不同!

这是因为词袋模型只关心词是否出现,不关心出现的顺序。

5.2.2 丢失语义信息 #

词袋模型将每个词视为完全独立的,无法理解词与词之间的关系:

例子:

  • "喜欢" 和 "爱" 是近义词,但词袋模型认为它们是两个完全不同的词
  • "好" 和 "坏" 是反义词,但词袋模型无法理解它们的对立关系

5.2.3 维度灾难 #

当词汇表很大时,向量会变得非常长,而且大部分位置都是0(稀疏向量):

例子:

  • 如果有10,000个不同的词,每个文档的向量就有10,000维
  • 一篇短文可能只包含几十个词,所以向量中大部分都是0
  • 这会占用大量内存,计算也会变慢

5.2.4 无法处理新词 #

如果遇到词汇表中没有的新词,词袋模型会直接忽略它,无法处理。

5.3 适用场景 #

适合使用词袋模型的场景:

  • 文本分类任务(如垃圾邮件检测、新闻分类)
  • 文档相似度计算(粗略比较)
  • 作为更复杂模型的基线(baseline)
  • 数据量较小,对效果要求不高的场景

不适合使用词袋模型的场景:

  • 需要理解语义的任务(如机器翻译、问答系统)
  • 需要考虑词序的任务(如文本生成)
  • 需要处理同义词、反义词的任务
  • 对效果要求很高的生产环境

访问验证

请输入访问令牌

Token不正确,请重新输入