首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

矩阵的奇异值分解(SVD)及其应用

编程知识
2024年07月26日 20:22

奇异值分解(Singular Value Decomposition, SVD)是矩阵的一种分解方法,与特征值分解不同,它可以应用于长方矩阵中,并将其分解成三个特殊矩阵的乘积。此外SVD分解还具有许多优良的性质,在图像压缩,数据降维和推荐系统等算法中都具有广泛的应用。

奇异值分解的引入

我们考虑二维的情形,考虑一组二维空间上的单位正交向量 \(\boldsymbol{v}_1 , \boldsymbol{v}_2\) ,设任意一个变换矩阵 \(M \in \mathbb R ^ {m \times 2}\) ,对其作变换得到另外一组正交向量 \(M\boldsymbol{v}_1, M\boldsymbol{v}_2\) ,容易知道变换后的正交向量仍然是该二维平面上的一组基底,可以对这组基底进行单位化得到 \(\boldsymbol{u}_1, \boldsymbol{u}_2\),即单位化前后的向量存在伸缩关系:

\[\begin{cases} \begin{aligned} M\boldsymbol{v}_1 &= \sigma_1 \boldsymbol{u}_1 \\ M\boldsymbol{v}_2 &= \sigma_2 \boldsymbol{u}_2 \\ \end{aligned} \end{cases} \]

此外,对于该二维平面上的任意一个向量 \(\boldsymbol{x} \in \mathbb R^2\) ,可以在基底 \((\boldsymbol{v}_1, \boldsymbol{v}_2)\) 下线性表示为

\[\boldsymbol{x} = (\boldsymbol{v}_1 \cdot \boldsymbol{x}) \boldsymbol{v}_1 + (\boldsymbol{v}_2 \cdot \boldsymbol{x}) \boldsymbol{v}_2 \]

对该向量作上述线性变换,可以得到

\[\begin{aligned} M\boldsymbol{x} &= (\boldsymbol{v}_1 \cdot \boldsymbol{x}) M \boldsymbol{v}_1 + (\boldsymbol{v}_2 \cdot \boldsymbol{x}) M \boldsymbol{v}_2 \\ &= (\boldsymbol{v}_1 \cdot \boldsymbol{x}) \sigma_1 \boldsymbol{u}_1 + (\boldsymbol{v}_2 \cdot \boldsymbol{x}) \sigma_2 \boldsymbol{u}_2 \\ &= \boldsymbol{v}_1 ^ \text T \boldsymbol{x} \ \sigma_1 \boldsymbol{u}_1 + \boldsymbol{v}_2 ^ \text T \boldsymbol{x}\ \sigma_2 \boldsymbol{u}_2 \\ &= \boldsymbol{u}_1 \sigma_1 \boldsymbol{v}_1 ^ \text T \boldsymbol{x} + \boldsymbol{u}_2 \sigma_2 \boldsymbol{v}_2 ^ \text T \boldsymbol{x} \\ &= \begin{pmatrix} \boldsymbol{u}_1 & \boldsymbol{u}_2 \end{pmatrix} \begin{pmatrix} \sigma_1 & \ \\ \ & \sigma_2 \\ \end{pmatrix} \begin{pmatrix} \boldsymbol{v}_1 ^ \text T \\ \boldsymbol{v}_2 ^ \text T \\ \end{pmatrix} \boldsymbol{x} \end{aligned} \]

若定义 \(\boldsymbol{U} = \begin{pmatrix} \boldsymbol{u}_1 & \boldsymbol{u}_2 \end{pmatrix}, \mathbf \Sigma = \begin{pmatrix} \sigma_1 & 0 \\ 0 & \sigma_2 \\ \end{pmatrix}, \boldsymbol{V} ^ \text T = \begin{pmatrix} \boldsymbol{v}_1 ^ \text T \\ \boldsymbol{v}_2 ^ \text T \\ \end{pmatrix}\) ,则对于任一变换矩阵 \(M \in \mathbb R ^ {2 \times 2}\) ,都可以分解成如下两组单位正交基底与对角矩阵的乘积的形式

