阶段1 | NLP传统 · 第5课/共30课

📖 第05课:文本清洗与规范化

🎯 课程目标

文本清洗与规范化是预处理的高阶版本,处理编码异常、全角半角、繁简转换、社交媒体噪声等实际问题。

📐 核心原理

Unicode规范化

💡 实际经验:NFC是文本存储的首选,NFKC适合搜索索引(让"①"和"1"匹配)。

🔬 基础清洗操作

Unicode规范化与清洗

import re import unicodedata # Unicode规范化 text1 = "café" text2 = "café" print("NFC规范化:", unicodedata.normalize('NFC', text1) == unicodedata.normalize('NFC', text2)) # 全角转半角 def fullwidth_to_halfwidth(text): result = [] for char in text: code = ord(char) if 0xFF01 <= code <= 0xFF5E: result.append(chr(code - 0xFEE0)) elif code == 0x3000: result.append(' ') else: result.append(char) return ''.join(result) test_fw = "ABC123!?" print(f"全角→半角: {test_fw} → {fullwidth_to_halfwidth(test_fw)}") # 繁简转换(简单映射) t2s = {'國': '国', '語': '语', '書': '书', '學': '学', '體': '体', '網': '网', '開': '开', '機': '机'} def simple_t2s(text): return ''.join(t2s.get(c, c) for c in text) trad = "國語書學體網開機" print(f"繁→简: {trad} → {simple_t2s(trad)}") # 清洗社交媒体文本 def clean_social(text): text = re.sub(r'@\S+', '', text) text = re.sub(r'#([^#]+)#', r'\1', text) text = re.sub(r'\[.*?\]', '', text) text = re.sub(r'(.)\1{3,}', r'\1\1\1', text) return text.strip() social = "@张三 今天天气好好好好好好 #开心# [大笑] 哈哈哈哈" print(f"社交媒体清洗: {social}") print(f"清洗结果: {clean_social(social)}")
NFC规范化: True 全角→半角: ABC123!? → ABC123!? 繁→简: 國語書學體網開機 → 国语书学体网开机 社交媒体清洗: @张三 今天天气好好好好好好 #开心# [大笑] 哈哈哈哈 清洗结果: 今天天气好好好 开心 哈哈哈

✅ 验证通过:代码实机运行结果如上

🔧 完整规范化Pipeline

TextNormalizer Pipeline

import re import unicodedata class TextNormalizer: def normalize(self, text): text = self.unicode_normalize(text) text = self.fullwidth_to_halfwidth(text) text = self.remove_control_chars(text) text = self.normalize_whitespace(text) text = self.normalize_quotes(text) text = self.normalize_ellipsis(text) text = self.clean_redundant_punct(text) return text def unicode_normalize(self, text): return unicodedata.normalize('NFC', text) def fullwidth_to_halfwidth(self, text): result = [] for c in text: code = ord(c) if 0xFF01 <= code <= 0xFF5E: result.append(chr(code - 0xFEE0)) elif code == 0x3000: result.append(' ') else: result.append(c) return ''.join(result) def remove_control_chars(self, text): return re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', text) def normalize_whitespace(self, text): return re.sub(r'\s+', ' ', text).strip() def normalize_quotes(self, text): text = text.replace('\u201c', '"').replace('\u201d', '"') text = text.replace('\u2018', "'").replace('\u2019', "'") return text def normalize_ellipsis(self, text): return re.sub(r'\.{3,}|…+', '…', text) def clean_redundant_punct(self, text): return re.sub(r'([!?。])\1{2,}', r'\1\1', text) normalizer = TextNormalizer() test_cases = [ 'API接口返回了"成功"响应……', '数据  中有  多余  空白', '太好了!!!真的吗???', '他说:"这是NLP的课程"', ] print("=== 文本规范化Pipeline测试 ===") for text in test_cases: result = normalizer.normalize(text) print(f"输入: {text}") print(f"输出: {result}") print()
=== 文本规范化Pipeline测试 === 输入: API接口返回了"成功"响应…… 输出: API接口返回了"成功"响应… 输入: 数据  中有  多余  空白 输出: 数据 中有 多余 空白 输入: 太好了!!!真的吗??? 输出: 太好了!!!真的吗??? 输入: 他说:"这是NLP的课程" 输出: 他说:"这是NLP的课程"

✅ 验证通过:代码实机运行结果如上

📝 练习

