首页 > 编程语言 >关于九种降维算法的一份介绍

关于九种降维算法的一份介绍

时间:2024-10-08 14:46:42浏览次数:8  
标签:digits plt 矩阵 降维 算法 九种 import 数据 sklearn

在这篇文章中我将介绍有关降维的一些东西,其中包括一些常见降维方法的概念、用途、优缺点以及python代码。

一、概念

降维是机器学习中常用到的一种技术,其用于减少数据集的维度,但又能保存数据集的重要信息,从而简化数据的处理,并提高计算效率、调高模型的性能以及方便可视化。

二、分类

降维可以分为两类,一类是线性降维,一类是非线性降维。

首先我们看线性降维,常见的算法有这几种:主成分分析(PCA)、线性判别分析(LDA)、因子分析(FA)、独立成分分析(ICA)等。

然后看非线性降维,常见的算法有这些:核主成分分析(KPCA)、非负矩阵分解(NMF)、等度量映射(Isomap)、局部线性嵌入(LLE)、t-分布随机邻域嵌入(t-SNE)、多维缩放(MDS)、拉普拉斯特征映射等。

三、算法详解

关于上述的几种算法,在这里将依次介绍。

3.1 PCA

首先是PCA,但是关于它我在之前的文章中有介绍,所以在这里我只用一句话来概括就是:PCA(主成分分析)是一种线性降维技术,通过将数据转换到新的坐标轴上并保留最大方差的方向来降低数据的维度,从而最大化信息保留的同时减少数据的复杂性。

此外,在这里我再附上一份PCA的代码,其内容为通过PCA将手写数字数据降维,并用特征值来绘制出一份图来,代码如下:

from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

digits = load_digits()
# 数据集实例图像
fig, axes = plt.subplots(2, 5, figsize=(10, 5),
                         subplot_kw={'xticks':(), 'yticks':()})
for ax, img in zip(axes.ravel(), digits.images):
    ax.imshow(img)
plt.show()

# PCA
pca = PCA(n_components=2)
pca.fit(digits.data)
digits_pca = pca.transform(digits.data)
colors = [
    "#FF6347",  # 热带橙红
    "#00BFFF",  # 亮青绿色
    "#4682B4",  # 明亮的蓝宝石色
    "#BA55D3",  # 亮紫罗兰色
    "#FFD700",  # 亮金色
    "#FF0000",  # 纯红色
    "#ADD8E6",  # 浅亮蓝色
    "#00FF7F",  # 明亮的绿色
    "#0000CD",  # 高饱和度的蓝色
    "#FFA07A"   # 橙色沙拉
]

plt.figure(figsize=(10, 10))
plt.scatter(digits_pca[:, 0], digits_pca[:, 1], color='none', alpha=0.5)
for i in range(len(digits.data)):
    plt.text(digits_pca[i, 0], digits_pca[i, 1], str(digits.target[i]),
             color = colors[digits.target[i]], fontdict={'weight':'bold', 'size':9})
plt.xlabel("First principal component")
plt.ylabel("Second principal component")
plt.show()

其绘制的图像为:

3.2 KPCA

然后我们说KPCA,它是当数据为非线性时,即在高维空间中,数据的结构表现出复杂的非线性结构时,而可以去捕捉这些非线性关系的方法。其实,KPCA就是添加一个核函数给PVA后得到的,而这个核函数也是与KSVM(核支持向量机)的核函数类似的。

那么,在这里就不得不说明下核技巧核函数了。

