【机器学习】线性判别分析

195c6eaed44984efe7a05808f5bb4fd9.jpeg

一、原理

对于LDA 如何找到最佳投影线性变换矩阵

c4273fa4626f27cdd3b94aa368fb73e6.jpeg

LDA(Linear Discriminant Analysis)和PCA(Principal Component Analysis)区别

0fc7dc59120bfd9c29e0871e2e9852c7.png

二、示例代码

2.1 自定义实现lda算法对iris数据集进行降维

4b2aa66f128f95360119fdbf93a679af.jpeg

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




def lda(X, y, dims):
    """
    线性判别分析算法 (LDA) 的实现


    参数:
        X: 数据矩阵, 形状为 (n_samples, n_features)
        y: 标签向量, 形状为 (n_samples,)
        dims: 降维后的维度数量


    返回:
        X_new: 降维后的数据矩阵, 形状为 (n_samples, dims)
    """
    # 获取所有类别标签
    target_nums = np.unique(y)
    # 初始化类内散布矩阵 Sw 和 类间散布矩阵 Sb 的列表
    Sw_list, Sb_list = [], []
    # 计算总体均值向量
    X_mean = X.mean(axis=0)
    # 遍历每个类别
    for target in target_nums:
        # 获取该类别的数据子集
        Xi = X[y == target]
        # 计算该类别的数据个数
        Xi_nums = Xi.shape[0]
        # 计算该类别数据的均值向量
        Xi_mean = Xi.mean(axis=0)
        # 计算类内散布矩阵
        Sw_list.append((Xi - Xi_mean).T.dot(Xi - Xi_mean))
        # 计算类间散布矩阵
        Sb_list.append(Xi_nums * (Xi - X_mean).T.dot(Xi - X_mean))
    # 将列表转换为 NumPy 数组
    Sw_list, Sb_list = np.array(Sw_list), np.array(Sb_list)
    # 计算总的类内散布矩阵和类间散布矩阵
    Sw, Sb = Sw_list.sum(axis=0), Sb_list.sum(axis=0)
    # 计算用于降维的矩阵 W  
    S = np.linalg.inv(Sw).dot(Sb)
    eig_vals, eig_vecs = np.linalg.eig(S)#特征值分解,得到特征值和特征向量
    # 对特征值进行排序并取前 dims 个
    eig_vals_idx = np.argsort(eig_vals) #将 eig_vals 中的索引按照特征值的升序排列
    eig_vals_idx = eig_vals_idx[::-1] #将排序后的索引数组进行反转,得到一个降序排列的索引数组。这样,特征值较大的索引将位于数组的前面。
    eig_vals_idx = eig_vals_idx[:dims] #保留最大的 dims 个特征值对应的索引
    W = eig_vecs[:, eig_vals_idx] #使用最终选择的索引构建降维的线性变换矩阵 W
    # 将数据进行降维
    X_new = X.dot(W)
    # 返回降维后的数据
    return X_new


if __name__ == '__main__':
    # 加载鸢尾花数据集
    iris_data = load_iris()
    # 获取数据和标签
    iris_X = iris_data.data  # 数据矩阵, 形状为 (150, 4)
    iris_y = iris_data.target  # 标签向量, 形状为 (150,)
    # 进行 LDA 降维, 保留 2 个维度
    res_data = lda(iris_X, iris_y, 2)
    # 可视化降维后的数据
    plt.figure()
    plt.scatter(res_data[:, 0], res_data[:, 1], c=iris_y)
    plt.show()

2.2 调用sklearn的lda算法对iris数据集进行降维

765f449803479f1d5b1b9abd05b52d37.jpeg

2.3 使用sklearn的lda算法对手写数字数据集进行降维,并通过散点图进行可视化

4164eecc8ff0296e525784cc049e43e2.jpeg

# 导入库
import os
import matplotlib.pyplot as plt
import numpy as np
import sklearn.datasets
import sklearn.discriminant_analysis
import matplotlib
#%matplotlib inline


# 加载手写数字数据集,并限制类别数为 6
digits = sklearn.datasets.load_digits(n_class=6)


# 获取数据特征和目标标签
x = digits.data
y = digits.target


# 定义绘图函数
def plot_embedding(x, title):
    # 获取数据最大最小值
    x_min, x_max = np.min(x, 0), np.max(x, 0)
    # 对数据进行归一化
    x = (x - x_min) / (x_max - x_min)
    # 创建绘图对象
    plt.figure()
    # 定义颜色列表
    c = ['red', 'blue', 'lime', 'black', 'yellow', 'purple']
    # 遍历每个类别 
    for l in range(6): 
        # 获取该类别的样本
        p = x[y == l]
        # 绘制散点图
        plt.scatter(p[:, 0], p[:, 1], s=25, c=c[l], alpha=0.5, label=str(l))


    # 添加图例
    plt.legend(loc='lower right')
    # 隐藏坐标轴
    plt.xticks([])
    plt.yticks([])
    # 添加标题
    plt.title(title)
    # 显示图形
    plt.show()




# 复制一份数据
x2 = x.copy()
#  对数据进行微调,使其可逆,这是为了解决线性判别分析对奇异矩阵的敏感性
x2.flat[::x.shape[1] + 1] += 0.01
# 使用线性判别分析进行降维
x_lda = sklearn.discriminant_analysis.LinearDiscriminantAnalysis(n_components=2).fit_transform(x2, y)


plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
# 绘制降维后的数据
plot_embedding(x_lda, '线性判别分析降维')

三、LDA应用概述

5d4d8a2483e58d32553ea0d45fb9e6d0.png

The End

猜你喜欢

转载自blog.csdn.net/cxyhjl/article/details/134917851
今日推荐