到目前为止,我们已经学习了:

  • Chapter 1 语言处理概览:了解了语言技术的整体框架和研究目标。
  • Chapter 2 语料库处理工具:学习了如何收集和处理语料库。
  • Chapter 3 编码与标注方案:学习了文本的编码方式、字符集以及标注方法,确保我们能够正确地表示和存储语言数据。

在有了语料和正确的编码之后,就要开始进行最基础的分析: 统计词频 ,对文本中的单词进行计数。

词语切分与计数 (Word segmentation & word count)

要做到这一点,首先要解决的问题就是如何找到文本中有哪些单词,以及它们各自的位置。这一步称为 分词(tokenization)。分词的结果是得到一系列 词元(token),每个 token 是文本中被切分出来的基本单位,可以是一个单词、一个符号,甚至在某些场景下是一个子词或字符。

分词是文本处理的基础环节,它使得计算机能够把连续的字符序列切分成有意义的最小单位,从而支持后续的统计、检索、相似度计算、分类、情感分析等任务。

分词 (Tokenization)

定义:从文本中获取 词元 (token)

1. 最简单的方法:空格 (Space)切分

  • 思路:用空格作为分隔,把字符序列分成单词。
  • 问题:
    • 日期(如 28/02/96)会被切碎。
    • 数字(如英文 9,812.345,法文 9 812,345)不同语言格式不同。
    • 缩写(m.p.h.)和首字母缩略词(S.N.C.F.)里带有点号。