\[M=\boldsymbol{U} \mathbf \Sigma \boldsymbol{V} ^ \text T \]

一般的,对于任意变换矩阵 \(A \in \mathbb R ^{m \times n}\) ,都存在单位正交阵 \(\boldsymbol{U} \in \mathbb R ^ {m \times m}, \boldsymbol{V} \in \mathbb R ^ {n \times n}\),类对角矩阵 \(\mathbf \Sigma \in \mathbb R ^{m \times n}\) ,满足

\[A = \boldsymbol{U} \mathbf \Sigma \boldsymbol{V} ^ \text T \]

上式即为矩阵的奇异值分解,其中类对角矩阵 \(\mathbf \Sigma\) 中的非零对角元素称为矩阵 \(A\) 的奇异值,矩阵 \(U,V\) 分别叫做左奇异矩阵和右奇异矩阵(酉矩阵)

奇异值分解的计算

下面考虑如何获取一个长方矩阵的奇异值分解,并给出一个具体的奇异值分解算例。

对于矩阵 \(A \in \mathbb R ^ {m \times n}\) ,我们考察其方阵形式 \(A ^ \text T A\)\(AA ^ \text T\) 。由于 \(A^\text T A\)\(n \times n\) 的实对陈方阵,因此可以对其进行特征值分解。

\[A ^ \text T A = Q \Lambda Q ^ \text T \]

同时,矩阵 \(A\) 存在奇异值分解,即

\[\begin{aligned} A ^ \text T A &= (\boldsymbol{U} \mathbf \Sigma \boldsymbol{V} ^ \text T) ^ \text T \boldsymbol{U} \mathbf \Sigma \boldsymbol{V} ^ \text T \\ &= V \Sigma ^ \text T U ^ \text T U \Sigma V ^ \text T \\ &= V \Sigma ^ \text T \Sigma V ^ \text T \\ &= V \Sigma ^ 2 V ^ \text T \end{aligned} \]

对比上面两式的结果

\[V = Q \\ \Sigma ^ 2 = \Lambda \]

可以发现右奇异矩阵即为 \(A^ \text T A\) 的特征向量矩阵,而所谓的奇异值则为 \(A^\text T A\) 的特征值的算术平方根。
同理可以再考察 \(AA^\text T\) ,即

\[\begin{aligned} AA^\text T &= (U\Sigma V^\text T)(U\Sigma V^\text T)^\text T \\ &= U\Sigma V^\text T V \Sigma ^\text T U ^ \text T \\ &= U \Sigma \Sigma ^ \text T U ^ \text T \end{aligned} \]

可以发现左奇异矩阵即为 \(AA^\text T\) 的特征向量矩阵。因此,要求解矩阵 \(A\) 的奇异值分解,只需分别计算 \(A^\text T A\)\(AA^\text T\) 的特征值分解即可,下面通过一个具体的算例进一步说明。
(算例)计算矩阵 \(A = \begin{pmatrix} 0 & 1 \\ 1 & 1 \\ 1 & 0 \\ \end{pmatrix}\)的 SVD 分解。
解:考察 \(A^\text T A\)\(AA^\text T\)

\[A^\text T A= \begin{pmatrix} 0 & 1 & 1 \\ 1 & 1 & 0 \\ \end{pmatrix} \begin{pmatrix} 0 & 1 \\ 1 & 1 \\ 1 & 0 \\ \end{pmatrix} = \begin{pmatrix} 2 & 1 \\ 1 & 2 \end{pmatrix} \\ \]

\[A A^\text T= \begin{pmatrix} 0 & 1 \\ 1 & 1 \\ 1 & 0 \\ \end{pmatrix} \begin{pmatrix} 0 & 1 & 1 \\ 1 & 1 & 0 \\ \end{pmatrix} = \begin{pmatrix} 1 & 1 & 0 \\ 1 & 2 & 1 \\ 0 & 1 & 1 \\ \end{pmatrix} \\ \]

