在Python中使用Scikit learn实现主成分分析(PCA)
在现代社会,从现实世界中产生的数据集,如社交媒体和物联网,具有高度丰富的信息。这些信息是由许多贡献的特征捕获的,这些特征将数据引向一个高维空间。
通常,这些特征中的一些是相关的,因此,并非所有的特征对数据都是重要的。因此,要弄清楚哪些特征在数据中是相关的,哪些是不相关的,这构成了一个挑战。
这样的任务要求我们做一些维度的数据分析。这就引出了降维的概念。
降维
通常情况下,机器学习模型很容易受到维度的诅咒。
然而,在降维的帮助下,我们有可能找到解决这个问题的有效办法。
在机器学习和统计学中,维度是指数据集中的特征数量。
我们可以将降维定义为在减少数据集中不需要的特征数量时使用的一种技术,也就是说,将高维空间变成低维空间。
根据降维,我们需要分析我们的特征空间,并从这些数据集中选择一个相关的特征子集。然后,这个子集被用于未来的建模。
降维可以通过几种方式完成,其中包括。
- 主成分分析
- [线性判别分析(LDA)]
- [核心PCA]
- [正则相关分析(CCA)。]
当详述线性可分离的高维数据时,PCA是最常用的降维技术。
既然我们现在已经知道了什么是降维,那么让我们转向我们感兴趣的话题,即PCA。
主成分分析(PCA)
PCA算法是一种降维技术,它通过将一个d-维的特征空间投射到一个k-维的子空间来降低数据集的维度,其中k 小于d 。
PCA通过将所有的从属特征投射到一个新的特征上,从现有的特征中创建新的特征,以使投射误差达到最小。
只有在数据是线性可分离的情况下,这种技术才能保证可靠的结果。
PCA算法可用于特征提取、股票市场预测、基因分析等方面。
PCA包括以下几个步骤。
- 对数据进行标准化。
- 从[协方差]或[相关矩阵]中确定[特征值]和[特征向量]。
- 将特征值按降序排列。
- 选择对应于
k最大特征值的第一个k特征向量,其中k是新特征空间的维度,并且它是使。 - 从选定的
k特征向量中构建一个投影矩阵M。 - 将原始数据集
X,通过M,得到新的k-维度的特征子空间Y。
现在,让我们来学习如何使用Python中的sklearn库对表格数据实现PCA算法。
前提条件
- 在你的计算机上安装Python
- Python编程技能
- 一个数据集
实现PCA
在我们的实现中,我们将使用一个由不同类型的葡萄酒的特征组成的数据集,其中有一个分类研究变量,即葡萄酒属于哪一种。
我们的任务是对这个数据集应用PCA,通过减少其特征的维度来降低其复杂性。
以下是本节课要遵循的步骤。
第1步:数据预处理
让我们把我们的数据导入工作空间,并使用head() 函数查看其前五行。
# importing libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
# importing the dataset.
dataset = pd.read_csv('/content/drive/MyDrive/Wine.csv')
# Have a look at the dataset first five records
dataset.head()
输出

