Machine Learning机器学习之高维数据降维(主成分分析PCA、线性判别分析、自编码器超级无敌详细讲解)

简介: Machine Learning机器学习之高维数据降维(主成分分析PCA、线性判别分析、自编码器超级无敌详细讲解)

前言

高维数据降维是指将具有大量特征的数据转换为具有更少特征的数据的过程。在现实世界中,许多数据集具有大量的特征,这可能会增加建模的复杂性,并导致维度灾难(Curse of Dimensionality)问题的出现。高维数据降维的目的是减少特征的数量,同时保留数据中最重要的信息,以便更好地理解数据、可视化数据、加快计算速度和提高模型性能。

思想原理:

  1. 维度灾难:随着特征数量的增加,数据空间的维度也会增加。高维数据具有稀疏性和冗余性,这可能会导致模型过拟合、计算复杂度增加和样本稀疏性等问题,即维度灾难。
  2. 信息压缩:高维数据降维的目标是在保留数据中最重要信息的前提下,减少数据的维度。通过降维,可以将数据中的冗余信息和噪声过滤掉,从而使得数据更加紧凑和易于处理。
  3. 特征选择和特征提取:高维数据降维可以通过特征选择(Feature Selection)和特征提取(Feature Extraction)两种方式实现。特征选择是从原始特征中选择最重要的一部分特征,而特征提取则是通过某种变换将原始特征转换为新的特征空间,以减少特征的数量。
  4. 降维方法:常见的高维数据降维方法包括主成分分析(PCA)、线性判别分析(LDA)、t-分布邻近嵌入(t-SNE)、自编码器(Autoencoder)等。这些方法在保留数据信息的同时,可以有效地减少数据的维度。

一、常见数据降维方法简介

1、降维方法分类情况

特征选择

  • 特征选择是从原始特征集中选择最重要的特征子集,保留最相关的特征,而丢弃不相关的或冗余的特征。这些方法不改变原始特征的形式,只是选择性地保留或删除特征。
  • 常见的特征选择方法包括:
  • 过滤法(Filter Methods):根据特征的统计量(如方差、相关系数等)或其他评价标准对特征进行评估和排序,然后选择排名靠前的特征子集。
  • 包装法(Wrapper Methods):通过建立预测模型来评估特征子集的性能,根据模型性能选择最佳特征子集。常见的包装法包括递归特征消除(Recursive Feature Elimination)和正向逐步选择(Forward Stepwise Selection)等。
  • 嵌入法(Embedded Methods):在模型训练过程中,通过正则化项或其他方式对特征进行选择,例如 L1 正则化(Lasso)和决策树剪枝等。

特征提取

  • 特征提取是通过某种变换将原始特征转换为新的特征空间,以减少特征的数量,同时保留数据的主要信息。这些方法可以将原始特征进行线性或非线性变换,从而得到新的特征表示。
  • 常见的特征提取方法包括:
  • 主成分分析(Principal Component Analysis,PCA):通过线性变换将原始特征投影到新的特征空间,使得投影后的特征具有最大的方差。PCA 是一种常用的线性降维方法。
  • 线性判别分析(Linear Discriminant Analysis,LDA):在保持类别信息的同时最大化类间距离和最小化类内距离,从而得到新的特征空间。LDA 通常用于分类任务。
  • t-分布邻近嵌入(t-distributed Stochastic Neighbor Embedding,t-SNE):通过非线性变换将高维数据映射到低维空间,使得相似的样本在低维空间中距离更近。t-SNE 通常用于可视化高维数据。
  • 自编码器(Autoencoder):通过神经网络模型将原始特征压缩到低维空间,然后再将低维表示重构为原始特征,以此来学习数据的有效表示。自编码器在无监督学习中广泛应用于特征学习和数据降维。

二、常见数据降维分析之主成分分析

2.1背景介绍

主成分分析(Principal Component Analysis,PCA)是一种常用的线性降维技术,用于将高维数据转换为低维数据,同时保留尽可能多的原始数据信息。PCA 旨在找到数据中最重要的特征,并将其映射到新的特征空间上,以便更好地理解数据结构、可视化数据、减少计算成本和提高模型性能。接下来,我们将深入介绍 PCA 的思想原理、数学公式、实现步骤以及应用场景。

2.2思想原理

PCA 的核心思想是通过线性变换将原始数据投影到新的特征空间,使得投影后的特征具有最大的方差。这意味着,通过 PCA 转换后的特征保留了原始数据中包含的大部分信息,同时尽可能减少了特征之间的相关性。具体来说,PCA 的实现步骤如下:

