【零基础学机器学习 17】机器学习中的主成分分析(PCA):完全指南

👨‍💻 作者简介:程序员半夏 , 一名全栈程序员,擅长使用各种编程语言和框架,如JavaScript、React、Node.js、Java、Python、Django、MySQL等.专注于大前端与后端的硬核干货分享,同时是一个随缘更新的UP主. 你可以在各个平台找到我!
🏆 本文收录于专栏: 零基础学机器学习
🔥 专栏介绍: 本专栏将帮助您了解机器学习、其工作原理以及如何使用它。本教程包含以下内容:监督和无监督学习、线性回归、随机森林算法、朴素贝叶斯分类器、K-means聚类算法等等等基础学习基础知识,以及各种实战案例。

43592febe975c9edf02281a1cbffcee3

前言

在学习本文之前,请先查看
【零基础学机器学习 16】机器学习中的主成分分析(PCA): 数学基础(协方差矩阵)

在进行数据分析时,我们通常面临两种挑战。一种是原始数据特征过少,难以挖掘潜在规律。针对这种情况,我们需要在数据收集阶段加倍努力。另一种挑战是特征过多,虽然意味着更多信息和挖掘价值,但也可能导致过拟合和计算量急剧增加。为解决这一问题,我们可以在预处理阶段对数据进行降维。

提到降维,主成分分析法(PCA)自然而然地成为首选,因为它在众多降维方法中应用最广泛。PCA是一种无监督学习方法,主要观点认为数据特征之间存在线性相关性,导致信息冗余。通过正交变换,用较少的线性无关数据表示线性相关特征,从而实现降维。

场景引入

下面是一个简单的学生成绩表格,包含学生的语文和数学成绩,现在我们想要给这四位学生分类,在下面这个数据集下,我们一眼可以看出来,我们可以分为80+。90+,满分这三类。因为语文成绩都一样,这导致数学成为了最主要的参考成绩。用本文的专业属于来说:数学成绩就是这组成绩的主成分。

学生语文数学
张三10080
李四10090
王五10080
赵六100100

再来看下面这组数据呢?这组数据层次不齐,我们好像没法一眼对学生进行分类了,那此时我们还想进行分类,我们最想做的事应该是啥呢?要是能把某一列数据去掉就好了,那是不是就剩一列数据了,我们就可以一眼对学生进行分类了。

学生语文数学
张三9285
李四9092
王五7592
赵六7888
孙77092

去掉一列数据的这个操作就叫做降维,原来是二维的数据,我们变为一维数据。现在我通过一种常用的降维方式-PCA主成分分析。把数据降到下面表格所示,这样我们又可以快速的分类了。

学生成绩
张三11.70617307
李四8.42604679
王五-6.30658051
赵六-2.60818307
孙7-11.21745628

数据降维

数据降维是机器学习中一种处理高维数据的方法,目的是减少数据的维度,同时保留尽可能多的信息。降维有助于可视化、去除噪声、减少计算复杂度、避免维度诅咒和特征提取。常见的降维技术包括主成分分析(PCA)、线性判别分析(LDA)和t-分布邻域嵌入算法(t-SNE)。

降维的原理是找到一个低维空间,将高维数据投影到这个空间上,使得投影后的数据能够保留原始数据的大部分信息。这里的信息通常是指数据的结构、分布和关系等。

假设在三维空间中有一组点,它们位于一个经过原点的斜面上。用x, y, z坐标轴表示这些点时,需要三个维度。但实际上,这些点我们可以通过旋转投影到二维平面上。问题的解决方法是旋转x, y, z坐标系,使数据平面与x, y平面重合。将旋转后的坐标记为x’, y’, z’,这样只需用x’和y’两个维度表示数据。

为了恢复原始表示,需保存两个坐标系之间的变换矩阵。这样就实现了数据降维。数据矩阵的秩为2,说明数据具有相关性。将数据中心移到新坐标系中,原本不相关的数据变得具有相关性。在n维空间中,n个点可以在一个n-1维子空间中分析。降维后的数据没有丢失信息,因为在第三个维度上的分量都为0。假设z’轴上有微小抖动,我们仍然用二维表示数据,因为x’和y’轴上的信息是主成分,足够进行分析。z’轴上的抖动可能是噪音,导致数据不完全相关。但z’轴上的分布与原点的夹角很小,说明有很大相关性。因此,数据在x’和y’轴上的投影构成了主成分。

