【问题标题】:Extracting the largest set of linearly independent vectors from a set of vectors in matlab从matlab中的一组向量中提取最大的线性独立向量集
【发布时间】:2015-01-12 17:02:10
【问题描述】:

我是使用 matlab 的新手。我找不到一种明显的方法来从给定的向量集中提取线性独立向量的最大子集。

所以给定一个集合 V = [v1 v2 -- vn] where dim(vi) >> n (i=1,2,3,....) 我需要找到一组随机的 r 个线性独立向量“vi”(其中 r 最大),即从 V 中删除所有 (n-r) 线性相关的“vi”向量。抱歉,如果这是模棱两可但找不到更好的方式来说明它。

【问题讨论】:

  • 请努力!如果您编辑问题并更彻底地解释您想要实现的目标,我将很乐意删除我的反对票和关闭投票。
  • 好的,我会试一试的。
  • 此外,您应该更好地定义问题。给定向量 [0 0 1], [0 1 1], [0 1 0],解可以是 {[0 0 1], [0 1 1]};或者它可以是 {[0 0 1], [0 1 0]};也可以是 {[0 1 1], [0 1 0]}。您想要哪种解决方案?只有最大 数量 个独立向量是明确定义的
  • 我知道这听起来很奇怪,但我需要一个随机集合。我的整个研究项目都是基于探索不同线性独立集的结果。
  • 这不是一个答案,但这可能会让你走上正轨。我写了一个关于检测矩阵(向量)中哪些列是线性相关的答案。 stackoverflow.com/questions/26041671/… - 您可以尝试使用这篇文章并继续进行下去,以便您可以从矩阵中移除这些向量,从而实现完全独立的矩阵。也许这就是你要找的!

标签: matlab vector


【解决方案1】:

我将假设您的向量都是n 维,并且我们可以将它们全部连接到一个矩阵中。如果我们进入矩阵和线性代数,您正在寻找的是矩阵的the Column Space。简单地说,列空间被定义为矩阵中的一组列,它们可以在n维空间中唯一地产生另一个向量。或者,它是列向量的所有可能线性组合的集合。因此,如果您想找到最大的线性独立向量集,您所要做的就是确定矩阵的列空间是什么。

因此,给定您的矩阵V,其大小为n x m,其中我们有m 列/向量,每列的大小为n x 1(或n 行),您可以调用rrefRow-Reded Echelon Form (RREF) 命令。这会将您的矩阵减少到其row-reduced echelon form。这是为矩阵寻找列空间的开始。你可以这样称呼它:

[R, RB] = rref(V);

R 将包含 V 的 RREF 形式,RB 将包含 构成列空间R 的索引或列号。因此,如果你想产生你的线性独立向量,你只需要这样做:

VMax = V(:,RB);

VMax 将仅包含构成列空间的V 的那些列,因此也包含那些是线性独立向量的列。如果您想确定我们有 多少 个独立向量,您只需计算我们有多少 RB 的值:

r = numel(RB);

这里有一个简单的例子来说明我的观点。假设我有这个矩阵:

>> V = [1 1 2 0; 2 2 4 9; 3 3 6 7; 4 4 8 3]

V =

     1     1     2     0
     2     2     4     9
     3     3     6     7
     4     4     8     3

第二列/向量只是第一个向量。第三列/向量只是第一个向量加上第二个向量,或者它可以是第一个或第二个向量的两倍。无论哪种方式,这不是线性独立向量,因为它基于第一个向量。第二个向量也是如此。最后一个向量独立于其他三个向量,因为我们无法创建组合或缩放来从其他三个向量生成最后一个向量。如果我们调用rref,将会发生这种情况:

>> [R, RB] = rref(V)

R =

     1     1     2     0
     0     0     0     1
     0     0     0     0
     0     0     0     0


RB =

     1     4

R 包含行缩减梯队形式,而RB 告诉我们哪些 是线性独立的或构成A 的列空间。如您所见,只有第 1 列和第 4 列是线性独立的,这很有意义。如果您还查看R 的最后两行,我们可以看到它们由全零组成。这暗示了矩阵的rank,它只是非零的总行数(或列数,取决于你在做什么)。这也告诉你有多少向量构成列空间。

要完成您的任务,只需执行以下操作:

>> VMax = V(:,RB)

VMax =

     1     0
     2     9
     3     7
     4     3

如您所见,VMax 的每一列都是来自V 的线性独立向量,这也构成了V 的列空间。