1. 中心化数据:首先,对原始数据进行中心化处理,即将每个特征的均值减去其平均值,以确保数据的均值为零。

2. 计算协方差矩阵:接下来,计算中心化后的数据的协方差矩阵。协方差矩阵反映了不同特征之间的相关性程度,其对角线上的元素表示每个特征的方差,非对角线上的元素表示不同特征之间的协方差。

3. 求取特征值和特征向量:对协方差矩阵进行特征值分解,得到特征值和对应的特征向量。特征值表示了数据在特征空间上的方差,而特征向量表示了数据在特征空间上的方向。

4. 选择主成分:按照特征值的大小对特征向量进行排序,选择前 k 个特征向量作为主成分(Principal Components),其中 k 是希望降维后的维度。

5. 投影到新空间:将原始数据投影到由选定的主成分构成的新的特征空间上,得到降维后的数据。

2.3数学公式

1. 数据中心化:

  若原始数据矩阵为 ,其中每行表示一个样本,每列表示一个特征,则中心化后的数据矩阵 可以表示为:

  其中, 是每个特征的均值向量。

2. 协方差矩阵:

  对中心化后的数据矩阵 计算协方差矩阵

  其中, 是样本数量。

3. 特征值分解:

  对协方差矩阵 进行特征值分解:

  其中, 是第 个特征值, 是对应的特征向量。

4. 选择主成分:

  根据特征值的大小对特征向量进行排序,选择前 k 个特征向量作为主成分。

5. 投影到新空间:

  将原始数据矩阵 投影到由选定的主成分构成的新的特征空间上,得到降维后的数据矩阵

  其中, 是包含前 k 个特征向量的矩阵。

2.4PCA算法实现(Python完整代码)

首先我们基于NumPy 来生成两个类别共100个样本点。第一步,我们将使用 NumPy 库生成随机的样本点,然后使用 Matplotlib 库进行可视化。每个样本点都有三个特征,代表三维空间中的坐标。我们将随机生成两个类别的样本点,并将它们可视化出来。

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
 
# 设置随机种子,以便结果可重现
np.random.seed(0)
 
# 随机生成两个类别的样本点
num_samples = 50
class_1 = np.random.randn(num_samples, 3)  # 第一个类别的样本点
class_2 = np.random.randn(num_samples, 3)   # 第二个类别的样本点
 
# 绘制三维散点图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
 
# 绘制第一个类别的样本点
ax.scatter(class_1[:, 0], class_1[:, 1], class_1[:, 2], c='r', label='Class 1')
# 绘制第二个类别的样本点
ax.scatter(class_2[:, 0], class_2[:, 1], class_2[:, 2], c='b', label='Class 2')
 
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Randomly Generated 3D Samples')
ax.legend()
 
plt.show()

图1 随机样本点生成结果

第二步,我们将通过定义pca函数实现对三维数据降维处理。然后,我们可以使用 Matplotlib 将降维后的二维数据可视化出来,同时绘制特征向量。

定义pca函数对数据降维处理:

def pca(X, k):
    """
    主成分分析(PCA)实现。
   参数:
    - X(numpy.ndarray):形状为(n_samples,n_features)的输入数据矩阵。
    - k(int):要保留的主成分数量。
   返回值:
    - numpy.ndarray:形状为(n_samples,k)的转换后的数据矩阵。
    - numpy.ndarray:形状为(n_features,k)的前 k 个特征向量。
    """
    # 中心化数据
    X_centered = X - np.mean(X, axis=0)
 
    # 计算数据的协方差矩阵
    cov_matrix = np.cov(X_centered, rowvar=False)
 
    # 对协方差矩阵进行特征值分解
    eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
 
    # 选择前 k 个特征向量
    top_k_eigenvectors = eigenvectors[:, :k]
 
    # 将数据投影到新的特征空间上
    transformed_data = np.dot(X_centered, top_k_eigenvectors)
 
    return transformed_data, top_k_eigenvectors

可视化数据结果其中,其中红色点代表第一个类别,蓝色点代表第二个类别。特征向量用箭头表示,箭头的方向和长度表示了数据变换后的主要方向和重要程度。

# 绘制二维分布图
plt.figure(figsize=(8, 6))
plt.scatter(transformed_data[:num_samples, 0], transformed_data[:num_samples, 1], c='r', label='Class 1')
plt.scatter(transformed_data[num_samples:, 0], transformed_data[num_samples:, 1], c='b', label='Class 2')
 
