目录
LDA的基本思想是将给定数据集投影到一条直线上,使得同类样本的投影点尽可能接近、异类样本投影点尽可能疏远。数学语言上看,即训练样本内的类内散度尽可能小,类间散度尽可能大
线性判别分析( l i n e a r linear linear d i s c r i m i n a n t discriminant discriminant a n a l y s i s analysis analysis, L D A LDA LDA)是一种经典的线性分类方法,其基本思想是 将数据投影到低维空间,使得 同类数据尽可能地接近,异类数据尽可能地疏远
一、LDA基本思想
- 线性判别分析的基本思想
- 将给定数据集投影到一条直线上,使得同类样本的投影点尽可能接近,异类样本的投影点尽可能疏远
- 按此规则训练完模型后,将新的样本投影到该直线上,根据投影点的位置来确定新样本点的类别
-
L
D
A
LDA
LDA模型二维示意图
- ➕代表正例,➖代表反例,虚线代表样本点到直线的投影,圆点代表两类投影的中心点- L D A LDA LDA的优化目标就是使投影后的类内距离小,类间距离大
二、LDA数学推导
给定数据集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) … ( x m , y m ) } D=\{(x_1,y_1),(x_2,y_2)\ldots (x_m,y_m)\} D={(x1,y1),(x2,y2)…(xm,ym)}, y i ∈ { 0 , 1 } y_i \in \{0,1\} yi∈{0,1},令 X i X_i Xi 、 μ i \mu_i μi和 ∑ i \sum_i ∑i分别为第 i ∈ { 0 , 1 } i \in \{0,1\} i∈{0,1}类数据的集合、均值向量和协方差矩阵。
- 假设将上述数据投影到直线 w w w上,则两类样本的中心在直线上的投影分别为 w T μ 0 w^T \mu_0 wTμ0和 w T μ 1 w^T \mu_1 wTμ1
- 考虑所有样本投影的情况下,假设两类样本的协方差分别为 w T ∑ 0 w w^T \sum_0w wT∑0w和 w T ∑ 1 w w^T \sum_1 w wT∑1w
- 直线 w w w为一维空间
- 上述值均为实数
(一)LDA优化目标求解
两个优化目标:
- 同类样本的投影点尽可能相近
- 同类样本投影点的协方差尽可能小,即 w T ∑ 0 w + w T ∑ 1 w w^T \sum_0w+w^T \sum_1w wT∑0w+wT∑1w尽可能小
- 异类样本的投影点尽可能疏远,使类中心点之间的距离尽可能远,即
∥
w
T
μ
0
−
w
T
μ
1
∥
2
2
\|w^T\mu_0-w^T\mu_1\|_2^2
∥wTμ0−wTμ1∥22尽可能大
最大化目标函数
-
F
=
∥
w
T
μ
0
−
w
T
μ
1
∥
2
2
w
T
∑
0
w
+
w
T
∑
1
w
=
w
T
(
μ
0
−
μ
1
)
(
μ
0
−
μ
1
)
T
w
w
T
(
∑
0
+
w
T
∑
1
)
w
(007-1)
F=\frac{\|w^T\mu_0-w^T\mu_1\|^2_2}{w^T\sum_0w+w^T\sum_1w}=\frac{w^T(\mu_0-\mu_1)(\mu_0-\mu_1)^Tw}{w^T(\sum_0+w^T\sum_1)w}\tag{007-1}
F=wT∑0w+wT∑1w∥wTμ0−wTμ1∥22=wT(∑0+wT∑1)wwT(μ0−μ1)(μ0−μ1)Tw(007-1)
- 定义类内散度矩阵: S w = ∑ 0 + ∑ 1 S_w=\sum_0+\sum_1 Sw=∑0+∑1
- 定义类间散度矩阵: S b = ( μ 0 − μ 1 ) ( μ 0 − μ 1 ) T S_b=(\mu_0-\mu_1)(\mu_0-\mu_1)^T Sb=(μ0−μ1)(μ0−μ1)T
-
L
D
A
LDA
LDA优化目标可由式
(
007
−
1
)
(007-1)
(007−1)改写为:
- F = w T S b w w T S w w (007-2) F=\frac{w^TS_bw}{w^TS_ww}\tag{007-2} F=wTSwwwTSbw(007-2)
- 进一步将式
(
007
−
2
)
(007-2)
(007−2)转换为约束优化问题:令
w
T
S
w
w
=
1
w^TS_ww=1
wTSww=1,则
- m i n − w T S b w s . t . w T S w w = 1 (007-3) \begin{split}min\ -w^TS_bw\\ s.t. \ w^TS_ww=1 \end{split}\tag{007-3} min −wTSbws.t. wTSww=1(007-3)
- 利用拉格朗日乘子法,将式
(
007
−
3
)
(007-3)
(007−3)转换为:
- S b w = λ S w w S_bw=\lambda S_ww Sbw=λSww
- 令
S
b
=
λ
(
μ
0
−
μ
1
)
S_b=\lambda(\mu_0-\mu_1)
Sb=λ(μ0−μ1),代入:
-
w
=
S
w
−
1
(
μ
0
−
μ
1
)
w=S_w^{-1}(\mu_0-\mu_1)
w=Sw−1(μ0−μ1)
- 考虑到
S
w
S_w
Sw矩阵数值解的稳定性,一般可以对其进行奇异值分解:
-
S w = U ∑ V T S_w=U\sum V^T Sw=U∑VT
- 假设我们的矩阵
S
w
S_w
Sw是一个
m
×
n
m×n
m×n的矩阵
- U U U是一个 m × m m×m m×m的矩阵
- ∑ \sum ∑是一个 m × n m×n m×n的矩阵,除了主对角线上的元素以外全为0,主对角线上的每个元素都称为奇异值
- V V V是一个 n × n n×n n×n的矩阵
- 奇异值分解定义图
- 假设我们的矩阵
S
w
S_w
Sw是一个
m
×
n
m×n
m×n的矩阵
-
对奇异值分解后的矩阵求逆即可得到 S w − 1 S_w^{-1} Sw−1
-
- 考虑到
S
w
S_w
Sw矩阵数值解的稳定性,一般可以对其进行奇异值分解:
-
w
=
S
w
−
1
(
μ
0
−
μ
1
)
w=S_w^{-1}(\mu_0-\mu_1)
w=Sw−1(μ0−μ1)
(二)完整LDA算法流程
- 对训练集按类别进行分组
- 分别计算每组样本的均值和协方差
- 计算类间散度矩阵 S w S_w Sw
- 计算两类样本的均值差 μ 0 − μ 1 \mu_0 - \mu_1 μ0−μ1
- 对类间散度矩阵 S w S_w Sw进行奇异值分解,并求其逆
- 根据 S w − 1 ( μ 0 − μ 1 ) S_w^{-1}(\mu_0-\mu_1) Sw−1(μ0−μ1)得到 w w w
- 最后计算投影后的数据点 Y = w X Y=wX Y=wX
二、LDA算法的代码实现
(一)编写思路
(二)基于Numpy的代码实现
1、定义LDA类
- 定义一个LDA类,其中包含权重矩阵的初始化、协方差矩阵计算方法的定义、数据投影方法的定义、LDA拟合和分类预测方法的定义。LDA的拟合方法是当中的核心部分。
- 代码部分
# 导入numpy 库
import numpy as np
### 定义LDA类
class LDA:
def _init_(self):
# 初始化权重矩阵
self.w = None
# 协方差矩阵计算方法
def calc_cov(self,X,Y=None):
m = X.shape[0]
# 数据标准化
X = (X - np.mean(X,axis=0))/np.std(X,axis=0)
Y = X if Y == None else (Y - np.mean(Y,axis=0))/np.std(Y,axis=0)
return 1/m * np.matmul(X.T,Y)
# 数据投影方法
def project(self,X,y):
# LDA拟合获取模拟权重
self.fit(X,y)
# 数据投影
X_projection = X.dot(self.w)
return X_projection
# LDA拟合方法
def fit(self,X,y):
# 按类分组
X0 = X[y == 0]
X1 = X[y == 1]
# 分别计算两类数据自变量的协方差矩阵
sigma0 = self.calc_cov(X0)
sigma1 = self.calc_cov(X1)
# 计算类内散度矩阵
Sw = sigma0 + sigma1
# 分别计算两类数据自变量的均值和差
u0,u1 = np.mean(X0,axis=0),np.mean(X1,axis=0)
mean_diff = np.atleast_1d(u0 - u1)
# 对类内散度矩阵进行奇异值分解
U,S,V = np.linalg.svd(Sw)
# 计算类内散度矩阵的逆
Sw_ = np.dot(np.dot(V.T,np.linalg.pinv(np.diag(S))),U.T)
# 计算w
self.w = Sw_.dot(mean_diff)
# LDA分类预测
def predict(self,X):
# 初始化预测结果为空列表
y_pred = []
# 遍历待预测样本
for x_i in X:
# 模型预测
h = x_i.dot(self.w)
y = 1 * (h < 0)
y_pred.append(y)
return y_pred
2、LDA算法的数据测试
- 使用 s k l e a r n sklearn sklearn的 i r i s iris iris数据集对模型进行测试,加载数据集后,筛选标签,仅取标签为0或1的数据,然后将数据集划分为训练集和测试集。然后创建 L D A LDA LDA模型实例,拟合训练集并对测试集进行预测,最后得到测试集上的分类准确率。
- 数据集剖析
import pandas as pd
iris_df = pd.DataFrame(data.data, columns=data.feature_names)
iris_df['species'] = [data.target_names[i] for i in data.target]
iris_df['species_label'] = data.target
iris_df
- 代码部分
# 导入相关库
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 导入iris数据集
data = datasets.load_iris()
# 数据与标签
X,y = data.data,data.target
# 取标签不为2的数据
X = X[y != 2]
y = y[y != 2]
# 划分训练集和测试集
X_train, X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=41)
# 创建LDA模型实例
lda = LDA()
# LDA模型拟合
lda.fit(X_train,y_train)
# LDA模型预测
y_pred = lda.predict(X_test)
# 测试集上的分类准确率
acc = accuracy_score(y_test,y_pred)
print('Accuracy of Numpy LDA:',acc)
- 基于Numpy的LDA模型分类准确度为0.85
(三)基于sklearn的模型实现
- s k l e a r n sklearn sklearn的 L i n e a r R e g r e s s i o n LinearRegression LinearRegression类同样可以实现这一效果, L i n e a r R e g r e s s i o n LinearRegression LinearRegression函数位于 s k l e a r n sklearn sklearn的 l i n e a r _ m o d e l linear\_model linear_model模块下,定义该类的一个线性回归实例后,直接调用其 f i t fit fit方法拟合训练集即可。
- 使用和上面一样的训练集和测试集
# 导入 LinearDiscriminantAnalysis模块
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# 创建LDA实例
clf = LinearDiscriminantAnalysis()
# 模型拟合
clf.fit(X_train,y_train)
# 模型预测
y_pred = clf.predict(X_test)
# 测试集上的分类准确率
acc = accuracy_score(y_test,y_pred)
print('Accuracy of sklearn LDA:',acc)
- 训练效果:
- 准确度为1.0