【问题标题】:Find max and min matrix marginal total variability查找最大和最小矩阵边际总变异性
【发布时间】:2016-11-20 12:47:51
【问题描述】:

有没有更优雅的方法来计算基于其填充和大小的二进制矩阵的边际列总数中的最大最小可变性水平 (CV) ?考虑到所有行和列的总计必须非零。例如

foo(n_col, n_row, fill){ get maximum possible CV }

假设我们有一个名为m 的矩阵,其中所有列和行的总数为> 0,但矩阵的填充最少。

m <- matrix(rep(0,25), nrow = 5)
diag(m) <- 1
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    1    0    0    0    0
#[2,]    0    1    0    0    0
#[3,]    0    0    1    0    0
#[4,]    0    0    0    1    0
#[5,]    0    0    0    0    1

variability1 <- sd(colSums(m))/mean(colSums(m))
variability1
# [1] 0
# the maximum and minimum for this fill is zero 
# considering that  all column and row totals must be > 0

也许我们可以在增加填充水平时检查最大值,例如:

# find out which matrix elements are zeros
empty <- which(m < 1)
# vector for results
variability <- rep(NA, length(empty))
#
for(i in 1:length(variability)){
m[empty[[i]] ] <- 1
variability[[i]] <- sd(colSums(m))/mean(colSums(m))
}
# we get what should the maximum CV for each given level of matrix fill...
c(variability1, variability)

我认为像这样按列填充矩阵可以保持边际列总数的最大可变性?对于不同大小、填充和形状的矩阵,是否有更简单的方法来实现最大和最小可变性?

