如何加速Python中50×50矩阵的指定规模组合生成?
优化50×50矩阵组合生成速度的方案
原代码的核心性能瓶颈
- 重复生成组合列表:每次循环都将
combinations生成器转为列表,还通过索引取元素,导致组合被重复计算N次(N为循环次数),完全冗余。 - 过度依赖Pandas DataFrame:大量可以用Numpy完成的计算(邻接矩阵生成、求和、均值)被包装成DataFrame,带来巨大的性能开销。
- 冗余的DataFrame操作:
dd11的拼接完全没必要,a和m都是标量,直接使用即可。 - 低效的字典构建:内层循环逐个赋值字典,不如字典推导式高效。
优化后的代码
from itertools import combinations import numpy as np import pandas as pd def ProduceAllPossibleCombinationsDictionary(CurrentNetworkMatrix, number_of_combinations): num_combination = number_of_combinations test_list = CurrentNetworkMatrix.columns test = [] # 直接遍历combinations生成器,避免重复创建组合列表 for key in combinations(test_list, num_combination): # 将切片矩阵转为Numpy数组,减少Pandas开销 mat_np = CurrentNetworkMatrix.loc[key, key].to_numpy() # 生成对称邻接矩阵,全部用Numpy操作 adj = np.triu(mat_np, k=1) adj += adj.T # 直接计算总和与均值,无需转DataFrame total_sum = np.sum(adj) mean_val = np.mean(adj) # 用字典推导式一次性构建结果字典,替代内层循环 controllability_combination_mean = {node: (key, mean_val) for node in key} test.append(controllability_combination_mean) return test
优化点解释
- 遍历生成器而非重复创建列表:
combinations是惰性生成器,直接遍历它可以让每个组合只生成一次,避免重复计算的巨大开销。 - Numpy替代冗余DataFrame操作:Numpy数组的计算速度远快于Pandas DataFrame,尤其是矩阵操作场景,能大幅降低计算时间。
- 移除冗余DataFrame拼接:直接使用标量变量存储均值和总和,省去不必要的DataFrame包装与合并步骤。
- 字典推导式简化循环:用字典推导式一次性生成结果字典,比逐个循环赋值更高效。
进阶优化:并行计算(适用于组合数量适中的场景)
如果优化后速度仍不满足需求,可以利用多核CPU并行处理组合:
from itertools import combinations import numpy as np import pandas as pd from joblib import Parallel, delayed def process_single_combination(key, matrix): mat_np = matrix.loc[key, key].to_numpy() adj = np.triu(mat_np, k=1) adj += adj.T mean_val = np.mean(adj) return {node: (key, mean_val) for node in key} def ProduceAllPossibleCombinationsDictionary(CurrentNetworkMatrix, number_of_combinations): num_combination = number_of_combinations test_list = CurrentNetworkMatrix.columns all_combinations = list(combinations(test_list, num_combination)) # 并行处理,n_jobs=-1表示使用所有CPU核心 test = Parallel(n_jobs=-1)(delayed(process_single_combination)(key, CurrentNetworkMatrix) for key in all_combinations) return test
关键提示
注意:50×50矩阵的组合数可能是天文数字,比如C(50,25)=2.25×10¹³,这种规模下无论怎么优化都不可能生成全部组合。如果你的需求是处理这类大组合数场景,建议改为采样部分组合,而非生成所有组合。
内容的提问来源于stack exchange,提问作者SnM
相关产品推荐
相关产品推荐

