简单例子弄懂主成分分析

一个简单的例子

情景叙述

        假设我们有一群学生的成绩数据,包括语文、数学、英语和物理这四门课的分数。

        每个学生都有这四门课对应的成绩,这就形成了一个四维的数据空间。但我们发现,可能数学和物理成绩往往有较强的相关性,英语和语文成绩也有一定的关联。 这时我们使用主成分分析(PCA),它会找到新的“综合科目”,也就是主成分。比如第一个主成分可能综合反映了学生的理科思维能力,与数学和物理成绩的关系较大;第二个主成分可能综合反映了学生的语言能力,与英语和语文成绩关系较大。

        通过这种方式,我们把原本复杂的四维数据,用两个新的“综合科目”(主成分)来近似表示,达到了降维和简化数据的目的,让我们能更清晰地看出学生在不同方面的总体表现趋势。

数学推导

         假设有n个学生(n个样本),p门成绩(p个指标),则可构成大小为n\timesp的样本矩阵\vec{x}:

        现在我们想要找到一组新的变量\vec{z_1}\vec{z_2}\cdots\vec{z_m}(m\leqslantp)来更方便地描述学生成绩,则变量变量\vec{z_1}\vec{z_2}\cdots\vec{z_m}可以表示为\vec{x_1}\vec{x_2}\cdots\vec{x_p}的线性组合:

        由于可以任意地对原始变量进行上述线性变换,由不同的线性变换得到的综合变量\vec{z}也不尽相同。为了取得较好的效果,我们总是希望\vec{z_i} = \vec{l_i}\cdot\vec{x}方差尽可能大且各\vec{z_i}之间相互独立。我们将线性变换约束在下面的原则之下:

计算步骤

1.计算原矩阵的相关系数矩阵:

2.计算R的特征值和特征向量

        求解特征值和特征向量的数学部分不再赘述,这里给出简单的pythn实现:

import numpy as np

def calculate_eigenvalues_eigenvectors(correlation_matrix):
    eigenvalues, eigenvectors = np.linalg.eig(correlation_matrix)
    return eigenvalues, eigenvectors

# 示例相关系数矩阵
correlation_matrix = np.array([[1, 0.5, 0.2], [0.5, 1, 0.3], [0.2, 0.3, 1]])

eigenvalues, eigenvectors = calculate_eigenvalues_eigenvectors(correlation_matrix)
print("特征值:", eigenvalues)
print("特征向量:", eigenvectors)
3.计算主成分贡献率以及累计贡献率

import numpy as np

def calculate_contribution_rates(eigenvalues):
    total_variance = np.sum(eigenvalues)
    contribution_rates = eigenvalues / total_variance
    cumulative_contribution_rates = np.cumsum(contribution_rates)
    return contribution_rates, cumulative_contribution_rates

# 示例特征值
eigenvalues = np.array([3.5, 1.2, 0.8])

contribution_rates, cumulative_contribution_rates = calculate_contribution_rates(eigenvalues)

print("主成分贡献率:", contribution_rates)
print("主成分累计贡献率:", cumulative_contribution_rates)

        一般取累计贡献率大于某一百分比的特征值所对应的前m个主成分,从而达到数据降维的作用。

具体情境示例

        在文章初描述的情境中,假设有10名学生A~J,分别有数学、物理、语文、英语四门学科成绩,具体数据如下:

Student: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
Math: [57, 51, 90, 99, 86, 84, 75, 82, 57, 78]
Physics: [69, 53, 90, 116, 98, 88, 91, 99, 66, 80]
Chinese: [59, 79, 74, 79, 53, 76, 56, 70, 51, 89]
English: [68, 80, 74, 92, 62, 79, 68, 83, 58, 91]

        进行主成分分析:

import numpy as np
from scipy.stats import zscore
from sklearn.decomposition import PCA

# 将数据转换为 numpy 数组
data = np.array([
    [57, 69, 59, 68],
    [51, 53, 79, 80],
    [90, 90, 74, 74],
    [99, 116, 79, 92],
    [86, 98, 53, 62],
    [84, 88, 76, 79],
    [75, 91, 56, 68],
    [82, 99, 70, 83],
    [57, 66, 51, 58],
    [78, 80, 89, 91]
])

# 标准化数据
data_std = zscore(data)

# 进行主成分分析
pca = PCA(n_components=2)  # 指定只保留 2 个主成分
pca.fit(data_std)

# 打印前 2 个主成分
print("第一个主成分:", pca.components_[0])
print("第二个主成分:", pca.components_[1])

# 获取解释方差比例(即每个主成分的贡献率)
explained_variance_ratio = pca.explained_variance_ratio_

# 计算累计贡献率
cumulative_contribution = np.cumsum(explained_variance_ratio)

print("前两个主成分的累计贡献率:", cumulative_contribution[1])

        输出结果如下:

第一个主成分: [0.53311981 0.47316645 0.45517108 0.53358791]
第二个主成分: [-0.42931496 -0.55051269  0.57499604  0.42661926]

前两个主成分的累计贡献率: 0.9732164017362895

         第一个主成分基本反映了平均分对于整体成绩的影响,第二个主成分反映了理科思维与语言能力的相对差异。

  • 26
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值