机器学习实验------PCA

目录

一、介绍

二、算法流程

(1)数据中心化

(2)计算协方差矩阵

(3)特征值分解

(4)选择特征

三、运行结果展示

四、实验中遇到的问题

五、PCA的优缺点

优点:

缺点:

六、总代码


一、介绍

PCA(principal components analysis)即主成分分析技术,又称主分量分析,旨在利用降维的思想,把多指标转化为少数几个综合指标。

本使用采用的是鸢尾花数据集,需要把鸢尾花的四个数据特征转化为两个数据特征使得他可以在坐标轴上面显示出来。

二、算法流程

(1)数据中心化

对原始数据进行中心化处理,即将每个特征的值减去该特征的均值,以保证数据的均值为零。

复制代码
pj = np.mean(X, axis=0)
X_pj = X - pj

也就是说将每个数据减去他的平均值得到新的数据。代码先计算他的平均值,再对每个数据减去他的平均值。

(2)计算协方差矩阵

找到一个轴,使得样本空间的所有点映射到这个轴的协方差最大。

公式:

复制代码
n = X.shape[0]
cov = np.dot(X_pj.T,X_pj) / (n - 1)

因为事先已经对他进行了数据中心化,所以得到的协方差就可以不用求解平均值,而直接np.dot(X_pj.T,X_pj)就得到第i个特征和第j个特征的协方差。除以(n-1)是为了得到无偏估计,这样求解准确度会更高。

(3)特征值分解

对矩阵A进行特征值分解就是将方阵分解为其特征值和特征向量的过程。

公式:

其中V就是特征值,lambda就是特征向量。

学习了代码后使用QR分解法来求解特征值和特征向量。

原理:

上三角形是对角线下方的值全部为零,上三角形的对角线就是他的特征值。我们通过不断把A进行相似矩阵转化,他的特征值是不会变的,通过迭代多次最后吧矩阵A转化为上三角形,就可以直接得到他的特征值了,特征向量就是变换过程中Q的累乘。

复制代码
def qr_algorithm(A, num=1000, tol=1e-6):
    n = A.shape[0]
    tzxl = np.eye(n)

    for i in range(num):
        Q, R = np.linalg.qr(A)
        A = np.dot(R, Q)
        tzxl = np.dot(tzxl, Q)

        t = np.sqrt(np.sum(np.square(A) - np.sum(np.square(np.diag(A)))))
        if t < tol:
            break

    tzz = np.diag(A)
    return tzz, tzxl
  1. 初始化特征向量为单位矩阵
  2. 迭代num次使得
  3. 对矩阵A进行 QR 分解,得到正交矩阵Q和上三角矩阵R,不断对特征向量进行更新A成为他的相似矩阵。
  4. 非对角线元素的范数,如果小到一定值,就说明更新差不多完成了,就退出循环。
  5. 最后特征值就是A对角线上的值,特征向量就是累乘。

(4)选择特征

我们已经得到了特征向量,先对他进行排序,选择最大的几个成分当作主成分,然后与中心化的X_pj相乘得到新的、降维后的数据集,然后就可以对降维后的数据集进行操作了。

复制代码
t1 = np.argsort(-tzz)
tzxl = tzxl[:, t1]
cnt = 2
zcf = tzxl[:, :cnt]
X1 = np.dot(X_pj, zcf)

三、运行结果展示

先将降维后的数据打印出来,可以看到已经变为样本二维的了。

打印出散点图

复制代码
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)
print(X1)
plt.rcParams['font.sans-serif'] = ['SimHei']
rcParams['axes.unicode_minus'] = False
plt.scatter(X1[:, 0], X1[:, 1], c=y_encoded, cmap='viridis')
plt.xlabel('主成分一')
plt.ylabel('主成分二')
plt.title('PCA')
plt.show()

将y的标签映射为数值。并且需要加上plt.rcParams['font.sans-serif'] = ['SimHei']和rcParams['axes.unicode_minus'] = False来保证中文和负号在图像中正常显示

四、实验中遇到的问题

因为这个实验的流程相对比较简短,主要的问题就是在特征值分解的理解上,刚开始因为直接计算特征值和特征向量的难度太大,没想到用相似矩阵来求解。后来使用QR分解法迭代求解特征值和特征向量就比较简便。

五、PCA的优缺点

优点:

  1. PCA可以将高维数据转化为低维,从而减少数据维度。可以降低计算复杂性和存储需求。
  2. PCA可以保留数据中最重要的特征,并且去除噪声和冗余信息。

缺点:

  1. PCA假设数据之间的关系是线性的,因此它可能无法有效处理非线性关系的数据。

  2. 对于非常大的数据集,计算协方差矩阵和进行特征分解可能会非常耗时且计算复杂度较高。

  3. 在降维的过程中保留的主成分不可能包含所有信息,不可避免的的导致信息模糊,丢失。

六、总代码

复制代码
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from matplotlib import rcParams
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
train_data = pd.read_csv("C:\\Users\\李烨\\Desktop\\新建文件夹\\6\\iris.txt", sep='\s+')

# 假设数据集的最后一列是目标标签
X = train_data.iloc[:, :-1].values  # 特征
y = train_data.iloc[:, -1].values  # 标签

pj = np.mean(X, axis=0)
X_pj = X - pj

n = X.shape[0]
cov = np.dot(X_pj.T, X_pj) / (n - 1)


def QR(A, num=1000, tol=1e-6):
    n = A.shape[0]
    tzxl = np.eye(n)

    for i in range(num):
        Q, R = np.linalg.qr(A)
        A = np.dot(R, Q)
        tzxl = np.dot(tzxl, Q)

        t = np.sqrt(np.sum(np.square(A) - np.sum(np.square(np.diag(A)))))
        if t < tol:
            break

    tzz = np.diag(A)
    return tzz, tzxl


tzz, tzxl = QR(cov)

t1 = np.argsort(-tzz)
tzxl = tzxl[:, t1]
cnt = 2
zcf = tzxl[:, :cnt]
X1 = np.dot(X_pj, zcf)

label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)
print(X1)
plt.rcParams['font.sans-serif'] = ['SimHei']
rcParams['axes.unicode_minus'] = False
plt.scatter(X1[:, 0], X1[:, 1], c=y_encoded, cmap='viridis')
plt.xlabel('主成分一')
plt.ylabel('主成分二')
plt.title('PCA')
plt.show()
相关推荐
Mintopia36 分钟前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮1 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬1 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia2 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区2 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两5 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
前端付豪5 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
strayCat232555 小时前
Clawdbot 源码解读 7: 扩展机制
人工智能·开源
王鑫星5 小时前
SWE-bench 首次突破 80%:Claude Opus 4.5 发布,Anthropic 的野心不止于写代码
人工智能