机器学习笔记--降维

1、概述

1.1 维数灾难

维数灾难: 通常是指在涉及到向量的计算的问题中,随着维数的增加,计算量呈指数倍增长的一种现象。

在这里插入图片描述

有的时候,维度太大也会导致机器学习性能的下降,并不是特征维度
越大越好,模型的性能会随着特征的增加先上升后下降

1.2 降维

(1)降维是将训练数据中的样本从高维空间转换到低维空间,要注意,不存在完全无损的降维

(2)降维的主要作用:

  • 减少冗余特征,降低数据维度

  • 数据可视化

(3)降维的优缺点

降维的优点:

  • 通过减少特征的维数,数据集存储所需的空间也相应减少,减少了特征维数所需的计算训练时间;

  • 数据集特征的降维有助于快速可视化数据;

  • 通过处理多重共线性消除冗余特征。

降维的缺点:

  • 由于降维可能会丢失一些数据;

  • 在主成分分析(PCA)降维技术中,有时需要考虑多少主成分是难以确定的,往往使用经验法则。

2、SVD(奇异值分解)

2.1 基本定义

定义矩阵 A 的 SVD 为

A = U Σ V T A=U \Sigma V^{T} A=UΣVT
在这里插入图片描述

符号定义
A = U Σ V T = u 1 σ 1 v 1 T + ⋯ + u r σ r v r T = σ 1 u 1 v 1 T + σ 2 u 2 v 2 T + ⋯ + σ r u r v r T \begin{aligned} A=U \Sigma V^{T}=u_{1} \sigma_{1} v_{1}^{T}+\cdots+u_{r} \sigma_{r} v_{r}^{T}\\ =\sigma_{1} u_{1} v_{1}^{T}+\sigma_{2} u_{2} v_{2}^{T}+\cdots+\sigma_{r} u_{r} v_{r}^{T} \end{aligned} A=UΣVT=u1σ1v1T++urσrvrT=σ1u1v1T+σ2u2v2T++σrurvrT
其中,

  • U 是一个 m × m m\times m m×m的正交矩阵,每个特征向量 u i u_{i} ui叫做 A 的左奇异向量;

  • Σ \Sigma Σ是一个 m × n m\times n m×n的矩阵,除了主对角线上的元素以外全为 0,主对角线上的每个元素都称为奇异值 σ \sigma σ;

  • V 是一个 n × n n\times n n×n的正交矩阵,每个特征向量 v i v_{i} vi叫做 A 的右奇异向量;

  • U 和 V 都是正交矩阵,即满足 U T U = E , V T V = E U^{T} U=E, V^{T} V=E UTU=E,VTV=E

  • r 为 A 的秩;

  • 注意:对任意 m × n m\times n m×n矩阵 A , A T A 和 A A T A^{T} A 和 A A^{T} ATAAAT都是对称矩阵,且有相同的特征值

2.2 SVD求解

(1)U 矩阵求解

方阵 A T A A^{T}A ATA是一个 m × m m\times m m×m的矩阵,对其进行特征分解,得到 m 个特征值 λ i \lambda_{i} λi和与其对应的 m 个特征向量 u i u_{i} ui;所有特征向量组成的 m × m m\times m m×m矩阵即为所求的 U。

(2)V 矩阵求解

同上,对 A A T AA^{T} AAT特征分解,得到 n × n n\times n n×n矩阵 V。

(3) Σ \Sigma Σ矩阵求解

特征值矩阵等于奇异值矩阵的平方,也就是说特征值和奇异值满足如下关系:
σ i = λ i \sigma_{i}=\sqrt{\lambda_{i}} σi=λi
又由于奇异值矩阵 Σ \Sigma Σ除了对角线上是奇异值,而其他位置都是0,那我们只需要求出每个奇异值 𝜎就可以了。

2.3 SVD降维的原理