降维不会严重影响结果的原因如下:

  1. 数据冗余:实际数据中往往存在冗余特征,这些特征之间具有较强的相关性。降维可以消除这些冗余特征,从而减少数据的维度。

  2. 信息保留:降维方法通常会选择保留数据中的主要成分,即那些解释数据变异最大的方向。这些方向上的信息对于数据分析和模型预测最为重要。

  3. 去噪:降维过程中,可以去除数据中的噪声成分,提高数据质量。这有助于提高模型的泛化能力和预测准确性。

  4. 维度诅咒:高维数据容易受到维度诅咒的影响,即随着维度的增加,数据的稀疏性和计算复杂度急剧增加。降维可以有效缓解维度诅咒问题,提高模型性能。

需要注意的是,降维过程中可能会丢失部分信息,但在实际应用中,这些丢失的信息通常对结果影响较小。合理选择降维方法和参数,可以在降低维度的同时,尽量保留数据的关键信息。

降维的好处

高维数据需要降维处理的原因主要有以下几点:

  1. 可视化:降维可以将高维数据投影到二维或三维空间,使其更容易可视化。这有助于我们更好地理解数据的结构和特征。

  2. 去除噪声:降维过程中,通常保留数据中的主要特征,而忽略较小的变化。这有助于去除数据中的噪声,提高数据质量。

  3. 减少计算复杂度:高维数据的计算复杂度很高,降维可以减少数据的维度,从而降低计算复杂度,提高算法的运行速度。

  4. 避免维度诅咒:在高维空间中,数据点之间的距离往往变得相对较大,导致数据稀疏。这使得许多机器学习算法在高维数据上的性能下降。降维有助于避免维度诅咒,提高模型的性能。

  5. 特征提取:降维可以将原始特征转换为新的特征,这些新特征可能更具代表性,有助于揭示数据的内在结构。

总之,降维处理可以帮助我们更好地理解和分析高维数据,提高数据质量,降低计算复杂度,避免维度诅咒,并有助于特征提取。

什么是主成分分析?

主成分分析(PCA)是一种流行的无监督学习技术,用于降低数据的维度。它在提高可解释性的同时,尽量减少信息损失。PCA有助于在数据集中找到最重要的特征,并简化数据以便于在二维和三维中绘制。PCA能够找到变量的一系列线性组合。

假设我们有一个包含人口年龄和收入的数据集。这两个变量可能存在一定程度的相关性,例如年龄较大的人可能收入较高。在这种情况下,我们可以使用PCA来提取一个新的变量(主成分),它能够捕捉年龄和收入之间的主要变化。这个新变量可能是年龄和收入的某种线性组合,例如PC1 = a * 年龄 + b * 收入。通过这种方式,我们可以用一个主成分来表示原始数据中的大部分信息,从而降低数据维度,简化分析和可视化。

相关概念

什么是主成分?

在主成分分析(PCA)中,主成分是数据集中方差最大的方向,可以看作是数据的主要变化趋势。第一主成分解释了数据中最大的方差,第二主成分解释了剩余方差中的最大部分,且与第一主成分正交,依此类推。通过保留前k个主成分,可以实现数据降维,同时保留数据中的大部分信息。

在下面的图示中,我们在一个二维平面上绘制了多个点。这里有两个主成分。PC1是主要的主成分,它解释了数据中的最大方差。PC2是另一个主成分,它与PC1正交。

PrincipalComponents维度

“维度”这个术语描述了研究中使用的特征或变量的数量。处理高维数据(如具有众多变量的数据集)时,很难可视化和解释变量之间的关系。降维方法如PCA在减少数据集中变量数量的同时,用于保留最重要的数据。PCA通过将原始变量转换为称为主成分的新变量集来实现这一目标,这些新变量是原始变量的线性组合。数据集的降低维度取决于研究中使用了多少主成分。PCA的目标是选择较少的主成分来解释数据的最重要变化。通过降低数据集的维度,PCA有助于简化数据分析,增强可视化,并使发现因素之间的趋势和关系变得更简单。