核技巧(Kernel Trick

核技巧是一种用于处理高维数据的技术,尤其是在数据难以直接处理时。它允许我们在高维空间中进行计算,而无需显式地将数据映射到这个空间。核技巧的关键在于使用核函数来代替直接在高维空间中的运算。

其核心思想是:在原始数据空间中使用特定的函数来代替高维空间中的内积运算。

原理为:当有数据集X,然后将之映射到更高维度空间F,由非线性映射Φ:X -> F定义,然后对于任意两个数据点x_{i}x_{j}可以用核函数k(x_{i},x_{j})来计算,它在更高维F的内积为(\phi (x_{i}),\phi(x_{j})),从而不必知道不必知道映射Φ的具体形式或显式计算映射后的数据点。

核函数(Kernel Function)

核函数是一种用于计算两个数据点在高维空间中相似度的函数。它通过映射函数 ϕϕ 将数据点映射到高维空间,并计算它们在该空间中的内积(即相似度)。其形式为:K(x_{i},x_{j})=(\phi(x_{i}),\phi(x_{j}))

而常见的核有线性核、多项式核、高斯核与sigmoid核等。

那么接下来就来说明这个核函数是如何运用到PCA中的。

一般在传统的PCA中,步骤有五步,分别为:1.标准化数据;2.计算协方差矩阵;3.求解特征值和特征向量;4.选择主成分;5.映射数据。

但到来KPCA中,我们则有六步,分别为:1.选择核函数;2.构建核矩阵;3.中心化核矩阵,关于中心化处理用如下公式进行:

4.特征值分解;5.选择主成分;6.映射数据,对于一个新的数据点x,在新的主成分空间中表示为:

将上述PCA中的代码修改为KPCA的代码则为如下:

from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
from sklearn.decomposition import KernelPCA
from sklearn.preprocessing import StandardScaler

# 加载数据集
digits = load_digits()

# 数据集实例图像
fig, axes = plt.subplots(2, 5, figsize=(10, 5),
                         subplot_kw={'xticks':(), 'yticks':()})
for ax, img in zip(axes.ravel(), digits.images):
    ax.imshow(img)
plt.show()

# 数据预处理(标准化)
scaler = StandardScaler()
digits_scaled = scaler.fit_transform(digits.data)

# KPCA
kpca = KernelPCA(n_components=2, kernel="rbf", gamma=0.1)  # 调整gamma参数
kpca.fit(digits_scaled)
digits_kpca = kpca.transform(digits_scaled)

# 绘制降维后的数据
colors = [
    "#FF6347",  # 热带橙红
    "#00BFFF",  # 亮青绿色
    "#4682B4",  # 明亮的蓝宝石色
    "#BA55D3",  # 亮紫罗兰色
    "#FFD700",  # 亮金色
    "#FF0000",  # 纯红色
    "#ADD8E6",  # 浅亮蓝色
    "#00FF7F",  # 明亮的绿色
    "#0000CD",  # 高饱和度的蓝色
    "#FFA07A"   # 橙色沙拉
]

plt.figure(figsize=(10, 10))
plt.scatter(digits_kpca[:, 0], digits_kpca[:, 1], color='none', alpha=0.5)
for i in range(len(digits_scaled)):
    plt.text(digits_kpca[i, 0], digits_kpca[i, 1], str(digits.target[i]),
             color = colors[digits.target[i]], fontdict={'weight':'bold', 'size':9})
plt.xlabel("First principal component (KPCA)")
plt.ylabel("Second principal component (KPCA)")
plt.title("KPCA Visualization of Handwritten Digits")
plt.show()

画出的图像也变成了这样:

  

3.3 LDA

线性判别分析(Linear Discriminant Analysis, LDA)是一种用于分类和降维的技术,尤其适用于多类别分类问题。在降维中,它通过投影将高维数据映射到低维空间,同时保持两类间距最大化和类内距离最大化。

其原理就是:通过线性组合找到一个投影方向,使不同类别的样本在该方向上分离程度最大化,并使同类差异最小化。总的来说,其有四个步骤,分别为:1.计算类间散度矩阵S_{B};计算类内散度矩阵S_{W};3.求解优化问题;4.投影数据。

我们发现LDA与PCA是由一定相似性的,因为它们都通过线性变换来创建新的特征(主成分或判别函数),但它们在优化目标上不同,PCA是最大化数据在新坐标下的方差,而LDA则是最大化类别间的距离以及最小化类内距离。

在实际使用时,python代码可以是这样的:

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
import numpy as np

data = load_iris()
X = data.data
y = data.target

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 实例化
lda = LinearDiscriminantAnalysis(n_components=2)

# 训练
lda.fit(X_train, y_train)

# 降维
X_train_lda = lda.transform(X_train)
X_test_lda = lda.transform(X_test)

# 输出降维后的数据形状
print("Train set shape after LDA:", X_train_lda.shape)
print("Test set shape after LDA:", X_test_lda.shape)

其输出为:

Train set shape after LDA: (105, 2)
Test set shape after LDA: (45, 2) 

3.4 NMF

NMF(Non-negative Matrix Factorization,非负矩阵分解的原理是:对于给定的一个非负矩阵V,NMF去找到两个非负矩阵W和H,使得V\approx WH。其中W矩阵称为基矩阵,H矩阵称为系数矩阵。

如下代码是将一个人脸识别的数据集提取基矩阵并绘图:

import os
import glob
from PIL import Image
import numpy as np
from sklearn.decomposition import NMF
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# 导入人脸图像
all_path = r"C:\Users\20349\Desktop\ArtificialIntelligence\ML\kaggle\人脸识别数据集"
image_paths = glob.glob(os.path.join(all_path, '*.jpg'))
target_size = (128, 128)
convert_mode = 'RGB'
first_image = Image.open(image_paths[0]).convert(convert_mode)
image_shape = first_image.size

images = []
labels = []

for idx, path in enumerate(image_paths):
    img = Image.open(path).convert(convert_mode)
    images.append(np.array(img))
    labels.append(idx)

image_array = np.array(images)
image_array = image_array.astype('float32') / 255.0
flattened_images = image_array.reshape(image_array.shape[0], -1)

X_train, X_test, y_train, y_test = train_test_split(
    flattened_images, labels, test_size=0.2, random_state=42
)

# NMF 处理
nmf = NMF(n_components=15, random_state=42)
nmf.fit(X_train)
X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test)

# 可视化
fig, axes = plt.subplots(3, 5, figsize=(15, 12), subplot_kw={'xticks': (), 'yticks': ()})
for i, (component, ax) in enumerate(zip(nmf.components_, axes.ravel())):
    ax.plot(component)
    ax.set_title(f"{i}.component")
plt.show()

画出的图为:

3.5 FA

因子分析的基本思想是假设观测变量由一些潜在的、不可观测的因子通过线性组合加上一定的随机误差构成。具体来说,假设有 pp 个观测变量 X1,X2,…,Xp​,因子分析假设这些变量可以表示为:

X=\mu +LF+\varepsilon

其中,X 是一个 p 维的观测变量向量,μ 是一个 p 维的均值向量,L 是一个 p×m 的因子载荷矩阵(factor loading matrix),其中 m<p,F 是一个 m 维的潜在因子向量,ϵ 是一个 p 维的误差向量,通常假定 ϵ 服从独立正态分布,且与 F 不相关。

因子分析可以分为两类,分别为:探索性因子分析与验证性因子分析。

代码如下:

import numpy as np
import pandas as pd
from sklearn.decomposition import FactorAnalysis
import matplotlib.pyplot as plt

# 生成模拟数据
np.random.seed(42)
n_samples = 1000
n_features = 5
X = np.random.randn(n_samples, n_features)

# 应用因子分析
fa = FactorAnalysis(n_components=2)
X_fa = fa.fit_transform(X)

# 可视化结果
plt.figure(figsize=(10, 6))
plt.scatter(X_fa[:, 0], X_fa[:, 1], alpha=0.5)
plt.xlabel("Factor 1")
plt.ylabel("Factor 2")
plt.title("Factor Analysis Result")
plt.show()

最终图像为:

3.6 MDS

多维尺度分析(Multidimensional Scaling, MDS)是一种统计技术,用于可视化高维数据的距离信息或相似度信息。它的主要目的是在低维空间中寻找数据点的位置,使得这些位置之间的距离能够反映原始数据的距离或相似度。

基本原理:MDS是通过某种方式将数据点映射到低维空间,从而在视觉上就可以观察数据点间的关系。

MDS主要分为两类:经典MDS(即Torgerson-Gower MDS)与非度量MDS。前者基于矩阵代数(特别是特征值分解)来解决距离保持问题。而后者更关注于保持数据点之间距离的顺序关系,而不是精确的距离值。经典MDS适用于从原始数据计算得到的相似度矩阵,而非度量MDS则通常用于类别数据或者当原始数据不是直接的距离时使用,它试图保持距离的等级而非绝对数值。

一般来说,MDS有四步,分别为:1.构造矩阵D;2.求中心化距离矩阵B,其中先计算D^{2},再求B=-\frac{1}{2}HD^{2}H,式子中H=I_{n}-\frac{1}{n}1_{n}1_{n}^{T}I_{n}表示单位矩阵,1_{n}表示全为1的n维列向量);3.特征值分解,其中用到式子B=U\Lambda U^T(U表示特征向量矩阵,λ表示对角线上的特征值矩阵);4.选择主成分,会选择k个最大特征值对应的U_{k}\Lambda _{k},然后计算X = U_{k}\sqrt{\Lambda _{k}}

