基于NLTK创建预预处理文本语料库:避免重复读取文件
解决方案:在读取语料时实时完成预处理,避免重复IO
我完全理解你的困扰——200MB的语料两次读写不仅效率低,后续扩展到更大规模时更是会成为瓶颈。咱们可以直接在读取文件的过程中完成所有预处理,不用生成任何中间文件,全程只做一次IO操作。
核心思路
逐行读取每个语料文件,在每行进入分词环节前,依次完成三个预处理步骤,再将有效单词直接收集到语料列表中。这样既避免了无效内容(行号、方括号标注)进入语料,也保证了所有单词都是小写形式。
完整实现代码
import nltk import os import re # 语料目录路径 corpusdir = "C:/corpus/" # 用于存储预处理后的所有单词 corpus_words = [] # 遍历目录下的所有文件 for filename in os.listdir(corpusdir): file_path = os.path.join(corpusdir, filename) # 只处理文件(跳过子目录) if os.path.isfile(file_path): # 以utf-8编码读取文件(可根据你的语料编码调整) with open(file_path, 'r', encoding='utf-8') as f: for line in f: # 1. 移除行首的4位数字行号 line = re.sub(r'^\d{4}', '', line) # 2. 移除所有被方括号包裹的内容(如[coughing]) line = re.sub(r'\[.*?\]', '', line) # 3. 转为小写并去除首尾空白字符 line = line.lower().strip() # 只处理非空行 if line: # 用NLTK标准分词器拆分单词,添加到语料列表 corpus_words.extend(nltk.word_tokenize(line)) # 构建词频分布(和你原来的逻辑一致) fdist = nltk.FreqDist(corpus_words)
预处理步骤详解
每个步骤都用正则表达式精准处理,确保效果符合需求:
- 移除行首4位数字:
re.sub(r'^\d{4}', '', line)^匹配行的开头,\d{4}精确匹配4个数字,直接替换为空字符串,完美去掉原始转录的行号。 - 移除方括号包裹内容:
re.sub(r'\[.*?\]', '', line)\[和\]是转义后的方括号(避免被正则解析为特殊语法),.*?是非贪婪匹配模式,能精准匹配每个独立的括号内容(比如一行有多个[coughing][laughing]时,会分别移除,不会误匹配中间的内容)。 - 转小写:
line.lower()
确保所有单词统一为小写形式,比如TREE会被转为tree,避免大小写导致的词频统计偏差。
额外优化建议
如果你的语料包含大量标点符号,想进一步过滤掉非单词内容,可以在转小写后添加一步:
# 移除所有非单词、非空格的字符 line = re.sub(r'[^\w\s]', '', line)
这样处理后,语料里只会保留字母、数字和空格,分词后的结果更纯净。
内容的提问来源于stack exchange,提问作者Jona
相关产品推荐
相关产品推荐