在PCA背景下,降维的数学表示如下:

给定一个具有n个观测值和p个变量的数据集,由n x p数据矩阵X表示,PCA的目标是将原始变量转换为一组k个称为主成分的新变量,以捕捉数据中最重要的变化。主成分定义为原始变量的线性组合,表示为:

PC_1 = a_11 * x_1 + a_12 * x_2 + … + a_1p * x_p

PC_2 = a_21 * x_1 + a_22 * x_2 + … + a_2p * x_p

PC_k = a_k1 * x_1 + a_k2 * x_2 + … + a_kp * x_p

其中a_ij是变量x_j在主成分PC_i上的加载或权重,x_j是数据矩阵X中的第j个变量。主成分按顺序排列,使得第一个成分PC_1捕捉数据中最重要的变化,第二个成分PC_2捕捉次重要的变化,依此类推。分析中使用的主成分数量k决定了数据集的降低维度。

相关性

相关性是一种统计量,用于表示两个变量之间线性关系的方向和强度。在主成分分析(PCA)中,通过计算相关性来得到协方差矩阵。协方差矩阵是一个方阵,显示数据集中所有变量对之间的两两相关性。协方差矩阵的对角线元素表示每个变量的方差,非对角线元素表示不同变量对之间的协方差。相关系数是一个标准化的相关性度量,范围在-1到1之间,用于确定两个变量之间线性关系的强度和方向。

相关系数为0表示两个变量之间没有线性关系,相关系数为1和-1分别表示完美的正相关和负相关。PCA中的主成分是初始变量的线性组合,用于最大化数据解释的方差。主成分是通过相关矩阵计算得出的。

在PCA框架下,相关性的数学表示如下:

给定一个具有n个变量(x1,x2,…,xn)的数据集,相关矩阵C是一个nxn对称矩阵,其组件如下:

C i j = c o v ( x i , x j ) / ( s d ( x i ) ∗ s d ( x j ) ) Cij = cov(xi, xj) / (sd(xi) * sd(xj)) Cij=cov(xi,xj)/(sd(xi)sd(xj))

其中,Cij是相关系数矩阵的第i行第j列元素,cov(xi, xj)是变量xi和xj的协方差,sd(xi)和sd(xj)分别是变量xi和xj的标准差。

相关系数的取值范围在-1到1之间,值越接近1表示正相关程度越高,值越接近-1表示负相关程度越高,值接近0表示无明显线性关系。相关系数矩阵可以帮助我们理解数据集中变量之间的关系。

相关矩阵C也可以用矩阵表示法表示如下:

C = X T X / ( n − 1 ) ( n − 1 ) C = X^T X / (n-1) (n-1) C=XTX/(n1)(n1)

正交性

在主成分分析(PCA)算法的背景下,"正交性"这个术语代表主成分之间是相互正交的。这意味着主成分之间没有冗余信息,它们彼此之间没有相关性即线性无关

PCA中的正交性可以用数学表示如下:正交性约束确保主成分彼此正交,即它们之间没有线性相关性。这有助于我们在降维过程中保留尽可能多的信息,并且使得主成分之间独立。

正交性约束表示为:

a i 1 ∗ a j 1 + a i 2 ∗ a j 2 + . . . + a i p ∗ a j p = 0 a_i1 * a_j1 + a_i2 * a_j2 + ... + a_ip * a_jp = 0 ai1aj1+ai2aj2+...+aipajp=0

表示任意两个不同主成分载荷向量之间的点积为零。其中, aik 和 ajk 分别是第 i 个和第 j 个主成分载荷向量的第 k 个分量。满足条件 i ≠ j。这意味着任意两个不同主成分的载荷向量之间的点积为零,表明主成分彼此正交。

特征向量

在我们的研究中,通过计算协方差矩阵的特征向量,我们得到了数据的主成分。这些特征向量表示了数据变化最大的方向,并用于定义一个新的坐标系来表示数据。