现在,您的下一个任务是每次运行算法时从该列空间中随机选择线性独立向量。请记住,由于有多种方法可以产生列空间,rref 的解决方案只会给你一个这样的列空间。如果我正确解释了您的问题,您希望生成随机列空间并每次选择这些向量的子集。感谢 Luis Mendo(也是来自 knedlsepp 的温和刺激),您可以做的是随机重新排列或置换列,然后在这个置换矩阵上运行 rref

因此,您可以这样做:

ind = randperm(size(V,2));
Vperm = V(:,ind);
[R,RB] = rref(Vperm);
VMax = Vperm(:,RB);

randperm 将生成一个从 1 到您指定给 randperm 的参数的随机排列数组。在我们的例子中,这是矩阵V 中的总列数。我们使用这个数组随机打乱V 的列,将其存储到Vperm 并运行我们之前完成的代码。通过进行这种随机洗牌,您将输入偏置到rref,以便您强制它选择不同的基向量,但是如果您有多个线性相关的向量,那么在某些情况下我们将选择其中一个线性相关向量来构建我们的基础。

【讨论】:

  • 自“V which consists of n x 1 vectors”以来VMax = V(:,RB); 真的正确吗?您将获得超出索引的错误或V 的所有值。也许V 应该是1 x nVMax = V(RB,:)
  • @kkuilla - 不,我可能没有正确地表达自己。我们正在寻找列空间,因此您想从V 中提取列。它可能应该是这样的:V 是一个n x m 矩阵,其中我们有m 列/向量,每列是一个n x 1 向量。此外,您不应该收到超出索引的错误,因为RB 将返回矩阵Vcolumn 索引,而我正在使用RB 来访问这些列。我会修改我的帖子。谢谢你的位置!
  • 我认为直到VMax = V(:,RB) 之前的第一部分可能是解决这个问题的最佳方法。但是我不认为 randperm-part 是 OP 想要的。另外:不应该是VMax(:,RB(ind))而不是VMax(:,ind)吗?
  • @knedlsepp - 哦,是的!当然!谢谢你的位置。
  • @knedlsepp - 我将保留最后一部分......因为老实说,我不太确定我是否正确解释了这个问题。在我得到更多澄清之前,我会保持原样。
【解决方案2】:

这种寻找由向量跨越的向量空间的基础的简单方法类似于 Luis Mendo 的。然而,与n choose r 相比,它应该具有更好的理论最坏情况复杂度,最大为nrank-computations。缺点是,最好的情况将执行rrank-computations,而不是1

想法很简单:

  • 计算Vrank r。这是您的集合中向量的最大数量。
  • chosen 向量集定义为空。
  • 对于V 中的每个向量V(:,k)(随机选择):
    • 如果向量V(:,k)与集合chosen中的向量线性无关:
      • 将其添加到所选向量集。
    • 如果集合chosen 已经有r 元素:
      • 返回 chosen 向量作为解。

生成的代码将如下所示:

function chosen = randBasis(V)
% V is a matrix of column vectors
% chosen are the indices of the randomly selected column vectors,
% so that span(V(:,chosen)) == span(V)

n = size(V,2);
r = rank(V);
chosen = []; 
currentRank = 0;
for k = randperm(n)
    if rank(V(:, [chosen, k])) > currentRank
        currentRank = currentRank+1;
        chosen = [chosen, k];
    end
    if currentRank==r
        break
    end
end

补充说明:

当您处理稀疏矩阵时,这种方法可能很有用,因为检查线性相关性可以用线性系统的解决方案代替秩计算。由于排名计算涉及对svd 的调用,因此相比之下它相当昂贵。尽管 rayryeng​​em> 的 rref-solution 是更优雅的解决方案,但出于某种原因,即使对于非稀疏矩阵,这种幼稚的方法似乎也更快。

使用mldivide 加速版本:

function chosen = randBasis(V)
n = size(V,2);
if issparse(V)
    r = sprank(V)
else
    r = rank(V);
end
chosen = []; 
for k = randperm(n)
    if isLinearlyIndependent(V(:,chosen),V(:,k))
        chosen = [chosen, k];
    end
    if numel(chosen)==r
        break
    end
end
end

function b = isLinearlyIndependent(V, v)
    warning('off','MATLAB:singularMatrix');
    bestapprox = V\v;
    bestapprox(~isfinite(bestapprox)) = 0;
    b = ~(norm(V*bestapprox-v,'inf')<=eps*norm(V,'inf'));
    warning('on','MATLAB:singularMatrix');
end

注意:

这两种迭代方法都存在一个不明显的数值问题: 考虑矩阵:

V = diag(10.^(-40:10:0))
V =
        1e-40            0            0            0            0
            0        1e-30            0            0            0
            0            0        1e-20            0            0
            0            0            0        1e-10            0
            0            0            0            0        1e+00

