fisher判别分析原理+python实现

参考资料:

判别分析是一种经典的现行分析方法,其利用已知类别的样本建立判别模型,对未知类别的样本进行分类。在这里我们主要讨论fisher判别分析的方法。

fishter原理

费歇(FISHER)判别思想是投影,使多维问题简化为一维问题来处理。选择一个适当的投影轴,使所有的样品点都投影到这个轴上得到一个投影值。对这个投影轴的方向的要求是:使每一类内的投影值所形成的类内离差尽可能小,而不同类间的投影值所形成的类间离差尽可能大。

公式推导

这里给出一个二维的示意图(摘自周志华老师的《机器学习》一书),在接下来的讨论中我们也将以二维的情况做分类来逐步分析原理和实现。
摘自周志华老师的机器学习
ps: 图中有一处描述似乎不是特别的准确,直线的方程应该是

0=wTx

而不是
y=wTx

ps: 因为在书关于此的其他讨论中,并未涉及任何y的概念,这里将y写入对我造成了某种误导。

对于给定的数据集,D(已经设置好分类标签), Xi,Ui,i 分别表示给定类别 i 的集合,均值向量,协方差矩阵。现将数据投影到直线x=0 上,则样本中心的投影为 0=w1u1+w2u2++wnun 。(n 为样本维度,接下来的讨论中将统一设置为2),写成向量形式则为 wTu=0 如果将所有的样本都投影到直线上,则两类样本的协方差分别为 wT0wwT1w 。要想达到较好的分类效果,应该是的同类样本的投影点尽可能的接近,也就是让同类样本投影点的协方差尽可能的小。即 (wT0w+wT0w) 尽可能小。同时也应该保证不同类样本投影点尽可能的互相远离,即 wTu0wTu1 尽可能大。如果同时考虑两者的关系可以得到下面需要最大化的目标:

J=wTu0wTu1wT0w+wT0w

这里定义“类内散度矩阵”(within-class scatter matrix)
Sw=0+1=xX0(xu0)(xu0)T+xX1(xu1)(xu1)T

以及类间离散度矩阵(between-class scatter matrix)
Sb=(u0u1)(u0u1)T

J 可重写为:
J=wTSbwwTSww

ps:sorry 这些公式确实敲得有点累,道个歉,我直接截图了。希望不影响大家的理解。

这里写图片描述

在推导出上面的公式之后我们就可以开始写代码了。

编程实现

数据生成

这里我偷一个懒,直接用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

fisher算法实现


def cal_cov_and_avg(samples):
    """
    给定一个类别的数据,计算协方差矩阵和平均向量
    :param samples: 
    :return: 
    """
    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):
    """
    fisher算法实现(请参考上面推导出来的公式,那个才是精华部分)
    :param c_1: 
    :param c_2: 
    :return: 
    """
    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)

判定类别

def judge(sample, w, c_1, c_2):
    """
    true 属于1
    false 属于2
    :param sample:
    :param w:
    :param center_1:
    :param center_2:
    :return:
    """
    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)

绘图

import matplotlib.pyplot as plt

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()

最后一步【贴图】
这里写图片描述