# 绘制特征向量
origin = np.zeros(2)  # 原点
plt.quiver(*origin, top_k_eigenvectors[0, 0], top_k_eigenvectors[1, 0], color='r', scale=3)
plt.quiver(*origin, top_k_eigenvectors[0, 1], top_k_eigenvectors[1, 1], color='b', scale=3)
 
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('PCA Result: 2D Distribution')
plt.legend()
plt.grid(True)
plt.show()

图2 二维空间分布特征向量可视化结果

完整源代码(Python):

import numpy as np
import matplotlib.pyplot as plt
 
# 设置随机种子,以便结果可重现
np.random.seed(0)
 
# 随机生成两个类别的样本点
num_samples = 50
class_1 = np.random.randn(num_samples, 3)  # 第一个类别的样本点
class_2 = np.random.randn(num_samples, 3)   # 第二个类别的样本点
 
# 绘制三维散点图
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
 
# 绘制第一个类别的样本点
ax.scatter(class_1[:, 0], class_1[:, 1], class_1[:, 2], c='r', label='Class 1')
# 绘制第二个类别的样本点
ax.scatter(class_2[:, 0], class_2[:, 1], class_2[:, 2], c='b', label='Class 2')
 
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Randomly Generated 3D Samples')
ax.legend()
 
plt.show()
 
def pca(X, k):
    """
    主成分分析(PCA)实现。
   参数:
    - X(numpy.ndarray):形状为(n_samples,n_features)的输入数据矩阵。
    - k(int):要保留的主成分数量。
   返回值:
    - numpy.ndarray:形状为(n_samples,k)的转换后的数据矩阵。
    - numpy.ndarray:形状为(n_features,k)的前 k 个特征向量。
    """
    # 中心化数据
    X_centered = X - np.mean(X, axis=0)
 
    # 计算数据的协方差矩阵
    cov_matrix = np.cov(X_centered, rowvar=False)
 
    # 对协方差矩阵进行特征值分解
    eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
 
    # 选择前 k 个特征向量
    top_k_eigenvectors = eigenvectors[:, :k]
 
    # 将数据投影到新的特征空间上
    transformed_data = np.dot(X_centered, top_k_eigenvectors)
 
    return transformed_data, top_k_eigenvectors
 
 
# 将样本点合并为一个数据集
X = np.vstack([class_1, class_2])
 
# 应用PCA算法进行降维
transformed_data, top_k_eigenvectors = pca(X, 2)
 
# 绘制二维分布图
plt.figure(figsize=(8, 6))
plt.scatter(transformed_data[:num_samples, 0], transformed_data[:num_samples, 1], c='r', label='Class 1')
plt.scatter(transformed_data[num_samples:, 0], transformed_data[num_samples:, 1], c='b', label='Class 2')
 
# 绘制特征向量
origin = np.zeros(2)  # 原点
plt.quiver(*origin, top_k_eigenvectors[0, 0], top_k_eigenvectors[1, 0], color='r', scale=3)
plt.quiver(*origin, top_k_eigenvectors[0, 1], top_k_eigenvectors[1, 1], color='b', scale=3)
 
plt.xlabel('Principal Component 1')
plt.ylabel('Principal Component 2')
plt.title('PCA Result: 2D Distribution')
plt.legend()
plt.grid(True)
plt.show()

2.5应用场景

PCA 广发应用机器学习领域的数据处理:

- 数据可视化:通过降维将高维数据映射到二维或三维空间,以便更好地理解数据结构和关系。

- 数据压缩:降低数据的维度可以节省存储空间和计算成本,提高数据处理效率。

- 特征提取:将原始特征转换为新的特征空间,以提取数据中的关键信息和模式

- 去除噪声:通过降维可以过滤掉数据中的噪声和冗余信息,使得模型更加稳健和高效。

三、常见数据降维分析之线性判别分析

3.1背景分析

线性判别分析(Linear Discriminant Analysis,LDA)是一种监督学习算法,用于降低数据维度并找到最佳分类特征。与PCA不同,LDA是为了降维后的数据点尽可能容易区分出来,因此在分类问题中更常用。

                                  图3 PCA与LDA一维度投影示例

3.2思想原理

LDA 的主要思想是将数据投影到一个低维空间,以便在新空间中能够最大化类别之间的差异性,同时最小化同一类别内的差异性。具体来说,LDA 将数据投影到一条直线(在一维情况下)、一个平面(在二维情况下)或一个超平面(在高维情况下),以最大化类别之间的距离(即类间散布矩阵)与最小化同一类别内的方差(即类内散布矩阵)之比。