作特征值分解并单位化特征向量

\[A^\text T A= \begin{pmatrix} \frac{1}{\sqrt 2} & \frac{1}{\sqrt 2} \\ \frac{-1}{\sqrt 2} & \frac{1}{\sqrt 2} \\ \end{pmatrix} \begin{pmatrix} 3 & 0 \\ 0 & 1 \\ \end{pmatrix} \begin{pmatrix} \frac{1}{\sqrt 2} & \frac{-1}{\sqrt 2} \\ \frac{1}{\sqrt 2} & \frac{1}{\sqrt 2} \\ \end{pmatrix} \\ \]

\[A A^ \text T= \begin{pmatrix} \frac{1}{\sqrt 6} & \frac{-1}{\sqrt 2} & \frac{1}{\sqrt 3} \\ \frac{2}{\sqrt 6} & 0 & \frac{-1}{\sqrt 3} \\ \frac{1}{\sqrt 6} & \frac{1}{\sqrt 2} & \frac{1}{\sqrt 3} \\ \end{pmatrix} \begin{pmatrix} 3 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 0 \\ \end{pmatrix} \begin{pmatrix} \frac{1}{\sqrt 6} & \frac{2}{\sqrt 6} & \frac{1}{\sqrt 6} \\ \frac{-1}{\sqrt 2} & 0 & \frac{1}{\sqrt 2} \\ \frac{1}{\sqrt 3} & \frac{-1}{\sqrt 3} & \frac{1}{\sqrt 3} \\ \end{pmatrix} \]

据此可以得到奇异值 \(\sigma_1 = \sqrt 3, \sigma_2 = 1\) ,则SVD分解为

\[A = \begin{pmatrix} \frac{1}{\sqrt 6} & \frac{-1}{\sqrt 2} & \frac{1}{\sqrt 3} \\ \frac{2}{\sqrt 6} & 0 & \frac{-1}{\sqrt 3} \\ \frac{1}{\sqrt 6} & \frac{1}{\sqrt 2} & \frac{1}{\sqrt 3} \\ \end{pmatrix} \begin{pmatrix} \sqrt 3 & 0 \\ 0 & 1 \\ 0 & 0 \\ \end{pmatrix} \begin{pmatrix} \frac{1}{\sqrt 2} & \frac{-1}{\sqrt 2} \\ \frac{1}{\sqrt 2} & \frac{1}{\sqrt 2} \\ \end{pmatrix} \\ \]

需要注意的一点是,在求解奇异值或者特征值矩阵时,为了方便后续处理,我们一般将特征值或奇异值按大小降序排列,且特征向量一般都做归一化处理。

奇异值分解的几何意义

单位正交矩阵可以看作空间中的旋转矩阵,而对角矩阵则表示沿坐标轴方向上的伸缩变换,因此对于一个矩阵,也可以看作是一种线性变换,所谓的奇异值分解就是将这一变换分解成两次旋转变换和一次沿坐标轴的拉伸变换的过程,更直观的变换过程如下图所示:

奇异值分解的应用

奇异值分解在平面拟合,图像压缩和降噪,主成分分析和推荐系统等算法中都有广泛的应用,下面以直线拟合和图像压缩为例说明。

直线拟合问题

设直线的方程为 \(ax+by+c=0\) ,采集到一组点集 \((x_i, y_i)\) ,需要根据这组点集拟合直线方程。要求解这一问题,可以构建误差函数

\[e_i = ax_i + by_i +c \]

当所有点的误差最小时,即认为拟合效果最好。这本质上是一个线性最小二乘问题,其数学形式可以表示为

\[\begin{aligned} (a,b)^* &= \arg \min \sum_{i=0}^{N}{e_i}^2 \\ &= \arg \min \sum_{i=0}^{N}{(ax_i + by_i + c)^ 2} \end{aligned} \]

