机器学习算法:LDA线性判别法

一、LDA线性判别法讲解

PCA 来降维属于无监督学习,其没有将样本类别标签考虑进去。LDA是一种有监督学习的降维技术,也就是说它将样本类别标签考虑了进去。LDA的思想为:给定样本训练集,将样本投影到一条直线上,使得同类样本的投影点尽可能近、不同类样本的投影点中心尽可能远。简单的概括一句话:投影后类内方差最小,类间方差最大。

假设有个二分类问题,训练集xi为N个不同维度的样本,那么样本点x在向量w的投影为:

该式子中,x为样本集合;y为转置后的特征空间;w是转置矩阵,通过w可以将两类x转换成N个一维的样本,分为y1和y2两个子集。设各类样本均值向量为��i,那么:

样本的协方差矩阵为:

目标函数:

(1)投影后的两类样本中心点尽可能远

该目标为找到一个最佳的w使投影后的两类样本中心点尽量远的直线是好的直线,该目标函数如下:

这里我们把f(w)当作目标函数,期望其值越大越好。

(2)投影后类内方差尽可能小

在这里我们引入另一个度量指标:散列值来表示同类数据样本点的离散程度,如下所示:

上述式子表示其值越大,表示越分散;其值越小,表示越集中。

(3)对于上述两个目标的求解

要使不同类别之间的中心距离尽量大,那么将其作为分子;要使相同类别样本之间距离尽可能小,那将其作为分母,求整体的最大值即可:

对于矩阵SB和SW,只要有数据和标签即可求解。如果对分子和分母同时求解,就会有无穷多解,常用的方法是先固定分母,经过缩放变换后,将其值限制为1,如下所示:

Python实现:

import numpy as np  #导入numpy库

x1 = [ 1, 2, 3, 1, 2 ]   

x2 = [ 3, 2 ,1, 3, 1 ]   

y =  [ 1, 1, 1, 2, 2 ]   

X =np.c_[x1, x2]  #两列合并

X

#导入LDA模块

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

#设置LDA降,并将降维后的维度设为1

lda = LinearDiscriminantAnalysis(n_components=1)

lda.fit(X,y)  #进行降维训练

print (“每个类别的均值: “,lda. means_)

print (“整体样本的均值: “,lda. xbar_)

X_LDA = lda.transform(X)  #生成的降维后的新变量X

print (“降维后变量:”, X_LDA)

print (“截距: “, lda.intercept_)

print (“权重W: “, lda.coef_)

二、LDA线性判别法的应用场景

LDA(Linear Discriminant Analysis)是一种有监督的降维和分类方法,其核心目标是:

【1】最大化类间距离:使不同类别投影后的均值差异最大

【2】最小化类内距离:使同类样本的投影点尽可能集中

数学目标函数:

其中 Sb 是类间散度矩阵,Sw​ 是类内散度矩阵。

(1) 模式识别与分类

 场景:小样本高维数据的分类

 案例:

        人脸识别(Eigenfaces vs. Fisherfaces)

         医学诊断(癌症亚型分类)

 优势:在类别可分性强时,效果优于PCA

(2) 生物信息学

 基因表达数据分析:

        将数万个基因特征降至2-3维

        可视化不同癌症类型的分离情况

 效果对比:

(3) 金融风控

 客户信用评分:

        输入:收入、负债、交易记录等30+特征

        输出:高风险/低风险客户的二维投影

 优势:明确显示决策边界

(4) 多分类任务

 手写数字识别:

        MNIST数据(784维→9维,因为类别数10-1)

        计算效率比SVM更高

 数学约束:
    LDA最大降维维度 = 类别数 – 1

(5) 语音识别

 声学特征降维:将MFCC(梅尔频率倒谱系数)从39维降至5-10维;保留最具判别力的频率特征

LDA与PCA的对比:

选择LDA的决策条件:

