Python中高效查找131000个300维重复数组的方法
高效找出大规模向量列表中的重复项
兄弟,你这双重循环的思路在小数据量下凑活能用,但面对131000个300维向量时,直接就拉胯了——毕竟O(n²)的时间复杂度意味着要执行1.7万亿次迭代,每一次还要做300个元素的逐值比较,这速度慢到离谱完全在意料之中。
咱们来换几个高效的思路,都是O(n)或者接近线性时间的方案:
方案1:用Numpy原生的unique函数(最优解)
Numpy的unique方法是用C实现的,效率拉满,专门处理这种大规模数组去重的场景,还能直接返回每个向量的出现次数。
import numpy as np # 先把你的列表转成2D Numpy数组(比纯Python列表处理快得多) embeddings_matrix = np.array(wordEmbeddings) # 按行去重,同时返回每个唯一行的出现次数 unique_embs, counts = np.unique(embeddings_matrix, axis=0, return_counts=True) # 提取出现次数>1的重复向量 duplicate_embs = unique_embs[counts > 1] # 计算总重复对数(和你原代码的count逻辑一致:每个重复对会被统计两次,比如A和B重复,i=A,j=B算一次,i=B,j=A又算一次) total_duplicate_pairs = sum(cnt * (cnt - 1) for cnt in counts if cnt > 1)
这个方法是最快的,因为完全利用了Numpy的底层优化,几乎没有Python层面的循环开销。
方案2:将向量转为可哈希类型,用字典统计
如果因为某些原因不能用Numpy的unique,可以把每个向量转换成可哈希的类型(比如元组或字节串),然后用字典统计出现次数。字典的查找是O(1)的,整体时间复杂度是O(n*300),比双重循环快几个数量级。
子方案2.1:转元组
import numpy as np from collections import defaultdict embeddings_matrix = np.array(wordEmbeddings) # 把每个行向量转成元组(Numpy数组不可直接哈希,元组可以) tuple_embs = [tuple(row) for row in embeddings_matrix] # 统计每个向量的出现次数 count_dict = defaultdict(int) for emb in tuple_embs: count_dict[emb] += 1 # 提取重复项和计算总对数 duplicates = [np.array(emb) for emb, cnt in count_dict.items() if cnt > 1] total_duplicate_pairs = sum(cnt * (cnt - 1) for cnt in count_dict.values())
子方案2.2:转字节串(更快)
用Numpy的view把向量转成字节串,这个操作是内存共享的,比转元组更高效:
import numpy as np from collections import defaultdict embeddings_matrix = np.array(wordEmbeddings) # 把每个行向量转成字节串(注意dtype要和原数组一致,比如原数组是float32就用np.float32) byte_embs = embeddings_matrix.view(np.float64).reshape(embeddings_matrix.shape[0], -1) hashable_embs = [bytes(row) for row in byte_embs] count_dict = defaultdict(int) for emb in hashable_embs: count_dict[emb] += 1 # 把字节串转回原向量 duplicates = [] for emb_bytes, cnt in count_dict.items(): if cnt > 1: original_emb = np.frombuffer(emb_bytes, dtype=np.float64).reshape(300,) duplicates.append(original_emb) total_duplicate_pairs = sum(cnt * (cnt - 1) for cnt in count_dict.values())
注意事项
- 如果你的向量里有浮点数精度问题(比如两个向量理论上相等,但因为计算误差有微小差异),直接用
array_equal或unique会漏判。这时候可以先对向量做量化处理,比如np.round(embeddings_matrix, decimals=6),把浮点数保留6位小数后再去重。 - 优先用方案1的
np.unique,速度最快,代码也最简洁。
内容的提问来源于stack exchange,提问作者Harsh2093
相关产品推荐
相关产品推荐

