计算大矩阵(300000 x 70000)的均值和协方差



我正在使用Numpy,并试图计算一个大矩阵(300000 x 70000(的均值和协方差。我有32GB大小的可用内存。就计算效率和易实现性而言,这项任务的最佳实践是什么?

我目前的实现如下:

def compute_mean_variance(mat, chunk_size):
row_count = mat.row_count
col_count = mat.col_count
# maintain the `x_sum`, `x2_sum` array
# mean(x) = x_sum / row_count
# var(x) = x2_sum / row_count - mean(x)**2
x_sum = np.zeros([1, col_count])
x2_sum = np.zeros([1, col_count])
for i in range(0, row_count, chunk_size):
sub_mat = mat[i:i+chunk_size, :]
# in-memory sub_mat of size chunk_size x num_cols
sub_mat = sub_mat.read().val
x_sum += np.sum(sub_mat, 0)
x2_sum += x2_sum + np.sum(sub_mat**2, 0)
x_mean = x_sum / row_count
x_var = x2_sum / row_count - x_mean ** 2
return x_mean, x_var

有什么改进的建议吗?

我觉得下面的实施应该更容易理解。它还使用numpy来计算列块的平均值和标准偏差。因此,它应该更有效,数值更稳定。

def compute_mean_std(mat, chunk_size):
row_count = mat.row_count
col_count = mat.col_count
mean = np.zeros(col_count)
std = np.zeros(col_count)
for i in xrange(0, col_count, chunk_size):
sub_mat = mat[:, i : i + chunk_size]
# num_samples x chunk_size
sub_mat = sub_mat.read().val
mean[i : i + chunk_size] = np.mean(sub_mat, axis=0)
std[i : i + chunk_size] = np.std(sub_mat, axis=0)
return mean, std

我假设为了计算方差,您正在使用Wiki所称的Naïve算法。然而,人们可能会发现:

由于CCD_ 1和CCD_,取消可能会导致结果的精度大大降低浮点运算的固有精度执行计算。因此,不应在实践如果标准偏差为相对于平均值较小。

作为一种替代方案,您可以使用两遍算法,即首先计算平均值,然后将其用于方差计算。原则上,这似乎是浪费,因为必须对数据进行两次迭代。然而,计算方差时使用的"平均值"不需要是真正的平均值,一个合理的估计(可能只从第一块计算(就足够了。这将简化为假设平均值的方法。

此外,一种可能性是将每个块的平均值/方差的计算直接委托给numpy,然后将它们组合,以便使用并行算法获得总体平均值/偏差。

所以我在大学有一个项目,涉及不同矩阵乘法算法的时间复杂性测试。

我已经在这里上传了源代码。

我发现的一个优化是,可以通过更改for循环的结构来优化数组访问,使其一次关注行,而不是遍历列。这是由于缓存在空间局部性方面的行为方式(即,您的计算机试图优化并排的阵列元素,而不是2D阵列中的逐行阵列元素(

此外,如果这些是"稀疏"矩阵(许多归零元素(,您可以更改数据结构,只记录非归零元素。

显然,如果你得到一个正规矩阵,将它们转换为稀疏矩阵的计算可能不值得,但我只是认为这些是值得分享的观察结果:(

最新更新