如何加速Python中6000首歌曲歌词的Word Embedding计算?
优化歌词Word Embedding计算速度的方法
核心性能瓶颈分析
你的代码存在几个关键低效点:重复调用Spacy的NLP管道、加载冗余组件、遍历方式不合理、未利用批量处理能力,这些导致处理6000首歌时耗时过长。以下是针对性的优化方案:
1. 消除Spacy管道重复调用
原代码中已通过nlp(text)生成完整的Doc对象,但又对每个token重新调用nlp(t)获取向量——这完全是冗余操作,每个Token对象本身自带vector属性,直接调用即可节省大量重复计算。
2. 精简Spacy管道组件
en_core_web_lg默认加载的parser、ner等组件对词嵌入计算毫无用处,反而占用大量资源。只保留必要的组件(tagger、lemmatizer)可大幅提速。
3. 优化文本遍历与批量处理
使用Spacy的nlp.pipe()批量处理文本,能更好地利用多核CPU;直接迭代DataFrame的Lyric列,避免iloc的索引查找开销。
4. 预分配内存存储结果
用Numpy数组预分配固定大小的存储空间,替代列表append的动态内存分配,进一步提升效率。
5. 优化CSV读取逻辑
用glob批量匹配CSV文件,代码更简洁,同时设置low_memory=False避免大文件读取的潜在问题。
完整优化代码
import os import glob import pandas as pd import numpy as np import spacy from tqdm.notebook import tqdm import warnings warnings.filterwarnings("ignore") # 批量读取CSV文件,优化读取效率 csv_files = glob.glob('songs/*.csv') songs = pd.concat( (pd.read_csv(file, index_col=None, header=0, low_memory=False) for file in csv_files), axis=0, ignore_index=True ) songs = songs.drop(columns=['Album', 'Date','Unnamed: 0']) # 加载Spacy模型,禁用不需要的管道组件 nlp = spacy.load('en_core_web_lg', disable=['parser', 'ner']) # 预分配Numpy数组存储结果(en_core_web_lg的向量维度为300) song_embeddings = np.zeros((len(songs), 300)) # 批量处理歌词文本,结合进度条 for idx, doc in enumerate(tqdm(nlp.pipe(songs['Lyric'], batch_size=32), total=len(songs))): # 过滤停用词、标点,提取有效token的向量 valid_vectors = [token.vector for token in doc if not token.is_stop and not token.is_punct] if valid_vectors: song_embeddings[idx] = np.mean(valid_vectors, axis=0) else: # 处理无有效token的情况,设为全0向量 song_embeddings[idx] = np.zeros(300)
额外优化建议
- 若不需要词形还原,可进一步禁用
lemmatizer组件,仅保留tagger(或直接禁用所有管道,仅用向量查找); - 根据你的CPU核心数调整
batch_size(建议16-64之间),内存充足时可适当增大; - 若数据集持续增长,可考虑结合
multiprocessing模块做多进程处理,不过Spacy的nlp.pipe()已做了多核优化,多数场景下足够。
内容的提问来源于stack exchange,提问作者xSamx02
相关产品推荐
相关产品推荐

