fisher线性判别算法python_干货|机器学习算法之线性判别分析

作者:just_sort

链接:https://blog.nowcoder.net/n/e668319c70b64fab945871e5ab6cc363

来源:牛客网

算法原理

在上文我们使用LDA实现了一个二分类任务。那么数据有大于2种类别,假设为C类,这时候怎么办呢?在上文我们定义的“类间散度矩阵”

就不再适用,所以我们这里引入“全局散度矩阵”:

其中muμ是所有示例的均值向量。将类内散度矩阵S_wSw​重定义为每个类别的散度矩阵之和,即:

从上面两个式

推得:

其中N代表类别数,m_imi​代表第i类的示例数。

关于这个等式的推导可以看南瓜书,我这里截图过来一下:

16b1892f0716ba203c62b865fbadfc40.png

这里偷了一张图,可以更好的理解这个算法。

500f54cee98ef8c23bd4f4af8f6f6d9f.png

显然,多分类LDA有多种实现方法:使用S_b,S_w,S_tSb​,Sw​,St​三者中的任意两个即可。常见一种实现是采用优化目标:

1f82439893ca399c0d6ad3eb5313c952.png

式3.35就是我们上篇博客写的“广义瑞利商”。其中的tr()为矩阵的迹,一个n×n的对角矩阵A的主对角线(从左上方至右下方的对角线)上各个元素的总和被称为矩阵A的迹(或迹数),一般记作tr(A)。

这个优化目标实际上等价于求解多个w组合成W,那么该问题就等价于求解多个上一章的优化目标,使用相同的方法,可以求得下式:

即是:

W的闭式解为

的d'个最大非零广义特征值对应的特征向量组成的矩阵,d'<=N-1d′<=N−1。

如果将W视为一个投影矩阵,则多分类LDA将样本投影到d'维空间,d'通常远小于数据的原有属性d'′。于是,可以通过这个投影来减小样本点的维数,且投影过程中使用了类别信息,因此LDA也常常被视为一种经典的监督降维技术。

接下来使用sklearn中的aris数据,并使用LDA算法对其进行降维,并可视化。

代码

#
coding = utf - 8
import numpy as np
from sklearn.datasets
import load_iris
import matplotlib.pyplot as plt# 这是sklearn中实现的LDA, 待会我们会比较自己实现的LDA和它的区别
from sklearn.discriminant_analysis
import LinearDiscriminantAnalysis

# k为目标
def LDA(X, y, k):
    label_ = list(set(y))
X_classify = {}
for label in label_:
    X1 = np.array([X[i]
        for i in range(len(X)) if y[i] == label
    ])
X_classify[label] = X1

miu = np.mean(X, axis = 0)
miu_classify = {}
for label in label_:
    miu1 = np.mean(X_classify[label], axis = 0)
miu_classify[label] = miu1

# St = np.dot((X - mju).T, X - mju)# 计算类内散度矩阵Sw
Sw = np.zeros((len(miu), len(miu)))
for i in label_:
    Sw += np.dot((X_classify[i] - miu_classify[i]).T, X_classify[i] - miu_classify[i])

# Sb = St - Sw# 计算类内散度矩阵Sb
Sb = np.zeros((len(miu), len(miu)))
for i in label_:
    Sb += len(X_classify[i]) * np.dot((miu_classify[i] - miu).reshape(
        (len(miu), 1)), (miu_classify[i] - miu).reshape((1, len(miu))))

# 计算S_w ^ {
    -1
}
S_b的特征值和特征矩阵
eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(Sw).dot(Sb))
sorted_indices = np.argsort(eig_vals)# 提取前k个特征向量
topk_eig_vecs = eig_vecs[: , sorted_indices[: -k - 1: -1]]
return topk_eig_vecs

def main():
    iris = load_iris()
X = iris.data
y = iris.target

W = LDA(X, y, 2)
X_new = np.dot(X, W)
plt.scatter(X_new[: , 0], X_new[: , 1], marker = 'o', c = y)
plt.show()

# 和sklearn的函数对比
lda = LinearDiscriminantAnalysis(n_components = 2)
lda.fit(X, y)
X_new = lda.transform(X)
plt.scatter(X_new[: , 0], X_new[: , 1], marker = 'o', c = y)
plt.show()


main()

降到二维的效果图

3685687887ddf9b450ad8d525bbb9c90.png

(我们实现的LDA算法的降维结果)

0ad43d3923939c1b5699692fb63aa486.png

可以看到使用LDA算法成功实现了多分类数据的降维。

查看作者更多博客:https://blog.nowcoder.net/bbuf

欢迎关注公众号:牛客NOIP竞赛学

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值