奇异值分解简介:从原理到基础机器学习应用

2024-06-17 16:32

本文主要是介绍奇异值分解简介:从原理到基础机器学习应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


矩阵分解在机器学习应用中的重要性无需多言。本文对适用范围很广的奇异值分解方法进行了介绍,并通过代码演示说明了其工作方式、计算方法及其常见的几种基础应用。

矩阵分解也叫矩阵因子分解,涉及到用给定矩阵的组成元素描述该矩阵。

奇异值分解(SVD)可能是最著名和使用最广泛的矩阵分解方法。所有矩阵都有一种 SVD 方法,这使得其比特征分解(eigendecomposition)等其它方法更加稳定。因此,这种方法在很多应用中都有应用,包括压缩、去噪、数据压缩。

在这份教程中,你将了解用于将矩阵分解成其组成元素的奇异值分解方法。

在完成本教程后,你将了解:

  • 奇异值分解是什么以及涉及什么

  • 如何计算 SVD 以及如何根据 SVD 元素重建矩形和方形矩阵

  • 如何使用 SVD 计算伪逆和执行降维

那就开始吧!

教程概览

本教程分为 5 部分,依次为:

1. 奇异值分解

2. 计算奇异值分解

3. 根据 SVD 重建矩阵

4. 用于伪逆的 SVD

5. 用于降维的 SVD

奇异值分解

奇异值分解(SVD)是一种用于将矩阵归约成其组成部分的矩阵分解方法,以使后面的某些矩阵计算更简单。

为了说明简单,我们将关注用于实数值矩阵的 SVD,而会忽略复数矩阵的情况。

其中 A 是我们希望分解的 n×m 的实矩阵,U 是一个 m×m 矩阵,Sigma(通常用大写的希腊字母 ∑表示)是一个 m×n 的对角矩阵,V^T 是一个 n×n 矩阵的转置,其中 T 是上标。奇异值分解是线性代数的一个亮点。

——《Introduction to Linear Algebra》第五版,2016 年,第 371 页

Sigma 矩阵中的对角值被称为原始矩阵 A 的奇异值。U 矩阵的列被称为 A 的左奇异向量,V 的列被称为 A 的右奇异向量。

SVD 是通过迭代式的数值方法计算的。我不会详细深入这些方法的细节。每一个矩形矩阵都有一个奇异值分解,尽管所得到的矩阵可能包含复数值以及浮点算术的局限性可能会导致某些矩阵无法简单利落地完成分解。 

奇异值分解(SVD)提供了另一种将矩阵分解成奇异向量和奇异值的方式。SVD 让我们可以发现某些与特征分解同种类型的信息。但是,SVD 有更广的适用性。

——《Deep Learning》,2016 年,第 44-45 

SVD 在矩阵求逆等其它矩阵运算的计算有广泛的应用,但也可用作机器学习中的数据归约方法。SVD 也可用在最小二乘线性回归、图像压缩和数据去噪中。

奇异值分解(SVD)在统计学、机器学习和计算机科学领域有很多应用。将 SVD 应用于矩阵就像是使用 X 射线进行透视……

——《No Bullshit Guide To Linear Algebra》,2017 年,第 297 页

计算奇异值分解

SVD 可以通过调用 svd() 函数进行计算。

该函数在处理矩阵后会返回 U、Sigma 和 V^T 元素。Sigma 对角矩阵是按奇异值向量的形式返回的。V 矩阵是以转置后的形式返回的,比如 V.T.

下面的示例定义了一个 3×2 矩阵并计算了奇异值分解。

运行这个示例,首先会显示定义的 3×2 矩阵,然后会显示分解计算得到的 3×3 的 U 矩阵、2 个元素的 Sigma 向量和 2×3 的 V^T 矩阵元素。

根据 SVD 重建矩阵

原始矩阵可以根据 U、Sigma 和 V^T 元素重建出来。

svd() 返回的 U、s 和 V 元素不能直接相乘。 

s 向量必须使用 diag() 函数转换成对角矩阵。默认情况下,这个函数将创建一个相对于原来矩阵的 m×m 的方形矩阵。这是有问题的,因为该矩阵的尺寸并不符合矩阵乘法的规则,即一个矩阵的列数必须等于后一个矩阵的行数。

在创建了方形的 Sigma 对角矩阵之后,各个矩阵的大小与我们分解的原始 n×m 矩阵是相关的,如下:

而事实上我们需要:

我们可以通过创建一个全是 0 值的 m×n 的新 Sigma 矩阵(比如:更多行)并使用通过 diag() 计算得到的方形对角矩阵来填充矩阵的前 n×n 部分。

运行这个示例,首先会显示原始矩阵,然后会显示根据 SVD 元素重建的矩阵。

上面使用 Sigma 对角矩阵的复杂之处仅存在于 m 和 n 不相等的情况中。当重建一个方形矩阵时,其对角矩阵可以直接使用,如下。

运行这个示例会显示原来的 3×3 矩阵和根据 SVD 元素直接重建的版本。

用于伪逆的 SVD 

伪逆(pseudoinverse)是将方形矩阵的矩阵求逆泛化应用到行数和列数不相等的矩形矩阵上。这也被称为广义逆(Generalized Inverse)或摩尔-彭若斯逆(Moore-Penrose Inverse),得名于两位独立发现该方法的研究者。

