LDA在多分类、降维中的应用以及python实现

问题引入

现有三种鸢尾花分别标为0,1,2类,存在4种不同的属性,即萼片长(setosa),萼片宽(versicolor),花瓣长与花瓣的宽度,现在需要对这三种鸢尾花的分布在二维平面中进行可视化分析。数据来自于sklearn中的dataset部分数据。

萼片长萼片宽花瓣长花瓣的宽度类别
5.13.51.40.20.0
4.93.01.40.20.0
4.73.21.30.20.0
7.03.24.71.41.0
6.43.24.51.51.0
6.93.14.91.51.0
6.33.36.02.52.0
5.82.75.11.92.0
7.13.05.92.12.0
6.32.95.61.82.0

高维数据进行可视化分析,常用思路是对数据进行降维。


符号说明

n n n表示列属性的个数。
x i \textbf{x}_i xi为nx1的列向量,在表格中代表一个不包括类别属性的行。
c = 0 , 1 , ⋯   , k , ⋯ c={0,1,\cdots,k,\cdots} c=0,1,,k,表示类别的集合,对应上述表格中的0、1。
m k m^k mk表示类别为c的样本总个数。
X k \textbf{X}^k Xk表示类别k组成的矩阵,大小为 m k × n m^k\times{n} mk×n
x i k , k ∈ c \textbf{x}_i^k,k\in{c} xik,kc为nx1列向量,在表格中表示类别为k的属性行。
m = ∑ k ∈ c m k m=\sum_{k\in{c}}{m^k} m=kcmk表示所有样本数。
θ \theta θ表示位于直线 l l l上的nx1的单位列向量。


前情提要

线性判别分析在二分类的应用中,我们有类内距离为
θ T S w θ = θ T ∑ k ∈ c ∑ i = 1 m k ( x i k − u k ) ( x i k − u k ) T θ \theta^T\textbf{S}_w\theta=\theta^T\sum_{k\in{c}}\sum_{i=1}^{m^k}(\textbf{x}_i^k-u^k)(\textbf{x}_i^k-u^k)^T\theta θTSwθ=θTkci=1mk(xikuk)(xikuk)Tθ
在看很多资料的时候,会发现人们习惯于直接定义类内散度为
S w = ∑ k ∈ c ∑ i = 1 m k ( x i k − u k ) ( x i k − u k ) T \textbf{S}_w=\sum_{k\in{c}}\sum_{i=1}^{m^k}(\textbf{x}_i^k-u^k)(\textbf{x}_i^k-u^k)^T Sw=kci=1mk(xikuk)(xikuk)T
然后再定义类内散度
S b = ( u 0 − u 1 ) ( u 0 − u 1 ) T \textbf{S}_b=(\textbf{u}^0-\textbf{u}^1)(\textbf{u}^0-\textbf{u}^1)^T Sb=(u0u1)(u0u1)T
最后再在散度两边乘以直线向量 θ \theta θ得到映射后的类内距离与类间距离,这种定义初次看来毫无实际意义,但是熟悉PCA以及LDA的二分类之后,就发现这种定义方法所代表数学意义很有用,具体描述如下。
如果存在 Θ = ( θ 1 , θ 2 , . . . , θ i , . . . θ n ) \Theta=(\theta_1,\theta_2,...,\theta_i,...\theta_n) Θ=(θ1,θ2,...,θi,...θn)组成一个新的标准正交基,那么 Θ T S w Θ \Theta^T\textbf{S}_w\Theta ΘTSwΘ就是新的标准正交基下的类内散度矩阵。对于对角线上的元素代表位于直线向量 θ i \theta_i θi上的类内距离即 θ i S w θ i \theta_i\textbf{S}_w\theta_i θiSwθi
既然这种定义方式存在其意义,那么我们在本文中就采用这种直接定义散度矩阵的方式进行介绍。


推导过程