【问题讨论】:

    标签: r matrix


    【解决方案1】:

    以下提供了问题的另一种表述,作为对二元矩阵的列和向量选择的优化,该二元矩阵的列和向量最大化给定fill 的可变性。提供了该公式有效性的非正式论点以及解决该公式的结果算法。生成的算法与 OP 的断言一致

    像这样按列填充矩阵可以保持边缘列总数的最大可变性

    首先,将fill 定义为n_rown_col 二进制矩阵m1 的数量。从问题陈述的约束条件来看,m 是一个所有行和列之和都大于零的二进制矩阵,fill[max(n_row, n_col),n_row*n_col] 范围内的整数。

    那么问题是对于fill 范围内[max(n_row, n_col),n_row*n_col] 的给定值,找到最大值

     sd(colSums(m))/mean(colSums(m))
    

    在所有m 中,m 是一个二进制矩阵,其中fill 的数量为1,并且所有行和列的总和都大于零。

    我们注意到,最好根据m 的列和的向量而不是m 本身来指定此优化问题的域。这是因为存在不同的m 具有相同的列和向量,因此存在相同的目标值。将列和的向量表示为x,上述优化问题可以重述为最大化问题之一:

    sd(x)/mean(x)
    

    这样x 的每个元素都是[1, n_row] 范围内的整数,而sum(x)fill

    此外,由于sum(x) 被限制为等于fill,因此对于给定的fill,分母项mean(x) 在所有x 上都是恒定的。因此,要最大化的等价目标函数就是sd(x) 或等价于x 的方差。

    为了使x 的方差最大化,我们需要选择x,使其值之间的差异最大化,同时仍然满足x 的约束。在这里,我们可以针对fill 归纳思考这个问题。假设对于给定的fill,我们有x 的解决方案,它在满足其约束的同时最大化x 的方差。问题变成了:当我们将fill 增加到fill + 1 时,最大化其方差的新x 是什么?因为我们有sum(x)=fillx 中的每个元素都是整数的约束,递增fill 意味着我们必须递增x 的一个且仅一个元素。暂时放宽对x 中每个元素的上限约束(即,x[i] &lt;= n_row 用于[1,n_col] 中的所有i),那么问题就变成了:x 中的哪个元素要增加以最大化增加x 的方差。对于这个问题的答案,我们可以看var(x)的泰勒级数展开:

    var(x + dx) = var(x) + gradient(var(x)) %*% dx + 1/2 * t(dx) %*% Hessian(var(x)) %*% dx
    

    其中dx 是长度为n_col 的向量,其中一个元素等于1,所有其他元素等于0(即指示向量)。由于var(x)x 中是二次的,所以二阶展开就足够了。此外,由于dx 是指示向量,因此只有 Hessian 矩阵的对角元素很重要。这些由以下人员提供:

    gradient(var(x))[i] = 2*(x[i]-mean(x))/(n_col-1),      for all i in [1,n_col]
    Hessian(var(x))[i,i] = 2/n_col                  ,      for all i in [1,n_col]
    

    由于 Hessian 的所有对角项都相同,因此泰勒级数的二阶项对于 dx 的任何选择都是相同的。因此,只有一阶项在确定要增加 x 中的哪个元素以使 x 的方差增加最大化时很重要。从梯度项可以看出,我们应该选择增加x中当前值x[i]最大的i-th元素,以最大化x的方差增加。现在,我们对x 的每个元素重新引入上限约束。然后,最佳选择是增加x 中具有最大当前值x[i] &lt; n_rowi-th 元素。请注意,如果x 中有多个这样的元素具有相同的最大值x[i] &lt; n_row,那么选择其中任何一个都会导致x 的方差最大增加相同。

    到目前为止,我们所展示的是,给定 fillx 的解决方案,在满足其约束的同时最大化 x 的方差,我们有一个规则 dx 最大化增量增量xfill + 1 的方差。仍有待证明该规则会产生一个新的x,它是最佳x,它使新fill + 1x 的方差最大化。我们现在通过矛盾来证明这一点。具体来说,如果这个新的x 没有使fill + 1x 的方差最大化,那么必须存在另一个fill 的列和向量x_1 和一个不同的规则dx_1 这样

    var(x_1 + dx_1) > var(x + dx)
    

    但是,由于 x 最大化 var(x)fill 并且梯度和 Hessian 方程适用于任何 x,我们有:

    var(x_1 + dx_1) = var(x_1) + gradient(var(x_1)) %*% dx_1 + 1/2 * t(dx_1) %*% Hessian(var(x_1)) %*% dx_1
                    <= var(x_1) + 2*(max(x_1)-mean(x_1))/(n_col-1) + constant
                    <= var(x) + 2*(max(x)-mean(x))/(n_col-1) + constant
                    = var(x + dx)
    

    因此矛盾。为了更清楚地解释这些步骤:

    1. 从第 1 步到第 2 步,dx_1x_1 的最佳选择是增加 x_1 中的最大元素并因此增加 gradient(var(x_1)) %*% dx_1 &lt;= 2*(max(x_1)-mean(x_1))/(n_col-1) 的那个。此外,对于给定的fill,所有xdx 的二阶项都是常数,因此我们简单地将其声明为constant
    2. 从第 2 步到第 3 步,我们有 (i) var(x_1) &lt;= var(x),我们假设 xfill 处最大化方差,(ii) gradient(var(x)) %*% dx = 2*(max(x)-mean(x))/(n_col-1) 最优规则 dxfill , 和 (iii) max(x_1) &lt;= max(x) 假设 x 最大化 fill 处的方差。要查看后者,请考虑fill-1 的列和x_-1 的共同前驱向量。将x_-1 递增到xx_1 之间的规则差异只是x_-1 中要递增的元素的不同选择。从x_-1处方差的泰勒级数展开,很明显x_-1中的元素选择要递增到x必须大于或等于要到x_1,因为@ 987654446@。因此,max(x_1) &lt;= max(x)。现在将此推理扩展到 任何 列和的公共向量在以前的一些 fill-k &gt;= max(n_row, n_col),包括初始的 fill,其中列和的初始向量都是 1 的。然后,对于一条路径,选择上面定义的最优增量规则以达到x;而对于另一条路径,选择增量规则的任意路径到达x_1。由于最优规则总是在每一步增加状态的最大元素(受限于上限),很明显再次max(x_1) &lt;= max(x)

    最后,为了完成数学归纳,我们从初始填充开始,其中x 是所有1 的。这对var(x) 进行了微不足道的优化,因为在给定初始填充的情况下,x 没有其他选择。现在,最佳增量规则dx 是选择x 的第一个元素进行增量,因为所有元素都是相等的。生成的 x + dx 微乎其微地最大化初始填充的方差加一,因为增加 x 的任何其他元素将导致相同的方差。

    上述论点立即建议使用以下算法在列和向量中分配 fill 的值:

    1. 循环遍历列和x的向量中的每个元素。
    2. 对于每个i-th 元素x[i] &lt;- min(n_row, fill - (ncol_-i))。请注意,我们从填充中减去(n_col-i),以便我们可以保留这些以至少用1 填充列和向量的其余元素,并且我们将数量限制为n_row 以满足问题的约束。
    3. 更新fill &lt;- fill - x[i]

    这个算法和相关的参数验证了 OP 的断言

    像这样按列填充矩阵可以保持边缘列总数的最大可变性

    在 R 中,代码如下:

    foo <- function(n_col, n_row, fill) {
      ## preallocate the vector of column sums x and initialize to NA
      x <- rep(NA, n_col)
      for (i in seq_len(n_col)) {
        x[i] <- pmin.int(n_row, fill-(n_col-i))
        fill <- fill - x[i]
      }
      ## compute the variability given the vector of column sums x
      sd(x)/mean(x)
    }
    

    认识到循环中fill 的重复递减可以用cumsum 替换,以上简化为:

    foo <- function(n_col, n_row, fill) {
      x <- pmin.int(pmax.int(cumsum(c(fill-n_col+1,rep(-n_row+1,n_col-1))),1),n_row)
      ## compute the variability given the vector of column sums x
      sd(x)/mean(x)
    }
    

    使用这个函数,我们恢复 OP 的结果:

    n_col=5
    n_row=5
    variability <- sapply(max(n_col,n_row):(n_col*n_row), function(fill) foo(n_col, n_row, fill))
    print(variability)
    ## [1] 0.0000000 0.3726780 0.6388766 0.8385255 0.9938080 0.8660254 0.8131156 0.8122329 0.8426501
    ##[10] 0.7319251 0.6666667 0.6404344 0.6443795 0.5414886 0.4707512 0.4330127 0.4259177 0.3049184
    ##[19] 0.1944407 0.0931695 0.0000000
    

    【讨论】:

      猜你喜欢
      • 2014-06-17
      • 1970-01-01
      • 1970-01-01
      • 2015-05-04
      • 1970-01-01
      • 1970-01-01
      • 2016-02-17
      • 2013-11-24
      • 1970-01-01
      相关资源
      最近更新 更多