【问题标题】:MATLAB: Efficient way to calculate a covariance matrix from this dataMATLAB:从该数据计算协方差矩阵的有效方法
【发布时间】:2015-10-19 21:00:58
【问题描述】:

我有一个数据文件,其中有 N=428 个受试者,每个受试者回答相同的 8 个问题。它看起来像这样:

 question subject  score    
    1        1       42         
    2        1       12
    3        1       13
    4        1       43
    5        1       22
    6        1       43 
    7        1       54
    8        1       66
    1        2       41
    2        2       11
   ...      ...     ...

我想计算并存储一个反映每个科目分数的协方差矩阵。

所以单元格 (1,1) 具有主题 1 的方差。那么单元格 (1,2) 和 (2,1) 将具有相同的值,即主题 1 和主题 2 之间的协方差。虽然在上表中您看不到主题 2 的所有数据,但看起来它们与主题 1 会有一些正协方差。

n 选择 k 必须计算唯一的协方差,我算出总共是 91378。

我怎样才能有效地做到这一点?

编辑:使用来自@GameOfThrows 的代码,我能够使用循环获得工作版本:

crowd_cov = NaN(428,428);

for i = 1:length(allpairs)
    Z = cov(score(indexSub1(i,1):indexSub1(i,2)),score(indexSub2(i,1):indexSub2(i,2)));
    first = allpairs(i,1);
    second = allpairs(i,2);
    crowd_cov(first,first) = Z(1,1);
    crowd_cov(second,second) = Z(2,2);
    crowd_cov(first,second) = Z(1,2);
    crowd_cov(second,first) = Z(2,1);
end

对此我很满意,尽管我仍然欢迎解释如何更有效地编码。

【问题讨论】:

  • 查找并存储每列的平均值,然后取每个条目与相应列平均值之间的平方差。还要记住,在你的协方差矩阵中,协方差 (i,j) = covariance(j,i)
  • 你建议我取所有 8×428 = 3424 分数的平均值,也就是 32.64。然后我取第一行 42-32.64 并将其平方,并对所有行执行相同操作。我该如何从那一点开始?
  • 我有点迷茫,为什么不用Matlab协方差函数(cov(A,B))对每个科目做协方差?
  • 我打算这样做,但我想知道在我的数据矩阵设置下如何最好地应用该函数。

标签: matlab covariance


【解决方案1】:

所以你想要协方差,它告诉我你有两个随机变量,比如科目 1 的分数和科目 2 的分数,我们现在希望列问题不会在这方面发挥重要作用,但是如果每个主题的问题数量相同,那么它将极大地提高程序的效率(因为它允许快速索引)。

allpairs = combnk(1:max(subject),2) %// all possible combinations of subjects starting from subject 1 to subject N and the 2 means you want pairs. 

现在请注意,这没有重复,因此 sub 1 vs sub 2 只发生一次, sub 2 vs sub 1 不存在。

现在你想对每一对做 matlab cov (你需要正确索引分数)。这就是如果你有相同数量的问题,它会为你节省很多时间,比如每个主题 8 个问题:

indexSub1 = [(allpairs(:,1)*8 -7),(allpairs(:,1)*8)]
indexSub2 = [(allpairs(:,2)*8 -7),(allpairs(:,2)*8)]

现在你有了所有正确的索引,你可以使用 cov;作为一个函数,将其应用于

的每 8 个元素
cov(score(indexSub1),score(indexSub2)).

如果问题的数量不相同,那么您可能必须使用 find 来正确索引,这会使您的程序变慢一点。

最后,您可以将矩阵转换为单元格并使用 cellfun 来应用 cov,或者您可以使用循环来进行更简单的表示(我建议使用循环吗?不)。

编辑:

为了澄清,我的建议是你有你的 indexSub1 和 indexSub2,你可以将它们转换成 91378*2 个单元格,其中每个单元格由 8 个分数组成。这将允许您使用 Matlab 的 cellfun(将函数应用于每个单元格)。这将大大提高您的速度。

【讨论】:

  • 每个主题的问题数相同 - 为 8。当我运行此代码时,我收到错误消息“未定义函数 'score' 用于输入参数类型为 'double'。”分数是否意味着其他东西?
  • 我现在意识到分数应该是分数的向量。当我这样做时,代码可以工作,尽管它只产生一个 2x2 协方差矩阵。您能否解释一下“将其应用于每 8 个元素”是什么意思?
  • @user1205901 如果两个随机变量的大小相同,则 Matlab cov 函数返回一个 2x2 协方差矩阵,在您的情况下,如果它们都有 8 个问题,那么您将得到一个 2x2 协方差矩阵每一对。
  • 另外,当我说将它应用于每 8 个元素时,我真正的意思是你可以在不使用 for 循环的情况下完成整个过程。考虑一下:如果我从 indexSub1 和 indexSub2(指 1 对)中取每 8 个分数并将它们放入一个单元格中,我应该有 91378 * 2 个单元格,其中每个单元格由 8 个分数组成。我现在可以使用 cellfun 将 cov 函数应用于每个单元格(这是一个比循环快得多的并行过程)。
猜你喜欢
  • 2012-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-13
  • 1970-01-01
  • 2013-06-30
  • 1970-01-01
相关资源
最近更新 更多