构造矩阵 \(A = \begin{pmatrix} x_0 & y_0 & 1 \\ x_1 & y_1 & 1 \\ \vdots & \vdots & \vdots \\ x_N & y_N & 1 \\ \end{pmatrix}, \boldsymbol{x} = \begin{pmatrix} a \\ b \\ c \\ \end{pmatrix}\) ,则可以将上述求解过程写成矩阵形式

\[\begin{aligned} (a,b)^* &= \arg \min (A\boldsymbol{x})^\text T(A\boldsymbol{x}) \\ &= \arg \min \boldsymbol{x}^\text T (A^\text T A)\boldsymbol{x} \\ &= \arg \min \boldsymbol{x} ^ \text T V \Sigma^2 V^\text T \boldsymbol{x} \end{aligned} \]

注意到 \(V^\text T \boldsymbol{x}\) 其实是向量 \(\boldsymbol{x}\) 在基底 \(V\) 下的一组坐标,可以记作 \(\bm \alpha\) ,即

\[V^\text T \boldsymbol{x} = \begin{pmatrix} \boldsymbol{v}_1^\text T \\ \boldsymbol{v}_2^\text T \\ \vdots \\ \boldsymbol{v}_N^\text T \\ \end{pmatrix} \boldsymbol{x} = \begin{pmatrix} \alpha_1 \\ \alpha_2 \\ \vdots \\ \alpha_N \\ \end{pmatrix} = \bm{\alpha} \]

则上式可以进一步写成

\[\begin{aligned} \boldsymbol{x}^\text T V \Sigma^2 V^\text T \boldsymbol{x} &= \bm \alpha^\text T \Sigma^2 \bm \alpha \\ &= \sigma_1^2 \alpha_1^2 + \sigma_2^2 \alpha_2^2 + \cdots + \sigma_N^2 \alpha_N^2 \\ &\ge \sigma_N^2 \end{aligned} \]

在考虑归一化的拟合解前提下,即 \(\bm{\left| x \right|} = 1\) 时,当且仅当坐标 \(\bm \alpha\)\(\begin{pmatrix} 0 & 0 & \cdots & 1 \end{pmatrix}^\text T\) 时取等号,此时求解以下方程

\[\begin{pmatrix} \boldsymbol{v}_1^\text T \\ \boldsymbol{v}_2^\text T \\ \vdots \\ \boldsymbol{v}_N^\text T \\ \end{pmatrix} \boldsymbol x = \begin{pmatrix} 0 \\ 0 \\ \vdots \\ 1 \\ \end{pmatrix} \]

容易得到,此时\(\boldsymbol x = \boldsymbol{v}_N\)。也就是说,要求解误差的最小值,只需要进行奇异值分解,取右奇异矩阵的最后一维作为解 \(\bm{x}\) 即可,此时对应的拟合误差即为 \(\sigma_N^2\) ,也就是在最小二乘意义下的最小误差。
下面通过一个直线拟合的编程实例来进一步说明上述结论。
(编程实例)考虑直线 \(x + 2y + 5 = 0\) ,给定一系列带有噪声的点集,根据这组点集拟合直线,并与真值对比,得到拟合参数的均方误差。
采用C++语言编写程序,调用Eigen线性代数库进行SVD分解,代码如下:

Eigen::Vector3d abc = Eigen::Vector3d(1, 2, 5).normalized();    // 直线参数真值
const double sigma = 0.6;   // 噪声方差
const size_t count = 15;    // 取样点的个数
// 利用 OpenCV 的随机数种子生成取样点
cv::RNG rng;
Eigen::MatrixXd A(count, 3);
for(size_t i=0; i<count; ++i) {
    A.row(i) << i, -(abc[0]/abc[1])*i - (abc[2]/abc[1]) + rng.gaussian(sigma), 1;
}
// SVD求解, 并取出 V 矩阵的最后一维作为拟合解 x
Eigen::VectorXd x = Eigen::JacobiSVD<Eigen::MatrixXd>(A, Eigen::ComputeThinV).matrixV().col(2);
// 输出求解结果
cout << "==> true value: abc = " << abc.transpose() << endl;        // 打印真值
cout << "==> svd solving result: x = " << x.transpose() << endl;    // 打印拟合参数
cout << "   ==> error RMS = " << sqrt( (A*x).squaredNorm() / double(count) ) << endl;   // 打印均方误差