【1】当以下条件满足时优先使用LDA:

   数据维度 < 样本量(p<np<n)

    类别数较少(<10)

    各类近似正态分布

    需要明确的可解释性投影方向

【2】避免使用LDA的情况:

    特征间存在高度非线性关系

    类别数 > 特征数

    数据标签噪声较大   

三、LDA 线性判别法的优缺点

LDA 作为经典的线性分类与降维方法,在标签充足、样本分布近似高斯且线性可分的场景中表现优异,尤其适合需要兼顾降维与分类的任务。但在面对高维小样本、类别不平衡或非线性数据时,需结合预处理或改进方法(如核 LDA、正则化 LDA)以提升效果。实际应用中,可根据数据特性与任务目标,灵活选择 LDA 或与其他算法(如 PCA、SVM)结合使用。

(一)LDA 的核心优点

(1) 明确的分类导向性
 LDA 以最大化类别区分度为目标(通过类间散度与类内散度的比值优化),降维结果直接服务于分类任务,相比无监督降维(如 PCA)更具针对性。
 案例:在文本分类中,LDA 可将高维词向量投影到最能区分不同主题的低维空间,提升分类准确率。

(2) 线性模型的高效性与可解释性
 基于线性变换,计算复杂度低(时间复杂度为 O (n³),n 为特征数),适合处理大规模数据。
 投影方向(权重向量)可直接反映各特征对分类的贡献度,例如在人脸识别中,权重高的像素点对应关键面部特征。

(3) 天然的降维上限约束
 降维后的维度上限为类别数-1,避免了维度冗余。例如,3 类数据最多降为 2 维,保证降维后仍保留足够分类信息。

(4) 对样本分布的假设兼容性
 假设各分类样本服从高斯分布且协方差矩阵相同,这一假设在许多实际场景(如生物特征识别、金融数据分箱)中近似成立,保证了模型有效性。

(5) 可扩展为非线性版本
 通过与核函数结合(如核 LDA),可处理非线性分类问题,将原始特征映射到高维空间后再进行线性判别。

(二)LDA 的主要缺点

(1) 对类别不平衡的敏感性
 目标函数基于类间散度,若某类样本数量过少,其类间散度贡献小,易被忽略。
  实例:医疗数据中疾病类样本远少于正常类时,LDA 可能过度偏向正常类,导致疾病检测率下降。

(2) 依赖样本的线性可分假设
 当类别间存在非线性边界时(如环形分布数据),线性投影无法有效区分,需依赖核方法或非线性变换。

(3) 高维小样本场景下的奇异性问题
 当特征维度 d 大于样本数 n 时,类内散度矩阵可能不可逆(病态矩阵),导致无法求解最优投影方向(需通过正则化或 PCA 降维预处理)。

(4) 缺乏对特征独立性的考量
LDA 仅已关注特征对分类的整体贡献,不处理特征间的相关性,可能存在冗余特征干扰。例如,在房价预测中,面积与总价高度相关,LDA 可能重复计算其权重。

(5) 对噪声和离群点的鲁棒性不足
类内散度计算受离群点影响大,若样本中存在异常值,可能导致最优投影方向偏移。
解决方案:可先通过聚类或异常检测过滤离群点,或使用加权 LDA 降低异常值权重。

(6) 无监督场景下的适用性局限
 依赖标签信息,无法直接用于无标签数据降维(而 PCA 可直接处理无监督数据)。

(三)LDA 与 PCA 的对比总结

(四)实际应用中的优化策略

【1】针对类别不平衡

使用加权 LDA(为少数类赋予更高权重)或过采样(如 SMOTE)扩充少数类样本。

【2】处理高维小样本

先通过 PCA 降维至n-1维(n 为样本数),再应用 LDA(即 PCA+LDA 组合方法)。

【3】提升鲁棒性

结合正则化项(如 L2 正则)约束权重向量,或使用核 LDA 处理非线性问题。

四、线性判别法LDA的例子

