python实现线性判别分析 (LDA) 降维算法

2024-08-25 16:28

本文主要是介绍python实现线性判别分析 (LDA) 降维算法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1.线性判别分析 (LDA) 降维算法的Python实现

线性判别分析(Linear Discriminant Analysis,LDA)是一种常用的降维技术,特别适用于有监督的分类问题。它通过投影到较低维度空间,最大化类间方差并最小化类内方差,从而实现数据的线性分离。LDA 不仅降低了数据的维度,还保留了用于区分类别的信息,使其在分类问题中具有良好的表现。

2.LDA算法的基本思想

LDA旨在通过寻找一个将数据投影到的线性子空间,使得投影后的类间方差最大化,同时类内方差最小化。这样可以保证不同类别的样本在投影后尽可能分离,且同一类别的样本尽可能聚集。

2.1类间方差矩阵 S B S_B SB

类间方差矩阵 S B S_B SB 用于衡量不同类别的均值之间的散布程度。公式为:

S B = ∑ i = 1 k N i ( μ i − μ ) ( μ i − μ ) T S_B = \sum_{i=1}^{k} N_i (\mu_i - \mu)(\mu_i - \mu)^T SB=i=1kNi(μiμ)(μiμ)T

其中:

  • N i N_i Ni 表示第 i i i 类的样本数
  • μ i \mu_i μi 是第 i i i 类的均值向量
  • μ \mu μ 是所有样本的均值向量
  • k k k 是类别的数量
2.2类内方差矩阵 S W S_W SW

类内方差矩阵 S W S_W SW 用于衡量每个类别内部的样本散布程度。公式为:

S W = ∑ i = 1 k ∑ x ∈ C i ( x − μ i ) ( x − μ i ) T S_W = \sum_{i=1}^{k} \sum_{x \in C_i} (x - \mu_i)(x - \mu_i)^T SW=i=1kxCi(xμi)(xμi)T

其中:

  • x x x 表示每个样本
  • C i C_i Ci 表示第 i i i 类的样本集合
2.3优化目标

LDA的目标是找到一个投影矩阵 W W W,使得投影后的样本最大化类间方差和类内方差的比值:

W = argmax ∣ W T S B W ∣ ∣ W T S W W ∣ W = \text{argmax} \frac{|W^T S_B W|}{|W^T S_W W|} W=argmaxWTSWWWTSBW

通过求解该优化问题,LDA可以找到最优的投影矩阵,将高维数据投影到低维空间。

3.LDA的Python实现

接下来,我们使用面向对象编程(OOP)的思想在Python中实现LDA算法。我们将创建一个 LDA 类,包含训练模型、降维和预测功能。

import numpy as npclass LDA:def __init__(self, n_components=None):"""初始化LDA模型:param n_components: 降维后的目标维度,如果为None,则降至类别数-1的维度"""self.n_components = n_componentsself.means_ = Noneself.scalings_ = Noneself.explained_variance_ratio_ = Nonedef fit(self, X, y):"""训练LDA模型:param X: 输入数据矩阵,形状为 (n_samples, n_features):param y: 标签数组,形状为 (n_samples,)"""n_samples, n_features = X.shapeclasses = np.unique(y)n_classes = len(classes)if self.n_components is None:self.n_components = n_classes - 1# 计算总体均值mean_overall = np.mean(X, axis=0)# 初始化类内方差矩阵和类间方差矩阵S_W = np.zeros((n_features, n_features))S_B = np.zeros((n_features, n_features))for c in classes:X_c = X[y == c]mean_c = np.mean(X_c, axis=0)S_W += (X_c - mean_c).T @ (X_c - mean_c)n_c = X_c.shape[0]mean_diff = (mean_c - mean_overall).reshape(n_features, 1)S_B += n_c * (mean_diff @ mean_diff.T)# 求解广义特征值问题A = np.linalg.inv(S_W) @ S_Beigvals, eigvecs = np.linalg.eig(A)# 按照特征值的绝对值大小排序eigvecs = eigvecs[:, np.argsort(-np.abs(eigvals))]eigvals = eigvals[np.argsort(-np.abs(eigvals))]# 选择前n_components个特征向量self.scalings_ = eigvecs[:, :self.n_components]self.explained_variance_ratio_ = np.abs(eigvals[:self.n_components]) / np.sum(np.abs(eigvals))# 保存每个类别的均值self.means_ = {}for c in classes:self.means_[c] = np.mean(X[y == c], axis=0)def transform(self, X):"""将数据投影到LDA子空间:param X: 输入数据矩阵,形状为 (n_samples, n_features):return: 投影后的数据,形状为 (n_samples, n_components)"""return X @ self.scalings_def predict(self, X):"""使用LDA模型进行分类预测:param X: 输入数据矩阵,形状为 (n_samples, n_features):return: 预测标签,形状为 (n_samples,)"""X_projected = self.transform(X)preds = []for x in X_projected:distances = [np.linalg.norm(x - mean) for mean in self.means_.values()]preds.append(np.argmin(distances))return np.array(preds)def fit_transform(self, X, y):"""训练模型并返回投影后的数据:param X: 输入数据矩阵,形状为 (n_samples, n_features):param y: 标签数组,形状为 (n_samples,):return: 投影后的数据,形状为 (n_samples, n_components)"""self.fit(X, y)return self.transform(X)

