【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析

系列文章目录

【学习笔记】 陈强-机器学习-Python-Ch4 线性回归
【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归
【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv)
【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归



前言

本学习笔记 仅为以防自己忘记了,顺便分享给一起学习的网友们参考。如有不同意见/建议,可以友好讨论。

本学习笔记 所有的代码和数据都可以从 陈强老师的个人主页 上下载

参考书目:陈强.机器学习及Python应用. 北京:高等教育出版社, 2021.

数学原理等 详见陈强老师的 PPT


参考了网友阡之尘埃Python机器学习05——判别分析


本次案例 需 安装 mlxtend 库
pip install mlxtend


一、线性判别分析 (LDA) &二次判别分析 (QDA)

1. 线性判别分析 (Linear Discriminant Analysis,LDA)

LDA是一种用于分类和降维的线性算法,旨在找到一个线性组合的特征,以最大化类别间的区分度。

  • 模型假设: 假设各类别的数据具有相同的协方差矩阵,即数据在每个类别中的协方差相同。
  • 决策边界: 由于协方差矩阵相同,LDA 的决策边界是线性的。
  • 计算复杂度: 相对较低,因为只需估计一个协方差矩阵。
  • 适用情况: 当数据的类别协方差矩阵相似时,LDA 效果较好。

LinearDiscriminantAnalysis()

LinearDiscriminantAnalysis 是 scikit-learn 中实现线性判别分析(LDA)的函数。
主要参数:

  • solver: 优化算法。可选值包括 svd, lsqr, eigen。默认为 svd
    - svd :使用奇异值分解 (SVD) 进行计算。
    - lsqr: 使用最小二乘法求解。
    - eigen:使用特征分解 (Eigen decomposition) 方法。
    - 如果对计算效率有要求,通常 ‘svd’ 是最稳定和高效的选择。如果需要对模型进行正则化,可以尝试 ‘lsqr’ 或 ‘eigen’ 并调整 。
  • shrinkage:当 solver 是lsqreigen 时,选择是否应用收缩 (shrinkage) 技术来改善模型的稳定性和性能。可选值:auto: 自动选择最适合的收缩策略。None: 不使用收缩。具体的收缩值(例如 ‘0.5’),以调整收缩强度。
  • priors:类别的先验概率。
  • n_components:降维后的目标维度。如果为 None,则自动选择使得目标维度不超过类别数减一(即 min(n_classes - 1, n_features))。
  • n_iter: 用于模型训练的迭代次数(如果使用了迭代算法)。这个参数通常与 solver=‘eigen’ 相关。
#例子
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

lda = LinearDiscriminantAnalysis(
    solver='svd',
    n_components=2, 
    priors=[0.5, 0.5, 0.2]
 )

2. 二次判别分析 (Quadratic Discriminant Analysis,QDA)

QDA 是一种分类方法,用于在特征空间中找到一个二次边界,将不同类别的样本分开。QDA 是判别分析的扩展,相比于线性判别分析(LDA),它允许每个类别有不同的协方差矩阵。

  • 模型假设: 允许各类别的数据具有不同的协方差矩阵。
  • 决策边界: 由于每个类别具有独立的协方差矩阵,QDA 的决策边界是二次的(即二次曲线)。
  • 计算复杂度: 相对较高,因为需要估计每个类别的协方差矩阵。
  • 适用情况: 当类别之间的协方差矩阵差异较大时,QDA 更有效。
  • 局限性:
    • 计算复杂度较高,尤其在数据维度很高时。
    • 对于小样本数据集,协方差矩阵的估计可能不稳定。
    • 对异常值敏感,可能需要正则化来改善稳定性。

QuadraticDiscriminantAnalysis ()

QuadraticDiscriminantAnalysis 是 scikit-learn 中实现 二次判别分析 (QDA) 的函数。
主要参数:

  • solver: 优化算法。可选值包括 svd, lsqr, eigen。默认为 svd
    - svd :使用奇异值分解 (SVD) 进行计算。
    - lsqr: 使用最小二乘法求解。
    - eigen:使用特征分解 (Eigen decomposition) 方法。
  • priors:类别的先验概率。
  • reg_param:正则化参数,控制对协方差矩阵的收缩。用于避免协方差矩阵的奇异性问题,通常在数据维度远大于样本数时使用。默认值: 0.0
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis

# 初始化 QDA 模型
qda = QuadraticDiscriminantAnalysis(
		priors=[0.5, 0.5, 0.2], 
		reg_param=0.1)

二、判别分析 案例:iris

1.介绍数据 load_iris

load_iris 是 scikit-learn 库中一个常用的数据集加载函数,它用于加载鸢尾花(Iris)数据集。鸢尾花数据集是机器学习领域中经典的数据集之一,经常被用来测试和演示各种分类算法。

数据集包含 150 个样本,每个样本都是鸢尾花的一个实例。每个样本有四个特征和一个标签。

