根据约束选择不相关的子集

时间:2016-01-08 00:18:32

标签: r algorithm performance subset correlation

考虑一个相关矩阵r,表示变量110之间的相关性:

r <- matrix(c(1, 0.61, 0.67, -0.14, 0.93, 0.77, 0.42, 0.61, 0.49, 0.97, 0.61, 
              1, 0.91, 0.26, 0.81, 0, 0.91, 0.67, -0.25, 0.66, 0.67, 0.91, 
              1, -0.15, 0.76, 0.24, 0.66, 0.78, -0.14, 0.63, -0.14, 0.26, -0.15, 
              1, 0.16, -0.56, 0.63, -0.31, -0.25, 0.11, 0.93, 0.81, 0.76, 0.16, 
              1, 0.51, 0.72, 0.61, 0.28, 0.97, 0.77, 0, 0.24, -0.56, 0.51, 
              1, -0.24, 0.34, 0.78, 0.65, 0.42, 0.91, 0.66, 0.63, 0.72, -0.24, 
              1, 0.41, -0.32, 0.57, 0.61, 0.67, 0.78, -0.31, 0.61, 0.34, 0.41, 
              1, -0.09, 0.53, 0.49, -0.25, -0.14, -0.25, 0.28, 0.78, -0.32, 
              -0.09, 1, 0.45, 0.97, 0.66, 0.63, 0.11, 0.97, 0.65, 0.57, 0.53, 
              0.45, 1), 10)

r看起来像这样:

##        [,1]  [,2]  [,3]  [,4] [,5]  [,6]  [,7]  [,8]  [,9] [,10]
##  [1,]  1.00  0.61  0.67 -0.14 0.93  0.77  0.42  0.61  0.49  0.97
##  [2,]  0.61  1.00  0.91  0.26 0.81  0.00  0.91  0.67 -0.25  0.66
##  [3,]  0.67  0.91  1.00 -0.15 0.76  0.24  0.66  0.78 -0.14  0.63
##  [4,] -0.14  0.26 -0.15  1.00 0.16 -0.56  0.63 -0.31 -0.25  0.11
##  [5,]  0.93  0.81  0.76  0.16 1.00  0.51  0.72  0.61  0.28  0.97
##  [6,]  0.77  0.00  0.24 -0.56 0.51  1.00 -0.24  0.34  0.78  0.65
##  [7,]  0.42  0.91  0.66  0.63 0.72 -0.24  1.00  0.41 -0.32  0.57
##  [8,]  0.61  0.67  0.78 -0.31 0.61  0.34  0.41  1.00 -0.09  0.53
##  [9,]  0.49 -0.25 -0.14 -0.25 0.28  0.78 -0.32 -0.09  1.00  0.45
## [10,]  0.97  0.66  0.63  0.11 0.97  0.65  0.57  0.53  0.45  1.00

此外,每个变量都有一个特定的&#34;得分&#34;。对于变量1到10,让我们分配分数1:10

score <- 1:10

我想选择与绝对值不大于n相关的thr变量子集(忽略对角线)。根据{{​​1}},可能存在许多此类子集。我想确定最小化总和&#34;得分的子集&#34;。

这是一个痛苦的手动操作,并且考虑所有子集对于大型矩阵是不可行的,除非n合理地接近候选变量的数量,或者1.是否有效的方法自动化程序?

FWIW,以下是全子集解决方案的外观:

n

以上表明以下变量组合最小化了总和得分,而绝对值与0.8之间没有相关性。

thr <- 0.8 # I use the term uncorrelated loosely in the title ;)
n <- 4
combos <- combn(ncol(r), n)
summed_score <- apply(combos, 2, function(x) {
  z <- abs(r[x, x])
  if(any(z[lower.tri(z)] > thr)) NA else sum(score[x])
})

min(summed_score, na.rm=T)
## [1] 13

which.min(summed_score)
## [1] 9

2 个答案:

答案 0 :(得分:2)

如果你能有效地解决这个问题,我认为你可以通过创建一个反映图中边缘是否存在的相关矩阵来有效地解决https://en.wikipedia.org/wiki/Independent_set_%28graph_theory%29#Finding_maximum_independent_sets。我假设如果你使用非常小的数字进行非零相关,你将产生一个实际可能发生的相关矩阵。如果是这种情况,那么你的问题是最糟糕的,因为最大的独立集是最坏的情况,尽管对于该链接提到的特殊情况有一些希望。不幸的是,一般近似似乎也是最坏的情况。

你能否决定你真的想要一些转化为更简单的图形问题的东西,例如找到哪些点直接或间接相互连接,你可以通过https://en.wikipedia.org/wiki/Disjoint-set_data_structure找到它们?

答案 1 :(得分:1)

我认为您应该订购combos,以便您按此顺序尝试

combos[,order(apply(combos,2,sum))]

然后,如果它通过约束(即没有任何高于阈值的相关性),那将是最好的解决方案,你可以停止搜索。

请参阅评论中的jbaums代码:

combos <- combos[, order(apply(combos, 2, function(x) sum(score[x])))];
for(i in seq_len(ncol(combos))) {
    z <- abs(r[combos[, i], combos[, i]]); 
    if(!any(z[lower.tri(z)] > thr)) break()
}

> combos[, i]
[1] 1 2 4 6