机器学习_12 降维

1.降维概述

维数灾难(Curse of Dimensionality): 通常指在涉及到向量的计算的问题中,随着维数的增加,计算量呈指数倍增长的一种现象。机器学习中指训练集中每条数据经常伴随着上千、上万个特征,处理很困难。模型的性能会随着特征的增加先上升后下降。

降维: 不存在完全无损的降维。降维通过对原始数据线性变换实现的。降维的作用: 减少冗余特征,降低数据维度;有利于数据可视化。
数据可视化:t-SNE将数据点之间的相似度转换为概率。
在这里插入图片描述

2.SVD奇异值分解

SVD:将一个矩阵A分解为三个矩阵的乘积——一个正交矩阵U(U*U的转置=1),一个对角矩阵,一个正交矩阵v的转置。
在这里插入图片描述
U矩阵求解:U是 A×A的转置 的所有特征向量组成的一个矩阵。
V矩阵求解:V是 A的转置×A 的所有特征向量组成的一个矩阵。
sigema矩阵求解:A的转置×A 的特征值取根号等于对角线元素(奇异值)。 或者用下述公式计算:在这里插入图片描述

由于对角矩阵对角线上的奇异值减少的非常快,可以用最大的k个的奇异值和对应的左右奇异向量来近似描述矩阵
在这里插入图片描述
在这里插入图片描述

3.PCA主成分分析

在这里插入图片描述
PCA识别在训练集中占最大方差量的轴。

在这里插入图片描述
PCA算法两种实现方法:

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

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

算法思想:
在这里插入图片描述
其中,V转置 包含我们正在寻找的所有主成分。

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

背景知识:
在这里插入图片描述
在这里插入图片描述
算法思想:
在这里插入图片描述
基于特征值分解协方差矩阵实现PCA算法的案例:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
PCA算法优缺点:

在这里插入图片描述

4.PCA代码实现

PCA是在数据集中找到“主成分”或最大方差方向的线性变换。 它可以用于降维。

1)实现PCA并将其应用于一个简单的二维数据集。

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

data = pd.read_csv('data/pcadata.csv')
# print(data.head())

X = data.values

# 可视化
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(X[:, 0], X[:, 1])
plt.show()

在这里插入图片描述

PCA的算法相当简单。 在确保数据被归一化之后,输出仅仅是原始数据的协方差矩阵的奇异值分解

def pca(X):
    # normalize the features
    X = (X - X.mean()) / X.std()

    # compute the covariance matrix
    X = np.matrix(X)
    cov = (X.T * X) / X.shape[0]

    # perform SVD
    U, S, V = np.linalg.svd(cov)

    return U, S, V


U, S, V = pca(X)
print(U, S, V)
  (matrix([[-0.79241747, -0.60997914],
           [-0.60997914,  0.79241747]]),
  array([1.43584536, 0.56415464]),
  matrix([[-0.79241747, -0.60997914],
           [-0.60997914,  0.79241747]]))

现在我们有主成分(矩阵U),我们可以用这些来将原始数据投影到一个较低维的空间中。 对于这个任务,我们将实现一个计算投影并且仅选择顶部K个分量的函数,有效地减少了维数。

def project_data(X, U, k):
    U_reduced = U[:,:k]
    return np.dot(X, U_reduced)


Z = project_data(X, U, 1)
print(Z)
matrix([[-4.74689738],
        [-7.15889408],
        [-4.79563345],
        [-4.45754509],
        [-4.80263579],
        [-7.04081342],
        [-4.97025076],
        [-8.75934561],
        [-6.2232703 ],
        [-7.04497331],
        [-6.91702866],
        [-6.79543508],
        [-6.3438312 ],
        [-6.99891495],
        [-4.54558119],
        [-8.31574426],
        [-7.16920841],
        [-5.08083842],
        [-8.54077427],
        [-6.94102769],
        [-8.5978815 ],
        [-5.76620067],
        [-8.2020797 ],
        [-6.23890078],
        [-4.37943868],
        [-5.56947441],
        [-7.53865023],
        [-7.70645413],
        [-5.17158343],
        [-6.19268884],
        [-6.24385246],
        [-8.02715303],
        [-4.81235176],
        [-7.07993347],
        [-5.45953289],
        [-7.60014707],
        [-4.39612191],
        [-7.82288033],
        [-3.40498213],
        [-6.54290343],
        [-7.17879573],
        [-5.22572421],
        [-4.83081168],
        [-7.23907851],
        [-4.36164051],
        [-6.44590096],
        [-2.69118076],
        [-4.61386195],
        [-5.88236227],
        [-7.76732508]])