2. 基于内容 (content-based) 规则

  • 用正则表达式找字母序列(\p{L}+),提取“看起来像单词”的片段。
  • 扩展后可以加数字(\p{N}+)和标点(\p{P})。
  • 问题:对编号(Item #N23-SW32A)、日期、特殊记号还是无效。

3. 基于边界 (boundary-based) 规则

  • 用空格(\s+)和标点(\p{P})作为边界切分。
  • 改进:标点符号两边插入空格,再切分。
  • 问题:有时标点本身也是 token 的一部分(如在 km/h 里)。

4. 进一步改进:微语法 (microgrammars)

  • 为某些特殊模式设计小规则:
    • 英文缩写:can’t → can n’twe’ll → we ’ll
    • 法语:j’aime → j’ aimeaujourd’hui 不能乱切。
  • 必要时配合词典子词算法(例如 BPE,byte pair encoding)来处理。

句子切分 (Sentence Segmentation)

1. 最简单的方法:把句号当作句子结束符

  • 思路:用空格作为分隔,把字符序列分成单词。
  • 问题:数字、小数、分数、百分比里的点会被误判。
  • 改进:增加对这些情况的识别。

2. 识别数字

  • 方法:通过正则模式识别日期、分数、百分比、小数。
  • 问题:缩写(如 U.S.)里的点依旧会误判。
  • 改进:增加对缩写的处理。

3. 添加缩写模式和缩写词典

  • 方法:维护缩写规则(如 Mr., St., U.S. 等)。
  • 效果:在常见缩写场景下避免误切分,显著提高准确率。

现在我们知道要如何从一大段话中把单词提取成不同的token了。那么在拿到 token 之后,我们应该怎么把它们组合起来,形成对整个文档的数值化表示,以便后续计算和比较?


词语 / 文档表示 (Word & Document Representation)

倒排索引 (Inverted Index)

举个例子来理解倒排索引:

  • D1: Apple releases a new iPhone in California.
  • D2: Samsung launches a smartphone in Korea.

由上面这两段文本,我们可以得出如下的倒排索引:

Words Posting lists
Apple (D1, 1)
releases (D1, 2)
a (D1, 3) → (D2, 3)
new (D1, 4)
iPhone (D1, 5)
in (D1, 6) → (D2, 5)
California (D1, 7)
Samsung (D2, 1)
launches (D2, 2)
smartphone (D2, 4)
Korea (D2, 6)

它和顺向索引有什么区别:

顺向索引:一个文档 → 它包含的所有单词。比如:D1 → {Apple, releases, new, iPhone, …}

倒排索引:一个单词 → 它出现过的所有文档。比如:Apple → (D1, 1)

其中,可以看到索引中的最后一列是Posting List。

什么是 Posting list?

  • Posting list(倒排列表) 就是倒排索引表中某个单词对应的条目。
  • 它记录了:
    1. 这个单词出现在哪些文档(Document ID)。
    2. 在每个文档中的具体位置(Position)。

例如:

  • in → (D1, 6) → (D2, 5)
    • 表示单词 in 在文档 D1 的第 6 个词出现过,在文档 D2 的第 5 个词出现过。

现在我们已经有了 倒排索引(Inverted Index),它能记录每个词出现在哪些文档以及具体位置。这种结构非常适合快速检索和统计,因为我们只需查看某个词的 posting list,就能立即知道它的文档分布情况。

然而,如果我们希望比较文档之间的相似性,仅仅知道“某个词在哪些文档里出现”还不够。我们需要把整篇文档表示为一个统一的数学形式——向量。这样就能把文本处理问题转化为向量空间中的计算问题,比如余弦相似度。

向量空间模型 (Vector Space Model)

核心思想:一个文档 (Document)⟷ 一个向量 (Vector),具体为:

$d = \big( C(w_1), C(w_2), \ldots, C(w_n) \big)$

这里的 $n$ 是词表的总长度。

这里的 $C(w_i)$ 可以有不同的定义:

  • 可以是 词频(Term Frequency, TF):词 $w_i$ 在文档中出现的次数。
  • 也可以是 TF-IDF 权重:在词频的基础上,结合逆文档频率计算得到的加权值。

那么,什么是 TF-IDF 权重?

在了解这个概念之前,我们需要先认识到一个问题,那就是单纯的词频可能会产生误导。以一篇论文为例:

  • “the” → 高频,但几乎没有意义
  • “cat” → 出现频率低,但很重要

可以看到词频并不能很好地代表词语的重要性。因此,我们引入 TF × IDF 来更好地衡量词语的重要性:

  • TF(Term Frequency,词频)

    表示某个词在一篇文档中出现的频率。

  • IDF(Inverse Document Frequency,逆文档频率)

    表示某个词在整个语料库中的区分度。公式为:

    $idf_j = \log \left( \frac{N}{n_j} \right)$

    其中:

    • $N$:语料库中的文档总数(total num of docs)
    • $n_j$:包含词 $j$ 的文档数量(num of docs where term j appears)

    这样一来,如果一个词出现在很多文档里(像 “the” 这种高频词),那么 $n_j$很大,$\frac{N}{n_j}$接近 1,取对数后 值很小 → 表示这个词没什么区分度。

    相反地,如果一个词只出现在很少的文档里(比如 “photosynthesis”),那么 $n_j$很小,$\frac{N}{n_j}$很大,$idf_j$的值也 越大 → 表示这个词更重要。

最后,把这两个量相乘得到的TF × IDF 就综合了词在文档中的重要性(TF)和词在语料库中的稀有度(IDF),可以更合理地衡量一个词的重要性。

现在,我们已经能成功用一个向量表示一个文档了。在此基础上我们可以使用这个“文档向量”来判断文档之间的相关性:

余弦相似度(Cosine Similarity)

我们仍以苹果和三星的句子为例:

  • D1: Apple releases a new iPhone in California.
  • D2: Samsung launches a smartphone in Korea.

列出词袋 (Bag of Words):

D. Apple Samsung releases launches new smartphone iPhone in California Korea
D1 1 0 1 0 1 0 1 1 1 0
D2 0 1 0 1 0 1 0 1 0 1

计算这两个向量的余弦相似度得到0.18,这表示这两个句子的相似性一般。

在此基础上,我们还可以以别的方式使用文档形成的向量,比如文档分类任务。

文档分类 (Document Classification)

文档可以按照不同需求被分成不同的类型,例如:

  • 情感分析(积极 / 消极 / 中性)
  • 垃圾邮件检测(垃圾 / 非垃圾)

自动分类

  • 使用标注语料库(例如 Reuters 语料库)
  • 监督式机器学习
  • 流程:向量化 → 逻辑回归 → 分类,比如像下面这样:

$X = \begin{bmatrix} \text{text}_1 \\ \vdots \\ \text{text}_n \end{bmatrix} ;\quad y = \begin{bmatrix} \text{class}1 \\ \vdots \\ \text{class}{x} \end{bmatrix}$

其中X的每一行都对应着一篇文档,y是每个文档的分类。接下来只需进行正常的逻辑回归训练即可。

更多可参考:pnugues/edan20: Language technology

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