LDA 的降维步骤包括:

  1. 计算每个类别的均值向量(类均值)
  2. 计算类间散布矩阵 和类内散布矩阵
  3. 根据公式 进行特征值求解,计算 散布矩阵的特征值和特征向量
  4. 选择前 k 个特征值对应的特征向量(k 为降维后的维度)构成投影矩阵
  5. 通过 将数据投影到选定的特征向量构成的子空间中

3.4LDA算法实现

根据3.2的LDA算法思想,我们按照上述步骤实现LDA降维函数定义。代码如下图,步骤不再累述:

# 定义LDA函数
 
def lda(X, y, n_components):
   
    """ 
    返回结果
    Returns:
    numpy.ndarray: Transformed data matrix with shape (n_samples, n_components).
    """
    # Step 1: 计算每个类别的均值向量(类均值)
    class_means = []
    for c in np.unique(y):
        class_means.append(np.mean(X[y == c], axis=0))
    
    # Step 2: 计算类内散布矩阵和类间散布矩阵
    Sw = np.zeros((X.shape[1], X.shape[1]))  # 类内散布矩阵
    Sb = np.zeros((X.shape[1], X.shape[1]))  # 类间散布矩阵
    overall_mean = np.mean(X, axis=0)
    for c, mean_vec in zip(np.unique(y), class_means):
        class_samples = X[y == c]
        class_scatter_matrix = np.zeros((X.shape[1], X.shape[1]))
        for sample in class_samples:
            sample, mean_vec = sample.reshape(-1, 1), mean_vec.reshape(-1, 1)
            class_scatter_matrix += (sample - mean_vec).dot((sample - mean_vec).T)
        Sw += class_scatter_matrix
        Sb += len(class_samples) * (mean_vec - overall_mean).dot((mean_vec - overall_mean).T)
    
    # Step 3: 计算散布矩阵的特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(np.linalg.inv(Sw).dot(Sb))
    
    # Step 4: 选择前 k 个特征值对应的特征向量(k 为降维后的维度)
    eig_pairs = [(np.abs(eigenvalues[i]), eigenvectors[:, i]) for i in range(len(eigenvalues))]
    eig_pairs = sorted(eig_pairs, key=lambda k: k[0], reverse=True)
    w_matrix = np.hstack((eig_pairs[i][1].reshape(X.shape[1], 1) for i in range(n_components)))
    
    # Step 5: 将数据投影到选定的特征向量构成的子空间中
    X_lda = X.dot(w_matrix)
    
    return X_lda
 

算法应用:加载了 Iris 数据集,然后调用了上面实现的 LDA 算法进行降维。最后,使用 Matplotlib 绘制了 LDA 降维结果的散点图。在图中,每个点代表一个样本,不同颜色的点表示不同类别的 Iris 鸢尾花,分别是 Setosa、Versicolor 和 Virginica

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
 
# 加载 Iris 数据集
iris = load_iris()
X = iris.data
y = iris.target
 
def lda(X, y, n_components):
    # Step 1: 计算每个类别的均值向量(类均值)
    class_means = []
    for c in np.unique(y):
        class_means.append(np.mean(X[y == c], axis=0))
 
    # Step 2: 计算类内散布矩阵和类间散布矩阵
    Sw = np.zeros((X.shape[1], X.shape[1]))  # 类内散布矩阵
    Sb = np.zeros((X.shape[1], X.shape[1]))  # 类间散布矩阵
    overall_mean = np.mean(X, axis=0)
    for c, mean_vec in zip(np.unique(y), class_means):
        class_samples = X[y == c]
        class_scatter_matrix = np.zeros((X.shape[1], X.shape[1]))
        for sample in class_samples:
            sample, mean_vec = sample.reshape(-1, 1), mean_vec.reshape(-1, 1)
            class_scatter_matrix += (sample - mean_vec).dot((sample - mean_vec).T)
        Sw += class_scatter_matrix
        Sb += len(class_samples) * (mean_vec - overall_mean).dot((mean_vec - overall_mean).T)
 
    # Step 3: 计算散布矩阵的特征值和特征向量
    eigenvalues, eigenvectors = np.linalg.eig(np.linalg.inv(Sw).dot(Sb))
 
    # Step 4: 选择前 k 个特征值对应的特征向量(k 为降维后的维度)
    eig_pairs = [(np.abs(eigenvalues[i]), eigenvectors[:, i]) for i in range(len(eigenvalues))]
    eig_pairs = sorted(eig_pairs, key=lambda k: k[0], reverse=True)
    w_matrix = np.hstack([eig_pairs[i][1].reshape(X.shape[1], 1) for i in range(n_components)])
 
    # Step 5: 将数据投影到选定的特征向量构成的子空间中
    X_lda = X.dot(w_matrix)
 
    return X_lda
 