以下是一个完整的医疗领域LDA实现案例,包含数据生成、模型构建、训练评估和可视化全流程,这个实现完整展示了LDA在医疗数据分析中的典型应用流程,所有代码都有详细注释,避免使用复杂语法,确保可读性。可视化部分已处理中文乱码问题,并去除了警告信息。

注意事项:

【1】实际医疗应用中需要更多样本(建议>100条)

【2】分类效果严重依赖数据是否符合LDA的高斯分布假设

【3】对于非线性可分数据,需考虑改用QDA或其他非线性方法

主要步骤:

【1】数据准备:

  创建10条模拟医疗数据,包含3个临床指标和诊断类别

【2】数据标准化:

  使用StandardScaler对特征进行Z-score标准化

  输出标准化后的数值范围(均值≈0,方差=1)

【3】LDA降维

  将3维特征降至2维(因为3个类别)

  输出投影矩阵,显示每个原始特征对判别分量的贡献

【4】可视化

  绘制降维后的二维散点图,不同类别用不同颜色标记

  图形显示各类别的分离情况

【5】分类器应用

 使用LDA作为分类器预测新样本

 输出测试集的预测结果与真实标签对比

【6】模型评估

 计算准确率和混淆矩阵

【7】决策边界

  绘制基于前两个判别分量的决策区域

 直观展示分类器的判断逻辑

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.metrics import accuracy_score, confusion_matrix
import warnings
warnings.filterwarnings(“ignore”)  # 去除警告

plt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文乱码
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# ==================== 1. 准备医疗数据集 ====================
# 模拟10条患者数据,3个特征+1个类别标签(0-健康,1-糖尿病,2-高血压)
# 特征:年龄,血糖水平(mmol/L),血压(mmHg)
medical_data = np.array([
    [35, 5.2, 120, 0],  # 健康
    [48, 6.8, 135, 1],  # 糖尿病
    [62, 7.5, 148, 2],  # 高血压
    [29, 5.1, 118, 0],
    [53, 9.1, 142, 1],
    [58, 8.3, 155, 2],
    [41, 5.8, 126, 0],
    [50, 10.2, 140, 1],
    [65, 7.9, 160, 2],
    [45, 6.1, 130, 0]
])

# 分离特征和标签
X = medical_data[:, :3]  # 前3列是特征
y = medical_data[:, 3]   # 最后1列是标签

print(“医疗数据示例:”)
print(“年龄 | 血糖 | 血压 | 类别”)
print(“—————————-“)
for row in medical_data:
    print(f”{int(row[0])}岁 | {row[1]} | {int(row[2])} | {int(row[3])}”)

# ==================== 2. 数据标准化 ====================
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

print(”
标准化后的数据(前3个样本):”)
print(X_scaled[:3])

# ==================== 3. 执行LDA降维 ====================
lda = LinearDiscriminantAnalysis(n_components=2)
X_lda = lda.fit_transform(X_scaled, y)  # 注意LDA需要标签!

print(”
LDA投影矩阵:”)
print(lda.scalings_)  # 显示投影方向

print(”
降维结果:”)
for i, (original, reduced) in enumerate(zip(X_scaled[:3], X_lda[:3])):
    print(f”样本{i}: {original} → {reduced}”)

# ==================== 4. 可视化降维结果 ====================
plt.figure(figsize=(10, 6))
colors = ['green', 'orange', 'red']
labels = ['健康', '糖尿病', '高血压']

for color, target, label in zip(colors, [0, 1, 2], labels):
    plt.scatter(
        X_lda[y == target, 0],  # 第一判别分量
        X_lda[y == target, 1],  # 第二判别分量
        color=color,
        label=label,
        alpha=0.7
    )

plt.title('LDA: 患者数据降维可视化')
plt.xlabel('第一判别分量 (解释方差: %.1f%%)' % (lda.explained_variance_ratio_[0]*100))
plt.ylabel('第二判别分量 (解释方差: %.1f%%)' % (lda.explained_variance_ratio_[1]*100))
plt.legend()
plt.grid()
plt.show()

