如何在Pandas中分批处理数据并优化命名实体提取?
优化命名实体提取性能的实用方案
1. 用spaCy批量处理替代逐行apply
spaCy自带的nlp.pipe()是专门为批量文本处理设计的,能复用内部计算资源,还支持多进程,比逐行调用apply快好几倍。直接替换原来的处理逻辑:
# 批量处理所有文本,生成spaCy Doc对象 df['named_entities'] = list(nlp.pipe(df['NOTE'], batch_size=50, n_process=-1)) # 把每个Doc里的实体转为文本列表 df['named_entities'] = df['named_entities'].apply(lambda doc: [ent.text for ent in doc.ents])
batch_size可以根据你的内存情况调整(比如内存够就设100),n_process=-1会自动用满所有CPU核心,最大化利用硬件资源。
2. 分块处理解决内存压力
如果6400行数据一次性加载处理导致内存吃紧,可以把数据拆成小块分批处理:
chunk_size = 1000 # 每批处理1000行,可按需调整 result_chunks = [] # 对已加载的DataFrame进行切片分块 for i in range(0, len(df), chunk_size): chunk = df.iloc[i:i+chunk_size].copy() chunk['named_entities'] = list(nlp.pipe(chunk['NOTE'], batch_size=50, n_process=-1)) chunk['named_entities'] = chunk['named_entities'].apply(lambda doc: [ent.text for ent in doc.ents]) result_chunks.append(chunk) # 合并所有分块结果 df = pd.concat(result_chunks, ignore_index=True) # 后续的explode步骤不变 e_df = df.explode('named_entities').reset_index(drop=True)
3. 跳过中间列表,直接生成扁平化结果
你可以不用先在原DataFrame里存实体列表,直接生成最终需要的扁平化数据,省掉explode步骤:
entities_flat = [] # 批量处理时同时记录原行索引和实体文本 for idx, doc in enumerate(nlp.pipe(df['NOTE'], batch_size=50, n_process=-1)): for ent in doc.ents: entities_flat.append((df.index[idx], ent.text)) # 直接转成目标DataFrame e_df = pd.DataFrame(entities_flat, columns=['original_index', 'named_entities'])
这样一步到位,减少内存里的中间数据占用。
4. 额外提速小技巧
- 禁用spaCy冗余组件:如果只需要实体识别,加载模型时可以关掉不需要的组件(注意部分模型的实体识别依赖词性标注,先测试再禁用):
nlp = spacy.load("en_core_web_sm", disable=["parser", "tagger"]) - 换轻量模型:比如
en_core_web_sm比大模型en_core_web_lg快很多,如果你的场景对精度要求不是极高,优先用轻量模型。
内容的提问来源于stack exchange,提问作者Rikky Bhai
相关产品推荐
相关产品推荐

