基于矩阵值计算期望值:高效匹配组合概率与对应值
高效计算多数组组合的期望值总和
问题背景
给定多组概率数组与对应的值数组,需要完成以下计算:
- 生成所有跨组元素组合的发生概率(组合内元素概率相乘)
- 计算每个组合的总价值(组合内对应值元素相加)
- 计算每个组合的期望值(概率×价值),最终求和得到整体期望值
当前实现通过为概率数组附加标识符并进行字符串匹配来关联对应值,在数十亿次比较中效率极低,需基于Python 3.8和Numpy 1.24优化。
输入数据
class_p = [0.0234375, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1748046875, 0.0439453125, 0.0, 0.35302734375, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3828125] league_p = [0.4765625, 0.0, 0.00634765625, 0.4658203125, 0.0, 0.0, 0.046875, 0.0, 0.0, 0.0029296875, 0.0, 0.0, 0.0, 0.0, 0.0] a2_p = [0.1171875, 0.0, 0.0, 0.1171875, 0.0, 0.0078125, 0.30322265625, 0.31103515625, 0.0, 0.0, 0.0, 0.1435546875, 0.0, 0.0, 0.0] p1_p = [0.0, 0.03125, 0.375, 0.09375, 0.0234375, 0.0, 0.46875, 0.0078125, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] p2_p = [0.3984375, 0.0, 0.0, 0.3828125, 0.08935546875, 0.08935546875, 0.023345947265625, 0.007720947265625, 0.0, 0.0, 0.0087890625, 0.00018310546875, 0.0, 0.0, 0.0] class_v = [55, 75, 55, 75, 500, 10000, 55, 55, 55, 75, 75, 55, 55, 500, 55, 55, 75, 75, 55, 55, 55] league_v = [0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 1500, 1500, 3000] a2_v= [0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 1500, 1500, 3000] p1_v = [0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 40, 1500, 1500, 3000] p2_v = [0, 0, 0, 0, 0, 0, 0, 0, 40, 40, 40, 40, 1500, 1500, 3000]
解决方案
方案一:利用期望线性性直接计算整体期望值(最优)
根据期望线性性质,多个随机变量之和的期望值等于各变量期望值的和,无需考虑变量是否独立。这意味着无需枚举所有组合,直接计算每组的期望再求和即可,时间复杂度为O(N)(N为所有数组元素总数之和)。
import numpy as np # 将列表转换为numpy数组 class_p_np = np.array(class_p) league_p_np = np.array(league_p) a2_p_np = np.array(a2_p) p1_p_np = np.array(p1_p) p2_p_np = np.array(p2_p) class_v_np = np.array(class_v) league_v_np = np.array(league_v) a2_v_np = np.array(a2_v) p1_v_np = np.array(p1_v) p2_v_np = np.array(p2_v) # 计算单组期望值:概率×对应值的总和 exp_class = np.sum(class_p_np * class_v_np) exp_league = np.sum(league_p_np * league_v_np) exp_a2 = np.sum(a2_p_np * a2_v_np) exp_p1 = np.sum(p1_p_np * p1_v_np) exp_p2 = np.sum(p2_p_np * p2_v_np) # 整体期望值为各组期望之和 total_expected_value = exp_class + exp_league + exp_a2 + exp_p1 + exp_p2 print(f"整体期望值:{total_expected_value}")
方案二:高效生成所有组合的概率与价值(需保留单组合数据时使用)
若需要保留每个组合的概率、价值和期望值,可利用Numpy的广播机制,将数组扩展为多维结构后进行向量化运算,避免Python层面的循环和字符串匹配。
import numpy as np # 转换为numpy数组 p_arrays = [np.array(arr) for arr in [class_p, league_p, a2_p, p1_p, p2_p]] v_arrays = [np.array(arr) for arr in [class_v, league_v, a2_v, p1_v, p2_v]] # 为每个数组增加维度,实现广播匹配:将每个数组的维度调整为仅自身维度为原长度,其余为1 for idx in range(len(p_arrays)): shape = [1] * len(p_arrays) shape[idx] = p_arrays[idx].shape[0] p_arrays[idx] = p_arrays[idx].reshape(shape) v_arrays[idx] = v_arrays[idx].reshape(shape) # 计算所有组合的概率(元素级相乘) combination_chances = np.prod(p_arrays, axis=0) # 计算所有组合的价值(元素级相加) combination_values = np.sum(v_arrays, axis=0) # 计算每个组合的期望值 combination_expectations = combination_chances * combination_values # 整体期望值为所有组合期望值的总和 total_expected_value = np.sum(combination_expectations) print(f"整体期望值:{total_expected_value}")
这种方法利用Numpy的底层优化,效率远高于原字符串匹配方案,同时避免了Python循环的开销。
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