# 调用 LDA 算法进行降维
X_lda = lda(X, y, n_components=2)
 
# 可视化 LDA 降维结果
plt.figure(figsize=(8, 6))
colors = ['r', 'g', 'b']
labels = ['Setosa', 'Versicolor', 'Virginica']
for i in range(3):
    plt.scatter(X_lda[y == i, 0], X_lda[y == i, 1], color=colors[i], label=labels[i])
plt.xlabel('LD1')
plt.ylabel('LD2')
plt.title('LDA Dimensionality Reduction of Iris Dataset')
plt.legend()
plt.grid(True)
plt.show()

图4 LDA对三个属性数据降维效果

 

3.5应用场景

  • 模式识别和分类:LDA 可以用于模式识别和分类问题,特别是当类别之间有明显的线性边界时。例如,人脸识别、手写数字识别等图像分类问题。
  • 特征提取和降维:LDA 可以用于提取数据中的关键特征,并将数据降低到更低维度的空间中。这对于高维数据的可视化和压缩具有重要意义。例如,在图像处理和计算生物学中,可以使用 LDA 将数据降维到更容易处理和理解的空间中。
  • 异常检测:LDA 可以用于检测数据中的异常点或异常模式。通过比较新样本与已知类别的分布,可以识别出与预期模式不同的样本。
  • 信号处理:LDA 可以用于信号处理领域,例如语音识别、音频分类等,以区分不同的信号模式或类别。
  • 文本分类:在自然语言处理领域,LDA 可以用于文本分类问题,例如垃圾邮件过滤、情感分析等,以区分文本数据中的不同类别或主题。

四、常见数据降维分析之t-分布邻近嵌入

4.1背景介绍

t-分布邻近嵌入(t-distributed Stochastic Neighbor Embedding,t-SNE)是一种非线性降维技术,用于将高维数据映射到低维空间。它是一种流形学习技术,旨在保留数据之间的局部结构,并在降维后尽可能地保持数据点之间的相对距离。

4.2思想原理

t-SNE 的核心思想是利用高维数据点之间的相似度来构建一个概率分布,然后在低维空间中尽可能地保持相似度。具体来说,它通过以下步骤实现降维:

  1. 计算相似度:对于给定的高维数据集,首先计算每对数据点之间的相似度。通常使用高斯核函数度量两个数据点之间的相似度,距离越近,相似度越高
  2. 构建条件概率分布:根据相似度计算每个数据点之间的条件概率分布。对于每个数据点,计算它与其他数据点的相似度,并将相似度转换为条件概率
  3. 优化嵌入:在低维空间中随机初始化数据点的位置,并利用梯度下降等优化方法来最小化高维空间中的相似度和低维空间中的条件概率分布之间的差异。目标是在低维空间中找到一个投影,使得高维数据点之间的相对距离尽可能地得到保留

4.3t-分布邻近嵌入算法

局部线性嵌入(Locally Linear Embedding,LLE),下面是实现 LLE 算法的关键步骤:

  1. 选择邻域参数: 对于每个数据点,选择其最近的 k 个邻居作为其邻域。
  2. 重构权重矩阵: 对于每个数据点,使用其邻域内的数据点来重构它本身。这涉及到求解一个线性系统,以最小化原始数据点与其邻域内数据点的线性组合之间的误差
  3. 计算嵌入坐标: 根据重构权重矩阵,将数据点映射到低维空间。这可以通过求解一个最小化误差函数的优化问题来实现。
def select_neighbors(X, k):
    # 计算每个数据点的欧氏距离矩阵
    dist_matrix = np.sqrt(np.sum((X[:, np.newaxis] - X) ** 2, axis=2))
    # 获取每个数据点的 k 个最近邻索引
    neighbor_indices = np.argsort(dist_matrix, axis=1)[:, 1:k+1]
    return neighbor_indices
 
def compute_weights(X, neighbor_indices):
    n_samples = X.shape[0]
    W = np.zeros((n_samples, n_samples))
    for i, neighbors in enumerate(neighbor_indices):
        # 计算局部权重矩阵
        Z = X[neighbors] - X[i]
        C = Z @ Z.T
        w = linalg.spsolve(C, np.ones(k))  # 使用稀疏求解器求解线性系统
        W[i, neighbors] = w / np.sum(w)  # 归一化权重
    return W
 