首先定义类内散度矩阵,与LDA的二分类一样
S w = ∑ k ∈ c ∑ i = 1 m k ( x i k − u k ) ( x i k − u k ) T (1) \textbf{S}_w=\sum_{k\in{c}}\sum_{i=1}^{m^k}(\textbf{x}_i^k-u^k)(\textbf{x}_i^k-u^k)^T\tag1 Sw=kci=1mk(xikuk)(xikuk)T(1)
再定义类间散度矩阵,与LDA稍微有些不同
S b = ∑ k 1 ∈ c ∑ k 2 ∈ c m k 1 m k 2 ( u k 1 − u k 2 ) ( u k 1 − u k 2 ) T = ∑ k ∈ c m k ( u k − u ) ( u k − u ) T (2) \begin{matrix} \begin{aligned} \textbf{S}_b&=\sum_{k_1\in{c}}\sum_{k_2\in{c}}m^{k1}m^{k2}(\textbf{u}^{k_1}-\textbf{u}^{k_2})(\textbf{u}^{k_1}-\textbf{u}^{k_2})^T\\ &=\sum_{k\in{c}}m^k(\textbf{u}^k-\textbf{u})(\textbf{u}^k-\textbf{u})^T \end{aligned} \end{matrix}\tag2 Sb=k1ck2cmk1mk2(uk1uk2)(uk1uk2)T=kcmk(uku)(uku)T(2)
其中
u = 1 m ∑ i = 1 m x i \textbf{u}=\frac{1}{m}\sum_{i=1}^{m}\textbf{x}_i u=m1i=1mxi
每个平均向量可以代表该类,将每个类之间的散度矩阵相加,可以表示总体的散度矩阵,这些倒还可以理解,肯定会有人质疑前面为什么加上系数,为什么不定义成 S b = ∑ k 1 ∈ c ∑ k 2 ∈ c ( u k 1 − u k 2 ) ( u k 1 − u k 2 ) T \textbf{S}_b=\sum_{k_1\in{c}}\sum_{k_2\in{c}}(\textbf{u}^{k_1}-\textbf{u}^{k_2})(\textbf{u}^{k_1}-\textbf{u}^{k_2})^T Sb=k1ck2c(uk1uk2)(uk1uk2)T形式,简单地阐述一下这种定义方式的合理性,我们知道二分类中定义成 S b = ( u 0 − u 1 ) ( u 0 − u 1 ) T \textbf{S}_b=(\textbf{u}^0-\textbf{u}^1)(\textbf{u}^0-\textbf{u}^1)^T Sb=(u0u1)(u0u1)T,前面没有系数, S b \textbf{S}_b Sb就算前面加系数也只不过是对矩阵等比例放大而已,对结果并不会产生任何影响,但是对于类别较多的数据就不一样了,比如说0类与1类的训练数据有100个,而2类的训练数据只有1个,那么再求解的过程中将权重更加偏向于那些数据集本身较多的类别会变得更加合理,所以 S b \textbf{S}_b Sb如此定义。
那么对于某个直线向量 θ \theta θ而言,类内距离为
θ T S w θ (3) \theta^T\textbf{S}_w\theta\tag3 θTSwθ(3)
类间距离为
θ T S b θ (4) \theta^T\textbf{S}_b\theta\tag4 θTSbθ(4)
求解目标仍然可以写为
arg ⁡ max ⁡ θ θ T S b θ θ T S w θ (5) \arg\max_{\theta}\frac{\theta^T\textbf{S}_b\theta}{\theta^T\textbf{S}_w\theta}\tag5 argθmaxθTSwθθTSbθ(5)
这种形式仍然可以用于分类,只不过是多分类罢了。
至于降维的应用,实际上还是需要数学理论的支持,首先明确一点,当数据从高维降到低维之后,各个维度之间一定是正交的,而且数据的特征会尽可能地被保留,LDA既然可以分类肯定可以保留特征,那么下面的推导就是证明LDA求解出来的多个极值解 θ i \theta_i θi之间是正交的直线罢了。
具体内容见LDA二分类,构造拉格朗日求极值,其中
J ( θ ) = θ T S w θ + λ ( θ T S b θ − t ) \textbf{J}(\theta)=\theta^T\textbf{S}_w\theta+\lambda(\theta^T\textbf{S}_b\theta-t) J(θ)=θTSwθ+λ(θTSbθt)
θ \theta θ求导=0之后可以得到
S b θ = λ S w θ \textbf{S}_b\theta=\lambda\textbf{S}_{w}\theta Sbθ=λSwθ
   ⟺    \iff