用代码举个例子为:

from sklearn.manifold import MDS
import numpy as np
import matplotlib.pyplot as plt

# 假设我们有一个距离矩阵
distance_matrix = np.array([[0, 1, 2],
                           [1, 0, 1],
                           [2, 1, 0]])

# 实例化
mds = MDS(n_components=2, metric=True, max_iter=3000, eps=1e-9, random_state=123,
          dissimilarity="precomputed", n_jobs=1)

# 拟合
pos = mds.fit(distance_matrix).embedding_

# 可视化
plt.figure()
plt.scatter(pos[:, 0], pos[:, 1])
for label, x, y in zip(["A", "B", "C"], pos[:, 0], pos[:, 1]):
    plt.annotate(label, xy=(x, y), xytext=(-5, 5), textcoords='offset points')
plt.show()

其输出图像为: 

最后这个二维的图表就表示之前那个3*3的距离矩阵二维后的大小。 

3.7 Isomap

ISOMAP(Isometric Mapping,等距映射)是一种非线性降维技术,它属于流形学习方法之一。这种技术主要用于将高维的数据映射到低维空间中,同时保持数据点之间的相对距离不变。ISOMAP的主要思想是利用数据点之间的最短路径距离(即测地线距离)来构建低维嵌入,从而更好地保留原始数据中的内在几何结构。

