线性判别器LDA

ops/2024/10/11 13:28:10/

一、LDA的基础介绍

LDA是一种有监督的降维方法,和它比较类似的是PCA(一种无监督的降维方法),如果对PCA不熟悉的朋友可以看看下面关于PCA的介绍。

1、PCA介绍和基本思想

​ 主成分分析(PCA)是一种利用正交变换把由线性相关变量表示的观测数据转化为少数几个由线性无关变量表示的数据。

​ 在主成分分析中,首先对给定的数据进行规范化,使得数据的每一变量的平均值为0,方差为1。之后对数据进行正交变换,原来由线性相关变量表示的数据,通过正交变换变成若干个线性无关的新变量表示的数据,新变量是可能的正交变换中变量的方差最大的,方差表示在新变量上信息的大小,将变量依次成为第一主成分,第二主成分。

2、PCA的相关定义

总体主成分分析的定义:

1 系数向量  \alpha^{\top}_i  是单位向量,即 \alpha^{\top}_i\alpha_i=1

2 变量  y_i,y_j  不相关,协方差等于0

3 变量  y_1  是𝑥所有的线性变换中方差最大的,  y_2  是与  y_1  不相关的𝑥的所有线性变换中方差最大的。

主成分分析的求法

假设   X={x_1,x_2,...x_m}  是𝑚维随机变量,∑是𝑥协方差矩阵的,∑的特征值为  \lambda_1\ge\lambda_2\ge...\ge\lambda_m\ge0  ,特征值对应的单位向量分别是   \alpha_1,\alpha_2,...\alpha_m

则𝑥的第𝑘主成分是:
y_k=\alpha_k^{\top}x=\alpha_{1k}x_1+\alpha_{2k}x_2+...+\alpha_{mk}x_m
则𝑥的第𝑘主成分的方差是:
var(y_k)=E[(y_k-E(y_k))^2]=E[(\alpha^{\top}_kx-\alpha_k^{\top}u)^2]
其中𝑢=𝐸(𝑥),上式子为:

var(y_k)=E[(\alpha_k^{\top}(x-u))^2]=E[\alpha^{\top}_k(x-u)^2\alpha_k]

因此:

$var(y_k)=\alpha_k^{\top}\sum\alpha_k=\lambda_k$

简单地介绍完PCA之后我们回到LDA地介绍。LDA与PCA相似的地方在于都是降维方法,参考的都是方差。不同的是LDA是有监督的,LDA的降维是:在投影之后,同类别的数据内方差尽可能小,不同类别之间的方差尽可能大。如果是将所有样本的X(特征)投影在同一条直线的话,那么就是label相同的数据投影结果应该很接近,反之label不一样的数据投影结果应该远一点。说起来很抽象,我们可以看一下下图:

"+"和"-"是两种label的类别。图中的位置是数据的坐标(数据的X(特征)是二维的,可以直接在坐标上表示),现在我们需要将二维的数据投影到一维,这意味着我们要将其映射到一条直线上面。如上图所示,我们映射到一条直线上面,同时保证:"+","-"类别内部所有的数据投影后结果比较靠近,"+"数据与"-"数据投影后离得较远。很明显,映射到不同的直线就有不同的结果:

为什么我们要做LDA?

降维最直观的目的是减少数据维度,这样可以减少内存花销和计算时间。但是,降维的目的不仅仅是降维,我们需要信息不能损失。如上所示,当我们数据是二维的时候,我们需要分类的话,很容易使用逻辑回归做一个分类器。但是当我们降维到一维之后,我们的信息肯定有了一定的损失,但是对于我们将降维后的数据进行分类的话,尽量不减少分类精度。简单来说:就是又要速度,又要精度。有时候经过降维还能起到人为增加误差,防止过拟合的作用。

有这么好的事情嘛?在一些情况下确实有:比如上图右侧将二维数据映射到一维后,我们很容易区分哪些数据为蓝色,哪些数据为红色。

二、LDA模型介绍以及推导

我们怎么保证某条直线是最优的。或者我们怎么求出最优的直线。如果在更高维度中,我们怎么得到一个映射关系?

1、LDA二分类的介绍

既然是直接的映射关系,我们可以定义  y=w^Tx  为。当𝑥的维度为2时,就是我们上面图的情况,我们需要找一个𝑤方向(也就是通过y=w^Tx将x映射成y,截距是无关紧要的)的直线来进行投影。所以我们需要找一个𝑤使得映射后满足要求。

假设我们数据集  D={(x_1,y_1),(x_2,y_2),(x_3,y_3),...(x_m,y_m)}  ,其实任意样本  y_i\in{0,1}  。我们定义  N_j=(j=0,1)  为第𝑗类样本的个数。  X_j(j=0,1)  为第𝑗类样本的集合。我们可以有:

均值  u_j  为:
$u_j=\frac{1}{N_j}\sum_{x \in X_j}w^Tx$

方法  \sum_j  的表达式为:
$\sum_j = \sum_{x\in X_j}(x-u_j)(x-u_j)^T$
其中𝑗=(0,1)。