S w − 1 S b θ = λ θ (6) \textbf{S}_{w}^{-1}\textbf{S}_b\theta=\lambda\theta\tag{6} Sw1Sbθ=λθ(6)

此时, λ \lambda λ S w − 1 S b \textbf{S}_{w}^{-1}\textbf{S}_b Sw1Sb的特征值, θ \theta θ为对应的特征向量,根据特征向量的性质,对于不同的 λ i \lambda_i λi之间 θ i \theta_i θi肯定是正交的,那么对于相同的 λ \lambda λ可以通过斯密特正交化方法正交化单位化处理成正交的形式,现在LDA可以进行降维才得到了数学上的保证。
对于多个 θ \theta θ而言,选取哪一个 θ \theta θ作为降维后的轴与PCA一样需要看 λ \lambda λ取值,证明如下:
S w \textbf{S}_w Sw为实对称矩阵,那么存在
S w θ = t 1 θ \textbf{S}_w\theta=t_1\theta Swθ=t1θ
带入(6)中得到
S b θ = λ t 1 θ (7) \textbf{S}_b\theta=\lambda{t_1}\theta\tag7 Sbθ=λt1θ(7)
与PCA选取较大的 λ \lambda λ一样,此处不再累述,在公式(6)中有, λ t 1 \lambda{t}_1 λt1越大, θ T S b θ \theta^T\textbf{S}_b\theta θTSbθ越大,类间会越分散。
根据拉格朗日的约定条件 θ T S w θ = t \theta^T\textbf{S}_w\theta=t θTSwθ=t可以知道 t 1 t_1 t1为一个定值,且 t 1 = t t_1=t t1=t
所以, λ \lambda λ越大, θ T S b θ \theta^T\textbf{S}_b\theta θTSbθ越大,类间会越分散。
最终得到结论是选取 λ \lambda λ较大的矩阵。
那么对于降维而言,公式(5)就变成
arg ⁡ imax   θ T S b θ θ T S w θ (8) \arg \textbf{imax}\space\frac{\theta^T\textbf{S}_b\theta}{\theta^T\textbf{S}_w\theta}\tag8 argimax θTSwθθTSbθ(8)
其中imax代表求极值
求解方式与公式(6)一样,如下
S w − 1 S b θ = λ θ \textbf{S}_{w}^{-1}\textbf{S}_b\theta=\lambda\theta Sw1Sbθ=λθ
如果需要降维到d维,只需要求出前d个较大的 λ \lambda λ所对应的 θ \theta θ即可。


补充知识

