14、降维,PCA算法

使用PCA将数据从2D减少到1D :

"""
这部分,你将运用PCA来实现降维。
您将首先通过一个2D数据集进行实验,以获得关于PCA如何工作的直观感受,然后在一个更大的图像数据集上使用它。
"""
from scipy.io import loadmat
import matplotlib.pyplot as plt
import numpy as np

# 加载二维数据
mat = loadmat('data\ex7data1.mat')
X = mat['X']
print(X.shape)  # (50, 2)
plt.scatter(X[:, 0], X[:, 1], facecolors='none', edgecolors='b')  # 蓝色空心散点图
# plt.show()

在这里插入图片描述
计算PCA主成分,并画出主成分:
在这里插入图片描述

def featureNormalize(X):
    '''
    标准化数据
    Args:
        X:数据集

    Returns:
        X_norm:标准化后的数据集
        means:均值from scipy.io import loadmat
import matplotlib.pyplot as plt
import numpy as np
        stds:方差
    '''
    means = X.mean(axis=0)  # 对各列求均值,返回 1* n 矩阵
    stds = X.std(axis=0, ddof=1)  # 对各列求无偏样本标准差(除以n-1)
    X_norm = (X - means) / stds  # 数据标准化
    return X_norm, means, stds


def pca(X):
    '''
    计算主成分
    Args:
        X: 训练集

    Returns:
        U,S,V: 主成分
    '''
    sigma = (X.T @ X) / len(X)  # 协方差矩阵
    U, S, V = np.linalg.svd(sigma)  # 用SVD计算主成分
    return U, S, V

在这里插入图片描述

X_norm, means, stds = featureNormalize(X) # 数据标准化
U, S, V = pca(X_norm) # 计算主成分
print(U)
'''
[[-0.70710678 -0.70710678]
 [-0.70710678  0.70710678]]
'''
print(U[:, 0])  # 从2D降到1D,所以只取U的第一列  [-0.70710678 -0.70710678]
print(S)  # [1.70081977 0.25918023]
# 画出主成分
plt.figure(figsize=(7, 5))
plt.scatter(X[:, 0], X[:, 1], facecolors='none', edgecolors='b')  # 数据散点图
plt.plot([means[0], means[0] + 1.5 * S[0] * U[0, 0]],
         [means[1], means[1] + 1.5 * S[0] * U[0, 1]],
         c='r', linewidth=3, label='First Principal Component')  # 第一个主成分
plt.plot([means[0], means[0] + 1.5 * S[1] * U[1, 0]],
         [means[1], means[1] + 1.5 * S[1] * U[1, 1]],
         c='g', linewidth=3, label='Second Principal Component')  # 第二个主成分
plt.grid()  # 显示网格
plt.axis('equal')  # 将横轴纵轴的定标系数设成相同值 ,即单位长度相同。不然两条线是不垂直的。
plt.legend()
plt.show()

在这里插入图片描述
将数据投影到PCA主成分上:

def projectData(X, U, K):
    '''
    将数据投影到主成分上
    Args:
        X:数据集
        U:投影矩阵
        K:降维后的维数

    Returns:
        Z:降维后的数据集
    '''
    Z = X @ U[:, :K]  # U[:, :K] 取U的前K列
    return Z


Z = projectData(X_norm, U, 1)  # 数据投影降维
# print(Z)
'''
[[ 1.48127391]
 ...
 [ 0.36423084]
 [-1.42814204]]
'''

数据恢复(降维后的坐标):

def recoverData(Z, U, K):
    '''
    数据恢复(降维后的坐标)
    Args:
        Z:降维后的数据集
        U:投影矩阵
        K:降维的维数

    Returns:
        X_rec:恢复后的数据
    '''
    X_rec = Z @ U[:, :K].T
    return X_rec


X_rec = recoverData(Z, U, 1)  # 恢复后的数据
# print(X_rec)
'''
[[-1.04741883 -1.04741883]
 ...
 [-0.2575501  -0.2575501 ]
 [ 1.00984892  1.00984892]]
'''

可视化降维投影:

# 可视化投影
plt.figure(figsize=(7, 5))
plt.axis("equal")
plot = plt.scatter(X_norm[:, 0], X_norm[:, 1], s=30, facecolors='none',
                   edgecolors='b', label='Original Data Points')  # 可视化源数据
plot = plt.scatter(X_rec[:, 0], X_rec[:, 1], s=30, facecolors='none',
                   edgecolors='r', label='PCA Reduced Data Points')  # 可视化降维后的数据
plt.title("Example Dataset: Reduced Dimension Points Shown", fontsize=14)
plt.xlabel('x1 [Feature Normalized]', fontsize=14)
plt.ylabel('x2 [Feature Normalized]', fontsize=14)
plt.grid(True)
# 画出每一个样本降维前后的直线距离长度,黑色虚线连接。
for x in range(X_norm.shape[0]):
    plt.plot([X_norm[x, 0], X_rec[x, 0]], [X_norm[x, 1], X_rec[x, 1]], 'k--')
    # 输入第一项全是X坐标,第二项都是Y坐标
plt.legend()
plt.show()

在这里插入图片描述
将PCA运用到人脸图像:

# 载入图像数据集
mat = loadmat('data/ex7faces.mat')
X = mat['X']
print(X.shape)  # (5000, 1024)


# 将图片展示出来
def displayData(X, row, col):
    fig, axs = plt.subplots(row, col, figsize=(8, 8))  # 画一个row行col列的子图
    for r in range(row):
        for c in range(col):
            axs[r][c].imshow(X[r * col + c].reshape(32, 32).T, cmap='Greys_r')  # 将数据恢复成单通道灰度图片矩阵(32*32=1024)
            # 关闭坐标刻度
            axs[r][c].set_xticks([])
            axs[r][c].set_yticks([])


displayData(X, 10, 10)  # 先展示100个图片
# plt.show()

在这里插入图片描述

# 找出图像中的主成分,并可视化
X_norm, means, stds = featureNormalize(X)  # 数据集标准化,均值,方差
U, S, V = pca(X_norm)  # 计算主成分
print(U.shape, S.shape)  # (1024, 1024) (1024,)
displayData(U[:, :36].T, 6, 6)  # 画出主成分(36维=6*6)
# plt.show()

在这里插入图片描述

# PCA降维
z = projectData(X_norm, U, K=36)  # 将图片降到36维
X_rec = recoverData(z, U, K=36)  # 将降维后的数据恢复为图像矩阵
displayData(X_rec, 10, 10)#显示降维后的图像
plt.show()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值