机器学习笔记 - SVD奇异值分解(1)

一、旋转或缩放

1、概述

        特征分解只能对方阵进行。对于非方阵的矩阵可以使用奇异值分解(SVD)。

        使用SVD,您可以将矩阵分解为三个矩阵。我们将这些新矩阵视为空间的子变换。不是在一个动作中进行转换,而是将其分解为三个动作。

        最后,我们会将SVD应用于图像处理,看到SVD对示例图像的影响。

        我们将A分解为3个矩阵(而不是使用特征分解的两个):

奇异值分解 (SVD)

         矩阵 U、D 和 V 具有以下属性:

        U和V是正交矩阵并且

        D是一个对角矩阵(除对角线外全为 0)。 然而D不一定是正方形的。 

        U称为A的左奇异向量,而V称为A的右奇异向量。沿D对角线的值是A的奇异值。

        以下是分解的维度:

奇异值分解的维度

         奇异值的对角矩阵不是正方形,而是具有 A 的形状。

        下面是Numpy文档中提供的示例,创建了一个与 A 形状相同的零矩阵并用奇异值填充它:

smat = np.zeros((9, 6), dtype=complex)
smat[:6, :6] = np.diag(s)

        对于奇异值分解背后的直觉需要对矩阵变换的思想进行一些解释。这里有几个示例展示了如何通过 2D 方阵转换空间。 希望可以更好地理解:A 是一个矩阵,可以看作是一个线性变换。 该变换可以分解为三个子变换:1. 旋转,2. 重新缩放,3. 旋转。 这三个步骤对应于三个矩阵 U、D 和 V。

        您可以从有关 SVD 的 Wikipedia 文章中查看细节步骤。

https://en.wikipedia.org/wiki/Singular_value_decompositionhttps://en.wikipedia.org/wiki/Singular_value_decomposition        每个矩阵都可以看作是一个线性变换

        您可以将矩阵视为特定的线性变换。当您将此矩阵应用于向量或另一个矩阵时,您将对其应用此线性变换。

2、例1

        1、

        2、

        3、

         我们从上面的计算看到,应用矩阵:,只是将向量的每个坐标加倍。 以下是 v 及其变换 w 的图形表示:

将矩阵应用于向量将每个坐标乘以 2

3、例2

         为了表示与矩阵相关的线性变换,我们还可以绘制单位圆并查看矩阵如何对其进行变换。 单位圆表示每个单位向量的坐标(长度为 1 的向量)。

单位圆

         然后可以将矩阵应用于所有这些单位向量,以查看它将产生的变形类型。

        

单位圆的每个坐标乘以2

         我们可以看到矩阵使圆的大小增加了一倍。但在某些变换中,应用于 x 坐标的变化与应用于 y 坐标的变化不同。 让我们继续看看它在图形上的含义。

4、例3

         对单位圆应用下面的矩阵变换

        

这次矩阵没有以相同的权重重新缩放每个坐标

         我们可以通过与此矩阵变换相关的方程来检查这一点。 假设新圆的坐标(变换后)是 x′ 和 y′。 旧坐标 (x, y) 和新坐标 (x′, y′) 之间的关系为:

         我们也知道单位圆的方程是(单位向量的范数是1)。通过替换,我们最终得到:

         我们可以检查这个方程是否对应于我们的变换圆。 让我们从画旧的圆圈开始。 其方程为:

x = np.linspace(-1, 1, 100000)
y = np.sqrt(1-(x**2))
plt.plot(x, y, sns.color_palette().as_hex()[0])
plt.plot(x, -y, sns.color_palette().as_hex()[0])
plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)
plt.show()

         现在让我们添加矩阵变换后得到的圆。 我们看到它被定义为

x1 = np.linspace(-3, 3, 100000)
y1 = 2*np.sqrt(1-((x1/3)**2))
plt.plot(x, y, sns.color_palette().as_hex()[0])
plt.plot(x, -y, sns.color_palette().as_hex()[0])
plt.plot(x1, y1, sns.color_palette().as_hex()[1])
plt.plot(x1, -y1, sns.color_palette().as_hex()[1])
plt.xlim(-4, 4)
plt.ylim(-4, 4)
plt.show()
方程的变换圆

         请注意,这些示例使用了对角矩阵(除对角线外全为零)。 一般规则是与对角矩阵相关的变换仅意味着每个坐标的重新缩放而不旋转。 这是理解 SVD 的第一个要素。