最后的最后,大家只要把上面所有的代码复制粘贴到一个文件夹下,在python3 环境下运行就好了。本人调试运行的环境为:

  • python3
  • ubuntu 16.04
  • pycharm
  • 42
    点赞
  • 228
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
### 回答1: Fisher线性判别是一种经典的分类算法,它可以将数据影到一个低维空间中,从而实现分类。在Python中,可以使用scikit-learn库来实现Fisher线性判别。具体实现步骤如下: 1. 导入需要的库: ```python from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score ``` 2. 生成数据集: ```python X, y = make_classification(n_samples=100, n_features=10, n_classes=2, random_state=42) ``` 3. 划分训练集和测试集: ```python X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.2, random_state=42) ``` 4. 训练模型: ```python lda = LinearDiscriminantAnalysis() lda.fit(X_train, y_train) ``` 5. 预测测试集: ```python y_pred = lda.predict(X_test) ``` 6. 计算准确率: ```python accuracy = accuracy_score(y_test, y_pred) print("Accuracy:", accuracy) ``` 以上就是Fisher线性判别的Python实现步骤。 ### 回答2: Fisher线性判别(Fisher Linear Discriminant,简称FLD)又叫做Fisher判别分析Fishers Discriminant Analysis,简称FDA),是一种常用的分类方法。其主要目的是将p维数据降到k维(k<p),以便于分类。Fisher线性判别最早是由1936年英国统计学家Ronald A. Fisher提出的,其思想是寻找一组影变换,使得变换后的数据能够更好地区分不同的类别。 在Python实现Fisher线性判别,可以使用Scikit-learn包中的LinearDiscriminantAnalysis类。这个类可以用于分类问题,也可以用于降维问题中,具体用法如下: 1. 导入相关库: from sklearn.datasets import make_classification from sklearn.discriminant_analysis import LinearDiscriminantAnalysis import matplotlib.pyplot as plt 2. 生成模拟数据: X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_redundant=0, n_classes=2, random_state=42) 3. 对数据进行FLD降维: lda = LinearDiscriminantAnalysis(n_components=1) X_lda = lda.fit_transform(X, y) 4. 可视化结果: fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10,5)) ax[0].scatter(X[:, 0], X[:, 1], c=y) ax[0].set_title('Original Data') ax[1].scatter(X_lda[:, 0], [0]*len(X_lda), c=y) ax[1].set_title('LDA Data') plt.show() 在上述代码中,首先使用make_classification函数生成一个二分类的模拟数据,然后使用LinearDiscriminantAnalysis类对数据进行FLD降维。最后通过可视化结果对比原始数据和FLD降维后的数据,从而看出降维的效果。 总体来说,Fisher线性判别是一种比较常用的降维方法,它可以帮助我们提高分类的精度,同时也可以减少运算的时间和空间复杂度。在Python实现Fisher线性判别非常方便,只需要导入Scikit-learn包中的LinearDiscriminantAnalysis类,并使用该类提供的函数即可实现。 ### 回答3: Fisher线性判别是一种二分类算法,主要用于对数值型数据进行分类。它的目标是找到一个线性影,将样本点从高维特征空间射到低维空间,在低维空间中进行分类。该算法的核心思想是将样本点影到一条直线上,使得不同类别的样本点在影后的结果中尽可能分开。具体步骤如下: 1. 将样本集按类别分开,得到两个类别的样本矩阵 X1 和 X2。 2. 分别求出两个类别的样本均值向量。m1 = mean(X1),m2 = mean(X2)。 3. 计算两个类别的散度矩阵 S1 和 S2。S1 = (X1 - m1) * (X1 - m1).T,S2 = (X2 - m2) * (X2 - m2).T。 4. 计算类内散度矩阵 Sw = S1 + S2。 5. 计算影向量 w,使得类内散度矩阵 Sw 最小,类间散度矩阵 Sb 最大。w = inv(Sw) * (m1 - m2)。 6. 将样本点 X 分别影到直线 w 上,得到低维空间的样本点 Y = w.T * X。 7. 根据低维空间的 Y 值进行分类。 以下是 Fisher 线性判别的 Python 代码实现: ```python import numpy as np class Fisher: def __init__(self): self.w = None def fit(self, X, y): # 按类别分离样本 X1 = X[y==0] X2 = X[y==1] # 计算样本均值向量 m1 = np.mean(X1, axis=0) m2 = np.mean(X2, axis=0) # 计算类内散度矩阵 Sw 和类间散度矩阵 Sb Sw = np.cov(X1.T) + np.cov(X2.T) Sb = np.outer(m1 - m2, m1 - m2) # 计算影向量 w self.w = np.linalg.inv(Sw).dot(m1 - m2) def predict(self, X): # 将样本点影到直线上 Y = X.dot(self.w.T) # 根据低维空间的值进行分类 return (Y > 0).astype(int) ``` 在这段代码中,我们使用了 numpy 库的 cov 函数计算样本协方差矩阵,还使用了 dot 函数计算影向量和矩阵乘法。通过 fit 函数训练模型,predict 函数进行预测,我们可以很方便地实现 Fisher 线性判别算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值