如何高效将高维数据应用到低维函数?以皮尔逊相关计算为例
解决三维数组与均值数组的批量皮尔逊相关系数计算问题
首先得说清楚为什么你直接调用pearsonr(data, means)会失败:scipy.stats.pearsonr本质是为两个长度相同的一维数组设计的——要么传两个一维数组,要么传两个形状完全一致的多维数组(它会自动展平成一维计算整体相关系数)。但你的data是三维数组(5,100,300),means是二维数组(5,300),维度不匹配,而且你要的是批量计算多个序列对的相关系数,不是单个整体的,所以直接调用肯定报错。
我先假设你的真实需求(毕竟“每个元素与均值数组的相关系数”表述不太准确,皮尔逊相关系数是序列之间的统计量):你应该是想对每个样本(第0维)的每个时序步(第1维),计算该时序步的特征向量(长度300)与对应样本的均值特征向量(长度300)之间的皮尔逊相关系数,最终得到形状为(5,100)的结果。如果是这个需求,下面给你两种实现方式:
方式一:循环实现(简单直观,适合小数据)
这种方式代码易懂,逐个遍历每个样本和时序步,调用pearsonr计算:
import numpy as np from scipy.stats import pearsonr # 你的原始数据 data = np.zeros((5, 100, 300)) means = data.mean(axis=1) # 形状(5, 300) # 初始化结果数组,存储每个样本每个时序步的相关系数 corrs = np.zeros((5, 100)) for sample_idx in range(data.shape[0]): for time_step in range(data.shape[1]): # 取出当前样本当前时序步的特征向量,和该样本的均值特征向量 current_seq = data[sample_idx, time_step, :] mean_seq = means[sample_idx, :] # 计算相关系数,只保留系数,忽略p值 corr, _ = pearsonr(current_seq, mean_seq) corrs[sample_idx, time_step] = corr
方式二:向量化批量计算(速度极快,适合大数据)
如果数据量很大,循环会很慢,这时候可以用numpy手动实现皮尔逊相关系数的公式,全程向量化计算:
import numpy as np data = np.zeros((5, 100, 300)) means = data.mean(axis=1) # 形状(5, 300) # 把means扩展一个维度,匹配data的时序维度,变成(5,100,300) means_expanded = np.expand_dims(means, axis=1) # 计算每个特征向量的均值 data_mean = data.mean(axis=2, keepdims=True) # 形状(5,100,1) means_mean = means.mean(axis=1, keepdims=True) # 形状(5,1) # 把means_mean扩展到(5,100,1),方便后续计算 means_mean_expanded = np.expand_dims(means_mean, axis=1) # 计算协方差:对应元素相乘后沿特征维度求和 cov = ((data - data_mean) * (means_expanded - means_mean_expanded)).sum(axis=2) # 计算两个序列的标准差 data_std = np.sqrt(((data - data_mean)**2).sum(axis=2)) means_std = np.sqrt(((means - means_mean)**2).sum(axis=1)) # 扩展means_std到(5,100),匹配data_std的形状 means_std_expanded = np.expand_dims(means_std, axis=1) # 计算相关系数,同时处理标准差为0的情况(避免除以0报错) corrs = np.divide( cov, data_std * means_std_expanded, where=(data_std != 0) & (means_std_expanded != 0) ) # 对于标准差为0的情况,直接设为NaN(或者0,根据你的需求调整) corrs[(data_std == 0) | (means_std_expanded == 0)] = np.nan
额外提醒
如果你真的是想计算data[i,:,j](长度100的时序序列)和常数means[i,j]的相关系数,那这个需求其实没有统计意义——因为常数序列的方差为0,皮尔逊相关系数的分母会变成0,结果要么无定义,要么为0。这种情况下建议重新确认你的需求哦。
内容的提问来源于stack exchange,提问作者mFoxRU
相关产品推荐
相关产品推荐