特征:
  花萼长度(sepal length, cm):花萼的长度。
  花萼宽度(sepal width, cm):花萼的宽度。
  花瓣长度(petal length, cm):花瓣的长度。
  花瓣宽度(petal width, cm):花瓣的宽度。
标签(目标变量): 数据集的每个样本都被标记为三种鸢尾花品种中的一种:
  Setosa:品种 A。
  Versicolor:品种 B。
  Virginica:品种 C。

import pandas as pd
import numpy as np
from sklearn.datasets import load_iris  # 导入 load_iris 函数

# 加载鸢尾花数据集
iris = load_iris()
dir(iris) #列出 iris 对象的所有属性和方法

结果输出:[‘DESCR’, ‘data’, ‘feature_names’, ‘filename’, ‘frame’, ‘target’, ‘target_names’, ‘data’, ‘target_names’]

# 打印数据集的形状和其他信息
print(iris.data.shape)
print(iris.feature_names)
print(iris.target_names)

结果输出:(150, 4)
[‘sepal length (cm)’, ‘sepal width (cm)’, ‘petal length (cm)’, ‘petal width (cm)’]
[‘setosa’ ‘versicolor’ ‘virginica’]

2. 处理数据

1)Xs

#重命名
iris.feature_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width'] 
#矩阵变为数据框
X = pd.DataFrame(iris.data, columns=iris.feature_names) 
print(X)

在这里插入图片描述

#相关系数
X.corr()

在这里插入图片描述

#热力图
import matplotlib.pyplot as plt
import seaborn as sns

sns.heatmap(X.corr(), cmap='nipy_spectral', annot=True)

在这里插入图片描述

2)y

#查看y的取值
y = iris.target
y

在这里插入图片描述

3.全样本 线性判别分析

#全样本 线性判别分析
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

model = LinearDiscriminantAnalysis()
model.fit(X, y)     #拟合
model.score(X, y)   #计算预测精度

结果输出: 0.98

#先验概率
print(model.priors_)
#特征变量分组均值
print(model.means_)
#线性判元对于组间方差的贡献
print(model.explained_variance_ratio_)
#线性判元的估计系数
print(model.scalings_)
#变为数据框展示
lda_loadings = pd.DataFrame(model.scalings_, index=iris.feature_names, columns=['LD1', 'LD2'])
lda_loadings

结果输出: [0.33333333 0.33333333 0.33333333]
[[5.006 3.428 1.462 0.246]
[5.936 2.77 4.26 1.326]
[6.588 2.974 5.552 2.026]]
[0.9912126 0.0087874]
[[ 0.82937764 -0.02410215]
[ 1.53447307 -2.16452123]
[-2.20121166 0.93192121]
[-2.81046031 -2.83918785]]
在这里插入图片描述

#线性判别得分
lda_scores = model.fit(X, y).transform(X) 
print(lda_scores.shape)
lda_scores[:5, :]

结果输出: (150, 2)
array([[ 8.06179978, -0.30042062],
[ 7.12868772, 0.78666043],
[ 7.48982797, 0.26538449],
[ 6.81320057, 0.67063107],
[ 8.13230933, -0.51446253]])

#变为数据框展示
LDA_scores = pd.DataFrame(lda_scores, columns=['LD1', 'LD2'])
#加入响应变量Species
LDA_scores['Species'] = iris.target
LDA_scores.head()

在这里插入图片描述

#创建映射字典: 将 响应变量Species的取值 映射到 具体品种
d = {0: 'setosa', 1: 'versicolor', 2: 'virginica'}
# 使用 map() 方法进行映射
LDA_scores['Species'] = LDA_scores['Species'].map(d) 
LDA_scores.head()

在这里插入图片描述

#散点图
sns.scatterplot(x='LD1', y='LD2', data=LDA_scores, hue='Species')

在这里插入图片描述

#取两个特征变量(petal_length、petal_width)
X2 = X.iloc[:, 2:4]
model = LinearDiscriminantAnalysis()
model.fit(X2, y)
model.score(X2, y) #预测准确率
#组间方差
model.explained_variance_ratio_ 

结果输出: 0.96
array([0.99470499, 0.00529501])

#画出 线性判别的决策边界
from mlxtend.plotting import plot_decision_regions
 
plot_decision_regions(np.array(X2), y, model)
plt.xlabel('petal_length')
plt.ylabel('petal_width')
plt.title('Decision Boundary for LDA')

在这里插入图片描述

4. 二次判别分析

#二次判别分析(分 训练集和测试集)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, 
    test_size=0.3, 
    stratify=y, 
    random_state=123
)


from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
model = QuadraticDiscriminantAnalysis()

model.fit(X_train, y_train)
model.score(X_test, y_test)  

结果输出: 0.9777777777777777

prob = model.predict_proba(X_test)
print(prob[:3])

pred = model.predict(X_test)
pred[:5]

