如何在给定特征值1的情况下找到特征向量,最大限度地减少内存使用



如果人们能帮助我找到一种有效的方法(可能是低内存算法)来解决以下问题,我将不胜感激。

我需要找到转移矩阵CCD_ 2的平稳分布CCD_。转换矩阵是一个非常大、非常稀疏的矩阵,其构造使得所有列的总和为1。由于平稳分布由方程Px = x给出,因此x简单地是与特征值1相关联的P的特征向量。

我目前正在使用GNU Octave生成转换矩阵,找到平稳分布,并绘制结果。我使用函数eigs(),它计算特征值和特征向量,可以只返回一个特征向量,其中特征值为1(实际上我必须指定1.1,以防止出现错误)。转换矩阵的构建(使用稀疏矩阵)相当快,但随着大小的增加,找到特征向量的速度越来越慢,而且在检查中等大小的问题之前,内存就用完了。

我当前的代码是

[v l] = eigs(P, 1, 1.01);
x = v / sum(v);

既然我知道1是特征值,我想知道是否有更好的方法来计算特征向量,或者有一种方法可以让更有效地使用内存,因为我真的不需要一个中等大小的密集矩阵。我天真地尝试了

n = size(P,1);       % number of states
Q = P - speye(n,n);
x = Qzeros(n,1);    % solve (P-I)x = 0

由于Q是奇异的(根据定义)。

如果有人对我应该如何处理这个问题有任何想法,我将不胜感激,因为这是一个我必须执行多次的计算,如果可能的话,我想在更大、更复杂的模型上尝试一下。

作为这个问题的背景,我正在求解随机SIR模型中牛群中感染人数的平衡分布。不幸的是,即使是中等规模的畜群,过渡矩阵也非常大。例如:在平均20个个体的SIR模型中(95%的情况下,种群在12到28个个体之间),P是21169乘21169,具有20340个非零值(即0.0005%的密度),并且使用了321 Kb(该大小的全矩阵将为3.3 Gb),而对于大约50个个体,P使用了3 Mb。x本身应该很小。我怀疑x0在某个地方有一个密集矩阵,这导致我内存不足,所以如果我可以避免使用全矩阵,我应该没事。

幂迭代是找到矩阵主特征值的标准方法。你选择一个随机向量v,然后用P反复击打它,直到你不再看到它有很大的变化。你想周期性地用sqrt(v^T v)除以v来归一化它

这里的收敛速度与最大特征值和第二大特征值之间的间隔成比例。每次迭代只需要进行几次矩阵乘法运算。

有一些更花哨的方法可以做到这一点(在这里搜索"PageRank"是一件好事),可以提高真正巨大的稀疏矩阵的速度,但我不知道它们在这里是否必要或有用。

您的方法看起来不错。然而,你所说的x,是Q的零空间。如果它支持稀疏矩阵,null(Q)会起作用,但它不起作用。网上有很多关于寻找稀疏矩阵的零空间的东西。例如:

http://www.mathworks.co.uk/matlabcentral/newsreader/view_thread/249467

http://www.mathworks.com/matlabcentral/fileexchange/42922-null-space-for-sparse-matrix/content/nulls.m

http://www.mathworks.com/matlabcentral/fileexchange/11120-null-space-of-a-sparse-matrix

似乎最好的解决方案是使用幂迭代方法,正如tmyklebu所建议的那样。

方法是迭代x = Px; x /= sum(x),直到x收敛。如果连续迭代之间的d1范数小于1e-5,我假设收敛,因为这似乎会给出好的结果。

收敛可能需要一段时间,因为最大的两个特征值相当接近(收敛所需的迭代次数可能会有很大的变化,根据所使用的模型和种群大小,从大约200到2000次不等,但最终会达到目的)。然而,内存需求很低,而且很容易实现。

相关内容

最新更新