我有一个类似于以下内容的优化问题
在这里,我的变量是矩阵 和,但是整个问题仍然是线性程序。其余变量是固定的。
当我尝试将此程序输入我最喜欢的线性编程工具时,遇到了一些麻烦。即,如果我以“标准”线性程序形式编写此代码,则参数矩阵和最终会重复一遍(每X列一次)。
是否有可以处理上述形式的优化的算法和/或程序包?现在我内存不足,因为和必须被复制很多次!
我有一个类似于以下内容的优化问题
在这里,我的变量是矩阵 和,但是整个问题仍然是线性程序。其余变量是固定的。
当我尝试将此程序输入我最喜欢的线性编程工具时,遇到了一些麻烦。即,如果我以“标准”线性程序形式编写此代码,则参数矩阵和最终会重复一遍(每X列一次)。
是否有可以处理上述形式的优化的算法和/或程序包?现在我内存不足,因为和必须被复制很多次!
Answers:
总览
您可能想尝试乘数交替方向方法(ADMM)的变体,发现该方法对于套索类型问题出奇地收敛。策略是用增强的拉格朗日公式来表达问题,然后对偶问题进行梯度上升。对于此特定的正则化问题特别好,因为该方法每次迭代的不平滑部分都有一个精确的解决方案,您可以简单地逐个元素地求值,而平滑部分涉及求解线性系统。
在这篇文章中,我们
以下绝妙的评论文章涵盖了此处的大多数大创意,
博伊德,斯蒂芬等人。“通过乘数的交替方向方法进行分布式优化和统计学习。” 机器学习中的Foundations andTrends®(2011):1-122。http://www.stanford.edu/~boyd/papers/pdf/admm_distr_stats.pdf
在详细讨论之前,我想指出这是一个方法/算法答案,而不是现有的实用代码答案-如果要使用此方法,则需要滚动自己的实现。
ADMM公式
通常,假设您要求解
经过适当的向量化处理后,原始帖子中的问题属于此类。(这只是原则上的-我们将看到实际上不需要进行矢量化处理)
您可以改用 ,具有拉格朗日
乘数的交替方向方法 通过对偶变量上的梯度上升来解决对偶问题 ,除了对偶子问题上的不精确交替投影。即,执行一次迭代
在参数和(在上面的Boyd&Parikh论文中进行了解释)的某些适度条件下,ADMM方法将收敛到真实的解。收敛速度是线性的,因为它的核心是梯度上升方法。通常,可以通过以下方法将其加速为超线性:1)根据启发式方法更改参数和,或2)使用Nesterov加速。有关更改惩罚参数的说明,请参见Boyd调查报告;对于将Nesterov加速与ADMM结合使用,请参见以下论文:
Goldstein,Tom,Brendan O'Donoghue和Simon Setzer。“快速交替方向优化方法。” CAM报告(2012):12-35。ftp://ftp.math.ucla.edu/pub/camreport/cam12-35.pdf
但是,即使总体收敛速度只是线性的,对于问题,已经观察到该方法可以非常迅速地找到稀疏模式,然后在精确值上收敛得更慢。由于找到稀疏模式是最困难的部分,因此这是非常偶然的!似乎是当前研究领域的确切原因。每个人都看到稀疏模式迅速收敛,但是似乎没人确切知道它为什么会发生。不久前,我通过电子邮件向Boyd和Parikh询问了有关此内容的信息,Parikh认为可以通过在控制系统上下文中解释该方法来进行解释。在下面的附录中可以找到对该现象的另一种启发式解释,
Goldstein,Tom和Stanley Osher。“ L1正则化问题的分裂Bregman方法。” SIAM影像科学杂志2.2(2009):323-343。ftp://ftp.math.ucla.edu/pub/camreport/cam08-29.pdf
当然,现在的困难在于解决针对您的特定情况的和更新子问题。由于拉格朗日在是平方的,因此更新子问题仅需要求解线性系统。的子问题似乎更难,因为它是不可微的,但事实证明,存在用于解决方案,可以通过元件施加元件的精确配方!现在,我们将更详细地讨论这些子问题,并在原始帖子中将它们指定为问题。
设置为更新子问题(线性系统)
对于更新,我们有
专门针对您的问题,它变成
其中表示Frobenius 范数(元素)。这是二次最小化问题,可以通过针对和取目标的偏导数并将它们设置为零来找到一阶最优条件。这是
正如原始海报贾斯汀·所罗门(Justin Solomon)的评论所指出的那样,该系统是对称的,因此共轭梯度是一种理想的无矩阵方法。下一节将讨论此系统以及如何更详细地解决/预处理它。
解决更新子问题(解析阈值解决方案)
现在我们转到子问题
首先要看的是,总和可以逐个元素分解
因此,我们可以逐个元素并行地解决优化问题,得到
此方程式的一般形式为
绝对值函数试图将最佳点拉向,而二次项试图将最佳点拉向。因此,真正的解决方案位于两者之间的线段上的某个位置,增大倾向于将最佳点拉向,而减小倾向于将最佳点拉向。
这是一个凸函数,但不能为零。最小化点的条件是目标在该点的微分包含零。二次项具有衍生物,并且绝对值函数具有衍生物为,集值次导数作为间隔当,和衍生物为。因此,我们得到了总体目标函数的子导数
由此可见,当且仅当,目标在的导数包含,在这种情况下是最小化器。另一方面,如果不是最小化器,那么我们可以将单值导数设置为零,然后求解最小化器。这样做会产生
将结果再次专门我们要在原始问题中尝试解决的实际问题,其中产生 的更新只是
正如原始海报贾斯汀·所罗门(Justin Solomon)在评论中指出的那样。总体而言,对进行更新仅需要遍历矩阵的条目并为每个条目评估上述公式。
系统的Schur补码
迭代过程中最昂贵的步骤是求解系统,
为此,值得为此系统构造一个好的求解器/预处理器。在本节中,我们通过矢量化,形成Schur补码,进行一些Krnoecker乘积运算然后取消矢量化来实现。得到的Schur补码系统是一个经过稍微修改的Sylvester方程。
接下来,关于矢量化和Kronecker产品的以下标识绝对是关键:
只要矩阵大小和可逆性使得方程的每一侧都是有效表达式,这些标识就成立。
系统的向量化形式为
或
其中和是右侧的简写符号。现在,我们在冷凝Kronecker产品的过程中执行块高斯消除/ Schur补码以消除矩阵的左下块。这是
非向量化,我们必须依次求解的两个方程是
为方形高阶时Schur补码系统的解
在本节中,我们通过使用矩阵预先计算的完整 SVD 并为Sylvester应用Bartels-Stewart算法的修改版本,来解决(上面的方程1)的Schur补码系统。方程。与标准版本相比,该算法略有修改,以在第二项中考虑额外的,这使其与Sylvester方程式不同。一旦经由第一方程发现,可以从第二方程容易被发现。通过您喜欢的任何方法来求解第二个方程都是很简单的。
该方法在ADMM流程开始之前需要先期成本来预先计算两个完整的SVD,但是这种方法可以快速应用于实际的ADMM迭代中。由于该方法处理约束矩阵的完整SVD,因此当它们接近正方形和高秩时是合适的。使用低等级SVD的更复杂的方法也是可能的,但将在后面的部分中介绍。
该方法发展如下。让 分别表示预先计算的满奇异值分解,并冷凝的右手侧是。然后,第一等式变成, 乘法通过正交因子清除左右,并设置一个新的临时未知数,这进一步变为
现在,我们可以找到通过求解对角线系统,
找到,我们计算,并且知道可以解决上面针对的第二个方程,这很简单,因为我们已经具有的特征值分解。
前期成本是计算和两个对称正定特征值分解,然后一次完整求解的每次迭代成本由少数矩阵矩阵乘法控制,而矩阵矩阵乘法的阶数相同幅度为1 CG重复。如果前期特征值分解的成本太高,则可以通过例如提前终止Lanczos迭代并保留最大的特征向量来进行不精确的计算。然后,该方法可以用作CG的良好预处理器,而不是直接求解器。
非常矩形或具有低秩近似的求解方法
现在我们将注意力转移到求解或预处理时:a)输入矩阵非常矩形-意味着它们的行多于列,反之亦然-或者b)秩近似低。下面的推导涉及Woodbury公式,Schur补语和其他类似操作的广泛使用。
我们从Schur补码系统开始
几次操作将该系统转换为更对称的形式,
现在我们引入低秩近似。令 是约 SVD或和低秩近似(是占位符,不是用过的)。将它们代入我们的系统会产生以下我们希望应用的矩阵逆
由于我们要求逆的矩阵是对身份的低阶更新,因此逻辑策略是尝试使用伍德伯里公式
但是,由于低阶和不正交,因此需要谨慎。因此,为了应用伍德伯里公式,我们将两个低等级更新都收集到一个大更新中。这样做并应用伍德伯里公式得出
可以通过逐块2x2逆公式
这篇文章已经足够长了,所以我将省去冗长的计算细节,但是最终结果是将必要的子矩阵插入到块式逆中,并将所有乘积相乘,得出整体逆的以下明确形式,
其中
通过这种形式,我们可以应用逆函数,并通过8个左右矩阵乘法三明治将其找到项。应用Kronecker乘积之和的一般公式为
请注意,我们最终得到的所有显式逆都是对角线,因此没有什么可以“求解”的。
线性求解器代码
我在Matlab中实现了以上两个求解器。似乎运作良好。求解器代码在这里。
https://github.com/NickAlger/MeshADMM/blob/master/zkronsolve.m
这里有一个用于检查求解程序是否正常工作的测试脚本。还通过示例显示了如何调用求解器代码。
https://github.com/NickAlger/MeshADMM/blob/master/test_zkronsolve.m
结束语
ADMM类型的方法非常适合解决此类问题,但是您需要滚动自己的实现。该方法的整体结构非常简单,因此在像MATLAB这样的东西中实现起来并不困难。
这篇文章中缺少的,需要为完全定义您的问题的方法而指定的部分是惩罚参数。幸运的是,只要参数值不疯狂,该方法通常就相当健壮。博伊德和帕里克(Boyd and Parikh)的论文中有一个关于惩罚参数的章节,其中的参考文献也有介绍,但是我只是对这些参数进行实验,直到获得合理的收敛速度为止。
如果约束矩阵是a)密集,正方形和高秩,或者b)具有良好的低秩逼近提出的求解器策略非常有效。可能是未来工作主题的另一个有用的求解器可能是针对以下情况进行优化的求解器-约束矩阵稀疏且方形且具有较高的秩,但是对于存在良好的前置条件。例如,如果是离散的拉普拉斯算子,那就是这种情况。
您可能希望使用无矩阵方法进行线性编程。我不知道有什么专门用于线性编程的方法,但是存在用于二次程序和一般非线性程序的无矩阵内点方法。二次程序的情况恰好与您的问题相对应,此时二次形式系数均为零。(您也可以定制使用精确线性求解来解决问题结构的方法,但是这种定制的实现可能不值得,并且不如使用无矩阵方法实用。)
我不知道任何实现内点方法无矩阵变体的商业优化软件包。IPOPT应该为非线性编程实现一种无矩阵内点方法,但是我无法追踪使您能够使用它的API调用。
除了CVX,您可能还可以使用GAMS或AMPL输入一次矩阵,并在建模语言中设置约束以使用该矩阵。但是,CVX,GAMS和AMPL的求解器后端使用的方法并不使用无矩阵求解器;所有这些都将需要标准形式的线性程序的完整系数矩阵,这将是巨大的(这将是矩阵的Kronecker乘积)。可能发生的情况是,您使用建模语言以上述形式输入了线性程序,然后建模语言会将数据转换为后端求解器可用的形式。这种形式将需要巨大的矩阵,而且我怀疑您会遇到相同类型的错误(除非您在具有足够内存的计算机上运行)。
您能负担得起Geoffrey Irving提到的那些SVD吗?如果可以的话,我将考虑采用迭代加权最小二乘法(IRLS)。这种方法可以解决,其中是权重矩阵。
迭代以作为全1矩阵开始;这产生一个最佳的。迭代以,其中是一个小常数,可防止被零除。我对收敛标准并不完全确定,但也许我上面提供的Wikipedia链接可以为您提供参考。
您还可以考虑平滑的一阶方法。我与他人合着的TFOCS可以使用其“平滑圆锥对偶”(SCD)求解器来解决此问题,但是使用起来并不容易。
如果您确实想尝试无矩阵内点方法,请阅读Jacek Gondzio的著作。
编辑:嗯,可能是IRLS无法使用SVD计算解决方案的情况。如果是这样,我将退回到其他选择之一。
您可以尝试使用CVX,它可以让您完全按照编写的形式对其进行编码(即,以为矩阵而不是向量)。可以使用更通用的凸解算器代替LP解算器来解决,但是如果凸解算器成功,那么我想您不会介意。
另一种可能性:使用求解器,使您的约束矩阵可以存储为稀疏矩阵。这仍然需要比您需要的内存更多的内存,但是远远少于将它们存储为密集矩阵的内存。在CVX中,如果您使用的kron
是稀疏矩阵,那么尝试一下将是微不足道的。