从数学上讲,您会说这个矩阵的秩为 5。然而,与其他列相比,只有最后两列在数值上是非零的。这就是rank(V) 给出2 的原因。这种迭代方法的问题在于,将线性独立向量添加到我们的集合实际上会导致线性相关集合! 想象一下这个算法选择了第一个向量。尽管所有其他向量在数学和数值上都是线性独立的,但子集{V(:,1), V(:,5)} 没有数字等级 2,但可以由我们的函数选择。这就是为什么该算法仅适用于具有相似范数的向量的原因。

结论是:

  • 数值数学很棘手。
  • 想要稳定,就必须付出计算成本的代价。
  • rref 是解决这个问题的方法。

【讨论】:

  • 非常好!我喜欢这个问题所产生的答案和讨论。
  • 这在加速方面是有道理的。看rref的出处,全是循环!顺便说一句,分析得很好!
  • @rayryeng:是的,我也看过源代码。这当然是因为svdrref 的“替代品”,具有更实际的应用。因此无需将rref 作为内置提供。 [至少就我而言,昨天是我第一次了解到这种形式的存在。]
【解决方案3】:

我会尝试这些方面的东西。不过,它可能不会很快:

  1. 计算向量形成的矩阵的秩。称它为 r
  2. 生成取自1:nr 数字的所有组合。
  3. 对这些组合进行随机排序。
  4. 采用第一个组合并检查该组合指示的向量是否独立(最大等级)。如果不是,请测试下一个组合。通过构造,可以保证某种组合会成功。

代码:

vectors = randi(3,4,3); %// example. Each vector is a row
n = size(vectors,1);
r = rank(vectors); %// step 1
combs = nchoosek(1:n,r); %// step 2
c = size(combs,1);
combs = combs(randperm(c),:); %// step 3
for s = 1:r %// step 4
    pick = combs(s,:);
    if rank(vectors(pick,:))==r
        break %// we're done. Now `pick` contains the selected vectors
    end
end
result = vectors(pick,:); %// each row is a vector

【讨论】:

  • @knedlsepp 这是另一种可能的方法,是的。但我怀疑它会大大降低复杂性。在您通过此过程成功收集r 独立向量之前,可能需要多次尝试
  • @knedlsepp 我想我现在明白你的意思了。是的,这听起来是个好主意。遍历n 向量就足够了(最初可以对它们进行随机排序以获得随机结果)。将其发布为答案!
  • @knedlsepp 但在 rayryeng 的方法中,请考虑 V = [0 0 1; 0 0 2; 0 1 1; 1 1 0].'Vmax 将始终包含第一个向量,而不是第二个。所以那里没有随机化。我说的对吗?
  • 是的,rayryeng 解决方案的随机化部分仍然缺失,但就找到 any 子集而言,我猜它是优越的。
  • @knedlsepp , Luis Mendo - 是的,你们俩都是对的。我还没有弄清楚随机化部分。这是我必须考虑的事情。感谢您的意见!
【解决方案4】:

一个例子的部分解决方案......对不起,我没有注意到你的评论 “不同线性独立集”...您的意思是“不同最大线性独立集”吗?抱歉,我只找到了最大线性独立集之一......但是使用[R, RB] = rref(M) 的解决方案给出了相同的答案

+ echo ('on')
+ more ('off')
+ format ('bank')
+ M = [0, 0, 1; 0, 1, 1; 0, 1, 0]'
M =

   0.00   0.00   0.00
   0.00   1.00   1.00
   1.00   1.00   0.00

+ [U, S, V] = svd (M)
U =

   0.00   0.00  -1.00
  -0.71   0.71   0.00
  -0.71  -0.71   0.00

S =

Diagonal Matrix

   1.73      0      0
      0   1.00      0
      0      0  -0.00

V =

  -0.41  -0.71  -0.58
  -0.82   0.00   0.58
  -0.41   0.71  -0.58

+ U (:, 1:2) * S (1:2, 1:2) * V (1:2, 1:2)'
ans =

   0.00   0.00
   0.00   1.00
   1.00   1.00

来自Applications_of_the_SVD的引述

M的非零奇异值对应的左奇异向量跨越M的范围。

【讨论】:

  • 您或许应该解释代码在做什么以及它对左奇异向量跨越M 的列空间的具体含义,而不是代码转储。只有精通线性代数的人才会理解您的帖子。
猜你喜欢
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2023-04-06
  • 2017-04-09
  • 2015-04-22
  • 2010-09-30
  • 1970-01-01
  • 2016-05-29
相关资源
最近更新 更多