中文语料库预处理

前言

最近在做 NPL 相关的文本分类的研究,因为好多开源项目都是英文数据集,在做英文文本预处理的时候,有很多公开的方法。但是中文文本的预处理方法较少,也很少有一些总结。

所以,我将自己处理中文数据集的一些心得体会再次做一个分享!

用到的库

1
2
3
4
import os
import re
import jieba
from collections import Counter

中文文本处理

去掉空格

1
2
context = context.replace(' ', '')
context = context.replace(' ', '')

中文文本与英文文本不一样之处在于,英文文本只有一种空格,而中文文本可能同时存在中文空格英文空格,所以上面运行了两条语句,第一条去掉中文空格,第二条去掉英文空格

去括号以及其中内容

1
2
3
4
5
context = re.sub('\(.*?\)', '', context)
context = re.sub('\[.*?\]', '', context)
context = re.sub('\{.*?\}', '', context)
context = re.sub('(.*?)', '', context)
context = re.sub('【.*?】', '', context)

中文文本常常出现一个括号 () or () 作为补充说明,或者 【】 标记书名、作者等,或 [] 中间加上数字作为注释,或 {} 中间加上一些说明等。以上的括号以及中间的内容针对于我们最终的分类任务并无太大作用,需要删除。

删除英文字母以及特殊字符

1
context = re.sub('[a-zA-Z]+?|-|\.|\!|\/|\+|,|\$|@|&|#|\*|\^|>|<|_', '', context)

上面用到了正则化的一些表示方法,一些符号在正则化的定义中作如下说明:

  • | 表示或者
  • [a-zA-Z]+? 表示匹配至少一个英文字母(不区分大小写)
  • \ 表示转义字符,将正则化里面带有特殊含义的字符转义为正常字符,因为 .!/+$*^ 在正则化表示中都带有特殊含义,所以前面要加转义字符

以后再补充其他的符号。(可能有一些拉丁字母等)

中文中“《》”的处理

1
context = re.sub('《.*?》', '@', context)

这里的处理方式比较特别,是我自己想的。因为在中文语料库中 《》 一般括起来的都是书籍、电影、画作、歌曲的名字。这部分的内容其实是重要的,不能直接删除,因为如果直接删除,语句会缺少了主语或者宾语,导致句子语法成分缺失。如果保留下来,在后续分词阶段又很鸡肋,因为很多文学创作和电影的名字都带有一些特殊的命名实体,分词会不准确,计算机也很难识别中间内容。所以我在这里做了一个折中的方案,把所有 《》 以及其内容都替换为 @ 这一个符号。计算后续在识别的时候就可以知道 @ 表示这一类(书籍、电影、画作、歌曲)的东西。

分句与分词

中文分句

1
2
3
sentences = re.split('(。”|!”|?”|?!|。|!|?)', context)
if len(sentences) > 1:
sentences = ["".join(i) for i in zip(sentences[0::2], sentences[1::2])]

第一句代码表示按照 。”,!”,?”,?!,,, 这些符号的先后顺序进行分句,并且在分句的过程中,保留以上分隔符。 if 后面的第二个句子,表示将句子与其后的分隔符进行拼接。

中文分词

1
words = jieba.lcut(sentence)

这里有一篇使用 jieba 这个分词工具的教程,挺全面的,可以参考
简明 jieba 中文分词教程

构建词表

1
2
3
4
5
6
words = []
"""
将文本分词后的结果放入words,代码略...
"""
vocab = Counter(words).most_common(30000)
word2index = {k_v[0]: i for i, k_v in enumerate(vocab)}

上面 30000 为自己定义的词表大小,即取前 30000 个词频较高的词语放入词表,最后的 word2index 为词汇与编码的映射结果。

坚持原创技术分享,您的支持将鼓励我继续创作!