4.代码解析

  1. 初始化

    • __init__ 方法初始化了LDA模型,包括目标维度 n_components,类均值 means_,特征向量 scalings_,以及解释方差比 explained_variance_ratio_
  2. 训练模型

    • fit 方法计算类内方差矩阵 S W S_W SW 和类间方差矩阵 S B S_B SB,并通过求解广义特征值问题找到投影矩阵 scalings_。同时,该方法保存每个类别的均值以便后续分类使用。
  3. 数据投影

    • transform 方法将输入数据投影到LDA子空间,返回降维后的数据。
  4. 预测分类

    • predict 方法将投影后的数据与每个类别的均值进行比较,基于欧氏距离进行分类预测。
  5. 训练并投影

    • fit_transform 方法结合了 fittransform,方便一次性完成训练和投影。

5.实际应用场景:手写数字识别

为了展示LDA的实际应用,我们使用手写数字数据集(如MNIST)来实现分类任务。这个数据集包含0-9的手写数字图像,通过LDA降维后,我们可以将其投影到2D或3D空间中进行可视化,并在低维空间中进行分类。

5.1数据准备

首先,我们从数据集中提取样本,并将图像展平为一维向量。

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler# 加载数据集
digits = load_digits()
X, y = digits.data, digits.target# 数据标准化
scaler = StandardScaler()
X = scaler.fit_transform(X)# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
5.2使用LDA降维

接下来,我们使用LDA将数据降维至2D,并可视化投影结果。

# 初始化LDA模型并进行训练
lda = LDA(n_components=2)
X_train_lda = lda.fit_transform(X_train, y_train)# 可视化LDA投影结果
import matplotlib.pyplot as pltplt.figure(figsize=(10, 6))
for i in range(10):plt.scatter(X_train_lda[y_train == i, 0], X_train_lda[y_train == i, 1], label=f'Class {i}')
plt.xlabel('LDA Component 1')
plt.ylabel('LDA Component 2')
plt.legend()
plt.title('LDA Projection of Digits Dataset')
plt.show()
5.3分类效果

最后,我们使用LDA进行分类,并评估模型的性能。

# 使用LDA进行分类预测
y_pred = lda.predict(X_test)# 计算准确率
from sklearn.metrics import accuracy_scoreaccuracy = accuracy_score(y_test, y_pred)
print(f'LDA Classification Accuracy: {accuracy:.4f}')

6.总结

通过LDA算法,我们可以在保证分类信息的前提下将高维数据投影到低维空间,从而减少计算复杂度并提高分类效率。本文展示了LDA的数学原理、Python实现以及在手写数字识别中的应用。通过面向对象编程的方式,我们实现了一个LDA类,集成了训练、投影和分类功能,便于在各种分类问题中应用LDA算法。

这篇关于python实现线性判别分析 (LDA) 降维算法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/1106052

相关文章

Python包管理工具pip的升级指南

《Python包管理工具pip的升级指南》本文全面探讨Python包管理工具pip的升级策略,从基础升级方法到高级技巧,涵盖不同操作系统环境下的最佳实践,我们将深入分析pip的工作原理,介绍多种升级方... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

在Linux中改变echo输出颜色的实现方法

《在Linux中改变echo输出颜色的实现方法》在Linux系统的命令行环境下,为了使输出信息更加清晰、突出,便于用户快速识别和区分不同类型的信息,常常需要改变echo命令的输出颜色,所以本文给大家介... 目python录在linux中改变echo输出颜色的方法技术背景实现步骤使用ANSI转义码使用tpu

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v