SVD分解可以将一个矩阵进行分解,对角矩阵对角线上的特征值递减存放,而且奇异值的减少特别的快,在很多情况下,前10%甚至 1%的奇异值的和就占了全部的奇异值之和的 99%以上的比例。

也就是说,对于奇异值,它跟我们特征分解中的特征值类似,我们也可以用最大的 k 个的奇异值和对应的左右奇异向量来近似描述矩阵。

也就是说:

A m × n = U m × m Σ m × n V n × n T ≈ U m × k Σ k × k V k × n T A_{m \times n}=U_{m \times m} \Sigma_{m \times n} V_{n \times n}^{T} \approx U_{m \times k} \Sigma_{k \times k} V_{k \times n}^{T} Am×n=Um×mΣm×nVn×nTUm×kΣk×kVk×nT
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uO3BXuDr-1636513161787)(D4FE7B1AE544452991EA636353CD20E5)]

将矩阵 A 进行奇异值分解后,我们选择其中最大的前 k 个奇异值与其相对应的左右奇异向量,便可以将原矩阵 A 进行近似表述。这便实现了降维。

3、主成分分析

主成分分析(PCA)是一种降维方法,通过将一个大的特征集转换成一个较小的特征集,这个特征集仍然包含了原始数据中的大部分信息,从而降低了原始数据的维数。

PCA的思想很简单——减少数据集的特征数量,同时尽可能地保留信息。

PCA算法的两种实现方法:

  • 基于SVD分解协方差矩阵实现PCA算法

  • 基于特征值分解协方差矩阵实现PCA算法

3.1 基于SVD分解协方差矩阵实现PCA算法

PCA 减少 n 维到 k 维:

设有 m 条 n 维数据,将原始数据按列组成n行m列矩阵 X

(1)均值归一化。我们需要计算出所有特征的均值,然后令 x j = x j − μ j x_{j}=x_{j}-\mu_{j} xj=xjμj( u j u_{j} uj是均值)。如
果特征是在不同的数量级上,我们还需要将其除以标准差 σ \sigma σ

(2)算协方差矩阵 ∑ = 1 m ∑ i = 1 n ( x ( i ) ) ( x ( i ) ) T \sum=\frac{1}{m} \sum_{i=1}^{n}\left(x^{(i)}\right)\left(x^{(i)}\right)^{T} =m1i=1n(x(i))(x(i))T

注意:如果上面 X 矩阵是 m × n m\times n m×n,则 ∑ = 1 m ∑ i = 1 n ( x ( i ) ) T ( x ( i ) ) \sum=\frac{1}{m} \sum_{i=1}^{n}\left(x^{(i)}\right)^{T}\left(x^{(i)}\right) =m1i=1n(x(i))T(x(i))

(3)计算协方差矩阵 Σ \Sigma Σ的特征向量,可以利用奇异值分解(SVD)来求解。即[U, S, V]= svd(sigma)

(4)如果我们希望将数据从 n 维降至 k 维,我们只需要从U 中选取前 k 个向量,获得一个 n × k n\times k n×k维度的矩阵,我们用 U r e d u c e U_{reduce} Ureduce表示,然后通过如下计算获得要求的新特征向量 z i z^{i} zi Z = U reduce  T X Z=U_{\text {reduce }}^{T} X Z=Ureduce TX

(5)计算时一定要考虑维度是否匹配。

3.2 基于特征值分解协方差矩阵实现PCA算法

(1)、(2)同上

(3)用特征值分解方法计算协方差矩阵 Σ \Sigma Σ的特征值和特征向量;

(4)对特征值从大到小排序,选择其中最大的 k 个。然后将其对应的 k 个特征向量分别作为行向量组成特征向量矩阵 P。

(5)将数据转换到 k 个特征向量构建的新空间中,即 𝑌 = 𝑃𝑋。

3.3 重建的压缩表示

