如何在MATLAB中没有任何内置函数或循环的情况下计算协方差矩阵?

时间:2014-10-18 21:01:21

标签: matlab matrix

是否有可能在不使用MATLAB中的任何内置函数或循环的情况下找到矩阵的协方差?我完全不知道解决这个问题的想法。

我想的是:

cov(x,y) = 1/(n-1) .* (x*y)

但是,我认为这不会起作用。有什么想法吗?

2 个答案:

答案 0 :(得分:5)

这是如何数值计算协方差矩阵的一个很好的例子。 http://www.itl.nist.gov/div898/handbook/pmc/section5/pmc541.htm。但是,为了完整起见,我们将此放在这篇文章中。 我对你的意思有点困惑"内置"函数是因为协方差要求您对矩阵的列求和。如果您无法使用任何内置函数来总结这些元素,那么我不知道如何在不使用for循环的情况下执行此操作。 编辑:我想出了如何在不使用内置函数或循环的情况下执行此操作,但您需要使用size来确定矩阵中的行数。 ..除非你在函数中将其指定为常量。

在数值上,您可以像这样计算协方差矩阵:

基本上,协方差矩阵的i th 行和j th 列使得您可以得到列i的乘积之和减去列i的列j的平均值减去列j的平均值。现在,将它们相加,然后除以n - 1。这被称为unbiased estimator。您还会注意到此矩阵是对称的,因为即使您翻转顺序(即查看列j然后列i之后),答案应该仍然相同。我假设你不能使用MATLAB中的mean,所以让我们从第一原则开始。

首先,计算一个计算每列平均值的行向量。你可以做什么来计算所有列的总和,而不使用sum,因为它也是一个内置函数,将这个1s的行向量乘以矩阵A,输出将是一个行向量,包含所有列的总和。就这样,这样做:

one_vector(1:size(A,1)) = 1;
mu = (one_vector * A) / size(A,1);

第一行代码的技巧是我们动态创建一个与矩阵A中的行数长度相同的数组。我们完全填满了1s。请注意,您可以使用ones,但您说您无法使用任何内置函数。 mu将在所有列中包含我们的向量。

现在,让我们通过用平均值减去每一列来预处理数据,因为这就是我们所做的定义。要在没有任何内置函数的情况下执行此操作,您可以做的是使用各自的方法减去所有列,重复mu的次数与one_vector中的1次相同。因此:

A_mean_subtract = A - mu(one_vector, :);

这里有点棘手(而且很酷)。如果我们转置矩阵A,您将看到行成为列,列成为行。如果我们采用此转置并乘以原始矩阵,我们实际上会获得矩阵i的列j和列A之间的乘积之和。这是我们协方差计算的第一部分。然后我们除以n - 1。因此,我们的协方差就是:

covA = (A_mean_subtract.' * A_mean_subtract) / (size(A,1) - 1);

这是一个简单的例子,以及我在上面向您展示的网站上看到的内容。假设A是这样的:

A = [4 2 0.5; 4.2 2.1 0.59; 3.9 2.0 0.58; 4.3 2.1 0.62; 4.1 2.2 0.63]

A =

    4.0000    2.0000    0.5000
    4.2000    2.1000    0.5900
    3.9000    2.0000    0.5800
    4.3000    2.1000    0.6200
    4.1000    2.2000    0.6300

运行上面的代码,这就是我们得到的:

covA =

    0.0250    0.0075    0.0042
    0.0075    0.0070    0.0034
    0.0042    0.0034    0.0026

您会发现这也与MATLAB中的cov函数匹配:

>> cov(A)

ans =

0.0250    0.0075    0.0042
0.0075    0.0070    0.0034
0.0042    0.0034    0.0026

提示

如果您在MATLAB命令提示符下键入edit cov,您实际上可以看到他们如何在没有任何for循环的情况下计算协方差矩阵......这与我给你的答案基本相同:)

如果您想更有效地执行此操作

假设您可以使用sumbsxfun,我们可以在更少(更有效率)的代码行中执行此操作。首先,使用sum

计算平均向量,就像我们上面所做的那样
mu = sum(A) / size(A,1);

现在,要使用每列相应的平均值减去矩阵A,您可以使用bsxfun来帮助您进行此减法:

A_mean_subtract = bsxfun(@minus, A, mu);

现在,像以前一样计算你的协方差矩阵:

covA = (A_mean_subtract.' * A_mean_subtract) / (size(A,1) - 1);

你应该得到与我们之前看到的完全相同的结果。

关于稳定性的小注释

我们正在使用定义来计算两列之间协方差的直接定义。但是,已经证明,如果提供某些类型的数据,使用直线定义可能会导致数值不稳定。请参考this Wikipedia page,该算法通过各种算法计算两个n长度向量之间的协方差,这些向量更稳定。

答案 1 :(得分:0)

enter image description here

这是合法的方法吗?