我们也可以通过反向转换步骤来恢复原始数据。

def recover_data(Z, U, k):
    U_reduced = U[:,:k]
    return np.dot(Z, U_reduced.T)

X_recovered = recover_data(Z, U, 1)
print(X_recovered)
    matrix([[3.76152442, 2.89550838],
            [5.67283275, 4.36677606],
            [3.80014373, 2.92523637],
            [3.53223661, 2.71900952],
            [3.80569251, 2.92950765],
            [5.57926356, 4.29474931],
            [3.93851354, 3.03174929],
            [6.94105849, 5.3430181 ],
            [4.93142811, 3.79606507],
            [5.58255993, 4.29728676],
            [5.48117436, 4.21924319],
            [5.38482148, 4.14507365],
            [5.02696267, 3.8696047 ],
            [5.54606249, 4.26919213],
            [3.60199795, 2.77270971],
            [6.58954104, 5.07243054],
            [5.681006  , 4.37306758],
            [4.02614513, 3.09920545],
            [6.76785875, 5.20969415],
            [5.50019161, 4.2338821 ],
            [6.81311151, 5.24452836],
            [4.56923815, 3.51726213],
            [6.49947125, 5.00309752],
            [4.94381398, 3.80559934],
            [3.47034372, 2.67136624],
            [4.41334883, 3.39726321],
            [5.97375815, 4.59841938],
            [6.10672889, 4.70077626],
            [4.09805306, 3.15455801],
            [4.90719483, 3.77741101],
            [4.94773778, 3.80861976],
            [6.36085631, 4.8963959 ],
            [3.81339161, 2.93543419],
            [5.61026298, 4.31861173],
            [4.32622924, 3.33020118],
            [6.02248932, 4.63593118],
            [3.48356381, 2.68154267],
            [6.19898705, 4.77179382],
            [2.69816733, 2.07696807],
            [5.18471099, 3.99103461],
            [5.68860316, 4.37891565],
            [4.14095516, 3.18758276],
            [3.82801958, 2.94669436],
            [5.73637229, 4.41568689],
            [3.45624014, 2.66050973],
            [5.10784454, 3.93186513],
            [2.13253865, 1.64156413],
            [3.65610482, 2.81435955],
            [4.66128664, 3.58811828],
            [6.1549641 , 4.73790627]])
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(list(X_recovered[:, 0]), list(X_recovered[:, 1]))
plt.show()

在这里插入图片描述

请注意,第一主成分的投影轴基本上是数据集中的对角线。 当我们将数据减少到一个维度时,我们失去了该对角线周围的变化,所以在我们的再现中,一切都沿着该对角线。

2)将PCA应用于脸部图像。
通过使用相同的降维技术,我们可以使用比原始图像少得多的数据来捕获图像的“本质”。

faces = loadmat('data/ex7faces.mat')
X = faces['X']
X.shape
# (5000, 1024)

def plot_n_image(X, n):
    """ plot first n images
    n has to be a square number
    """
    pic_size = int(np.sqrt(X.shape[1]))
    grid_size = int(np.sqrt(n))

    first_n_images = X[:n, :]

    fig, ax_array = plt.subplots(nrows=grid_size,ncols=grid_size,sharey=True,sharex=True,figsize=(8, 8))

    for r in range(grid_size):
        for c in range(grid_size):
            ax_array[r, c].imshow(first_n_images[grid_size * r + c].reshape((pic_size, pic_size)))
            plt.xticks(np.array([]))
            plt.yticks(np.array([]))

练习代码包括一个将渲染数据集中的前100张脸的函数。 而不是尝试在这里重新生成,您可以在练习文本中查看他们的样子。 我们至少可以很容易地渲染一个图像。

face = np.reshape(X[3,:], (32, 32))

plt.imshow(face)
plt.show()

在这里插入图片描述

看起来很糟糕。 这些只有32 x 32灰度的图像(它也是侧面渲染,但我们现在可以忽略)。 我们的下一步是在面数据集上运行PCA,并取得前100个主要特征。

U, S, V = pca(X)
Z = project_data(X, U, 100)

现在我们可以尝试恢复原来的结构并再次渲染。

X_recovered = recover_data(Z, U, 100)
face = np.reshape(X_recovered[3,:], (32, 32))
plt.imshow(face)
plt.show()

在这里插入图片描述
我们可以看到:数据维度减少,但细节并没有怎么损失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值