python代码完成Fisher判别

发布于 2020-05-05  84 次阅读


一.算法描述

Fisher线性判别分析的基本思想:选择一个投影方向(线性变换,线性组合),将高维问题降低到一维问题来解决,同时变换后的一维数据满足每一类内部的样本尽可能聚集在一起,不同类的样本相隔尽可能地远。
Fisher线性判别分析,就是通过给定的训练数据,确定投影方向W和阈值w0, 即确定线性判别函数,然后根据这个线性判别函数,对测试数据进行测试,得到测试数据的类别。
线性判别函数的一般形式可表示成 :
在这里插入图片描述
其中
在这里插入图片描述
Fisher选择投影方向W的原则,即使原样本向量在该方向上的投影能兼顾类间分布尽可能分开,类内样本投影尽可能密集的要求。 如下为具体步骤:

(1)W的确定

各类样本均值向量mi
在这里插入图片描述
样本类内离散度矩阵 和总类内离散度矩阵
在这里插入图片描述
样本类间离散度矩阵
在这里插入图片描述
在投影后的一维空间中,各类样本均值
在这里插入图片描述
样本类内离散度和总类内离散度
在这里插入图片描述
样本类间离散度
在这里插入图片描述
Fisher准则函数为
在这里插入图片描述

(2)阈值的确定

是个常数,称为阈值权,对于两类问题的线性分类器可以采用下属决策规则:
令 则:
在这里插入图片描述

如果g(x)>0,则决策x属于w1 ;如果g(x)<0,则x属于w2 ;如果g(x)=0,则可将x任意分到某一类,或拒绝。

(3)Fisher线性判别的决策规则

Fisher准则函数满足两个性质:
1.投影后,各类样本内部尽可能密集,即总类内离散度越小越好。
2.投影后,各类样本尽可能离得远,即样本类间离散度越大越好。
根据这个性质确定准则函数,根据使准则函数取得最大值,可求出
在这里插入图片描述

这就是Fisher判别准则下的最优投影方向。
最后得到决策规则

在这里插入图片描述

在这里插入图片描述

对于某一个未知类别的样本向量x,如果y=WT·x>y0,则x∈w1;否则x∈w2。

二.数据描述

1.iris数据

IRIS数据集以鸢尾花的特征作为数据来源,数据集包含150个数据集,有4维,分为3 类,每类50个数据,每个数据包含4个属性,是在数据挖掘、数据分类中非常常用的测试集、训练集。

2.sonar数据

Sonar数据集包含208个数据集,有60维,分为2类,第一类为98个数据,第二类为110个数据,每个数据包含60个属性,是在数据挖掘、数据分类中非常常用的测试集、训练集。

“群内离散度”要求的是距离越远越好;而“群间离散度”的距离越近越好

三.python代码

1.数据生成

scikit-learn的接口来生成数据:

from sklearn.datasets import make_multilabel_classification
import numpy as np

x, y = make_multilabel_classification(n_samples=20, n_features=2,
                                      n_labels=1, n_classes=1,
                                      random_state=2)  # 设置随机数种子,保证每次产生相同的数据。

# 根据类别分个类
index1 = np.array([index for (index, value) in enumerate(y) if value == 0])  # 获取类别1的indexs
index2 = np.array([index for (index, value) in enumerate(y) if value == 1])  # 获取类别2的indexs

c_1 = x[index1]   # 类别1的所有数据(x1, x2) in X_1
c_2 = x[index2]  # 类别2的所有数据(x1, x2) in X_2

2.fisher算法实现

def cal_cov_and_avg(samples):
    u1 = np.mean(samples, axis=0)
    cov_m = np.zeros((samples.shape[1], samples.shape[1]))
    for s in samples:
        t = s - u1
        cov_m += t * t.reshape(2, 1)
    return cov_m, u1
def fisher(c_1, c_2):
    cov_1, u1 = cal_cov_and_avg(c_1)
    cov_2, u2 = cal_cov_and_avg(c_2)
    s_w = cov_1 + cov_2
    u, s, v = np.linalg.svd(s_w)  # 奇异值分解
    s_w_inv = np.dot(np.dot(v.T, np.linalg.inv(np.diag(s))), u.T)
    return np.dot(s_w_inv, u1 - u2)

3.判定类别

def judge(sample, w, c_1, c_2):
    u1 = np.mean(c_1, axis=0)
    u2 = np.mean(c_2, axis=0)
    center_1 = np.dot(w.T, u1)
    center_2 = np.dot(w.T, u2)
    pos = np.dot(w.T, sample)
    return abs(pos - center_1) < abs(pos - center_2)
w = fisher(c_1, c_2)  # 调用函数,得到参数w
out = judge(c_1[1], w, c_1, c_2)   # 判断所属的类别
print(out)

4.绘图

在jupyter下面绘制需要添加以下代码:

%matplotlib inline

这样才能在当前的jupyter下显示出图片

import matplotlib.pyplot as plt
%matplotlib inline
plt.scatter(c_1[:, 0], c_1[:, 1], c='#99CC99')
plt.scatter(c_2[:, 0], c_2[:, 1], c='#FFCC00')
line_x = np.arange(min(np.min(c_1[:, 0]), np.min(c_2[:, 0])),
                   max(np.max(c_1[:, 0]), np.max(c_2[:, 0])),
                   step=1)

line_y = - (w[0] * line_x) / w[1]
plt.plot(line_x, line_y)
plt.show()

运行结果:
在这里插入图片描述

四.理解和心得

Fisher判别法是判别分析的方法之一。Fisher判别法是一种投影方法,把高维空间的点向低维空间投影。在原来的坐标系下,可能很难把样品分开,而投影后可能区别明显。一般说,可以先投影到一维空间(直线)上,如果效果不理想,在投影到另一条直线上(从而构成二维空间),依此类推。每个投影可以建立一个判别函数。

五.参考链接

没有显示图片问题解决方案
fisher判别分析原理+python实现
波波