fisher线性判别算法python_Fisher线性判别(LDA)python实现

LDA概述

首先,LDA是一个用于分类的有监督算法。

基本想法非常质朴,不失一般性的以二维平面二分类为例:

对于两类样本点,我们的目的是想找一条直线,将两类样本点映射到这条直线上时,使这两类之间的类间间距最大,类内间距最小。

图形上的直观理解如下。

对于第一张图,不同类映射到同一条直线上时出现混叠区域,难以判别类别。

对于第二张图,不同类映射到同一条直线上时没有混叠,分界鲜明(类间间距最大),且同一类内部样本距离样本中心点较近(类内间距最小)

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第1张图片

推导

不想看的可跳过,毕竟现在都是直接调包(不过建议看下,可以深入理解算法,并且再次体会数学的美妙)

整个算法的推导是一个数学上很优美的过程,详细过程如下。

注意:在模式识别中,所有向量都是m×1形式。

定义类均值向量:

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第2张图片

类内散度矩阵:

d70d031debcadaaae97f06a4c082e462.png

物理意义上理解:就是各样本到自己所属类别中心点的欧式距离平方的和

类间散度矩阵:

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第3张图片

物理意义上理解:就是两类样本中心点的欧式距离的平方

假设我们已经找到最优的那条直线,将其记为向量u’

则新的(y1, y2)可以由下式得到:

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第4张图片

同理,计算出新的Sw和Sb

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第5张图片

则按照LDA最初始的想法,我们想让投影得到的类间距离最大,类内距离最小,我们可以构造下面这个函数:

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第6张图片

即最大化该函数(在特征选择中也称该函数为JF判据,属于基于类内类间距离选择特征的一种判据)

接下来就是常规操作了,求导求极值

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第7张图片

注意其中最后一步中的 α 是代换掉了倒数第二个公式中的最后两项向量的内积(可轻易证明其内积为一常数)且 λ 也为常数(亦可证得)

因为向量的大小不影响方向,所以直线向量可摒弃前面的常系数

所以决策域可表示为

fisher线性判别算法python_Fisher线性判别(LDA)python实现_第8张图片

算法总结

计算两类的均值向量

计算总类内散度阵

计算总类内散度阵的逆

按照 u 的计算公式求解 u

计算投影过后的两类的均值向量

计算分类阈值

对未知模式 x 判决模式类

可以看出,整个算法就是在进行数学运算,所以LDA是一个数学上非常优美的算法。

应用方向

作为特征抽取的技术

可以提高数据分析过程中的计算效率

对于不适用与正则化的模型,可以降低因维度灾难带来的过拟合

算法实现(python)

因为其数学过于优美,理解其思路后计算机编程实现非常简单

函数实现:

import numpy as np

def LDA(x, y): # x: all the input vector y: labels

x_1 = np.array([x[i] for i in range(len(x)) if y[i] == 1])

x_2 = np.array([x[i] for i in range(len(x)) if y[i] == -1])

mju1 = np.mean(x_1, axis=0) # mean vector

mju2 = np.mean(x_2, axis=0)

sw1 = np.dot((x_1 - mju1).T, (x_1 - mju1)) # Within-class scatter matrix

sw2 = np.dot((x_2 - mju2).T, (x_2 - mju2))

sw = sw1 + sw2

return np.dot(np.linalg.inv(sw), (mju1 - mju2))

测试:

import numpy as np

import matplotlib.pyplot as plt

import LDA

mean_1 = (-5, 0)

mean_2 = (5, 0)

cov = [[1, 0],

[0, 1]]

size = 200

np.random.seed(1)

x_1 = np.random.multivariate_normal(mean_1, cov, size)

np.random.seed(2)

x_2 = np.random.multivariate_normal(mean_2, cov, size)

x = np.vstack((x_1, x_2))

y = [-1] * 200 + [1] * 200

plt.scatter(x_1[:, 0], x_1[:, 1], color='blue', marker='o', label='Positive')

plt.scatter(x_2[:, 0], x_2[:, 1], color='red', marker='x', label='Negative')

plt.legend(loc='upper left')

plt.title('Original Data')

w = LDA.LDA(x, y)

x1 = 1

y1 = -1 / w[1] * (w[0] * x1)

x2 = -1

y2 = -1 / w[1] * (w[0] * x2)

plt.plot([x1, x2], [y1, y2], 'r')

plt.show()

print(w)

网络原因结果图传不上去了,先这样吧,代码可以直接运行,我写的时候写成了两个文件,你们稍微改下调用时代码即可。

你可能感兴趣的:(fisher线性判别算法python_Fisher线性判别(LDA)python实现)