中文分词

cws = chinese word segmentation

为什么要分词?

英文: 天然空格分割 + 词根

古文一般不加标点, 读书主要目的是”离经辨志” (“离”及断句), “明句读” (句号, 逗号).

20世纪后, 逐步统一规范了中文标点符号

有了标点符号后, 需进一步分词的意义? 消除歧义

业务功能落地场景

分词评价指标

词典分词

字符串匹配算法

问题: 文本长度N, 词典大小M, 词最长为D, 找出文本中所有在词典的词

Trie / 前缀树

最长前缀匹配O(D) 应用场景: CIDR/路由表, 域名查找 (最长后缀)

全文匹配 (一个朴素的办法): 每个位置做一次前缀匹配O(N*D). 问题: 不匹配时很多计算路径信息被浪费了

AC:

See Code

多种分法的决策

词典无权重信息

词典有权重信息 (词频)

viterbi vs 寻路

都是DP, 保存到当前位置结束的最大权重及前向位置

See Code

OOV / 新词发现

不在词典中的片段, 直接当作新词肯定是不合适的, 需要尝试再切一下

HMM / Hidden Markov Model

状态: 当前字组成词的何处 表征: 输出的字

HMM考虑点

词典分词 和 HMM交互问题

两阶段流程:

  1. 先基于词典分出来最大路径
  2. 剩下的单字片段HMM尝试再合并做新词发现

问题:

改进办法 (beam search 思路):

jieba (0.39)

https://github.com/fxsjy/jieba/tree/v0.39

# https://github.com/fxsjy/jieba/issues/212
jieba.lcut("我们中出了叛徒", HMM=True)
['我们', '中出', '了', '叛徒']

See Code

实现上可优化点:

序列标注问题

tagging, pos, ner, chunking, …

对比分词, 多了一个词性维度

序列标注: N*S DAG 网格上的最大路径选择

词性:

MEMM & CRF & SP

REF dm-ner.md

深度学习模型

模型层级

  1. 表征层 (独热编码变稀疏表征): Embedding / BERT / …
  2. 记忆层: RNN / Bi-LSTM / Bi-GRU
    • 学输入对每个状态的概率表达
  3. 表达层: HMM / CRF / SP / …
    • 学状态迁移概率

LAC

https://github.com/baidu/lac

https://github.com/PaddlePaddle/models/tree/release/1.8/PaddleNLP/lexical_analysis

https://github.com/PaddlePaddle/PaddleNLP/tree/develop/examples/lexical_analysis

模型结构: Embedding + bi-GRU * 2 + CRF

评价

逆向想法:

  1. 模型参数提取, 构造相同网络结构后导出ONNX
  2. 用于生成文本训练数据, 训练还原

LTP

TODO https://github.com/HIT-SCIR/ltp

HanLP

TODO https://github.com/hankcs/HanLP

Zipf Law / Power Law / 幂律 / 长尾理论 / 马太效应 / 二八定律

ref: https://www.nature.com/articles/srep00812

编码 / Tokenization / 压缩 / 无监督自学习生成字典

TODO

上述分词 (构造词典, 计算HMM经验概率) 需要大量标注好的数据, 如何无监督的方式出分词? 语料 -> 最小编码字典过程

无损压缩 OR 有损压缩 ?

有损压缩: 掐头去尾

Reference

HOME