5、例4

        非对角矩阵可以产生旋转。使用三角函数讨论旋转时更容易,我们设有矩阵

这个矩阵将对我们的向量或矩阵逆时针旋转一个角度θ。我们的新向量是让我们从坐标 x=0 和 y=1 的向量 u 和坐标 x=1 和 y=0 的向量 v 开始。 矢量 u' v' 是旋转矢量。

单位向量逆时针旋转,θ=45

         首先,让我们创建一个函数 plotVectors() 来绘制向量:

def plotVectors(vecs, cols, alpha=1):
    plt.figure()
    plt.axvline(x=0, color='#A9A9A9', zorder=0)
    plt.axhline(y=0, color='#A9A9A9', zorder=0)

    for i in range(len(vecs)):
        x = np.concatenate([[0,0],vecs[i]])
        plt.quiver([x[0]],
                   [x[1]],
                   [x[2]],
                   [x[3]],
                   angles='xy', scale_units='xy', scale=1, color=cols[i],
                   alpha=alpha)

        绘制向量u和v

orange = '#FF9A13'
blue = '#1190FF'

u = [1,0]
v = [0,1]

plotVectors([u, v], cols=[blue, blue])

plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)

plt.text(-0.25, 0.2, r'$\vec{u}$', color=blue, size=18)
plt.text(0.4, -0.25, r'$\vec{v}$', color=blue, size=18)
plt.show()

        它们是我们空间的基向量。 我们将计算这些向量的变换:

         我们现在绘制这些新向量以检查它们是否是我们旋转了 45∘ 角的基础向量。

u1 = [-np.sin(np.radians(45)), np.cos(np.radians(45))]
v1 = [np.cos(np.radians(45)), np.sin(np.radians(45))]

plotVectors([u1, v1], cols=[orange, orange])
plt.xlim(-1.5, 1.5)
plt.ylim(-1.5, 1.5)

plt.text(-0.7, 0.1, r"$\vec{u'}$", color=orange, size=18)
plt.text(0.4, 0.1, r"$\vec{v'}$", color=orange, size=18)
plt.show()

         numpy 函数 sin 和 cos 以弧度为单位进行输入。 我们可以使用函数 np.radians() 将角度从度数转换为弧度数。

        我们也可以变换一个圆。 我们将采用一个重新缩放的圆,以便能够看到旋转的效果。

x = np.linspace(-3, 3, 100000)
y = 2*np.sqrt(1-((x/3)**2))

x1 = x*np.cos(np.radians(45)) - y*np.sin(np.radians(45))
y1 = x*np.sin(np.radians(45)) + y*np.cos(np.radians(45))

x1_neg = x*np.cos(np.radians(45)) - -y*np.sin(np.radians(45))
y1_neg = x*np.sin(np.radians(45)) + -y*np.cos(np.radians(45))

u1 = [-2*np.sin(np.radians(45)), 2*np.cos(np.radians(45))]
v1 = [3*np.cos(np.radians(45)), 3*np.sin(np.radians(45))]

plotVectors([u1, v1], cols=['#FF9A13', '#FF9A13'])

plt.plot(x, y, '#1190FF')
plt.plot(x, -y, '#1190FF')

plt.plot(x1, y1, '#FF9A13')
plt.plot(x1_neg, y1_neg, '#FF9A13')

plt.xlim(-4, 4)
plt.ylim(-4, 4)
plt.show()

         我们可以看到圆已经旋转了 45∘ 角。 我们从示例 3(因子 3 和 2)的重新缩放权重中选择了向量的长度来匹配圆。

二、结论

        我们了解了如何通过旋转或缩放矩阵来转换向量和矩阵。SVD可以看作是将一个复杂变换分解为3个更简单的变换(旋转、缩放、旋转)。

        请注意,我们本节只采用了方阵。 SVD可以用非方阵来完成,但很难表示与非方阵相关的变换。 例如,一个 3 x 2 矩阵会将 2D 空间映射到 3D 空间。

         下一篇我们将使用SVD进行矩阵分解。

猜你喜欢

转载自blog.csdn.net/bashendixie5/article/details/124266777