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

时间:2018-07-16 23:46:32

标签: python numpy matrix linear-algebra

我正在使用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

2 个答案:

答案 0 :(得分:2)

我假设为了计算方差,您正在使用Wiki称为Naïve algorithm。但是,可能会在这里找到

  

由于x2_sum / row_countx_mean ** 2可以是非常相似的数字,   取消可能导致结果的精度大大降低   比浮点算法固有的精度   执行计算。因此,不应将这种算法用于   实践。如果标准偏差为   相对于均值而言较小。

作为替代,您可以使用two-pass algorithm,即先计算均值,然后在计算方差时使用它。原则上,这似乎是浪费的,因为必须对数据进行两次迭代。然而,在方差的计算中使用的“均值”不必是真实的均值,合理的估计值(也许仅从第一个块计算得出)就足够了。然后,这将简化为assumed mean的方法。

此外,一种可能性是将每个块的均值/方差的计算直接委派给numpy,然后将它们组合起来,以便使用parallel algorithm获得总体均值/方差。

答案 1 :(得分:2)

因此,我在大学里有一个项目,涉及不同矩阵乘法算法的时间复杂度测试。

我已经上传了源代码here

我发现的一项优化是,您可以通过更改for循环的结构来优化数组访问,以一次专注于行,而不是遍历列。这是由于缓存的行为具有空间局部性(例如,您的计算机尝试针对2D数组中并排而不是逐行的数组元素进行优化)

如果这些是“稀疏”矩阵(很多零元素),则可以更改数据结构以仅记录非零元素。

很显然,如果给定一个普通矩阵,那么将它们转换为稀疏矩阵的计算可能不值得,但我只是认为这些值得分享:)