由于我们只需要分别两类,最好的分类方法就是将其投影到一条直线即可。我们使用𝑤进行投影。此时,投影后的均值为:

$\hat u_j=\frac{1}{N_j}\sum_{x \in X_j}w^Tx=w^Tu_j$
同理方差为:

$\hat {\sum_{j}}=w^T \sum_j w$

我们的目标是:同类之间均值尽可能地大,即:
  $||w^Tu_0-w^Tu_1||_2^2$  最大化
同类之间方差尽可能地小,即:
  $w^T \sum_0 w+w^T \sum_1 w$  最小化

综上所述:可以定义我们的优化目标为:

J(w)=\frac{||w^T-u_0-w^Tu_1||_2^2}{w^T \sum_0 w+w^T \sum_1 w}=\frac{w^T(u_0-u_1)(u_0-u_1)^Tw}{w^T(\sum_0+\sum_1)w}

一般我们定义:

$S_w=\sum_0+\sum_1=\sum_{x \in X_0}(x-u_0)(x-u_0)^T+\sum_{x \in X_1}(x-u_1)(x-u_1)^T$
为"类内散度矩阵"

$S_b=(u_0-u_1)(u_0-u_1)^T$
为"类间散度矩阵"

因此我们可以将J(w)可以表示为:

J(w)=\frac{w^TS_bw}{w^TS_ww}

由于分子分母都是𝑤的二次项,因此最后的结果和𝑤的大小无关(假设𝑤是最优解,那么𝛼𝑤也一定是最优解)。所以我们可以令:
$w^TS_ww=1$
于是我们的优化目标为:

min -w^TS_bw

s.t -w_{T}S_{w}w = 1

由拉格朗日乘子法:

F(w)=-w^TS_bw+\lambda (w^TS_ww-1)

𝐹(𝑤)对𝑤求导:

\frac{\partial(F(w))}{\partial dw}=-2S_bw+2\lambda S_w w=0

我们可以发现:  $S_bw=(u_0-u_1)(u_0-u_1)^Tw$  可以发现  $(u_0-u_1)^Tw$  是一个常数,我们可以设  $\alpha=(u_0-u_1)^Tw$  。于是我们将上面的公式替换为:

  $\alpha(u_0-u_1)=\lambda S_w w$  ,

于是:

$S_w w=\frac{\alpha}{\lambda}(u_0-u_1)=>w=\frac{\alpha}{\lambda}S_w^{-1}(u_0-u_1)$    。

由于  $S_w,(u_0-u_1)$  都是已知量,所有以我们可以直接求出𝑤。(由于我们只要求得𝑤的方向即可, $\frac{\alpha}{\lambda}$   常数可以忽略不记,因为w无论乘以任何一个不为0的常数都是我们所求的解。)

注: $S_w$   不是任何时候都有逆向量的,这时候可以根据SVD求得。

2、推广到多分类

当类别为多个时:

S_b=\sum_{i,j|i\neq j}[(u_i-u_j)(u_i-u_j)^T]

有时候我们也可以写作这样:

S_b=\sum_{i=1}^C {n_i(u_i-u)(u_i-u)^T}

其中𝑢为所以样本平均值,  u_i  为i类别样本平均值,  n_i  为i类别样本个数。两种计算方式的结果是成比例的。但是第二种方式计算的复杂度更低,因此我们常用第二种方式。

S_w=\sum_{i}[\sum_{x \in X_i}(x-u_i)(x-u_i)^T]

最优公式为:

J(W)=\frac{W^TS_bW}{W^TS_wW}

根据上文的推导,我们有:

S_w^{-1}S_b W=\lambda W

假设我们有:  $W=[w_1,w_2,..w_k]$  (k的维度是降维后的维度)。那么很有趣的是  w_i  为矩阵  S_w^{-1}S_b  的特征向量。于是我们需要求的矩阵𝑊为矩阵的  S_w^{-1}S_b  的前k个特征向量。(关于特征向量的这里就不再介绍了)

三、LDA的代码