# 定义LLM算法函数
def lle(X, k, n_components):
    n_samples = X.shape[0]
    # Step 1: 选择邻域参数
    neighbor_indices = select_neighbors(X, k)
    # Step 2: 重构权重矩阵
    W = compute_weights(X, neighbor_indices)
    # Step 3: 计算嵌入坐标
    M = np.eye(n_samples) - W
    eigvals, eigvecs = linalg.eigs(M, k=n_components+1, which='SM')
    idx = np.argsort(np.abs(eigvals))
    return eigvecs[:, idx[1:n_components+1]]

接下来我们通过随机生成1000个数据点来检验LLM算法实现的降维效果。

import numpy as np
from scipy.sparse import linalg
import matplotlib.pyplot as plt
 
 
def select_neighbors(X, k):
    # 计算每个数据点的欧氏距离矩阵
    dist_matrix = np.sqrt(np.sum((X[:, np.newaxis] - X) ** 2, axis=2))
    # 获取每个数据点的 k 个最近邻索引
    neighbor_indices = np.argsort(dist_matrix, axis=1)[:, 1:k+1]
    return neighbor_indices
 
def compute_weights(X, neighbor_indices):
    n_samples = X.shape[0]
    W = np.zeros((n_samples, n_samples))
    for i, neighbors in enumerate(neighbor_indices):
        # 计算局部权重矩阵
        Z = X[neighbors] - X[i]
        C = Z @ Z.T
        w = linalg.spsolve(C, np.ones(k))  # 使用稀疏求解器求解线性系统
        W[i, neighbors] = w / np.sum(w)  # 归一化权重
    return W
 
def lle(X, k, n_components):
    n_samples = X.shape[0]
    # Step 1: 选择邻域参数
    neighbor_indices = select_neighbors(X, k)
    # Step 2: 重构权重矩阵
    W = compute_weights(X, neighbor_indices)
    # Step 3: 计算嵌入坐标
    M = np.eye(n_samples) - W
    eigvals, eigvecs = linalg.eigs(M, k=n_components+1, which='SM')
    idx = np.argsort(np.abs(eigvals))
    return eigvecs[:, idx[1:n_components+1]]
 
# 随机生成1000个数据点,包含3个属性特征
X = np.random.randn(1000, 3)  # 生成三维随机数据
k = 3  # 邻域参数
n_components = 2  # 降维后的维度
embedding = lle(X, k, n_components)
 
# 绘制降维后的数据点
plt.figure(figsize=(8, 6))
plt.scatter(embedding[:, 0], embedding[:, 1])
plt.xlabel('Component 1')
plt.ylabel('Component 2')
plt.title('LLE Visualization')
plt.grid(True)
plt.show()
 

图5 LLM算法实现降维效果

五、自编码器(Autoencoder)

5.1自编码器思想与原理

自编码器(Autoencoder)是一种无监督学习模型,它通过尝试重构输入数据来学习有效的数据表示。自编码器通常由两部分组成:编码器(Encoder)和解码器(Decoder)编码器将输入数据映射到潜在空间中的低维表示,而解码器则将该低维表示映射回原始数据空间

自编码器的目标是最小化输入数据与重构数据之间的差异,这可以通过最小化重构误差来实现。通常使用均方误差(MSE)或者交叉熵作为重构误差的度量。

自编码器的训练过程通常分为以下步骤:

  1. 将输入数据传递给编码器,获取潜在表示。
  2. 使用潜在表示重构原始数据,并计算重构误差。
  3. 使用反向传播算法优化网络参数,以最小化重构误差。

自编码器通常被用于数据压缩、特征学习和去噪等应用中。它们也可以用作生成模型的一部分,例如生成对抗网络(GAN)中的生成器部分。

常见的自编码器类型包括标准自编码器、稀疏自编码器、去噪自编码器、变分自编码器等。、

5.2自编码器算法