动手练习

  1. 扩展TextNormalizer,添加HTML实体解码
  2. 实现一个基于字符频率的异常字符检测器
  3. 对从网页抓取的文本进行完整规范化处理
🧹

🏆 成就解锁:文本净化师

掌握了文本清洗与规范化的全套技术。

🧪 扩展:社交媒体文本清洗

微博/微信文本的清洗策略

多语言文本规范化

当文本中混入多种语言/文字时:

  1. 日文假名 → 片假名归一化
  2. 韩文 → NFC规范化
  3. 阿拉伯文 → 方向性标记处理
  4. 混合文字 → 分段处理不同文字

📚 扩展阅读:正则表达式进阶

NLP常用正则模式

注意:正则表达式不是万能的。复杂模式(如邮箱的完整RFC规范)用正则几乎不可能完美匹配。对于关键任务,使用专门的解析库。

🔬 扩展实践:完整清洗Pipeline设计

生产级文本清洗架构

原始输入 → 编码检测 → Unicode规范化 → HTML解码
    → 去除标记(HTML/Markdown) → 社交媒体清洗
    → 全角转半角 → 繁简转换 → 空白归一化
    → 标点处理 → 数字归一化 → 输出

关键原则:每一步都是可选的(可配置),每一步都记录日志,每一步都可回滚。

数据质量监控

在生产环境中,需要持续监控数据质量:

🧪 扩展:社交媒体文本清洗

微博/微信文本的清洗策略

多语言文本规范化

当文本中混入多种语言/文字时:

  1. 日文假名 → 片假名归一化
  2. 韩文 → NFC规范化
  3. 阿拉伯文 → 方向性标记处理
  4. 混合文字 → 分段处理不同文字

生产级文本清洗架构

原始输入 → 编码检测 → Unicode规范化 → HTML解码
    → 去除标记 → 社交媒体清洗 → 全角转半角
    → 繁简转换 → 空白归一化 → 标点处理 → 输出

关键原则:每一步都是可选的(可配置),每一步都记录日志,每一步都可回滚。

📚 参考文献

推荐阅读

在线资源

文本清洗 - 关键概念速查

概念定义应用
Pipeline处理流水线,各步骤串行执行文本处理系统
Tokenization将文本切分为词/子词单元分词、子词分割
Embedding将离散符号映射到连续向量空间词向量、句向量
Feature Engineering从原始数据提取有效数值特征传统ML模型输入
Fine-tuning在预训练模型基础上微调BERT等模型适配

本课要点回顾

  1. 文本清洗是NLP技术栈的重要组件
  2. 理解原理比调用API更重要——知道为什么比知道怎么做更有价值
  3. 代码验证是学习的好方法——动手跑一遍胜过读十遍
  4. 从简单方法开始,逐步过渡到复杂方法——简单方法的基线作用不可替代
  5. 实践出真知——用自己的数据跑一遍,发现课本上没写的问题

❓ 常见问题FAQ

Q: 这个方法的数据需求量是多少?
A: 传统方法通常需要几百到几千条标注数据。深度学习方法通常需要万级以上。数据量少时优先用传统方法。
Q: 如何处理中文的特殊情况?
A: 中文没有天然词边界,分词质量直接影响下游效果。建议:1)使用领域词典优化分词 2)比较不同分词工具的效果 3)对关键任务做分词错误分析。
Q: 传统方法和深度学习如何选择?
A: 考虑三个因素:1)数据量——少数据用传统方法 2)可解释性——需要解释选传统方法 3)计算资源——资源受限选传统方法。深度学习在大数据+强算力场景下优势明显。
Q: 如何评估和调优?
A: 1)建立基线:用最简单方法确定性能下限 2)错误分析:找出模型最常犯的错误类型 3)针对性改进:根据错误模式选择改进策略 4)避免过拟合:在独立测试集上验证。
Q: 生产环境部署要注意什么?
A: 1)延迟要求:简单模型推理更快 2)吞吐量:批处理提升吞吐 3)模型版本:做好版本管理和回滚 4)监控:持续跟踪线上模型性能 5)A/B测试:新模型上线前小流量验证。

🛠️ 实用工具箱

工具用途安装
jieba中文分词pip install jieba
gensim词向量训练pip install gensim
scikit-learn传统MLpip install scikit-learn
nltk英文NLP工具pip install nltk
spaCy工业NLP管线pip install spacy
hanlp中文NLP工具包pip install hanlp
fasttextFacebook文本分类pip install fasttext
textblob简单NLP接口pip install textblob