数学上,协方差矩阵C的特征向量由v_1, v_2, …, v_p表示,相应的特征值分别表示为λ_1, λ_2, …, λ_p。特征向量的计算满足以下关系:

C v_i = λ_i v_i

这表明当特征向量v_i与协方差矩阵C相乘时,结果是特征值λ_i与特征向量v_i的标量乘积。这一性质在我们的研究中具有重要意义,因为它揭示了数据的主要变化方向。

PCA原理及步骤

  1. 数据标准化:在进行PCA之前,先对数据进行标准化。这将确保每个特征的均值为0,方差为1。

Z = x − μ σ Z=\frac{x-\mu}\sigma Z=σxμ

上面的公式表示数据标准化(Z-score标准化)的过程。其中:

  • Z:表示标准化后的数据值
  • x:表示原始数据值
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传是独立特征的平均值外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 是 独立特征的标准差外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过这个公式,我们可以将原始数据转换为标准化数据,使得标准化后的数据具有均值为0,标准差为1的特性。

  1. 构建协方差矩阵:构建一个方阵,用于表示多维数据集中两个或多个特征之间的相关性。

Covariance

  1. 求特征向量和特征值:计算特征向量(单位向量)和特征值。特征值是我们将协方差矩阵的特征向量乘以的标量。

image-20230924210258883

  1. 按降序排列特征向量并选择主成分个数

实操:Numpy实现PCA

例如模拟给出10个学生的语数外物理化学成绩具体数据假设我们有以下10名学生的语文、数学、英语、物理和化学成绩数据:

学生  语文  数学  英语  物理  化学
1    80    90    85    92    88
2    78    85    82    89    84
3    92    88    90    85    86
4    75    70    78    72    74
5    88    95    91    96    93
6    82    80    83    78    81
7    90    92    89    94    91
8    72    75    70    76    73
9    84    87    86    82    85
10   95    98    94    99    97

我们使用PCA对这些数据进行降维分析:

  1. 数据预处理:对每门课程的成绩进行标准化,使其均值为0,方差为1。
  2. 计算协方差矩阵:计算5门课程之间的协方差矩阵。
  3. 计算协方差矩阵的特征值和特征向量。
  4. 选择主成分:假设我们选择前2个最大特征值对应的特征向量作为主成分。
  5. 数据降维:将原始数据投影到选定的2个特征向量构成的新特征空间中,得到降维后的数据。

1. 数据预处理:标准化后的成绩数据如下:

学生  语文         数学        英语        物理         化学
1   -0.50096731  0.4794633   0.02996108  0.65638763  0.38259364
2   -0.77928248 -0.11986583 -0.41945506  0.31092045 -0.1639687
3    1.16892371  0.23973165  0.77898797 -0.14970244  0.10931247
4   -1.19675523 -1.91785321 -1.01867658 -1.64672685 -1.53037456
5    0.61229337  1.07879243  0.92879335  1.11701052  1.06579657
6   -0.22265214 -0.71919495 -0.26964968 -0.95579251 -0.57389046
7    0.89060854  0.71919495  0.62918259  0.88669907  0.7925154
8   -1.61422799 -1.31852408 -2.21711962 -1.18610396 -1.66701515
9    0.05566303  0.11986583  0.17976646 -0.49516961 -0.02732812
10   1.58639647  1.4383899   1.37820949  1.46247769  1.61235891

2. 计算协方差矩阵:

      语文    数学    英语    物理    化学
语文  1.11111111 0.92297321 1.04510728 0.79091253 0.95875707
数学  0.92297321 1.11111111 0.97563897 1.05978178 1.0900826
英语  1.04510728 0.97563897 1.11111111 0.87328127 1.03120766
物理  0.79091253 1.05978178 0.87328127 1.11111111 1.05494069
化学  0.95875707 1.0900826  1.03120766 1.05494069 1.11111111

3. 计算特征值和特征向量:

特征值:

5.03716277 0.42103289 0.06191762 0.02933052 0.00611176

特征向量:

1: [-0.42826522 -0.62050141  0.61924007 -0.21724188  0.03024246]
2: [-0.45859316  0.26949533  0.23544264  0.7682068  -0.26737548]
3: [-0.44712198 -0.41284969 -0.71422648 -0.02323958 -0.3449312]
4: [-0.43478453  0.5912376   0.09556527 -0.60116868 -0.3014365]
5: [-0.4661819   0.14947742 -0.20458819  0.02684042  0.84720375]

4. 选择主成分:选择前2个最大特征值对应的特征向量作为主成分。

5. 数据降维:将原始数据投影到选定的2个特征向量构成的新特征空间中,得到降维后的数据:

学生  主成分1  主成分2
1    -0.48247339  0.87296478
2    0.51751264  0.78373273
3   -0.9447225  -1.05448716
4    3.27691997 -0.55606713v
5    -2.15474867  0.34707971
6     1.22883949 -0.59522306
7    -1.74753529  0.02415097
8    3.58013868  0.61118143
9    0.06884624 -0.37330007
10   -3.34277718 -0.0600322

现在我们可以在二维空间中观察学生的整体表现,发现学生之间的相似性和差异,以及课程之间的相关性。

6. 代码实现

以下是使用Python和NumPy库进行PCA降维分析的代码:

import numpy as np

# 原始成绩数据
data = np.array([
    [80, 90, 85, 92, 88],
    [78, 85, 82, 89, 84],
    [92, 88, 90, 85, 86],
    [75, 70, 78, 72, 74],
    [88, 95, 91, 96, 93],
    [82, 80, 83, 78, 81],
    [90, 92, 89, 94, 91],
    [72, 75, 70, 76, 73],
    [84, 87, 86, 82, 85],
    [95, 98, 94, 99, 97]
])

# 数据预处理:标准化
mean = np.mean(data, axis=0)
std = np.std(data, axis=0)
normalized_data = (data - mean) / std
print("标准化的数据:\n", normalized_data)
# 计算协方差矩阵
cov_matrix = np.cov(normalized_data.T)
print("协方差矩阵:\n", cov_matrix)

# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
print("特征值:\n", eigenvalues)
print("特征向量:\n", eigenvectors)

# 选择主成分:前2个最大特征值对应的特征向量
num_components = 2
sorted_indices = np.argsort(eigenvalues)[::-1]
principal_components = eigenvectors[:, sorted_indices[:num_components]]

# 数据降维
reduced_data = np.dot(normalized_data, principal_components)

print("降维后的数据:\n", reduced_data)

实操:sklearn-PCA葡萄酒分类

导包

import numpy as np 
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

导入数据集

这个数据集是从 https://archive.ics.uci.edu/ml/datasets/wine 的葡萄酒数据集中提取的,去除了关于葡萄酒类型的信息,以便进行无监督学习。

这些数据是对意大利同一产区种植的葡萄酒进行化学分析的结果,但这些葡萄酒来自三个不同的品种。分析确定了三种葡萄酒中每种葡萄酒的13种成分的含量。

属性包括:

  1. Alcohol 酒精度
  2. Malic acid 苹果酸
  3. Ash 灰分
  4. Alcalinity of ash 灰分碱度
  5. Magnesium 镁
  6. Total phenols 总酚
  7. Flavanoids 黄烷酚类化合物
  8. Nonflavanoid phenols 非黄烷酚类化合物
  9. Proanthocyanins 原花青素
  10. Color intensity 色彩强度
  11. Hue 色调
  12. OD280/OD315 of diluted wines 稀释葡萄酒的 OD280/OD315 比值
  13. Proline 脯氨酸
dataset_train = pd.read_csv("C:\\Users\\Administrator\\Downloads\\wine-clustering.csv")
dataset_train.head()

image-20230926224557790

dataset_train.iloc[:,1:].describe()
# 这行代码的作用是显示dataset_train中从第二列开始(Python的索引从0开始,所以1表示第二列)到最后一列的所有列的描述性统计信息,
# 包括:数量、均值、标准差、最小值、四分位数(25%、50%、75%)以及最大值。这对于我们初步了解数据的分布和特性非常有帮助。

image-20230926225151327

绘制特相关性热力图

# 导入所需的库
import matplotlib.pyplot as plt
import seaborn as sns