1. 为什么求解公式定义成 arg ⁡ max ⁡ θ θ T S b θ θ T S w θ \arg\max_{\theta}\frac{\theta^T\textbf{S}_b\theta}{\theta^T\textbf{S}_w\theta} argθmaxθTSwθθTSbθ
却不直接定义成 arg ⁡ min ⁡ θ θ T S w θ θ T S b θ \arg\min_{\theta}\frac{\theta^T\textbf{S}_w\theta}{\theta^T\textbf{S}_b\theta} argθminθTSbθθTSwθ
实际上,求最小值的方式也对,利用拉格朗日求解之后就会发现, λ \lambda λ越小, θ T S w θ \theta^T\textbf{S}_w\theta θTSwθ越小,我们目标是求解类内距离最小,最终降维后选取的是前d个较小的 λ \lambda λ,与PCA结论恰好相反,可能为了方便记忆,故意写成第一个公式进行求解。
2. 公式(8)是本人根据自己理解写出的公式,实际上教材中的公式常常写作
arg ⁡ max ⁡ t r ( Θ T S b Θ ) t r ( Θ T S w Θ ) \arg\max\frac{tr(\Theta^T\textbf{S}_b\Theta)}{tr(\Theta^T\textbf{S}_w\Theta)} argmaxtr(ΘTSwΘ)tr(ΘTSbΘ)
Θ = ( θ 1 , θ 2 , . . . , θ i , . . . θ n ) \Theta=(\theta_1,\theta_2,...,\theta_i,...\theta_n) Θ=(θ1,θ2,...,θi,...θn)
这种写法比较简洁,但是对于刚刚入门的人而言可能有点难以理解,求迹就是求对角线和,等价于
arg ⁡ max ⁡ ∑ i = 1 n ( θ i T S b θ i ) ∑ i = 1 n ( θ i T S w θ i ) \arg\max\frac{\sum_{i=1}^n(\theta_i^T\textbf{S}_b\theta_i)}{\sum_{i=1}^n(\theta_i^T\textbf{S}_w\theta_i)} argmaxi=1n(θiTSwθi)i=1n(θiTSbθi)
写成拉格朗日的形式就会发现,对 θ i \theta_i θi求导,那么 θ j , i ≠ j \theta_j,i\neq{j} θj,i=j相当于是个常数,求导之后含有 θ j \theta_j θj的项变成0,结果不变。
3. 构造拉格朗日的时候,本人将分母写作常数t,很多教材都写作1,求导结果都一样,等于1的写法,是数学中的一个求解定理,需要拥有相应的数学知识才能立即反应过来,实际上 θ \theta θ是个直线,也就是说,不管是 θ \theta θ还是 t θ \sqrt{t}\theta t θ都是正确解,所以分母等于常数t还是等于1,都可以约掉,本人希望尽可能将数学知识限定在非数学系大学本科数学教学范围之内,不愿做过多的拓展,故意写作成常数t。


python代码

利用sklearn降维之后的图如下,代码来自于sklearn官方文档
在这里插入图片描述

import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

iris = datasets.load_iris()

X = iris.data
y = iris.target
target_names = iris.target_names

lda = LDA(n_components=2)
X_r2 = lda.fit(X, y).transform(X)

plt.figure()
for c, i, target_name in zip("rgb", [0, 1, 2], target_names):
    plt.scatter(X_r2[y == i, 0], X_r2[y == i, 1], c=c, label=target_name)
plt.legend()
plt.title('LDA of IRIS dataset')

plt.show()

下面是自己的python代码实现结果,虽然形式上有区别,但两者都可以区分三个不同种类

在这里插入图片描述
源码如下

from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
#有num个种类
#降到k维
def desc(num,k):
	iris = datasets.load_iris()
	xa = iris.data
	y = iris.target
	target_names = iris.target_names
	#所有元素的平均值
	ua=np.array([np.mean(xa,axis=0)])
	n=xa.shape[1]
	#存储x值
	x=[[]for i in range(num)]
	u=[[]for i in range(num)]
	sw=np.zeros([n,n])
	sb=np.zeros([n,n])
	for i in range(y.shape[0]):
		x[y[i]].append(xa[i])
	for i in range(num):
		x[i]=np.array(x[i])
		u[i]=np.array([np.mean(x[i],axis=0)])
	#去中心化,计算Sw
	for i in range(num):
		x[i]=x[i]-u[i]
		sw=sw+np.dot(x[i].T,x[i])
		sb=sb+x[i].shape[0]*np.dot((u[i]-ua).T,(u[i]-ua))
	#求Sw_1Sb的特征值与特征向量
	eig_value,eig_vec=np.linalg.eig(np.dot(np.linalg.inv(sw),sb))
	print(eig_vec)
	#对特征值进行排序,返回标号
	index=np.argsort(eig_value)
	#获取取最后k个特征向量
	eig_vec_k=eig_vec[:,index[:-k-1:-1]]
	colors=["r","g","b"]
	#绘图
	for i in range(xa.shape[0]):
		plt.scatter(np.dot(xa[i],eig_vec_k[:,0]),np.dot(xa[i],eig_vec_k[:,1]),color=colors[y[i]])
	plt.title("my LDA")
	plt.show()

