《机器学习》西瓜书课后习题3.5——python实现线性判别分析

本文详细介绍了如何使用Python编程实现二类线性判别分析(LDA),并应用于西瓜数据集。首先,通过预处理数据,将西瓜分为好瓜和非好瓜两类。接着,计算两类数据的均值向量和协方差矩阵,进而求得类内散度矩阵和类间散度矩阵。然后,利用这些信息求得LDA的权重向量w。最后,通过绘制二维散点图展示分类效果,发现使用LDA得到的直线并不能完全分离所有数据点,但能明显区分大部分样本。
摘要由CSDN通过智能技术生成

《机器学习》西瓜书课后习题3.5——python实现线性判别分析

《机器学习》西瓜书P69

3.5 编程实现线性判别分析,并给出西瓜数据集3.0a上的结果

理论学习参见文章:线性判别分析LDA原理总结

注意:在该文章中针对w的求法出现了两种方式,一种是
w = S − 1 w ( μ 0 − μ 1 ) w=S^-1 w(μ_0−μ_1) w=S1w(μ0μ1)
该方法指的应该是针对二类LDA,所以我们在解决西瓜数据集问题是求w的方法采用此方法。

另一种方法是:
计 算 S − 1 w S b 的 最 大 的 d 个 特 征 值 和 对 应 的 d 个 特 征 向 量 ( w 1 , w 2 , . . . w d ) , 得 到 投 影 矩 阵 W 计算S^−1_wS_b的最大的d个特征值和对应的d个特征向量(w_1,w_2,...w_d),得到投影矩阵W S1wSbdd(w1,w2,...wd),W
此方法针对的解决多分类问题是采用的策略,在本问题中并不适用,具体详见下文。


二类线性判别分析的解决步骤:

  1. 求出均值向量、协方差矩阵
  2. 求散度矩阵
  3. 求出w

下面我们按照上述思路逐步完成,并绘出图像。

一. 数据的预处理

将西瓜集中的数据进行分割、修改

#读取西瓜数据集中的数据并进行预处理
def loadDataset(filename):
    dataset=[]
    with open(filename,'r',encoding='utf-8') as csvfile:
        csv_reader=csv.reader(csvfile)
        header=next(csv_reader)
        for row in csv_reader:
            if row[3] == '是':
                row[3]=1
            else:
                row[3]=0
            del(row[0])
            dataset.append(copy.deepcopy(row))
    data=[[float(x) for x in row]for row in dataset]
    print(data)
    return data

二. LDA算法实现

关于求均值向量、协方差矩阵可参见python中numpy函数中的部分用法,在这不再赘述,直接适用。

def LDA(data):
    data0=[]
    data1=[]
    for x in data:
        if x[2]==1:
            del(x[2])
            data1.append(copy.deepcopy(x))
        else:
            del (x[2])
            data0.append(copy.deepcopy(x))

    # 求得两类数据的均值向量
    mean0 = np.mean(data0)
    mean1 = np.mean(data1)
    # 得到两种数据的协方差矩阵
    diff1 = data1 - mean1
    diff0 = data0 - mean0
    cov1 = np.dot(np.transpose(diff1), diff1)
    cov0 = np.dot(np.transpose(diff0), diff0)
    # 计算类内散度矩阵
    Sw = cov1 + cov0
    # 计算类间散度矩阵
    Sb=np.dot(np.transpose(mean0-mean1),(mean0-mean1))
    Sw_Inv=np.linalg.inv(Sw)
    # a,b=np.linalg.eig(np.dot(Sw_Inv,Sb))# 计算矩阵的特征值和所对应的特征向量
    # index = np.argsort(-a)# 将-a中的元素从小到大排列,提取其对应的index(索引)
    # maxIndex = index[:1]
    # w = b[:, maxIndex]
    # print(w)
    w=np.dot(Sw_Inv,mean0-mean1)
    print(w)
    return w

注意:上面有一部分代码加以注释,在此予以说明,

a,b=np.linalg.eig(np.dot(Sw_Inv,Sb))# 计算矩阵的特征值和所对应的特征向量
index = np.argsort(-a)# 将-a中的元素从小到大排列,提取其对应的index(索引)
maxIndex = index[:1]
w = b[:, maxIndex]

这块代码是为了求在多类LDA方法中要求的特征向量和特征值,为了验证,我们也用此方法求得了一个w,也参与了后序的运算,最终得到了图像如下:

img

很明显,所有的点并未完全得到分离,尤其是在直线上存在点的重合现象,因此使用特征向量和特征值所求得的w并不能很好的适用于二分类问题,因此抛弃该方法!

三. 绘图

def DrawGraph(dataset,w):
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    # matplotlib画图中中文显示会有问题,需要这两行设置默认字体

    plt.xlabel('密度')
    plt.ylabel('含糖量')
    plt.xlim(xmax=0.8, xmin=-0.3)
    plt.ylim(ymax=0.5, ymin=-0.3)
    # 画两条坐标轴并设置轴标签x,y
    x1=[]
    y1=[]
    x2=[]
    y2=[]

    for x in dataset:
        if x[2]==1:
            x1.append(copy.deepcopy(x[0]))
            y1.append(copy.deepcopy(x[1]))
        else:
            x2.append(copy.deepcopy(x[0]))
            y2.append(copy.deepcopy(x[1]))

    colors1 = '#00CED1'  # 点的颜色
    colors2 = '#DC143C'
    area = np.pi * 4 ** 2  # 点面积
    # 画散点图
    plt.scatter(x1, y1, s=area, c=colors1, alpha=0.4, label='好瓜')
    plt.scatter(x2, y2, s=area, c=colors2, alpha=0.4, label='非好瓜')
    plt.plot([0, 9.5], [9.5, 0], linewidth='0.5', color='#000000')

    # plot line
    w = w.flatten()
    x1 = np.linspace(-1, 1, 102)
    x2 = -w[0] * x1 / w[1]
    plt.plot(x1, x2, label="LDA")
    plt.legend()
    #plt.savefig(r'C:\Users\hp\Desktop\《机器学习》笔记\LDA.png', dpi=300)
    plt.show()

最终得到的图像如下:在这里插入图片描述

  • 7
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yozu_Roo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值