程序运行结果截图为:

注意SVD分解时考虑的是归一化的向量,因此得到的也是归一化后的拟合结果,与实际直线参数之间差了一个比例系数。
可以看到在噪声方差为0.6,取样点数为15个点时,得到的拟合结果的均方误差为0.2,拟合结果基本可以接受,在噪声方差更小的情况下,可以得到更可靠的拟合结果。

图像压缩问题

考虑一个 \(m \times n\) 的矩阵 \(A\) ,其奇异值分解式为

\[A=U_{m \times m}\Sigma_{m\times n} V_{n \times n}^\text T \]

我们发现求得的奇异值衰减速度较快,前面几项的奇异值较大,而越往后的奇异值则越小,也就是说我们可以通过只保留前面几项奇异值来对 \(A\) 进行近似,这种做法可以压缩存储空间,在图像处理领域有着广泛的应用。具体做法是我们可以取出前 \(k\) 个奇异值,得到近似的 \(\tilde A\) ,其中 \(\frac{k}{\min\{m,n\}}\) 称为矩阵的压缩比。

\[A \approx \tilde A = U_{m \times k} \Sigma_{k \times k} V_{k \times n}^\text T \]


(编程实例)给定一张图片(如下),考虑采用不同的压缩比对其进行压缩,并对比分析压缩效果。

采用C++语言编写程序,调用OpenCV图像处理库来进行图像矩阵的SVD分解,采用不同的压缩比(0.01, 0.05, 0.1, 0.2, 0.3, 0.5)重复执行程序,得到输出结果。程序代码如下:

// 读入图像
cv::Mat img_original = cv::imread("../image.png", cv::IMREAD_GRAYSCALE);
cv::Mat img = img_original.clone();
img.convertTo(img, CV_64FC1, 1/255.0);
// 对图像进行SVD分解
cv::Mat U, Vt, W;
cv::SVD::compute(img, W, U, Vt);
// 图像压缩操作
int rank = min(img.rows, img.cols);
cv::Mat W_hat = cv::Mat(rank, rank, CV_64FC1, cv::Scalar(0));  // 取前k维的奇异值矩阵
double compression_ratio = 0.3;     // 设定压缩比
int k = rank * compression_ratio;
for(size_t i=0; i<k; ++i) {
    W_hat.at<double>(i, i) = W.at<double>(i, 0);
}
cv::Mat img_compression = U * W_hat * Vt;   // 计算压缩后的图像
// 压缩图像输出
img_compression.convertTo(img_compression, CV_8UC1, 255.0);
cv::imwrite("./ratio=0_3.png", img_compression);

输出压缩结果如下所示

  • 压缩比 = 0.01
  • 压缩比 = 0.05
  • 压缩比 = 0.1
  • 压缩比 = 0.2
  • 压缩比 = 0.3
  • 压缩比 = 0.5

    可以看到测试图像的基本轮廓信息在压缩比为0.05的时候就已经大致凸显,而在压缩比为0.2时就已经基本保留图像的细节信息,压缩效率较好。

参考资料

[1] http://www.ams.org/publicoutreach/feature-column/fcarc-svd
[2] https://blog.csdn.net/lomodays207/article/details/88687126
[3] https://www.cnblogs.com/pinard/p/6251584.html
[4] https://blog.csdn.net/u012198575/article/details/99548136