# 设置图形的大小(宽度为12,高度为7)
plt.figure(figsize=(12,7))

# 计算数据集 dataset_train 中各变量之间的相关性矩阵
corr = dataset_train.corr()

# 使用 seaborn 的 heatmap 函数绘制相关性矩阵的热力图
# vmin=-1:设置颜色条的最小值为 -1
# center=0:设置颜色条的中心值为 0
# vmax=1:设置颜色条的最大值为 1
# annot=True:在每个单元格中显示相关系数
sns.heatmap(corr, vmin=-1, center=0, vmax=1, annot=True)

# 显示图形
plt.show()

image-20230926232820549

数据标准化

# 导入所需的预处理类
from sklearn.preprocessing import StandardScaler, Normalizer

# 创建 StandardScaler 对象
scaler = StandardScaler()

# 使用 StandardScaler 对数据框 df 进行拟合和转换,然后将结果存储在 wine_scaled 变量中
wine_scaled = scaler.fit_transform(dataset_train)

这段代码执行了以下操作:

  1. 导入:从sklearn.preprocessing模块导入StandardScalerNormalizer类。

  2. 实例化:创建一个StandardScaler对象并将其赋值给变量scaler

  3. 拟合和转换:使用scalerfit_transform方法对数据框df进行拟合和转换。这个方法首先计算df中每个特征的均值和标准差,然后使用公式(x - mean) / std对每个特征值进行缩放。这样,df中的特征将被转换为具有零均值和单位方差的标准正态分布。

  4. 结果:将缩放后的数据赋值给变量wine_scaled。这个变量现在包含了原始数据df经过StandardScaler预处理后的版本,可以用于后续的机器学习模型训练和评估。

StandardScaler

  • 目标:将特征缩放到具有零均值和单位方差的标准正态分布。
  • 方法:对每个特征,减去其均值并除以其标准差。
  • 公式:(x - mean) / std
  • 适用场景:当特征的分布大致为正态分布时,或者模型对特征的尺度和分布敏感时(例如,支持向量机、线性回归等)。

PCA

  1. 导入:从sklearn.decomposition模块导入PCA类,用于主成分分析。

  2. 实例化:创建一个PCA对象,设置n_components=2,表示将数据降至二维。将对象赋值给变量pca

  3. 设置图形尺寸:使用plt.figure设置图形尺寸为8x6英寸。

  4. 拟合和转换:使用pcafit_transform方法对已缩放的数据wine_scaled进行拟合和转换,将结果存储在变量X_pca中。

  5. 创建数据框:将X_pca转换为pd.DataFrame对象,列名为PC1PC2,并将结果存储在变量principal_df中。

  6. 绘制散点图:使用plt.scatter绘制principal_dfPC1PC2列的散点图,点的大小设置为40。

  7. 美化图形:使用plt.titleplt.xlabelplt.ylabel设置图形的标题和坐标轴标签。

这段代码的目的是将多维数据wine_scaled通过主成分分析(PCA)降至二维,然后绘制散点图以便于可视化。

# 导入 PCA 类,用于进行主成分分析
from sklearn.decomposition import PCA

# 创建 PCA 对象,并设置主成分的数量为 2
pca = PCA(n_components=2)

# 设置 matplotlib 图形的大小为 8x6
plt.figure(figsize=(8,6))

# 使用 PCA 对象对已经标准化的数据 wine_scaled 进行拟合和转换,将结果赋值给 X_pca
X_pca = pca.fit_transform(wine_scaled)

# 将 X_pca 转换为 DataFrame 对象,并设置列名为 'PC1' 和 'PC2'
principal_df = pd.DataFrame(data = X_pca, columns = ['PC1', 'PC2'])

# 使用 matplotlib 创建散点图,x 坐标为 'PC1' 列的值,y 坐标为 'PC2' 列的值,点的大小为 40
plt.scatter(principal_df.iloc[:,0], principal_df.iloc[:,1], s=40)

# 设置图形的标题为 'PCA plot in 2D'
plt.title('PCA plot in 2D')

# 设置 x 轴的标签为 'PC1'
plt.xlabel('PC1')