desc(3,2)
  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: PythonLDA(Latent Dirichlet Allocation)是一种主题建模算法,可以用于将高维的数据降维到更低维的表示。降维是为了消除数据的冗余信息和噪声,以达到简化数据、提高模型性能、加快计算速度的目的。 使用PythonLDA降维,主要步骤如下: 1. 导入必要的库,如gensim、nltk等。 2. 准备数据集,将文本数据进行清洗、分词、去停用词等预处理步骤。 3. 利用gensim库LdaModel函数建立LDA模型。在建模过程,需要指定主题数、语料库、词典等参数。 4. 利用训练好的LDA模型对给定的数据进行降维,得到低维表示结果。 5. 可视化降维结果,通过绘制主题分布、主题词等图表,观察数据的潜在主题结构。 PythonLDA降维方法广泛应用于文本挖掘、信息检索、推荐系统等领域。通过降维,可以发现数据的潜在主题信息,提取关键词、主题分布等特征,帮助进一步分析和理解数据。同时,LDA降维可以简化数据表示,提高计算效率,便于后续建模和应用。 总之,PythonLDA降维是一种有效的数据处理方法,可以将高维的数据转化为低维表示,发现数据的潜在主题,并提取有用的特征。它在文本挖掘、信息检索等领域有广泛应用,为数据分析和建模提供了强有力的工具。 ### 回答2: Python LDA(Latent Dirichlet Allocation)是一种概率主题模型,它可以帮助我们将高维的数据降维到更低的维度。 在使用Python LDA进行降维时,首先需要将原始数据转化为文本格式。然后,我们可以使用Python的gensim库来构建LDA模型。为了训练模型,我们需要指定一些参数,比如主题的数量、迭代次数等。 训练完成后,可以使用LDA模型对新数据进行降维。我们可以使用模型的transform方法将原始数据映射到主题空间。这样,每个文档就会表示为一个向量,其每个维度代表一个主题。这个向量就是我们降维后的表示。 在降维后,我们可以使用这些主题向量进行进一步的分析。比如可以计算主题之间的相似度,或者对文档进行聚类。可以使用Python的sklearn库来实现这些操作。 总结来说,Python LDA可以帮助我们将高维数据降维到更低的维度。它可以将文本数据转化为主题向量表示,方便后续的分析任务。通过使用Python的gensim和sklearn库,我们可以方便地构建和应用LDA模型。 ### 回答3: Python LDA(Latent Dirichlet Allocation)是一种常用的主题模型算法,主要用于文本数据的降维和主题分析。降维是指将高维的文本数据映射到低维空间,以达到简化数据和提取数据特征的目的。 Python LDA降维的基本步骤如下: 1. 数据预处理:包括文本清洗、分词、去除停用词等。对文本数据进行预处理可以消除噪声和冗余信息,为后续的降维提供干净的数据。 2. 构建词袋模型:将预处理后的文本数据转化为数值向量表示。可以使用CountVectorizer或TfidfVectorizer等工具来构建词袋模型。 3. 使用LDA进行训练:采用Python的gensim库LdaModel类进行训练。通过调整主题数量,可以得到合理的主题分布。 4. LDA降维:通过主题-词分布和文档-主题分布,将原始的文本数据降维为主题向量。这种降维方式保留了文本数据的主题特征,减少了维度。 对于降维的结果,可以使用可视化工具如matplotlib绘制主题分布的图表,帮助我们理解文本数据的主题结构。 Python LDA降维在文本挖掘、文本分类、信息检索等领域具有广泛的应用。它能够从大量文本数据提取主题信息,并加以分析和利用。通过降维,我们可以在保留了关键信息的前提下,减少数据的复杂度,提高数据处理的效率和准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值