其步骤主要为四步:1.临近图构建;最短路径计算(可以用著名的Dijkstra算法或Floyd算法);3.运用MDS算法;4.特征值分解。

我们用三维的“瑞士卷”数据集举例,代码如下:

import numpy as np
from sklearn.datasets import make_swiss_roll
from sklearn.manifold import Isomap
import matplotlib.pyplot as plt

# 生成瑞士卷数据集
X, _ = make_swiss_roll(n_samples=1000, noise=0.05)

# 实例化 ISOMAP 类
isomap = Isomap(n_neighbors=10, n_components=2)

# 拟合并转换数据
X_isomap = isomap.fit_transform(X)

# 可视化结果
plt.figure(figsize=(10, 8))
plt.scatter(X_isomap[:, 0], X_isomap[:, 1], c=X[:, 0], cmap=plt.cm.Spectral)
plt.title("ISOMAP of the Swiss Roll dataset")
plt.colorbar().set_label('z value')
plt.show()

图像如下,我们观察它可以发现其中每个点的颜色反映了原始数据集的位置:

 

3.8 LLE

LLE(Locally Linear Embedding,局部线性嵌入)是一种用于非线性降维的流形学习方法。LLE 的目标是在低维空间中保持数据点之间的局部关系,即将每个数据点表示为其最近邻点的线性组合。这种方法特别适合处理那些具有非线性结构的数据集。

