如何优化300万条MySQL推文预处理流程适配Gensim Word2Vec训练
300万条推文语料训练Word2Vec的效率优化方案
原有代码核心性能瓶颈
- 一次性调用
fetchall()拉取全量300万条数据到内存,内存占用极高,引发系统内存交换拖慢整体速度 - 停用词用列表存储,
in成员查询时间复杂度为O(n),百万级调用下耗时会成倍增长 - 用
sentences = sentences + [xxx]做列表拼接,每次操作都会生成全新列表,时间复杂度随列表长度线性增长 - 正则表达式未预编译,每次循环都要重新解析正则规则,产生不必要的开销
- 全量语料预处理后全部存入内存列表,进一步拉高内存占用,拉长整体处理流程
具体优化方案
1. 替换停用词存储结构
将停用词列表转为set类型,将成员查询复杂度从O(n)降到O(1):
stopwords = set(open('stopwords.txt', encoding='utf-8').read().split('\n'))
2. 预编译正则表达式
提前编译正则规则,避免循环内重复编译:
# 放在循环外全局定义 pattern = re.compile(r'[^\w\s-]')
3. 优化列表操作
将列表拼接替换为append(),单次操作复杂度为O(1):
# 替换原有的sentences = sentences + [[...]]写法 sentences.append([w for w in pattern.sub(' ', p.clean(row[0])).lower().split() if w not in stopwords and len(w) > 2])
4. 自定义迭代器喂给Word2Vec(核心优化)
不需要把全量语料都加载到内存,自定义迭代器边拉取数据库数据、边预处理、边喂给模型,内存占用可降低90%以上,同时避免全量列表的操作开销:
import mysql.connector import re from gensim.models import Word2Vec import preprocessor as p # 全局预处理配置 p.set_options( p.OPT.URL, p.OPT.MENTION, p.OPT.HASHTAG, p.OPT.NUMBER ) pattern = re.compile(r'[^\w\s-]') stopwords = set(open('stopwords.txt', encoding='utf-8').read().split('\n')) # 自定义语料迭代器 class TweetCorpus: def __iter__(self): conn = mysql.connector.connect(...) # 使用非缓冲游标,分批拉取数据,避免一次性加载全表 cursor = conn.cursor(buffered=False) cursor.execute("SELECT text FROM tweet") for row in cursor: text = p.clean(row[0]) cleaned_text = pattern.sub(' ', text).lower() words = [w for w in cleaned_text.split() if w not in stopwords and len(w) > 2] if words: # 过滤空句子,避免无效输入 yield words cursor.close() conn.close() # 直接传入迭代器训练,不需要提前构造全量sentences列表 model = Word2Vec(TweetCorpus(), workers=4) # workers参数设为CPU核心数可加快训练速度
额外可选优化点
- 若预处理速度仍不满足要求,可提前用多进程批量预处理语料,将分词结果按行存到本地文本文件,后续训练直接读本地文件,避免重复请求数据库
- 可先将tweet表的text字段导出为本地CSV文件再读取,比逐行请求数据库速度更快
- 若确认preprocessor库的clean方法是性能瓶颈,可以自行编写正则规则替换,减少不必要的封装开销
内容的提问来源于stack exchange,提问作者LJG
相关产品推荐
相关产品推荐

