用 Python 从头开始​​进行主成分分析

主成分分析(简称 PCA)被称为降维技术。

它自 1901 年以来一直存在,至今仍被用作机器学习和统计学中的主要降维方法。PCA是一种无监督统计方法。

在本文中,我们将对 PCA 有一些直观的了解,并使用 Python 和 NumPy 从头开始​​实现它。

为什么首先要使用 PCA?

为了支持使用 PCA 的原因,我们来看一个例子。

假设我们有一个包含两个变量和 10 个数据点的数据集。如果我们被要求可视化数据点,我们可以很容易地做到。结果也非常容易解释。

X1 2 8 1 4 22 15 25 29 4 2
X2 3 6 2 6 18 16 20 23 6 4
示例数据点
在二维上绘制数据

现在,如果我们尝试增加变量的数量,我们几乎不可能想象比三维更高的维度。 

我们在分析高维数据集时面临的这个问题就是通常所说的“维数灾难”。该术语最初由理查德·E·贝尔曼(Richard E. Bellman)创造。

主成分分析将高维数据减少到较低维度,同时捕获数据集的最大可变性。数据可视化是PCA最常见的应用。PCA 还用于通过减少数据的维数来加快算法的训练速度。

用python实现PCA

为了从下面给出的内容中获得最大的直觉,我们假设您必须了解一点线性代数和矩阵如果没有,那么我们强烈建议您在 YouTube 上观看Grant Sanderson的 3Blue1Brown 线性代数系列,以重温概念,因为它将对您未来的机器学习之旅非常有益。

我们可以将主成分分析视为将 n 维椭球体拟合到数据,以便椭球体的每个轴代表一个主成分。主成分轴越大,其表示的数据的变异性就越大。

示例:将椭圆拟合到数据

 在Python中实现PCA的步骤

#Importing required libraries
import numpy as np

1.减去每个变量的均值

从数据集中减去每个变量的平均值,以便数据集应以原点为中心。事实证明,这样做在计算协方差矩阵时非常有帮助。

#Generate a dummy dataset.
X = np.random.randint(10,50,100).reshape(20,5)
# mean Centering the data 
X_meaned = X - np.mean(X , axis = 0)

上述代码生成的数据具有维度 (20,5),即 20 个示例,每个示例有 5 个变量。我们计算每个变量的平均值,并从相应列的每一行中减去该平均值。

2. 计算协方差矩阵

计算以均值为中心的数据的协方差矩阵。您可以在这篇内容丰富的维基百科文章中了解有关协方差矩阵的更多信息

协方差矩阵是一个方阵,表示元素之间的协方差。元素与其自身的协方差只不过是它的方差。

这就是为什么协方差矩阵的对角线元素只是元素的方差。

# calculating the covariance matrix of the mean-centered data.
cov_mat = np.cov(X_meaned , rowvar = False)

我们可以找到很容易计算协方差矩阵的numpy.cov( )方法。的默认值rowvar设置为True,请记住将其设置为False以获得所需维度的协方差矩阵。

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

现在,计算计算出的协方差矩阵的特征值和特征向量。我们得到的协方差矩阵的特征向量彼此正交,每个向量代表一个主轴。

较高的特征值对应于较高的变异性。因此,具有较高特征值的主轴将是捕获数据中较高变异性的轴。

正交意味着向量彼此垂直。特征值和向量似乎非常可怕,直到我们了解其背后的想法和概念。

#Calculating Eigenvalues and Eigenvectors of the covariance matrix
eigen_values , eigen_vectors = np.linalg.eigh(cov_mat)

NumPylinalg.eigh( )方法返回复埃尔米特矩阵或实对称矩阵的特征值和特征向量。

4. 对特征值进行降序排序

按降序对特征值及其相应的特征向量进行排序。

请记住,特征向量矩阵中的每一列都对应于一个主成分,因此按其特征值的降序排列它们将自动按其变异性的降序排列主成分。

