You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多分组特征下子集数据均值的高效向量化计算方案咨询

双分组场景下的高效向量化均值计算

需求背景

基于两个分组特征(分别包含4个和5个分组),计算每个(i,j)组合分组对应的observables数据均值。

非向量化实现代码

import numpy as np

N = 110
observables = np.random.rand(N)

I = np.random.randint(np.array([0,0])[:,None], np.array([4,5])[:,None], 
                     size=(2,N))

# 可将I理解为对数据的两种分组标记,一组有4个分组,另一组有5个分组
# 需要计算所有i(第一组索引)和j(第二组索引)组合对应的均值
averages = np.zeros((4,5))

# 非向量化实现
for i in range(4):
 for j in range(5):
   J = np.argwhere((I[0,:]==i) & (I[1,:]==j)).flatten()
   averages[i,j] = np.mean(observables[J])

尝试的低效向量化实现

当N较大(如N=1000)时,因最小公倍数(LCM)导致数据量激增,效率极低:

import math

# 低效的向量化实现
J = [np.argwhere((I[0,:]==i) & (I[1,:]==j)).flatten() for i in range(4)
     for j in range(5)]
lengths = [len(j) for j in J]

L = math.lcm(*lengths)

J = np.array([np.tile(j,int(L/len(j))) for j in J])

averages_vectorized = np.reshape(np.mean(observables[J], axis=1), (4,5))

其他尝试(本质仍含循环)

列表推导式实现,本质是隐藏的循环:

J = [np.argwhere((I[0,:]==i) & (I[1,:]==j)).flatten() for i in range(4)
     for j in range(5)]

averages_list_comrehension = np.reshape(np.array([np.mean(observables[j]) for j in J]), (4,5))

待验证思路

曾考虑在observables末尾添加nan值,扩展索引至统一长度后用np.nanmean计算,但需适配PyTensor张量场景,不确定PyTensor是否支持nan张量及nanmean操作。


高效向量化解决方案

方案1:利用np.bincount实现分组统计

将二维的(i,j)分组转换为一维唯一索引,通过bincount分别计算每组总和与数量,最终相除得到均值:

# 将(i,j)转换为唯一的一维索引:i*5 + j(第二组共5个分组)
group_ids = I[0] * 5 + I[1]

# 计算每组的观测值总和
sum_vals = np.bincount(group_ids, weights=observables, minlength=4*5)
# 计算每组的元素数量
counts = np.bincount(group_ids, minlength=4*5)

# 处理空分组(避免除以0),若需保留空值为nan可跳过此步
counts[counts == 0] = 1
averages = sum_vals / counts

# 重塑为(4,5)的结果矩阵
averages = averages.reshape(4,5)

该方法完全向量化,无显式/隐式循环,时间复杂度O(N),大N场景下效率极高。

方案2:利用np.add.at进行累加

通过广播索引直接对结果矩阵累加观测值和计数,再计算均值:

averages = np.zeros((4,5))
counts = np.zeros((4,5))

# 按分组索引累加观测值和计数
np.add.at(averages, (I[0], I[1]), observables)
np.add.at(counts, (I[0], I[1]), 1)

# 计算均值,自动处理空分组(空分组结果为nan)
averages = np.divide(averages, counts, where=counts!=0)

此方法同样完全向量化,逻辑直观,性能与bincount方案接近。

针对PyTensor场景的适配

PyTensor支持bincount操作,无需依赖nan值处理,适配代码如下:

import pytensor.tensor as pt

# 假设observables和I为PyTensor张量
group_ids = I[0] * 5 + I[1]
sum_vals = pt.bincount(group_ids, weights=observables, minlength=20)
counts = pt.bincount(group_ids, minlength=20)

# 处理除以0,空分组设为0(可根据需求调整)
averages = pt.where(counts != 0, sum_vals / counts, pt.zeros_like(sum_vals))
averages = averages.reshape((4,5))

内容的提问来源于stack exchange,提问作者Sina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:43:24