数据科学4月6日上机作业
——made by njtech_计2104 Melody
2.1. 鸢尾花数据可视化
任务:对每种类型的鸢尾花的四个属性进行可视化绘图,观察各属性在不同类型间的相关性及区分度。
注:
-
数据可以选择使用任务1.2步骤3清理之后的数据,也可使用sklearn包自带的载入数据方式,参考代码如下:
from sklearn import datasets iris = datasets.load_iris()
-
画图可以使用matplotlib包。
-
可依次选取每项特征绘制,例如,以萼片长度为x轴、萼片宽度为y轴作散点图进行观察。完成后继续观察下一组特征。
-
结果可参见下图示例。
代码:
from sklearn import datasets
import matplotlib.pyplot as plt
iris = datasets.load_iris()
data = iris.data
target = iris.target
feature_names = iris.feature_names
target_names = iris.target_names
# 设置图像大小和颜色
plt.figure(figsize=(15, 15))
colors = ['red', 'green', 'blue']
# 绘制每种属性的组合
for i in range(4):
for j in range(4):
plt.subplot(4, 4, i * 4 + j + 1)
if i == j:
plt.text(0.5, 0.5, feature_names[i], fontsize=12, ha='center')
else:
for k in range(3):
plt.scatter(data[target == k, i], data[target == k, j], c=colors[k], label=target_names[k], alpha=0.7)
# 设置坐标轴
if j == 0:
plt.ylabel(feature_names[i])
if i == 3:
plt.xlabel(feature_names[j])
# 添加图例
plt.legend(loc='upper right', bbox_to_anchor=(1.25, 0.95))
plt.show()
2.2. 鸢尾花数据的3D可视化
使用如任务2.1中的可视化方法只能观察两两特征间的关系。然而,真实数据中,仅用两组数据往往不足以完成分类问题。例如在上例中,萼片长度和叶片宽度这组数据,尚可满足区分山鸢
类鸢尾花的需求,但注意观察图中黄色和灰色部分具有大量重叠数据,明显无法对杂色鸢尾与维吉尼亚鸢尾进行区分。其它散点图中也可发现杂色鸢尾与维吉尼亚鸢尾具有不少重叠。为更好的区分三类鸢尾花,我们可以尝试添加新的特征进行可视化绘图。与任务2.1类似,请依次选取3个特征绘制3D散点图,观察是否足以区分三类花型。
注:绘制3D图可尝试使用mpl_toolkits.mplot3d库中的Axes3D,示例结果如下:
代码:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import datasets
# 加载鸢尾花数据集
iris = datasets.load_iris()
data = iris.data
target = iris.target
feature_names = iris.feature_names
target_names = iris.target_names
colors = ['red', 'green', 'blue']
# 对每个特征组合生成一个 3D 图形
for f in range(4):
# 创建一个 3D 图形
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
# 选择三个特征进行绘制
features = [i for i in range(4) if i != f]
for k in range(3):
ax.scatter(
data[target == k, features[0]],
data[target == k, features[1]],
data[target == k, features[2]],
c=colors[k],
label=target_names[k],
alpha=0.7
)
# 设置轴标签
ax.set_xlabel(feature_names[features[0]])
ax.set_ylabel(feature_names[features[1]])
ax.set_zlabel(feature_names[features[2]])
# 添加图例
ax.legend(loc='upper right')
plt.title(f"3D Scatter Plot excluding {feature_names[f]}")
plt.show()
2.3. 使用PCA(主成分分析)对数据进行降维
在任务2.3中尝试选取不同的3项特征重复实验,我们依然无法去除重叠的数据,需要考虑引入全部4种特征进行分类。然而,4项特征全部引入后我们将难以进行数据可视化(无法绘制四维视图),因此我们考虑使用PCA,利用正交变换将以线性相关变量表示的观测数据转化为少数几个以线性无关变量表示的数据,对鸢尾花的四维数据进行降维,然后绘制三维视图。
PCA算法的具体流程请自行在网上搜索研习,注意,其分解后的主成分就是其协方差矩阵对应的特征向量,按照对应的特征值大小进行排序,最大的特征值就是第一主成分,其次是第二主成分,以此类推。
PCA算法分析
Q:为什么是PCA?
A:PCA(Principal Component Analysis,主成分分析)是一种常用的无监督线性降维方法。它的目的是通过将原始数据集投影到一个新的坐标系,找到一个最优的低维空间,使得数据在这个新空间中的方差最大化。
Q:为什么PCA算法能找到最优的低维空间?
A:PCA 算法能找到最优的低维空间,是因为它试图找到能够最大化原始数据投影方差的正交基向量。这些正交基向量定义了新的低维空间。在这个低维空间中,数据的重要信息得以保留,同时减少了数据的维度。
Q:PCA具体的步骤是?
A:
-
数据中心化:通过减去每个特征的均值,将数据集的中心移到原点。这一步可以消除数据的平移影响,确保计算协方差矩阵时只考虑数据的形状和分布。中心化后,数据在新的坐标系中的方差变得更容易最大化。
-
计算协方差矩阵:协方差矩阵表示数据特征之间的相关性。对角线上的元素表示各特征的方差,非对角线上的元素表示两个特征之间的协方差。协方差矩阵可以帮助我们了解数据的形状和结构,为下一步计算特征向量提供基础。
-
计算协方差矩阵的特征值和特征向量:特征值表示方差,特征向量表示方向。较大的特征值对应的特征向量表示更多的信息。这一步是为了找到能够最大化数据投影方差的正交基向量,即主成分方向。
-
选择前 k 个主成分:将特征值从大到小排序,选择前 k 个较大的特征值对应的特征向量作为主成分。这一步是为了选取能够保留最多信息的主成分,同时降低数据的维度。
-
将原始数据投影到选定的主成分上:通过矩阵乘法,将原始数据投影到新的低维空间。这一步实现了数据的降维,得到了在新的低维空间中的数据表示。
代码:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import datasets
def pca(data, n_components=2):
# 数据中心化
data_centered = data - np.mean(data, axis=0)
# 计算协方差矩阵
cov_matrix = np.cov(data_centered.T)
# 计算协方差矩阵的特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
# 对特征值进行降序排序,并获取对应的索引
sorted_idx = np.argsort(eigenvalues)[::-1]
# 选择前 n 个主成分
selected_eigenvectors = eigenvectors[:, sorted_idx[:n_components]]
# 将数据投影到选定的主成分上
reduced_data = np.dot(data_centered, selected_eigenvectors)
return reduced_data
# 加载鸢尾花数据集
iris = datasets.load_iris()
data = iris.data
target = iris.target
target_names = iris.target_names
# 使用自定义 PCA 函数将数据降至三维
reduced_data = pca(data, n_components=3)
# 创建一个 3D 图形
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
# 绘制降维后的数据
colors = ['red', 'green', 'blue']
for k in range(3):
ax.scatter(reduced_data[target == k, 0], reduced_data[target == k, 1], reduced_data[target == k, 2], c=colors[k], label=target_names[k], alpha=0.7)
# 设置轴标签
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')
ax.set_zlabel('PC3')
# 添加图例
ax.legend(loc='upper right')
plt.title('Iris dataset PCA (3 principal components)')
plt.show()