因此,我们重新排列的特征向量矩阵中的第一列将是捕获最高变异性的主要成分。

#sort the eigenvalues in descending order
sorted_index = np.argsort(eigen_values)[::-1]
 
sorted_eigenvalue = eigen_values[sorted_index]
#similarly sort the eigenvectors
sorted_eigenvectors = eigen_vectors[:,sorted_index]

np.argsort返回相同形状的索引数组。

5. 从重新排列的特征值矩阵中选择一个子集

根据我们的需要从重新排列的特征值矩阵中选择一个子集,即 number_comp = 2。这意味着我们选择了前两个主成分。

# select the first n eigenvectors, n is desired dimension
# of our final reduced data.
 
n_components = 2 #you can select any number of components.
eigenvector_subset = sorted_eigenvectors[:,0:n_components]

n_components = 2 意味着我们的最终数据应该减少到只有 2 个变量。如果我们将其更改为 3,那么我们的数据就会减少到 3 个变量。

6. 转换数据

最后,通过特征向量子集的转置和以均值为中心的数据的转置之间的点积来变换数据。通过点积的结果转置,我们得到的结果是数据从高维降维到低维。

#Transform the data
X_reduced = np.dot(eigenvector_subset.transpose(),X_meaned.transpose()).transpose()

X_reduced 的最终维度将为 ( 20, 2 ),并且最初数据具有更高维度 ( 20, 5 )。

现在我们可以使用现有的工具可视化我们的数据。欢呼!任务完成。

Python 中主成分分析的完整代码

现在,让我们通过创建一个函数来组合上述所有内容,并在一个示例中从头开始尝试我们的主成分分析。

import numpy as np
 
def PCA(X , num_components):
     
    #Step-1
    X_meaned = X - np.mean(X , axis = 0)
     
    #Step-2
    cov_mat = np.cov(X_meaned , rowvar = False)
     
    #Step-3
    eigen_values , eigen_vectors = np.linalg.eigh(cov_mat)
     
    #Step-4
    sorted_index = np.argsort(eigen_values)[::-1]
    sorted_eigenvalue = eigen_values[sorted_index]
    sorted_eigenvectors = eigen_vectors[:,sorted_index]
     
    #Step-5
    eigenvector_subset = sorted_eigenvectors[:,0:num_components]
     
    #Step-6
    X_reduced = np.dot(eigenvector_subset.transpose() , X_meaned.transpose() ).transpose()
     
    return X_reduced

我们定义了一个名为 PCA 的函数,接受数据矩阵和组件数量作为输入参数。

我们将使用IRIS 数据集并对其应用 PCA 函数。

import pandas as pd
 
#Get the IRIS dataset
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
data = pd.read_csv(url, names=['sepal length','sepal width','petal length','petal width','target'])
 
#prepare the data
x = data.iloc[:,0:4]
 
#prepare the target
target = data.iloc[:,4]
 
#Applying it to PCA function
mat_reduced = PCA(x , 2)
 
#Creating a Pandas DataFrame of reduced Dataset
principal_df = pd.DataFrame(mat_reduced , columns = ['PC1','PC2'])
 
#Concat it with target variable to create a complete Dataset
principal_df = pd.concat([principal_df , pd.DataFrame(target)] , axis = 1)

重要提示:在应用任何机器学习算法之前,我们应该在必要时对数据进行标准化。在上面的代码中,我们没有标准化我们的数据,但我们在实现 PCA 时这样做了。

让我们使用seabornmatplotlib库绘制我们的结果。

import seaborn as sb
import matplotlib.pyplot as plt
 
plt.figure(figsize = (6,6))
sb.scatterplot(data = principal_df , x = 'PC1',y = 'PC2' , hue = 'target' , s = 60 , palette= 'icefire')
降维图

就是这样!它工作得很好。

结论

在本文中,我们了解了 PCA、PCA 的工作原理,并使用NumPy实现了 PCA 。快乐学习!