结果输出: [[1.30728298e-117 4.25364516e-001 5.74635484e-001]
[4.80474602e-185 1.17558005e-003 9.98824420e-001]
[1.12275433e-056 9.99994095e-001 5.90465247e-006]]
array([2, 2, 1, 1, 2])

from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.metrics import cohen_kappa_score


print(confusion_matrix(y_test, pred))
 
print(classification_report(y_test, pred))
 
print(cohen_kappa_score(y_test, pred))

结果输出:[[15 0 0]
[ 0 14 1]
[ 0 0 15]]
在这里插入图片描述0.9666666666666667

#同样选取两个特征变量进画出其决策边界
X2 = X.iloc[:, 2:4]
model = QuadraticDiscriminantAnalysis()
model.fit(X2, y)
print(model.score(X2, y))
 
plot_decision_regions(np.array(X2), y, model)
plt.xlabel('petal_length')
plt.ylabel('petal_width')
plt.title('Decision Boundary for QDA')

结果输出: 0.98
在这里插入图片描述

三、课后练习题:seeds_dataset.csv

import pandas as pd
import numpy as np

# 1. 导入数据
csv_path = r'D:\桌面文件\Python\【陈强-机器学习】MLPython-PPT-PDF\MLPython_Data\seeds_dataset.csv'
seeds = pd.read_csv(csv_path)
print(seeds.shape) #形状
seeds[:5] #前5

结果输出: (210, 8)
在这里插入图片描述

#统计特征
seeds.describe()

在这里插入图片描述

#响应变量的分布
seeds.Class.value_counts()

结果输出: Class
1 70
2 70
3 70
Name: count, dtype: int64

#全样本 线性判别分析
X = seeds.iloc[:,:-1] 
y = seeds.iloc[:,-1] 

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

model = LinearDiscriminantAnalysis()
model.fit(X, y)     #拟合
model.score(X, y)   #计算预测精度

结果输出: 0.9666666666666667

#先验概率
print(model.priors_)
#特征变量分组均值
print(model.means_)
#线性判元对于组间方差的贡献
print(model.explained_variance_ratio_)
#线性判元的估计系数
print(model.scalings_)
#线性判别得分
lda_scores = model.fit(X, y).transform(X) 
print(lda_scores.shape)
lda_scores[:5, :]

结果输出: [0.33333333 0.33333333 0.33333333]
[[14.33442857 14.29428571 0.88007 5.50805714 3.24462857 2.66740286
5.08721429]
[18.33428571 16.13571429 0.88351714 6.14802857 3.67741429 3.6448
6.0206 ]
[11.87385714 13.24785714 0.84940857 5.22951429 2.85377143 4.7884
5.1164 ]]
[0.68141241 0.31858759]
[[-4.23778614e-01 4.19531669e+00]
[ 3.79919995e+00 -8.50579585e+00]
[ 5.92772810e+00 -8.69823024e+01]
[-5.98819597e+00 -7.83067468e+00]
[ 3.70482197e-02 7.14104253e-01]
[-4.50472160e-02 3.21253808e-01]
[ 3.11807592e+00 6.91384931e+00]]
(210, 2)
array([[-0.43132208, -3.44768583],
[-0.75286941, -4.1839799 ],
[-1.09393189, -2.95867452],
[-1.7680201 , -3.25241433],
[ 0.49441123, -3.43848523]])

#变为数据框展示
LDA_scores = pd.DataFrame(lda_scores, columns=['LD1', 'LD2'])
#加入响应变量y
LDA_scores['Class'] = y
#散点图
import matplotlib.pyplot as plt
import seaborn as sns

sns.scatterplot(x='LD1', y='LD2', data=LDA_scores, hue='Class')

在这里插入图片描述

#二次判别分析(分 训练集和测试集)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, 
    test_size=1/3, 
    stratify=y, 
    random_state=0
)

# 训练 LDA
lda = LinearDiscriminantAnalysis()
lda.fit(X_train, y_train)
y_pred_lda = lda.predict(X_test)

#打印 混淆矩阵
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, y_pred_lda))

#打印准确率
print("训练 LDA 准确率:", lda.score(X_train, y_train))

# 打印分类报告
from sklearn.metrics import classification_report
print("LDA Classification Report:\n", classification_report(y_test, y_pred_lda))

结果输出: [[20 1 3]
[ 0 23 0]
[ 1 0 22]]
训练 LDA 准确率: 0.9857142857142858
在这里插入图片描述

# 训练 QDA
qda = QuadraticDiscriminantAnalysis()
qda.fit(X_train, y_train)
y_pred_qda = qda.predict(X_test)

#打印 混淆矩阵
print(confusion_matrix(y_test, y_pred_lda))

#打印准确率
print("训练 LDA 准确率:", lda.score(X_train, y_train))

# 打印分类报告
print("QDA Classification Report:\n", classification_report(y_test, y_pred_qda))

结果输出:
[[20 1 3]
[ 0 23 0]
[ 1 0 22]]
训练 QDA 准确率: 0.9857142857142858
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值