其步骤有四步:1.构建邻域图;2.计算权重矩阵W;3.构造拉普拉斯矩阵L;4.特征值分解。我们详细看第二三步:首先在计算权重矩阵W时,对于每个数据点x_{i}找到一组权重w_{ij},使得x_{i}可以由其最近邻点通过线性组合得到,而使得x_{i}\approx \sum_{j\in N(i)}^{}w_{ij}x_{ij}。其中,权重w_{ij}通常通过最小化目标函数来确定,这个目标函数为:min\sum_{i=1}^{N}||x_{i}-\sum_{j\in N(i)}w_{ij}x_{j}||^2,同时约束条件为:\sum_{j\in N(i)} w_ij = 1。然后是第三步的拉普拉斯矩阵L,L=(I-W)^T(I-W),I为单位矩阵。

LLE 有几种不同的变种,包括但不限于标准 LLE(Standard LLE)、修改的 LLE(Modified LLE)、Hessian LLE 和 Local Tangent Space Alignment(LTSA)等。

同样,还是用“瑞士卷”数据集来举例子,代码如下:

from sklearn.datasets import make_swiss_roll
from sklearn.manifold import LocallyLinearEmbedding
import matplotlib.pyplot as plt

# 生成瑞士卷数据集
X, _ = make_swiss_roll(n_samples=1000, noise=0.05)

# 实例化 LLE 类
lle = LocallyLinearEmbedding(n_neighbors=10, n_components=2, method='standard')

# 拟合并转换数据
X_lle = lle.fit_transform(X)

# 可视化结果
plt.figure(figsize=(10, 8))
plt.scatter(X_lle[:, 0], X_lle[:, 1], c=X[:, 0], cmap=plt.cm.Spectral)
plt.title("LLE of the Swiss Roll dataset")
plt.colorbar().set_label('z value')
plt.show()

其图像为: 

3.9 t-SNE

t-SNE(t-Distributed Stochastic Neighbor Embedding,t-分布随机近邻嵌入)是一种常用的非线性降维技术,主要用于数据可视化。t-SNE 的核心思想是将高维空间中的数据点映射到低维空间(通常是二维或三维),同时保持数据点之间的相似度。具体来说,t-SNE 在高维空间中计算数据点之间的概率分布,在低维空间中计算相应的概率分布,并通过优化低维空间中的布局来最小化这两个分布之间的差异。

其步骤有三步,分别为:1.计算高维空间中的相似度;2.计算低维空间的相似度;3.优化布局。详细看,在第一步中,对于每一个数据点x_i我们计算其与其他数据点间的相似度通常来使用高斯核来计算,而形成一个条件概率P_{j|i},表示数据点x_{i }是数据点x_{j}的邻居的概率。而为了确保对称性,需要计算联合概率P_{ij}=\frac{P_{j|i}+P_{i|j}}{2n};然后在计算低维空间的相似度时要用到student分布(即t分布)。

同样,还是用“瑞士卷”数据集来举例子,代码如下:

import numpy as np
from sklearn.datasets import make_swiss_roll
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt

# 生成瑞士卷数据集
X, _ = make_swiss_roll(n_samples=1000, noise=0.05)

# 实例化 t-SNE 类
tsne = TSNE(n_components=2, perplexity=30, learning_rate=200, n_iter=1000, random_state=42)

# 拟合并转换数据
X_tsne = tsne.fit_transform(X)

# 可视化结果
plt.figure(figsize=(10, 8))
plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=X[:, 0], cmap=plt.cm.Spectral)
plt.title("t-SNE of the Swiss Roll dataset")
plt.colorbar().set_label('z value')
plt.show()

绘制的图像为: 

此上 

标签:digits,plt,矩阵,降维,算法,九种,import,数据,sklearn
From: https://blog.csdn.net/2301_79096986/article/details/142685923