基于PyTorch 构建一个简单的全连接自编码器,并在 MNIST 数据集上进行训练和测试。自编码器的编码器部分由一个全连接层组成,激活函数为 ReLU解码器部分也是一个全连接层,激活函数为 Sigmoid。在训练过程中,使用二元交叉熵作为损失函数,并使用 Adam 优化器进行优化。最后,通过编码和解码图像,可视化原始图像与重构图像。(注意运行环境需要安装pytorch;代码动态下载MNIST数据集在data文件夹中,可能需要点时间等待;迭代次数选择20,如果环境装有GPU可以根据实际情况调整;因为时间关系实际效果还有很大提升空间(训练效果一般,仅供参考学习,勿喷哦!)各位伙伴可以分享自己的训练参数情况,或者更好的重构图像代码)

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
 
 
# 定义自编码器模型
class Autoencoder(nn.Module):
    def __init__(self, input_dim, latent_dim):
        super(Autoencoder, self).__init__()
        self.encoder = nn.Sequential(
            nn.Linear(input_dim, latent_dim),
            nn.ReLU()
        )
        self.decoder = nn.Sequential(
            nn.Linear(latent_dim, input_dim),
            nn.Sigmoid()
        )
 
    def forward(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded
 
 
# 加载MNIST数据集并预处理
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=256, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=256, shuffle=False)
 
# 实例化自编码器模型
input_dim = 28 * 28  # 输入大小为28x28=784
latent_dim = 64  # 潜在空间维度
autoencoder = Autoencoder(input_dim, latent_dim)
 
# 定义损失函数和优化器
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(autoencoder.parameters(), lr=0.001)
 
# 训练自编码器
num_epochs = 20
for epoch in range(num_epochs):
    for data in train_loader:
        img, _ = data
        img = img.view(img.size(0), -1)
        output = autoencoder(img)
        loss = criterion(output, img)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
    print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {loss.item():.4f}')
 
# 使用自编码器进行编码和解码
encoded_imgs = autoencoder.encoder(test_dataset.data.float().view(-1, input_dim))
decoded_imgs = autoencoder.decoder(encoded_imgs)
 
# 可视化原始图像与重构图像
n = 10  # 可视化样本数
plt.figure(figsize=(20, 4))
for i in range(n):
    # 原始图像
    ax = plt.subplot(2, n, i + 1)
    plt.imshow(test_dataset.data[i].numpy(), cmap='gray')
    plt.title("Original")
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
 
    # 重构图像
    ax = plt.subplot(2, n, i + 1 + n)
    plt.imshow(decoded_imgs[i].detach().numpy().reshape(28, 28), cmap='gray')
    plt.title("Reconstructed")
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

5.3 运行结果:

图6 原始图像与重构图像代码

六、总结

今天我们涉及了机器学习的各个方面,包括传统机器学习算法(如线性回归、逻辑回归、决策树、随机森林、支持向量机等)、降维算法(如主成分分析、局部线性嵌入、t-分布邻近嵌入等)、深度学习算法(如自编码器)、以及一些常用的数据集和数据处理技巧。我们还介绍了这些算法的原理、应用场景和代码实现。总的来说,今天的内容涵盖了机器学习的基础知识和常见技术,为进一步学习和应用机器学习提供了基础。

最后,创作不易!非常感谢大家的关注、点赞、收藏、评论啦!谢谢四连哦!好人好运连连,学习进步!工作顺利哦!