矩阵求逆不是为非方形矩阵定义的。[...] 当 A 的列数大于行数时,那么使用伪逆求解线性方程是众多解决方案中的一种。

——《Deep Learning》,2016 年,第 46 页

伪逆表示为 A^+,其中 A 是被求逆的矩阵,+ 是上标。

伪逆是使用 A 的奇异值分解计算的:

或者,没有点符号:

其中 A^+ 是 A 的伪逆,D^+ 是对角矩阵 Sigma 的伪逆,U^T 是 U 的转置。 

我们可以根据 SVD 运算得到 U 和 V。

根据 Sigma 创建一个对角矩阵,计算 Sigma 中每个非零元素的倒数,然后如果原始矩阵是矩形的就取其转置,就可以计算得到 D^+。

伪逆提供了一种求解线性回归方程的方法,尤其是当行数多于列数时,而这也是很常见的情况。 

NumPy 提供了函数 pinv() 来计算矩形矩阵的伪逆。

下面的示例定义了一个 4×2 的矩阵并计算了其伪逆。

运行这个示例,首先显示定义的矩阵,然后显示计算出的伪逆。

我们可以通过 SVD 采用人工的方式计算伪逆,并将结果与 pinv() 函数的结果进行比较。 

首先我们必须计算 SVD。然后我们必须计算 s 数组中每个值的倒数。然后将这个 s 数组转换成一个对角矩阵,它额外增加了一行 0 以使其变成矩形形式。最后,我们可以根据这些元素计算伪逆。 

具体实现方式为:

下面列出了完整的示例。

运行这个示例,首先显示定义的矩形矩阵,然后显示其伪逆,结果与上面 pinv() 函数的结果一致。

用于降维的 SVD 

SVD 的一大常见应用是降维。 

具有大量特征的数据(比如特征数(列数)多于观察数(行数))也许可以被归约成与所涉预测问题最相关的更小特征子集。

其结果是一个秩更低的矩阵,据说接近原始矩阵。

为了做到这一点,我们可以在原来的数据上执行一次 SVD 操作并选择 Sigma 中前 k 个最大的奇异值。这些列可以从 Sigma 中选择得到,行可以从 V^T 中选择得到。

然后可以重建原始向量 A 的近似 B。

在自然语言处理中,这种方法可以被用在文档中词出现情况或词频的矩阵上,并被称为隐含语义分析(Latent Semantic Analysis)或隐含语义索引(Latent Semantic Indexing)。 

在实践中,我们可以保留和使用被称为 T 的描述性数据子集。这是矩阵的密集总结或投射。

此外,这种变换既可以在原来的矩阵 A 上计算和应用,也可以在其它类似的矩阵上计算和应用。

下面的示例是使用 SVD 的数据归约。

首先定义一个 3×10 的矩阵,其列数多于行数。然后计算 SVD 并且只选取其前两个特征。这些元素再重新结合起来,得到原始矩阵的准确再现。最后计算转换的方式有两种。

运行这个示例,首先显示定义的矩阵,然后是重建的近似矩阵,然后是原始矩阵的两个同样的变换结果。

scikit-learn 提供了直接实现这种功能的 TruncatedSVD 类。 

TruncatedSVD 的创建必须指定所需的特征数或所要选择的成分数,比如 2。一旦创建完成,你就可以通过调用 fit() 函数来拟合该变换(比如:计算 V^Tk),然后再通过调用 transform() 函数将其应用于原始矩阵。结果得到上面被称为 T 的 A 的变换。

下面的示例演示了 TruncatedSVD 类。

运行这个示例,首先显示定义的矩阵,然后是该矩阵变换后的版本。

可以看到,结果得到的值与上面人工计算的结果一致,但某些值的符号不一样。由于所涉及的计算的性质以及所用的基础库和方法的差异,可以预见在符号方面会存在一些不稳定性。只要对该变换进行训练以便复用,这种不稳定性在实践中应该不成问题。

原文链接:https://machinelearningmastery.com/singular-value-decomposition-for-machine-learning/

这篇关于奇异值分解简介:从原理到基础机器学习应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1069962

相关文章

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

Android Mainline基础简介

《AndroidMainline基础简介》AndroidMainline是通过模块化更新Android核心组件的框架,可能提高安全性,本文给大家介绍AndroidMainline基础简介,感兴趣的朋... 目录关键要点什么是 android Mainline?Android Mainline 的工作原理关键

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

C#中async await异步关键字用法和异步的底层原理全解析

《C#中asyncawait异步关键字用法和异步的底层原理全解析》:本文主要介绍C#中asyncawait异步关键字用法和异步的底层原理全解析,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录C#异步编程一、异步编程基础二、异步方法的工作原理三、代码示例四、编译后的底层实现五、总结C#异步编程

SpringShell命令行之交互式Shell应用开发方式

《SpringShell命令行之交互式Shell应用开发方式》本文将深入探讨SpringShell的核心特性、实现方式及应用场景,帮助开发者掌握这一强大工具,具有很好的参考价值,希望对大家有所帮助,如... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定