相关文章

  • 【优选算法】(第二十八篇)
    目录K个⼀组翻转链表(hard)题目解析讲解算法原理编写代码两数之和(easy)题目解析讲解算法原理编写代码K个⼀组翻转链表(hard)题目解析1.题目链接:.-力扣(LeetCode)2.题目描述给你链表的头节点head,每k个节点⼀组进⾏翻转,请你返回修改后的链表。k是⼀个正整数,它的值⼩......
  • 【开题报告】基于Springboot+vue基于协同过滤算法的网上书城(程序+源码+论文) 计算机毕
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,电子商务已成为人们日常生活中不可或缺的一部分,其中网上书城作为知识传播与文化传播的重要平台,其用户群体日益庞大且需求多......
  • 【STL详解】STL标准模板库入门 | STL版本 | STL六大组件 | STL优点 | 常用STL容器vect
    目录1、概述1.1、C++标准库1.2、Boost开源库2、STL版本2.1、HP原始版本2.2、P.J.实现版本2.3、RW实现版本2.4、SGI实现版本2.5、STLport实现版本3、STL的六大组件3.1、STL六大组件构成3.2、六大组件的交互关系4、STL优点5、STL常用容器vector、list......
  • 【算法】博弈论(C/C++)
    个人主页:摆烂小白敲代码创作领域:算法、C/C++持续更新算法领域的文章,让博主在您的算法之路上祝您一臂之力欢迎各位大佬莅临我的博客,您的关注、点赞、收藏、评论是我持续创作最大的动力目录博弈论:1.Grundy数与Nim博弈Nim博弈规则:Grundy数的计算:例题:2.极大极小算法......
  • FTP连接池与多线程上传下载算法实现(C语言)
    FTP连接池与多线程上传下载算法实现(C语言)设计思路伪代码示例C代码示例为了避免多线程环境下FTP连接池在故障重连时导致的竞争条件和coredump问题,我们需要设计一个精细的连接池管理系统,确保在连接重连时,其他线程不会尝试使用该连接。以下是一个简化的设计思路和示......
  • 【开题报告+论文+源码】基于SpringBoot的过滤协同算法之网上服装商城设计与实现
    项目背景与意义随着互联网技术的飞速发展和普及,电子商务在全球范围内得到了迅猛的发展。特别是在中国,电子商务市场呈现出爆炸式的增长态势,成为推动经济发展的重要力量。其中,网上服装商城作为电子商务的一个重要分支,以其便捷、高效、多样的购物方式受到了广大消费者的青睐。与......
  • 代码随想录算法训练营第七天|第454题.四数相加II,383. 赎金信,第15题. 三数之和
    第454题.四数相加II文章链接:https://programmercarl.com/0454.四数相加II.html视频讲解:https://www.bilibili.com/video/BV1Md4y1Q7Yh/题目链接:https://leetcode.cn/problems/4sum-ii/description/题目思路:首先定义一个unordered_map,key放a和b两数之和,value放a和b两数之......
  • 【算法】记忆化搜索
    【ps】本篇有5 道 leetcode OJ。 目录一、算法简介二、相关例题1)斐波那契数.1-题目解析.2-代码编写2)不同路径.1-题目解析.2-代码编写3)最长递增子序列.1-题目解析.2-代码编写4)猜数字大小II.1-题目解析.2-代码编写5)矩阵中的最长递增路径.1-题......
  • 代码随想录算法训练营第八天| 151.翻转字符串里的单词
    151.翻转字符串里的单词文章链接:https://programmercarl.com/0151.翻转字符串里的单词.html#思路视频链接:https://www.bilibili.com/video/BV1uT41177fX/?vd_source=6cb513d59bf1f73f86d4225e9803d47b题目链接:https://leetcode.cn/problems/reverse-words-in-a-string/classS......
  • 面试淘天集团大模型算法工程师, 开心到飞起!!!
    应聘岗位:淘天集团-大模型算法工程师面试轮数:整体面试感觉:1.自我介绍在自我介绍环节,我清晰地阐述了个人基本信息、教育背景、工作经历和技能特长,展示了自信和沟通能力。2.技术问题2.1在大模型微调过程中,评价指标是怎样设定的?在大模型微调过程中,评价指标的设定是......