# 设置 y 轴的标签为 'PC2'
plt.ylabel('PC2')

X_pca = pca.fit_transform(wine_scaled)这行代码的作用是将已经标准化的数据wine_scaled通过主成分分析(PCA)降维,并将降维后的数据存储在X_pca中。

image-20230927222108954

PC1和PC2是根据原始数据的特征进行线性组合得到的新的特征。PC1是第一个主成分,它是在原始数据的特征上具有最大方差的线性组合。PC2是第二个主成分,它是在原始数据的特征上与PC1正交(无相关性)且具有次大方差的线性组合。

通过在散点图中以PC1和PC2作为横纵坐标,我们可以观察到数据在这两个主成分上的分布情况。不同数据点的位置和相对位置可以反映出数据在主成分空间中的差异和相关性。

底层逻辑

PCA的目标是找到一个新的坐标系,使得数据在这个坐标系下的方差最大化。具体步骤如下:

  1. 计算数据的协方差矩阵。
  2. 计算协方差矩阵的特征值和特征向量。
  3. 将特征值从大到小排序,选择前k个最大特征值对应的特征向量,构成一个投影矩阵。
  4. 将原始数据与投影矩阵相乘,得到降维后的数据。

在这个例子中,原始数据集dataset_train经过标准化后,使用PCA进行降维。首先,计算标准化后的数据wine_scaled的协方差矩阵,然后进行特征值分解,选择最大的2个特征值对应的特征向量作为主成分。最后,将标准化后的数据投影到这两个主成分上,得到降维后的数据X_pca。通过散点图可视化降维后的数据,横轴表示第一个主成分(PC1),纵轴表示第二个主成分(PC2)。这样的降维过程可以帮助我们更好地理解数据的结构和模式。

分解代码

以下是一个简化的PCA实现,用于说明底层逻辑:

import numpy as np

def pca(X, n_components):
    # 计算协方差矩阵
    # 在计算协方差矩阵时,通常需要将数据集的每个特征作为列进行表示。而原始数据集X通常是以每个样本作为行的形式进行表示的。因此,为了计算协	方差矩阵,需要对数据集进行转置,使得每个特征对应于新的数据集的列。

	# 通过使用转置矩阵(X.T),可以将原始数据集的行和列进行交换,从而得到一个新的数据集,其中每个特征对应于新数据集的列。然后,通过调用	np.cov()函数计算新数据集的协方差矩阵。这样做可以确保协方差矩阵的计算是基于特征之间的关系,而不是样本之间的关系。
    cov_matrix = np.cov(X.T)

    # 计算特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)

    # 对特征值进行降序排序,并获取排序后的索引
    # np.linalg.eig(cov_matrix)将返回两个数组:eigenvalues和eigenvectors。其中,eigenvalues是一个包含协方差矩阵的特征值的一维`	数组,eigenvectors是一个包含对应特征值的特征向量的二维数组。
    sorted_indices = np.argsort(eigenvalues)[::-1]

    # 选择前n_components个最大特征值对应的特征向量
    top_k_eigenvectors = eigenvectors[:, sorted_indices[:n_components]]

    # 将原始数据与投影矩阵相乘,得到降维后的数据
    # X.dot()是NumPy中的一个函数,用于计算矩阵乘法。它用于将矩阵X与另一个矩阵相乘。
    # 在这种情况下,X是一个矩阵,可以是一个二维数组。调用X.dot(Y)将返回矩阵X和Y的乘积。
    #矩阵乘法是通过将矩阵X的行与矩阵Y的列进行相乘,并将结果相加得到的。矩阵乘法要求两个矩阵的维度满足一定的条件,即第一个矩阵的列数必须等	于第二个矩阵的行数。
    X_pca = X.dot(top_k_eigenvectors)

    return X_pca

# 使用自定义的PCA函数对wine_scaled进行降维
X_pca = pca(wine_scaled, n_components=2)

绘制肘部图

# 导入KMeans类,用于执行K-means聚类算法
from sklearn.cluster import KMeans
# 导入warnings库,用于处理警告信息
import warnings
# 忽略警告信息
warnings.filterwarnings("ignore")
# 导入os库,用于操作系统相关功能
import os as os
# 初始化一个空列表,用于存储不同聚类数量下的惯性值
inertia = []