与降维过程相反,还原后的数据为
X appox  = U reduce  Z X_{\text {appox }}=U_{\text {reduce }} Z Xappox =Ureduce Z
显然,这必然会损失一部分信息。

3.4 PCA算法优缺点

(1)PCA算法优点

  • 仅仅需要以方差衡量信息量,不受数据集以外的因素影响

  • 各主成分之间正交,可消除原始数据成分间的相互影响的因素

  • 计算方法简单,主要运算时特征值分解,易于实现

  • 它是无监督学习,完全无参数限制的

(2)PCA算法缺点

  • 主成分各个特征维度的含义具有一定的模糊性,不如原始样本特征的解释性强

  • 方差小的非主成分也可能含有对样本差异的重要信息,因降维丢弃可能对后续数据处理有影响

4、课后习题

# @Time : 2021/11/1 10:54
# @Author : xiao cong
# @Function : 主成分分析

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat

data = loadmat("ex7data1.mat")
# print(data)
X = data["X"]
print("X.shape = ", X.shape)

plt.scatter(X[:, 0], X[:, 1], s=30, c='b')  # 画出散点图
plt.title("Original Data Points")
plt.xlabel("X1")
plt.ylabel("X2")
plt.show()


def feature_normalize(X):  # 数据标准化
    means = X.mean(axis=0)
    stds = X.std(axis=0, ddof=1)
    X_norm = (X - means) / stds
    return means, stds, X_norm


def pca(X):
    m = X.shape[0]
    sigma = np.dot(X.T, X) / m
    U, S, V = np.linalg.svd(sigma)  # 奇异值分解
    return U, S, V


means, stds, X_norm = feature_normalize(X)
U, S, V = pca(X_norm)
print("[U, S, V] = ", U, S, V)


# 进行降维(降到一维)
def project_data(X, U, k):
    U_reduce = U[:, :k]
    return np.dot(X, U_reduce)


Z = project_data(X_norm, U, 1)


# print("Z = ", Z)


# 恢复数据
def recover_data(Z, U, k):
    U_reduce = U[:, :k]
    return np.dot(Z, U_reduce.T)


X_recovered = recover_data(Z, U, 1)

# 画出重建前后的散点图
plt.figure(figsize=(7, 5))
plt.scatter(X_norm[:, 0], X_norm[:, 1], s=30, c='b', label="Original Data Points")
plt.scatter(X_recovered[:, 0], X_recovered[:, 1], s=30, c='r', label="PCA Reduced Data Points")

for i in range(X_norm.shape[0]):
    plt.plot([X_norm[i, 0], X_recovered[i, 0]], [X_norm[i, 1], X_recovered[i, 1]], 'k--')

plt.title("Example Dataset: Reduced Dimension Points Shown")
plt.xlabel("X1[Feature Normalized]")
plt.ylabel("X2[Feature Normalized]")
plt.legend()
plt.axis("equal")  # 等间距
plt.grid()
plt.show()

# ********************************************************************************************
# 在人脸图像上运行PCA,看看如何在实践中使用它来减少维度。
faceData = loadmat("ex7faces.mat")
# print(faceData)
X = faceData["X"]
print(X.shape)


def display_data(X, row, column, dim):
    fig, ax = plt.subplots(row, column, figsize=(row, column))
    for r in range(row):
        for c in range(column):
            ax[r][c].imshow(X[r * 10 + c].reshape(dim, dim).T, cmap='Greys_r')
            ax[r][c].set_xticks([])
            ax[r][c].set_yticks([])  # 去除坐标轴

    plt.show()


display_data(X, row=10, column=10, dim=32)

# PCA 降维
means, stds, X_norm = feature_normalize(X)
U, S, V = pca(X_norm)
Z = project_data(X_norm, U, k=100)
display_data(Z, row=10, column=10, dim=10)

# 重建恢复
X_rec = recover_data(Z, U, k=100)
display_data(X_rec, row=10, column=10, dim=32)
  • 15
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值