许多复杂的矩阵运算无法利用计算机有限的精度来高效或稳定地解决。
矩阵分解是一种将矩阵简化为其组成部分的方法,从而使计算更复杂的矩阵运算变得更容易。矩阵分解方法,也称为矩阵因式分解方法,是计算机中线性代数的基础,即使对于求解线性方程组、计算逆矩阵和矩阵行列式等基本运算也是如此。
在本教程中,您将了解矩阵分解以及如何在Python中计算它们。
完成本教程后,您将了解:
- 什么是矩阵分解以及为什么这类运算很重要。
- 如何在Python中计算LU和QR矩阵分解。
- 如何在Python中计算Cholesky矩阵分解。
用我的新书《机器学习线性代数》启动您的项目,其中包括所有示例的分步教程和Python源代码文件。
让我们开始吧。
- 2018年3月更新:修正了QR分解描述中的一个小拼写错误。
- 2019年7月更新:修正了描述正定矩阵时的一个小拼写错误。

机器学习矩阵分解入门
照片由 mickey 拍摄,保留部分权利。
教程概述
本教程分为4个部分,它们是:
- 什么是矩阵分解?
- LU矩阵分解
- QR矩阵分解
- Cholesky分解
在机器学习线性代数方面需要帮助吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
什么是矩阵分解?
矩阵分解是将矩阵简化为其组成部分的一种方法。
这种方法可以简化更复杂的矩阵运算,这些运算可以在分解后的矩阵上进行,而不是在原始矩阵本身上进行。
矩阵分解的一个常见类比是数字的因式分解,例如将10分解为2 x 5。因此,矩阵分解也称为矩阵因式分解。与分解实数值一样,分解矩阵的方法有很多种,因此有一系列不同的矩阵分解技术。
两种简单且广泛使用的矩阵分解方法是LU矩阵分解和QR矩阵分解。
接下来,我们将更详细地了解这些方法中的每一种。
LU矩阵分解
LU分解适用于方阵,它将一个矩阵分解为L和U两个部分。
1 |
A = L . U |
或者,不使用点符号。
1 |
A = LU |
其中 A 是我们希望分解的方阵,L 是下三角矩阵,U 是上三角矩阵。
因子L和U是三角矩阵。通过消元法得到的分解是 A = LU。
— 第97页,《线性代数导论》,第五版,2016年。
LU分解是通过迭代数值过程找到的,对于那些不能分解或难以分解的矩阵可能会失败。
在实践中,一种在数值上更稳定的分解变体称为LUP分解,或带部分主元选择的LU分解。
1 |
A = P . L . U |
为了简化分解过程,对父矩阵的行进行重新排序,而附加的 P 矩阵指定了一种置换结果或将结果恢复到原始顺序的方法。此外,还有LU分解的其他变体。
LU分解通常用于简化线性方程组的求解,例如在线性回归中寻找系数,以及计算矩阵的行列式和逆矩阵。
LU分解可以在Python中使用lu()函数实现。更具体地说,这个函数计算的是LPU分解。
下面的示例首先定义了一个3×3的方阵。计算LU分解,然后从其组成部分重建原始矩阵。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# LU 分解 from numpy import array from scipy.linalg import lu # 定义一个方阵 A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(A) # LU 分解 P, L, U = lu(A) print(P) print(L) print(U) # 重构 B = P.dot(L).dot(U) print(B) |
运行该示例首先会打印定义的3×3矩阵,然后是分解的P、L和U分量,最后重建原始矩阵。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[[1 2 3] [4 5 6] [7 8 9]] [[ 0. 1. 0.] [ 0. 0. 1.] [ 1. 0. 0.]] [[ 1. 0. 0. ] [ 0.14285714 1. 0. ] [ 0.57142857 0.5 1. ]] [[ 7.00000000e+00 8.00000000e+00 9.00000000e+00] [ 0.00000000e+00 8.57142857e-01 1.71428571e+00] [ 0.00000000e+00 0.00000000e+00 -1.58603289e-16]] [[ 1. 2. 3.] [ 4. 5. 6.] [ 7. 8. 9.]] |
QR矩阵分解
QR分解适用于m x n矩阵(不限于方阵),它将矩阵分解为Q和R两个部分。
1 |
A = Q . R |
或者,不使用点符号。
1 |
A = QR |
其中A是我们希望分解的矩阵,Q是一个大小为m x m的矩阵,R是一个大小为m x n的上三角矩阵。
QR分解是通过迭代数值方法找到的,对于那些不能分解或难以分解的矩阵可能会失败。
与LU分解类似,QR分解常用于求解线性方程组,尽管它不限于方阵。
QR分解可以在NumPy中使用qr()函数实现。默认情况下,该函数返回的Q和R矩阵具有较小或“简化”的维度,这样更经济。我们可以通过将mode参数指定为'complete'来将其更改为返回预期的m x m(对于Q)和m x n(对于R)的大小,尽管这对于大多数应用来说不是必需的。
下面的示例定义了一个3×2矩阵,计算QR分解,然后从分解后的元素重建原始矩阵。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# QR 分解 from numpy import array from numpy.linalg import qr # 定义一个 3x2 矩阵 A = array([[1, 2], [3, 4], [5, 6]]) print(A) # QR 分解 Q, R = qr(A, 'complete') print(Q) print(R) # 重构 B = Q.dot(R) print(B) |
运行该示例首先打印定义的3×2矩阵,然后是Q和R元素,最后是重建的矩阵,该矩阵与我们开始时的矩阵相匹配。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
[[1 2] [3 4] [5 6]] [[-0.16903085 0.89708523 0.40824829] [-0.50709255 0.27602622 -0.81649658] [-0.84515425 -0.34503278 0.40824829]] [[-5.91607978 -7.43735744] [ 0. 0.82807867] [ 0. 0. ]] [[ 1. 2.] [ 3. 4.] [ 5. 6.]] |
Cholesky分解
Cholesky分解适用于所有特征值都大于零的方对称矩阵,即所谓的正定矩阵。
出于对机器学习的兴趣,我们将专注于实值矩阵的Cholesky分解,并忽略处理复数的情况。
该分解定义如下
1 |
A = L . L^T |
或不使用点符号
1 |
A = LL^T |
其中 A 是被分解的矩阵,L 是下三角矩阵,L^T 是 L 的转置。
该分解也可以写成上三角矩阵的乘积,例如
1 |
A = U^T . U |
其中 U 是上三角矩阵。
Cholesky分解用于求解线性回归的线性最小二乘问题,以及仿真和优化方法。
在分解对称矩阵时,Cholesky分解的效率几乎是LU分解的两倍,因此在这些情况下应优先选用。
虽然对称正定矩阵相当特殊,但它们在某些应用中出现得相当频繁,因此了解它们的特殊因式分解,即Cholesky分解,是很有好处的。当您可以使用它时,Cholesky分解在求解线性方程组方面比其他方法快大约两倍。
— 第100页,《数值方法:科学计算的艺术》,第三版,2007年。
Cholesky分解可以在NumPy中通过调用cholesky()函数实现。该函数只返回L,因为我们可以根据需要轻松访问L的转置。
下面的示例定义了一个3×3的对称正定矩阵并计算了Cholesky分解,然后重建了原始矩阵。
1 2 3 4 5 6 7 8 9 10 11 12 |
# Cholesky分解 from numpy import array from numpy.linalg import cholesky # 定义一个3x3矩阵 A = array([[2, 1, 1], [1, 2, 1], [1, 1, 2]]) print(A) # Cholesky分解 L = cholesky(A) print(L) # 重构 B = L.dot(L.T) print(B) |
运行该示例首先打印对称矩阵,然后是分解得到的下三角矩阵,最后是重建的矩阵。
1 2 3 4 5 6 7 8 9 10 11 |
[[2 1 1] [1 2 1] [1 1 2]] [[ 1.41421356 0. 0. ] [ 0.70710678 1.22474487 0. ] [ 0.70710678 0.40824829 1.15470054]] [[ 2. 1. 1.] [ 1. 2. 1.] [ 1. 1. 2.]] |
扩展
本节列出了一些您可能希望探索的扩展本教程的想法。
- 使用您自己的数据,为每个操作创建5个示例。
- 搜索机器学习论文,并找到每个操作被使用的一个例子。
如果您探索了这些扩展中的任何一个,我很想知道。
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
书籍
- 第6.6节 矩阵分解。《线性代数精要》,2017年。
- 第7讲 QR因式分解,《数值线性代数》,1997年。
- 第2.3节 LU分解及其应用,《数值方法:科学计算的艺术,第三版》,2007年。
- 第2.10节 QR分解,《数值方法:科学计算的艺术》,第三版,2007年。
- 第2.9节 Cholesky分解,《数值方法:科学计算的艺术》,第三版,2007年。
- 第23讲,Cholesky分解,《数值线性代数》,1997年。
API
文章
总结
在本教程中,您了解了矩阵分解以及如何在Python中计算它们。
具体来说,你学到了:
- 什么是矩阵分解以及为什么这类运算很重要。
- 如何在Python中计算LU和QR矩阵分解。
- 如何在Python中计算Cholesky矩阵分解。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,Jason,使用上三角矩阵的Cholesky分解是否有拼写错误?
我认为“A = U^T . T”应该是“A = U^T . U”
谢谢,已修正。
嗨,Jason,说得好!您能把非负矩阵分解(NMF)的Py API,比如sklearn.decomposition.NMF(),称为更有效和灵活的吗?
不错,谢谢。
你好,关于Cholesky分解一节中正定矩阵的定义有误
“[…] 所有值都大于零的方对称矩阵,即所谓的正定矩阵。”
这不完全正确:一个矩阵M是正定的,如果它的所有特征值都为正;或者根据定义,对于所有向量z:z' * M * z > 0。由于z可以表示为M的特征向量的线性组合,这两个陈述是等价的。还值得一提的是,当且仅当M是正定矩阵时,Cholesky分解才存在。
对于文章中的说法,一个反例是矩阵A=[1 2; 2 1]。由于det(A) = -3,并且行列式是A的特征值的乘积,所以必然存在一个值< 0的特征值。
感谢Janez的澄清,非常感谢!
Jason,
好文章。感谢分享。一个建议……我认为如果能多提供一些关于这些因式分解“为什么”的见解,这篇文章会更有帮助。例如,谈论QR分解中Q的正交性是一个可以被利用的重要属性(例如,在约束流形上的投影等)。
很好的建议,Joe,谢谢。
在QR分解部分的第一行,我认为应该是用于“m X n”矩阵,因为Q是“m X m”,R是“m X n”。
谢谢,我会把它加到Trello上并进行研究。
这里面的东西比你看到的要多得多……例如,无数据的数据……看看偷了我作品的政府……市、州、联邦、军队……
什么是无数据的数据?
我为reddit.com上的一个大型数据集做了一个tensorflow矩阵分解模型用于推荐系统。通过adam优化器的梯度下降效果很好。问题是代码进行了稀疏到稠密的转换,这当然会限制容量。很快我就会发现这个容量到底是多少。也许可以完全避免稠密转换,保持全稀疏,不确定。一个很棒的地方是它收敛快,并且能正确处理缺失数据,这在推荐系统中非常重要,特别是在我的应用中99.99%的稀疏性是显而易见的。垃圾进=垃圾出。它通过使用忽略缺失数据的成本函数来解决缺失数据问题。在一些推荐系统中,除了做出巨大的误导性假设外,没有办法进行预插补,所以你肯定需要在某些推荐系统中正确处理缺失数据,而不做假设。模型是pq + user_bias + item_bias + regularization (L2)。pq是因子矩阵。偏置项是学习得到的,而不是常量或预先计算的。TF是一个相当不错的分解模型求解器,因为它可以使用你拥有的任意数量的GPU卡。
无论如何,我正在转向深度神经网络模型以获得更好的容量。它基于Hinton描述的语义哈希设计,中间有一个二元潜在向量。然而,让Keras给我生成一个真正的二元向量似乎几乎不可能,这是一个大问题,在这种情况下是致命的。我用Keras实验了好几天,什么都行不通。我可能不得不转向全部使用tensorflow,这会很麻烦,但也许TF有能力生成一个二元潜在向量。
很棒。
嘿,我也在做类似的工作,用MovieLens数据集构建一个推荐系统。我正尝试用潜在因子模型为MovieLens数据集构建一个简单的推荐系统。我试图从观察到的评分集中构建一个模型,它将稀疏矩阵分解为N * K和K * M,其中N是用户数,M是电影数,K是我试图学习的潜在空间中的维度数。但我很难决定损失函数中的正则化项。这是我在stack exchange上发布的确切问题陈述
https://datascience.stackexchange.com/questions/43497/regularization-term-in-matrix-factorization
抱歉,我没有关于推荐系统的教程。也许将来会有。
在一些应用中没有缺失数据。在其他应用中只有少量缺失数据。还有一些应用中,缺失数据占大多数,比如隐式反馈推荐系统。必须非常小心地选择一种能恰当处理缺失数据的分解方法,否则垃圾数据会主导你的模型,使其毫无价值。例如,当没有缺失值时,奇异值分解是完全可以的。然而,SVD不能在评分推荐系统中正确运行,因为在某个时间点,缺失值是可用评分矩阵的大部分——它会运行,但如果你假设缺失的星级评分为零,结果就是无稽之谈。在这种情况下,我设计的一个很好的解决方案是基于梯度的推荐系统,其中缺失数据对优化器的损失贡献为零。我在tensorflow中制作了这样一个系统,效果很好。
底线是,不要把垃圾数据输入你的模型,并期望它能学到有用的东西,因为它不会。SVD或QR等方法可能完全没问题,但这强烈依赖于应用,决定使用那些不能处理缺失数据的矩阵分解算法是否明智。
很棒的提示,Geoffrey。
这个很不错,
你是否可以再写一篇关于低秩矩阵分解的文章
好建议,谢谢!
ReLU只是一个开关。
开=恒等函数=连接。
关=零=断开。
对于ReLU网络的特定输入向量,所有开关的状态都已确定。
多个点积的点积仍然是点积。
因此,对于该特定输入向量,网络输出可以浓缩为作用于输入向量的单个矩阵。
我想你可以对那个矩阵进行因式分解并从中得到一些度量。
无论如何,传统的神经网络似乎以一种痛苦的方式计算那个矩阵,也许它们应该被称为“卷积”神经网络(Convoluted Neural Networks,双关语,意为“复杂的”)。
感谢分享你的想法,Sean。
你好,亲爱的
求解形如Mx = b的线性方程组,求向量X
,使用QR分解。
通过线性代数法则。
X=R^-1 *Q^T *b
通过这个法则你可以找到向量X
但我想用python实现
你可以使用上面的QR分解,并将其与这篇文章中的示例结合起来
https://machinelearning.org.cn/solve-linear-regression-using-linear-algebra/
抱歉,我没有能力为你实现它。
对角化一个矩阵 M,使其可以写成 D = P −1 的形式
MP,
其中 D 是对角矩阵。
这可以帮助你计算对角线
https://machinelearning.org.cn/introduction-to-types-of-matrices-in-linear-algebra/
工作做得很好,但能否用R代替python呢?我是学R的学生。
谢谢您。
感谢您的建议。