# 对不同的聚类数量进行迭代,从2到10
for k in range(2, 11):
    # 创建KMeans实例,设置聚类数量、初始化次数、最大迭代次数和随机种子
    kmeans = KMeans(n_clusters=k, n_init=15, max_iter=500, random_state=0)
    # 对数据进行拟合,执行K-means聚类算法
    kmeans.fit(X_pca)
    # 将每次迭代的惯性值添加到列表中
    inertia.append(kmeans.inertia_)
    # 设置绘图区域的大小
    plt.figure(figsize=(8, 6))

# 绘制肘部图,展示不同聚类数量下的惯性值
plt.plot(range(2, 11), inertia, marker='o')
# 设置图表标题
plt.title('Elbow Diagram')
# 设置x轴标签
plt.xlabel('Number of Clusters')
# 设置y轴标签
plt.ylabel('Inertia')
# 显示图表
plt.show()

image-20231008213502891

执行kmeans聚类

# 创建KMeans实例,设置聚类数量为3,初始化次数为15,最大迭代次数为500,随机种子为0
kmeans = KMeans(n_clusters=3, n_init=15, max_iter=500, random_state=0)

# 使用KMeans实例对经过PCA降维的葡萄酒数据进行拟合,并预测每个数据点的簇标签
clusters = kmeans.fit_predict(X_pca)
labels = kmeans.labels_

# 创建一个8x5英寸的图形和坐标轴
fig, ax = plt.subplots(figsize=(8, 5))

# 在坐标轴上绘制散点图,使用PCA降维后的数据,颜色由簇标签决定,使用inferno色图
ax.scatter(X_pca[:, 0], X_pca[:, 1], c=labels, cmap='inferno')

# 设置图形标题和坐标轴标签
ax.set_title('PCA - 2 dimensions', fontsize=15)
ax.set_xlabel('Component 1', fontsize=13)
ax.set_ylabel('Component 2', fontsize=13)

# 显示图形
plt.show()

image-20231009221220679

评估

from sklearn.metrics import silhouette_samples, silhouette_score
import matplotlib.cm as cm
import numpy as np

# 计算每个样本的Silhouette系数
sample_silhouette_values = silhouette_samples(X_pca, clusters)

# 创建Silhouette图的图形和坐标轴
fig, ax1 = plt.subplots(1, 1)
# 设置x轴范围
ax1.set_xlim([-0.1, 1])
# 设置y轴范围
ax1.set_ylim([0, len(X_pca) + (3 + 1) * 10])

# 初始化y轴的下界
y_lower = 10
# 设置簇的数量
n_clusters = 3
# 遍历每个簇,绘制簇内样本的Silhouette系数
for i in range(n_clusters):
    # 获取当前簇的Silhouette系数
    ith_cluster_silhouette_values = sample_silhouette_values[clusters == i]
    # 对Silhouette系数进行排序
    ith_cluster_silhouette_values.sort()

    # 计算当前簇的样本数量
    size_cluster_i = ith_cluster_silhouette_values.shape[0]
    # 计算y轴的上界
    y_upper = y_lower + size_cluster_i

    # 为每个簇选择颜色并填充区域
    color = cm.nipy_spectral(float(i) / n_clusters)
    ax1.fill_betweenx(np.arange(y_lower, y_upper),
                      0, ith_cluster_silhouette_values,
                      facecolor=color, edgecolor=color, alpha=0.7)

    # 在每个簇的中间位置添加簇标签
    ax1.text(-0.05, y_lower + 0.5 * size_cluster_i, str(i))

    # 更新y轴的下界
    y_lower = y_upper + 10

# 设置图形标题和坐标轴标签
ax1.set_title("Silhouette Plot")
ax1.set_xlabel("The silhouette coeficient values")
ax1.set_ylabel("sample")

# 显示图形
plt.show()

image-20231009224034591

通过观察Silhouette图,我们可以对聚类算法的性能进行评估。大部分样本的Silhouette系数都较高,说明聚类效果较好。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YOLO大师

你的打赏,我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值