2022 12月5日 LDA 学习笔记

​ 线性判别分析(Linear Discriminant Analysis)在图像识别领域应用广泛。这里LDA需要和自然语言处理中的隐含狄利克雷分布(Latent Dirichlet Allocation,简称LDA)区别开来。

​ 官方介绍:将一个高维空间中的数据投影到一个较低维的空间中,且投影后要保证各个类别的类内方差小而类间均值差别大

​ 和PCA的差距在于不要求投影后信息量最大,而是区分度最大,这也是主成分分析的不足之处。两种算法的选取需要看使用者的需求。

详细计算推导视频

详细推导博客

  • 类间距离散度SB和类内距离散度SW

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x4en9TZj-1670196219611)(LDA.assets/image-20221205070456906-0195100.png)]

  • 结论:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k9kBs8z5-1670196219612)(LDA.assets/image-20221205070637434.png)]

LDA算法计算步骤:

对d维数据进行标准化处理(d为特征数量)
对每一类别,计算d维的均值向量
构造类间的距离矩阵和类内的散度矩阵
计算矩阵的特征值和对应的特征向量
选取前k个特征值对应的特征向量,构造一个d x k维的转换矩阵W,特征向量以列的形式排列
使用转换矩阵W将样本映射到新的特征子空间上

代码一

import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

def lda(data, target, n_dim):
    '''
    :param data: (n_samples, n_features)
    :param target: data class
    :param n_dim: target dimension
    :return: (n_samples, n_dims)
    '''

    clusters = np.unique(target)

    if n_dim > len(clusters)-1:
        print("K is too much")
        print("please input again")
        exit(0)

    #within_class scatter matrix
    Sw = np.zeros((data.shape[1],data.shape[1]))
    for i in clusters:
        datai = data[target == i]
        datai = datai-datai.mean(0)
        Swi = np.mat(datai).T*np.mat(datai)
        Sw += Swi

    #between_class scatter matrix
    SB = np.zeros((data.shape[1],data.shape[1]))
    u = data.mean(0)  #所有样本的平均值
    for i in clusters:
        Ni = data[target == i].shape[0]
        ui = data[target == i].mean(0)  #某个类别的平均值
        SBi = Ni*np.mat(ui - u).T*np.mat(ui - u)
        SB += SBi
    S = np.linalg.inv(Sw)*SB
    eigVals,eigVects = np.linalg.eig(S)  #求特征值,特征向量
    eigValInd = np.argsort(eigVals)
    eigValInd = eigValInd[:(-n_dim-1):-1]
    w = eigVects[:,eigValInd]
    data_ndim = np.dot(data, w)

    return data_ndim

if __name__ == '__main__':
    iris = load_iris()
    X = iris.data
    Y = iris.target
    data_1 = lda(X, Y, 2)

    data_2 = LinearDiscriminantAnalysis(n_components=2).fit_transform(X, Y)


    plt.figure(figsize=(8,4))
    plt.subplot(122)
    plt.title("LDA")
    plt.scatter(data_1[:, 0], data_1[:, 1], c = Y)

    plt.subplot(121)
    plt.title("natural data")
    plt.scatter(data_2[:, 0], data_2[:, 1], c = Y)
    plt.savefig("LDA.png",dpi=600)
    plt.show()

代码二

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import sklearn.datasets

# 生成3类3维特征的数据集
X, y = sklearn.datasets.make_classification(n_samples=1000, n_features=3, n_redundant=0, n_classes=3, n_informative=2,
                           n_clusters_per_class=1, class_sep=0.5, random_state=10)
fig = plt.figure()
ax = Axes3D(fig, rect=[0, 0, 1, 1], elev=30, azim=20)
ax.scatter(X[:, 0], X[:, 1], X[:, 2], marker='o', c=y)
plt.show()

# 第一步,标准化数据集
Xmean = X.mean(axis=0)
Xstd = X- Xmean

# 第二步,计算每个类别的向量均值
mean_vec = []
for k in np.unique(y):
    mean_vec.append(np.mean(Xstd[y == k],axis=0)) #每一个特征维度的均值,这里规模是3*1

# 第三步,计算类内散度矩阵和类间散度矩阵
d = 3
Sw = np.zeros((d, d))  # 类内散度矩阵,规模是d*d(特征维度)
for k in np.unique(y):
    # numpy对于一维向量,矩阵相乘需要用reshape得到d*d维矩阵,否则是一个数字
    s = (Xstd[y == k].T).dot(Xstd[y == k]) / (y[y == k].shape[0]) - (mean_vec[k].reshape(d, 1)).dot(
        mean_vec[k].reshape(d, 1).T)
    Sw = Sw + s

Sb = np.zeros((d, d))  # 类间散度矩阵,规模是d*d(特征维度)
for k in range(len(mean_vec)):
    for j in range(k + 1, len(mean_vec)):
        sm = np.array(mean_vec[k] - mean_vec[j]).reshape(d, 1)
        Sb = Sb + np.dot(sm, sm.T)

# 第四步,构造S矩阵(Sw逆矩阵乘以Sb矩阵),并求解特征向量和特征根
S = np.dot(np.linalg.inv(Sw),Sb)
e,v = np.linalg.eig(S) #一列为一个特征向量

# 第五步,组合W矩阵并计算降维后数据集Z
W = np.column_stack((v[:,0],v[:,1])) #向量组合用np.column_stack
Z = -np.dot(Xstd,W) #得到降维后的数据集

# 最后,来看看降维效果
plt.scatter(Z[:, 0], Z[:, 1],marker='o',c=y)
plt.show()

# 直接调用sklearn包看看,结果和手动实现是否一致。
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis(n_components=2)
lda.fit(Xstd,y)
X_new = lda.transform(Xstd)
plt.scatter(X_new[:, 0], X_new[:, 1],marker='o',c=y)
plt.show()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小蒋的学习笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值