如何使用NumPy加速列表元素字典存在性校验及特征向量生成
NumPy加速二元组特征向量生成方案
核心思路
提前把固定的二元组词表做索引映射,预处理仅执行一次,处理句子时用NumPy向量化操作代替Python层级循环,消除冗余的字典排序、创建开销。
预处理代码(仅执行一次)
import numpy as np # 按字典序排序二元组词表,和原有逻辑的排序规则完全对齐 sorted_bigrams = sorted(self.bigram_freq.keys()) # 建立二元组到数组索引的映射表 bigram_to_idx = {gram: idx for idx, gram in enumerate(sorted_bigrams)} # 特征向量的固定维度 feature_dim = len(sorted_bigrams)
计数特征版本(和原有逻辑完全对齐,统计二元组出现次数)
outputVector = [] for sentence in sentences: bigram_pairs = self.retrieve_pairs(sentence) # 初始化全零特征向量 feat_vec = np.zeros(feature_dim, dtype=np.int32) # 过滤出存在于词表的二元组对应的索引 valid_idx = [bigram_to_idx[pair] for pair in bigram_pairs if pair in bigram_to_idx] # 对应索引位置累加计数,重复出现的二元组会自动叠加 np.add.at(feat_vec, valid_idx, 1) # 可按需选择保留NumPy数组或者转成Python列表 outputVector.append(feat_vec.tolist())
二值特征版本(使用np.where实现,只要出现过就标记为1,不统计次数)
如果你只需要判断二元组是否出现,不需要计数,可以用这个实现,完全匹配你提到的np.where思路:
outputVector = [] for sentence in sentences: bigram_pairs = self.retrieve_pairs(sentence) # 生成词表中每个二元组是否在当前句子出现的掩码 exist_mask = np.isin(sorted_bigrams, bigram_pairs) # 用np.where生成二值特征向量 feat_vec = np.where(exist_mask, 1, 0).astype(np.int32) outputVector.append(feat_vec.tolist())
性能优化点
- 原有逻辑中每个句子循环内的字典创建、排序操作被移到预处理阶段,仅执行一次,大幅降低线性开销
- NumPy向量化操作替代Python层级的键值对遍历,在万级以上句子、千级以上二元组词表的场景下,速度可提升10~100倍
- 若后续计算仍使用NumPy接口,可以直接保留数组格式,不需要转Python列表,进一步节省开销
内容的提问来源于stack exchange,提问作者Abhiram Natarajan
相关产品推荐
相关产品推荐