From:https://www.cnblogs.com/jiachengyu/p/18326192
本文地址: http://shuzixingkong.net/article/466
0评论
提交 加载更多评论
其他文章 微服务:解决复杂业务的妙方
1 微服务介绍 1)什么是微服务 ​ 微服务(Microservices)是一种软件架构风格,它将一个大型应用程序拆分成许多较小的、松散耦合的、独立运行的服务。这些服务通常围绕特定功能或业务领域组织,可以独立开发、部署、扩展和更新。微服务之间通过轻量级的通信协议(如HTTP/REST、消息队列等)相
微服务:解决复杂业务的妙方 微服务:解决复杂业务的妙方 微服务:解决复杂业务的妙方
.NET 控件转图片
Windows应用开发有很多场景需要动态获取控件显示的图像,即控件转图片,用于其它界面的显示、传输图片数据流、保存为本地图片等用途。 下面分别介绍下一些实现方式以及主要使用场景 RenderTargetBitmap 控件转图片BitmapImage/BitmapSource,在WPF中可以使用Ren
.NET 控件转图片 .NET 控件转图片
【工具】IDEA怎么查看maven依赖链路?
当我在SpringBoot项目中想加个依赖,但是不确定现有依赖的依赖的依赖.....有没有添加过这个依赖,怎么办呢?如果添加过了但是不知道我需要的这个依赖属于哪个依赖的下面,怎么查呢? IDEA中提供了很方便的视图可以满足我们的需求 第一步点击项目右侧的maven 第二步选中Dependencies
【工具】IDEA怎么查看maven依赖链路? 【工具】IDEA怎么查看maven依赖链路? 【工具】IDEA怎么查看maven依赖链路?
Jetpack Compose学习(12)——Material Theme的主题色切换
原文:Jetpack Compose学习(12)——Material Theme的主题色切换-Stars-One的杂货小窝 闲着无事研究了下Jetpack Compose M3 主题切换效果 本系列以往文章请查看此分类链接Jetpack compose学习 如何生成主题 首先,我们需要知道的是,M3
Jetpack Compose学习(12)——Material Theme的主题色切换 Jetpack Compose学习(12)——Material Theme的主题色切换 Jetpack Compose学习(12)——Material Theme的主题色切换
后端说,单页面SPA和前端路由是怎么回事
没有请求的路由 在传统开发中,浏览器点击一个超链接,就会像后端web服务器发送一个html文档请求,然后页面刷新。但开始单页面开发后,就完全不同了。 单页面?这个概念难以理解。我用一个js作为整个web应用,然后再这个js中操作dom变化,以此来实现页面变化。这不叫单页面吗?这叫!但不完善,因为这种
后端说,单页面SPA和前端路由是怎么回事
Asp .Net Core 系列:详解授权以及实现角色、策略、自定义三种授权和自定义响应
什么是授权(Authorization)? 在 ASP.NET Core 中,授权(Authorization)是控制对应用资源的访问的过程。它决定了哪些用户或用户组可以访问特定的资源或执行特定的操作。授权通常与身份验证(Authentication)一起使用,身份验证是验证用户身份的过程,授权与身
Asp .Net Core 系列:详解授权以及实现角色、策略、自定义三种授权和自定义响应
通过Jupyter Notebook+OpenAI+ollama简单的调用本地模型
通过Jupyter Notebook+OpenAI+ollama简单的调用本地模型 起因是收到了ollama的邮件,貌似支持使用openai来调用本地的ollama下载的模型为自己用 想了下正好试下,因为这几天正好在尝试用Jupyter Notebook来写点调用api的方式来使用大语言模型,看看后
通过Jupyter Notebook+OpenAI+ollama简单的调用本地模型 通过Jupyter Notebook+OpenAI+ollama简单的调用本地模型 通过Jupyter Notebook+OpenAI+ollama简单的调用本地模型
提高 C# 的生产力:C# 13 更新完全指南
前言 预计在 2024 年 11 月,C# 13 将与 .NET 9 一起正式发布。今年的 C# 更新主要集中在 ref struct 上进行了许多改进,并添加了许多有助于进一步提高生产力的便利功能。 本文将介绍预计将在 C# 13 中添加的功能。 注意:目前 C# 13 还未正式发布,因此以下内容