Python 3.5加载Google GloVe超大字典过慢,求10秒内加载方案
优化GloVe字典加载速度:从60-160秒到10秒以内的方案
嘿,我之前也踩过GloVe字典加载慢的坑,40万条100维向量的规模确实容易把脚本卡得半死。给你几个亲测有效的优化思路,应该能帮你把加载时间压到10秒以内:
一、用二进制预加载文件彻底解决文本解析开销
GloVe默认的文本格式虽然易读,但逐行解析+转换向量的开销极大。最有效的办法是一次性把文本转换成二进制格式,之后每次加载直接读二进制,速度能提升一个数量级:
预处理脚本(只需运行一次)
import numpy as np def convert_glove_to_binary(glove_txt_path, save_npy_path): embeddings_dict = {} # 用utf-8编码读取,避免乱码 with open(glove_txt_path, 'r', encoding='utf-8') as f: for line in f: values = line.split() word = values[0] # 用float32存储,既省内存又快 vector = np.asarray(values[1:], dtype="float32") embeddings_dict[word] = vector # 保存为numpy二进制文件 np.save(save_npy_path, embeddings_dict) # 执行一次转换 convert_glove_to_binary("glove.6B.100d.txt", "glove_400k_100d.npy")
快速加载代码
import numpy as np # 直接读取二进制文件,秒级加载 embeddings_dict = np.load("glove_400k_100d.npy", allow_pickle=True).item()
二、用内存映射(mmap)减少磁盘IO开销
如果不能提前预处理文本文件,试试用mmap把整个文件映射到内存,避免频繁的磁盘读写操作,比普通逐行读取快3-5倍:
import mmap import numpy as np def load_glove_fast(glove_path): embeddings_dict = {} with open(glove_path, 'r', encoding='utf-8') as f: # 映射整个文件到内存 with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as mm: # 迭代读取每一行 for line in iter(mm.readline, b''): line = line.decode('utf-8').strip() values = line.split() word = values[0] vector = np.asarray(values[1:], dtype=np.float32) embeddings_dict[word] = vector return embeddings_dict
三、NumPy批量转换向量,减少Python循环开销
逐行转换向量会产生大量Python层面的循环开销,改成批量处理能利用NumPy的底层C优化:
import numpy as np def load_glove_batch(glove_path): # 一次性读取所有行,减少IO次数 with open(glove_path, 'r', encoding='utf-8') as f: lines = f.read().splitlines() words = [] vector_list = [] for line in lines: parts = line.split() words.append(parts[0]) vector_list.append(parts[1:]) # 批量转换为float32数组,比逐行转快很多 vectors = np.array(vector_list, dtype=np.float32) # 打包成字典 embeddings_dict = dict(zip(words, vectors)) return embeddings_dict
四、借助第三方库的C实现加速
如果上面的方法还不够,试试用gensim这类专门处理词向量的库,它们的底层是C实现的,加载速度比纯Python快2-3倍:
from gensim.models import KeyedVectors # 直接加载GloVe文件,gensim会自动优化处理 model = KeyedVectors.load_word2vec_format('glove.6B.100d.txt', binary=False) embeddings_dict = dict(zip(model.index_to_key, model.vectors))
优先推荐二进制预加载的方案,这个方法的速度提升最显著,基本能直接把加载时间压到10秒以内。如果因为某些原因不能预处理,mmap或者gensim的方案也能满足需求。
内容的提问来源于stack exchange,提问作者Zichera
相关产品推荐
相关产品推荐