# ==================== 5. 作为分类器使用 ====================
# 划分训练集和测试集(简单示例,实际应用需交叉验证)
X_train, X_test = X_scaled[:7], X_scaled[7:]
y_train, y_test = y[:7], y[7:]

# 训练LDA分类器
lda_classifier = LinearDiscriminantAnalysis()
lda_classifier.fit(X_train, y_train)

# 预测
y_pred = lda_classifier.predict(X_test)

print(”
测试集真实标签:”, y_test)
print(“测试集预测标签:”, y_pred)

# ==================== 6. 模型评估 ====================
accuracy = accuracy_score(y_test, y_pred)
conf_mat = confusion_matrix(y_test, y_pred)

print(”
模型评估:”)
print(f”准确率: {accuracy:.2f}”)
print(“混淆矩阵:”)
print(conf_mat)

# ==================== 7. 修正后的决策边界可视化 ====================
# 创建一个新的LDA模型专门用于2D可视化
lda_vis = LinearDiscriminantAnalysis(n_components=2)
X_lda_vis = lda_vis.fit_transform(X_scaled, y)
lda_classifier_vis = LinearDiscriminantAnalysis()
lda_classifier_vis.fit(X_lda_vis, y)  # 在降维后的数据上训练

plt.figure(figsize=(10, 6))

# 生成网格点
x_min, x_max = X_lda_vis[:, 0].min() – 1, X_lda_vis[:, 0].max() + 1
y_min, y_max = X_lda_vis[:, 1].min() – 1, X_lda_vis[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
                     np.arange(y_min, y_max, 0.02))

# 预测网格点类别
Z = lda_classifier_vis.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 绘制决策区域
plt.contourf(xx, yy, Z, alpha=0.3, levels=[-0.5, 0.5, 1.5, 2.5], colors=colors)

# 绘制数据点
for color, target, label in zip(colors, [0, 1, 2], labels):
    plt.scatter(
        X_lda_vis[y == target, 0],
        X_lda_vis[y == target, 1],
        color=color,
        label=label,
        edgecolors='black'
    )

plt.title('LDA决策边界可视化(基于降维数据)')
plt.xlabel('第一判别分量')
plt.ylabel('第二判别分量')
plt.legend()
plt.show()

输出结果:

医疗数据示例:
年龄 | 血糖 | 血压 | 类别
----------------------------
35岁 | 5.2 | 120 | 0
48岁 | 6.8 | 135 | 1
62岁 | 7.5 | 148 | 2
29岁 | 5.1 | 118 | 0
53岁 | 9.1 | 142 | 1
58岁 | 8.3 | 155 | 2
41岁 | 5.8 | 126 | 0
50岁 | 10.2 | 140 | 1
65岁 | 7.9 | 160 | 2
45岁 | 6.1 | 130 | 0

标准化后的数据(前3个样本):
[[-1.24233296 -1.23702137 -1.28610446]
 [-0.05480881 -0.24740427 -0.17739372]
 [ 1.22406336  0.18555321  0.78348892]]

LDA投影矩阵:
[[ 0.00378016 -0.82540646]
 [-0.43341907 -1.94087296]
 [ 2.93348092  2.02065929]]

降维结果:
样本0: [-1.24233296 -1.23702137 -1.28610446] → [-3.24131046  0.82755206]
样本1: [-0.05480881 -0.24740427 -0.17739372] → [-0.41335855  0.16696754]
样本2: [1.22406336 0.18555321 0.78348892] → [2.22255467 0.21267917]

测试集真实标签: [1. 2. 0.]
测试集预测标签: [1. 2. 1.]

模型评估:
准确率: 0.67
混淆矩阵:
[[0 1 0]
 [0 1 0]
 [0 0 1]]

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容