import numpy as np
from sklearn import datasetsfrom sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_splitX = datasets.load_iris()['data']
Y = datasets.load_iris()['target']class LDA:def __init__(self, k_after):"""x:         样本xy:         样本yn_i:      第i类样本的个数u_i:      第i类样本均值,格式为{i:[]}n_label:  样本的类别k_after:   降维后的维度k_before:  降维前的维度]labels:    不同的类别,比如[1,2,3]"""self.n_i = {}self.u_i = {}self.k_after = k_afterself.k_before = X.shape[0]self.labels = Noneself.sigmas = {}self.S = None  # S_wself.B = None  # S_bself.w = Nonedef fit(self, X, y):self.n = len(np.unique(y))self.n_label = len(set(y))labels = np.unique(y)self.labels = labelsN = X.shape[0]  # 样本的个数means = []for label in labels:tmp = np.mean(X[y == label], axis=0)  ##第i类的平均u_imeans.append(tmp)self.u_i[label] = tmp  ##记录第i类样本的均值self.n_i[label] = len(X[y == label])   #记录第i类样本的个数if len(labels) == 2:tmp = (means[0] - means[1])tmp = tmp.reshape(-1, 1)  # 转化为(k_before,1)维度的列向量B = np.dot(tmp, tmp.T)  # (u[0]-u[1])(u[0]-u[1])^Telse:mean_all = np.mean(X, axis=0)B = np.zeros((X.shape[1], X.shape[1]))for label in self.u_i:n_i = self.n_i[label]tmp = self.u_i[label] - mean_alltmp = tmp.reshape(-1, 1)B += n_i * np.dot(tmp, tmp.T)S = np.zeros((X.shape[1], X.shape[1]))for label in self.u_i:u_i = self.u_i[label]for row in X[y == label]:tmp = (row - u_i)tmp = tmp.reshape(-1, 1)S += np.dot(tmp, tmp.T)self.S = SS_inv = np.linalg.inv(S)  # 矩阵S_w的逆S_inv_B = S_inv @ B  # S_w*Bdiag, p = np.linalg.eig(S_inv_B)  ## 特征值,特征向量ind = diag.argsort()[::-1]  ##按照特征值大小排序diag = diag[ind]w = p[:, ind]  # 按照特征值大小将特征向量排序self.w = w[:, :self.k_after]def predict(self, x):x = np.asarray(x)return np.dot(x, self.w)model = LDA(2)
model.fit(X, Y)
X2=model.predict(X)
将数据X,Y映射到一维或者2维的结果如下图所示:
model = LDA(2)
model.fit(X, Y)
X2=model.predict(X)model2 = LDA(1)
model2.fit(X, Y)
X3=model2.predict(X)colors = ['red', 'green', 'blue']
fig, ax = plt.subplots(figsize=(10, 8))
for i in range(len(X)):point=X2[i]pred=Y[i]ax.scatter(point[0], point[1], color=colors[pred], alpha=0.5)ax.scatter(X3[i][0], X3[i][0], color=colors[pred], alpha=0.5)# ax.scatter(proj[0], proj[1], color=colors[pred], alpha=0.5)
plt.show()

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
lda = LDA(n_components=2)#设置转换后的维度
X2 = lda.fit_transform(X,Y)

http://www.ppmy.cn/ops/123517.html

相关文章

获取时隔半个钟的三天

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

服务器源IP暴露后的安全风险及防御措施

在互联网安全领域&#xff0c;服务器的源IP地址泄露可能成为黑客攻击的切入点。本文将列举十种常见的攻击类型&#xff0c;并提供相应的防御建议&#xff0c;帮助管理员们更好地保护服务器免受潜在威胁。 一、引言 服务器源IP地址的暴露意味着攻击者可以直接针对服务器发起攻击…

浅谈2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者

目录 1.概述 1.1. 跨学科的融合 1.2. 推动科学研究的工具 1.3. 对科学界的激励 1.4. 技术的社会影响 2.机器学习与神经网络的发展前景 2.1.具体应用与作用 2.1.1. 医疗健康 2.1.2. 金融 2.1.3. 制造业 2.1.4. 交通与物流 2.1.5. 零售 2.2.未来展望 2.3.科学研究与…

U mamba配置问题;‘KeyError: ‘file_ending‘

这个错误仍然是因为在 dataset_json 中找不到 file_ending 键。请尝试以下步骤&#xff1a; 检查 JSON 文件&#xff1a;确认 JSON 文件中确实有 file_ending&#xff0c;并且它的拼写完全正确。 打印 JSON 内容&#xff1a;在抛出异常之前&#xff0c;添加打印语句输出 datas…

红帽操作系统Linux基本命令2( Linux 网络操作系统 06)

本文接着上篇Linux常用命令-1继续往后学习其他常用命令。 2.3 目录操作类命令 1&#xff0e;mkdir命令 mkdir命令用于创建一个目录。该命令的语法为&#xff1a; 上述目录名可以为相对路径&#xff0c;也可以为绝对路径。 mkdir命令的常用参数选项如下。 -p&#xff1a;在创…

红黑树学习

红黑树: k v 方式 用在哪里&#xff1a; 1.hash 强查找的过程&#xff1a; 1.rbtree 2.hash 3.b/b tree 4.链表 红黑树&#xff1a; 1.每个结点是红的或者是黑的 2.根结点是黑的 3.每个叶子结点是黑的 4.如果一个结点是红的&#xff0c;则它的两个儿子是黑的 5.对每个节点&…

【AGC005D】~K Perm Counting(计数抽象成图)

容斥原理。 求出f(m) &#xff0c;f(m)指代至少有m个位置不合法的方案数。 怎么求&#xff1f; 注意到位置为id&#xff0c;权值为v ,不合法的情况&#xff0c;当且仅当 v idk或 v id-k 因此&#xff0c;我们把每一个位置和权值抽象成点 &#xff0c;不合法的情况之间连一…

Sequelize 做登录查询数据

在 Sequelize 中处理登录请求通常意味着你需要根据提供的用户名或电子邮件以及密码来查询数据库中的用户。由于密码在数据库中应该是以哈希形式存储的&#xff0c;因此你还需要验证提供的密码是否与存储的哈希密码匹配。 以下是一个简单的例子&#xff0c;展示了如何使用 Sequ…