相关文章
|
4天前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】金融数据分析中的机器学习应用
【4月更文挑战第30天】本文探讨了机器学习在金融数据分析中的应用,如股价预测、信用评分、欺诈检测、算法交易和风险管理,并以Python为例展示了如何进行股价预测。通过使用机器学习模型,金融机构能更准确地评估风险、识别欺诈行为并优化交易策略。Python结合scikit-learn库简化了数据分析过程,助力金融从业者提高决策效率。随着技术发展,机器学习在金融领域的影响力将持续增强。
|
4天前
|
机器学习/深度学习 Python
【Python 机器学习专栏】混淆矩阵与 ROC 曲线分析
【4月更文挑战第30天】本文介绍了机器学习中评估模型性能的两种工具——混淆矩阵和ROC曲线。混淆矩阵显示了模型在不同类别上的预测情况,包括真正例、假正例、真反例和假反例,帮助评估模型错误类型和数量。ROC曲线则通过假正率和真正率展示了模型的二分类性能,曲线越接近左上角,性能越好。文章还提供了Python中计算混淆矩阵和ROC曲线的代码示例,强调它们在模型选择、参数调整和理解模型行为中的应用价值。
|
4天前
|
机器学习/深度学习 存储 数据采集
【Python 机器学习专栏】PCA(主成分分析)在数据降维中的应用
【4月更文挑战第30天】本文探讨了主成分分析(PCA)在高维数据降维中的应用。PCA通过线性变换找到最大化方差的主成分,从而降低数据维度,简化存储和计算,同时去除噪声。文章介绍了PCA的基本原理、步骤,强调了PCA在数据降维、可视化和特征提取上的优势,并提供了Python实现示例。PCA广泛应用在图像压缩、机器学习和数据分析等领域,但降维后可能损失解释性,需注意选择合适主成分数量及数据预处理。
|
4天前
|
机器学习/深度学习 Python
【Python机器学习专栏】时间序列数据的特征工程
【4月更文挑战第30天】本文探讨了时间序列数据的特征工程,强调其在捕捉季节性、揭示趋势、处理异常值和提升模型性能中的重要性。介绍了滞后特征、移动窗口统计特征、时间戳特征、频域特征和波动率特征等方法,并提供了Python实现示例。通过有效特征工程,可提高时间序列分析的准确性和预测可靠性。
|
4天前
|
机器学习/深度学习 计算机视觉 Python
【Python 机器学习专栏】图像数据的特征提取与预处理
【4月更文挑战第30天】本文探讨了图像数据的特征提取与预处理在机器学习中的重要性。图像数据具有大容量、信息丰富和冗余性高的特点。特征提取涉及颜色、纹理和形状特征;预处理包括图像增强、去噪和分割。Python的OpenCV和Scikit-image库在处理这些任务时非常有用。常见的特征提取方法有统计、变换和基于模型的方法,而预处理应注意保持图像真实性、适应性调整及验证评估。有效的特征提取和预处理能提升模型性能,Python工具使其更高效。
|
4天前
|
机器学习/深度学习 自然语言处理 算法
【Python机器学习专栏】文本数据的特征提取与表示
【4月更文挑战第30天】本文探讨了文本特征提取与表示在机器学习和NLP中的重要性。介绍了词袋模型、TF-IDF和n-gram等特征提取方法,以及稀疏向量和词嵌入等表示方式。Python中可利用sklearn和gensim库实现这些技术。有效的特征提取与表示有助于将文本数据转化为可处理的数值形式,推动NLP和机器学习领域的进步。
|
4天前
|
机器学习/深度学习 数据采集 算法
【Python机器学习专栏】使用Scikit-learn进行数据编码
【4月更文挑战第30天】本文介绍了Python Scikit-learn库在机器学习数据预处理中的作用,尤其是数据编码。数据编码将原始数据转化为算法可理解的格式,包括标签编码(适用于有序分类变量)、独热编码(适用于无序分类变量)和文本编码(如词袋模型、TF-IDF)。Scikit-learn提供LabelEncoder和OneHotEncoder类实现这些编码。示例展示了如何对数据进行标签编码和独热编码,强调了正确选择编码方法的重要性。
|
4天前
|
机器学习/深度学习 数据采集 算法
【Python机器学习专栏】数据标准化与归一化技术
【4月更文挑战第30天】在机器学习中,数据预处理的两大关键步骤是标准化和归一化,旨在调整数据范围以优化算法性能。标准化将数据缩放到特定区间,如[-1, 1]或[0, 1],适合基于距离的算法,如KNN、SVM。归一化则将数据线性变换到[0, 1],保持相对关系。Python中可使用`sklearn.preprocessing`的`MinMaxScaler`和`StandardScaler`实现这两种操作。选择哪种方法取决于数据分布和算法需求。预处理能提升模型理解和性能,增强预测准确性和可靠性。
|
4天前
|
机器学习/深度学习 数据采集 数据可视化
【Python 机器学习专栏】数据缺失值处理与插补方法
【4月更文挑战第30天】本文探讨了Python中处理数据缺失值的方法。缺失值影响数据分析和模型训练,可能导致模型偏差、准确性降低和干扰分析。检测缺失值可使用Pandas的`isnull()`和`notnull()`,或通过可视化。处理方法包括删除含缺失值的行/列及填充:固定值、均值/中位数、众数或最近邻。Scikit-learn提供了SimpleImputer和IterativeImputer类进行插补。选择方法要考虑数据特点、缺失值比例和模型需求。注意过度插补和验证评估。处理缺失值是提升数据质量和模型准确性关键步骤。
|
4天前
|
机器学习/深度学习 算法 Python
【Python机器学习专栏】数据特征选择与降维技术
【4月更文挑战第30天】本文探讨了Python中数据特征选择与降维技术在机器学习和数据分析中的应用。特征选择包括单变量选择、递归特征消除(RFE)、树模型的特征重要性和相关性分析,有助于去除冗余和无关特征。降维技术涵盖PCA、LDA以及非线性方法如KPCA和ISOMAP,用于在低维空间保留信息。这些技术能简化数据、提升模型性能及可解释性。