正如我们可以看到的,我们的数据有13个特征和一个目标变量。
每一行都是一种葡萄酒的类型。这些酒的特征包括从酒精含量到脯氨酸,以及这种酒所属的客户群。
我们总共有三个细分市场,即细分市场1、2和3。每个细分市场的客户对属于该细分市场的任何葡萄酒都有相同的偏好。
现在,我们了解了这个数据集,让我们用PCA对这个数据进行降维,并开发一个不太复杂的数据集。
降维后的数据集应该为未来的模型提供一个很好的方法来学习这些特征之间的关联性。
为了检验这一点,我们将在降维后的数据集上进一步实现逻辑回归,并使用混淆矩阵检验其性能。
让我们运行下面的代码,让我们的数据准备好应用PCA。
# Splitting the data into features and target sets
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, -1].values
# splitting the data into the training and test set.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
# Feature scalling
from sklearn.preprocessing import StandardScaler
stndS = StandardScaler()
X_train = stndS.fit_transform(X_train)
X_test = stndS.transform(X_test)
第2步:将PCA应用到数据集上
为了将PCA应用于我们的数据集,我们将在训练集和测试集上分别这样做,如图所示。
# Importing the PCA class from the decomposition module in sklearn
from sklearn.decomposition import PCA
# create a PCA object
pca = PCA(n_components = 2)# extracted features we want to end up within our new dataset(2).
# Apply the above object to our training dataset using the fit method.
X_train = pca.fit_transform(X_train)
# Apply the PCA object to the test set only to transform this set
X_test = pca.transform(X_test)
在这里,我们指定主成分的数量,以2 ,并对训练和测试数据集进行转换。因此,一个N- 维的数据集被简化为一个2- 维的数据集。
第3步:在新的训练数据集上训练逻辑模型
这里,我们将在新的训练集上建立一个逻辑回归。
# Importing the LogisticRegression class from the linear_model module in sklearn
from sklearn.linear_model import LogisticRegression
# create object of the above classifier
clfy = LogisticRegression(random_state = 0) # pass seed to ensure results are reproducible
clfy.fit(X_train, y_train) # calls fit method from the classifier object to fit the data to our model
第4步:打印混淆矩阵和我们的逻辑回归模型的准确性
# Importing the confusion_matrix and accuracy_score class from the metrics module in sklearn
from sklearn.metrics import confusion_matrix, accuracy_score
y_pred = clfy.predict(X_test) # calls a predict method from the classfier object to target variable of the X_test
# creating a confussion matrix
cm = confusion_matrix(y_test, y_pred)
print(cm)
# model score
accuracy_score(y_test, y_pred)
输出
[[14 0 0]
[ 1 15 0]
[ 0 0 6]]
0.9722222222222222
在上面的输出中,很明显我们在新的数据集上实现的模型的准确率为97.2% 。这表明PCA不仅能够通过减少特征的数量来降低模型的复杂性,而且还能够保留数据集中的很多信息。
最初的数据集(在降低维度之前)在实施上产生了100% 的准确性。
然而,虽然非常准确,但那个有13个特征的模型太复杂了,它很可能会受到维度诅咒的影响。
由于PCA可以简化模型并同时保持其性能,这证明了它的力量。
在它的帮助下,高维度的数据集可以被降低到低维度,这样就有可能对其进行可视化。
例如,我们的数据集在13个维度上是不可能实现可视化的。然而,当把它降低到二维时,就有可能实现如下的可视化。
第5步:训练集结果的可视化
from matplotlib.colors import ListedColormap
X_set, y_set = X_train, y_train
# Create a rectangular grid out of the array of X_set values
X1, X2 = np.meshgrid(np.arange(start = X_set[:, 0].min() - 1, stop = X_set[:, 0].max() + 1, step = 0.01),
np.arange(start = X_set[:, 1].min() - 1, stop = X_set[:, 1].max() + 1, step = 0.01))
plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape),
alpha = 0.75, cmap = ListedColormap(('red', 'green', 'blue')))
plt.xlim(X1.min(), X1.max()) # Sets the x limits on the current axis
plt.ylim(X2.min(), X2.max()) # Sets the y limit on the current axis
for i, j in enumerate(np.unique(y_set)):
plt.scatter(X_set[y_set == j, 0], X_set[y_set == j, 1], # create a scatter plot using X_set and y_set of the traing set
c = ListedColormap(('red', 'green', 'blue'))(i), label = j) # creating a colarmap of discrete colour levels
plt.title('Logistic Regression (Training set)') # adds a tittle to the plot
plt.xlabel('PC1') # labels the x-axis
plt.ylabel('PC2') # labels the y-axis
plt.legend() # Creating a key to the plot
plt.show() # displays the scatter plot
输出

第6步:测试集结果的可视化
from matplotlib.colors import ListedColormap
X_set, y_set = X_test, y_test
# Create a rectangular grid out of the array of X_set values
X1, X2 = np.meshgrid(np.arange(start = X_set[:, 0].min() - 1, stop = X_set[:, 0].max() + 1, step = 0.01),
np.arange(start = X_set[:, 1].min() - 1, stop = X_set[:, 1].max() + 1, step = 0.01))
plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape),
alpha = 0.75, cmap = ListedColormap(('red', 'green', 'blue')))
plt.xlim(X1.min(), X1.max())
plt.ylim(X2.min(), X2.max())
for i, j in enumerate(np.unique(y_set)):
plt.scatter(X_set[y_set == j, 0], X_set[y_set == j, 1], # creating a scatter plot using X_set and y_set of the test set
c = ListedColormap(('red', 'green', 'blue'))(i), label = j) # creating a colarmap
plt.title('Logistic Regression (Test set)') # adding a tittle to the plot
plt.xlabel('PC1') # labels the x-axis
plt.ylabel('PC2') # labels the y-axis
plt.legend() # creates a key to the plot
plt.show() # shows the scatter plot
输出

结语
在这篇文章中,我们学习了PCA算法所涉及的步骤,并在python中实现了同样的算法。
我们的实现显示了通过使用PCA将高维特征减少到低可见维度来降低模型的复杂性和增强可视化的重要性。
现在我们已经看到了这个算法的伟大之处,我们可以将其应用于其他具有更大维度的数据集,并摆脱与这种高维度相关的计算成本。