机器学习:线性判别分析LDA(Python)

news2024/12/25 12:23:05

一、线性判别分析的定义

二、线性判别分析——二分类模型

lda2classify.py

import numpy as np


class LDABinaryClassifier:
    """
    线性判别分析二分类模型
    """
    def __init__(self):
        self.mu = None  # 各类别均值向量
        self.Sw_i = None  # 各类内散度矩阵
        self.Sw = None  # 类内散度矩阵(within-class scatter matrix)
        self.weight = None  # 模型的系数,投影方向
        self.w0 = None  # 阈值

    def fit(self, x_train, y_train):
        """
        线性判别分析核心算法,计算投影方向及判别阈值
        :param x_train: 训练集
        :param y_train: 目标集
        :return:
        """
        x_train, y_train = np.asarray(x_train), np.asarray(y_train)
        class_values = np.sort(np.unique(y_train))  # 不同的类别取值
        n_samples, n_features = x_train.shape  # 样本量和特征变量数
        class_size = []  # 计算各类别的样本量
        if len(class_values) != 2:
            raise ValueError("仅限于二分类且线性可分数据集......")
        # 1. 计算类均值,Sw散度矩阵,Sb散度矩阵
        self.Sw_i = dict()  # 字典形式,以类别取值为键,值是对应的类别样本的类内散度矩阵
        self.mu = dict()  # 字典形式,以类别取值为键,值是对应的类别样本的均值向量
        self.Sw = np.zeros((n_features, n_features))
        for label_val in class_values:
            class_x = x_train[y_train == label_val]  # 按类别对样本进行划分
            class_size.append(class_x.shape[0])  # 该类别的样本量
            self.mu[label_val] = np.mean(class_x, axis=0)  # 对特征取均值构成均值向量
            self.Sw_i[label_val] = (class_x - self.mu[label_val]).T.dot(class_x - self.mu[label_val])
            self.Sw += self.Sw_i[label_val]  # 累加计算类内散度矩阵
        # print(self.Sw)

        # 2. 计算投影方向w
        # u, sigma, v = np.linalg.svd(self.Sw)  # 奇异值分解
        # inv_sw = v * np.linalg.inv(np.diag(sigma)) * u.T  # 求逆矩阵
        inv_sw = np.linalg.inv(self.Sw)
        self.weight = inv_sw.dot(self.mu[0] - self.mu[1])  # 投影方向
        # print(self.weight)

        # 3. 计算阈值w0
        self.w0 = (class_size[0] * self.weight.dot(self.mu[0]) + class_size[1] * self.weight.dot(self.mu[1])) / n_samples
        # print(self.w0)

        return self.weight

    def predict(self, x_test):
        """
        根据测试样本
        :param x_test:
        :return:
        """
        x_test = np.asarray(x_test)
        y_pred = self.weight.dot(x_test.T) - self.w0
        y_test_pred = np.zeros(x_test.shape[0], dtype=np.int64)  # 初始测试样本的类别值
        y_test_pred[y_pred < 0] = 1  # 小于阈值的为负类
        return y_test_pred

test_lda2classify.py

from sklearn.datasets import load_iris, load_breast_cancer
from lda2classify import LDABinaryClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report


# iris = load_iris()
# X, y = iris.data[:100, :], iris.target[:100]

bc_data = load_breast_cancer()
X, y = bc_data.data, bc_data.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=111, stratify=y)

lda = LDABinaryClassifier()
lda.fit(X_train, y_train)
y_test_pred = lda.predict(X_test)
print(classification_report(y_test, y_test_pred))


鸢尾花取前两类:

breast_cancer 数据集:

三、线性判别分析——多分类降维算法

lda_multi_dim_reduction.py

import numpy as np
import scipy as sp

class LDAMulti_DimReduction:
    """
    线性判别分析多分类降维
    """
    def __init__(self, n_components=2):
        self.n_components = n_components  # 降维后的维度
        self.Sw, self.Sb = None, None
        self.eig_values = None # 广义特征值
        self.W = None  # 投影矩阵

    def fit(self, x_samples, y_target):
        """
        线性判别分析多分类降维核心算法,计算投影矩阵
        :param x_train:
        :param y_train:
        :return:
        """
        x_samples, y_target = np.asarray(x_samples), np.asarray(y_target)
        class_values = np.sort(np.unique(y_target))  # 不同的类别取值
        n_samples, n_features = x_samples.shape  # 样本量和特征变量数
        self.Sw = np.zeros((n_features, n_features))
        for i in range(len(class_values)):
            class_x = x_samples[y_target == class_values[i]]
            mu = np.mean(class_x, axis=0)
            self.Sw += (class_x - mu).T.dot(class_x - mu)
        mu_t = np.mean(x_samples, axis=0)
        self.Sb = (x_samples - mu_t).T.dot(x_samples - mu_t) - self.Sw
        self.eig_values, eig_vec = sp.linalg.eig(self.Sb, self.Sw)
        # print(self.eig_values)
        idx = np.argsort(self.eig_values)[::-1]  # 从大到小
        self.eig_values = self.eig_values[idx]
        vec_sort = eig_vec[:, idx]
        self.W = vec_sort[:, :self.n_components]
        # print(self.W)
        return self.W

    def transform(self, x_samples):
        """
        根据投影矩阵计算降维后的新样本数据
        :param x_samples:
        :return:
        """
        if self.W is not None:
            return x_samples.dot(self.W)
        else:
            raise ValueError("请先进行fit,构造投影矩阵,然后降维...")

    def fit_transform(self, x_samples, y_target):
        """
        计算投影矩阵并降维
        :param x_samples:
        :param y_target:
        :return:
        """
        self.fit(x_samples, y_target)
        return x_samples.dot(self.W)

    def variance_explained(self):
        """
        解释方差比
        :return:
        """
        idx = np.argwhere(np.imag(self.eig_values) != 0)
        if len(idx) == 0:
            self.eig_values = np.real(self.eig_values)
        ratio = self.eig_values / np.sum(self.eig_values)
        return ratio[:self.n_components]

test_lda_dim_reduction.py

from sklearn.datasets import load_iris, load_wine, make_classification
from lda_multi_dim_reduction import LDAMulti_DimReduction
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.preprocessing import StandardScaler


iris = load_iris()
X, y = iris.data, iris.target

# X, y = make_classification(n_samples=2000, n_features=20, n_informative=3, n_classes=5,
#                            n_redundant=0, n_clusters_per_class=1, class_sep=2, random_state=42)
# 
# wine = load_wine()
# X, y = wine.data, wine.target

X = StandardScaler().fit_transform(X)

lda = LDAMulti_DimReduction(n_components=3)
lda.fit(X, y)
x_new = lda.transform(X)
print(lda.variance_explained())

plt.figure(figsize=(14, 5))

plt.subplot(121)
plt.scatter(x_new[:, 0], x_new[:, 1], marker="o", c=y)
plt.xlabel("PC1", fontdict={"fontsize": 12})
plt.ylabel("PC2", fontdict={"fontsize": 12})
plt.title("LDA Dimension Reduction (Myself)", fontdict={"fontsize": 14})
plt.grid(ls=":")
# plt.subplot(222)
# plt.scatter(x_new[:, 1], x_new[:, 2], marker="o", c=y)
# plt.xlabel("PC2", fontdict={"fontsize": 12})
# plt.ylabel("PC3", fontdict={"fontsize": 12})
# plt.title("LDA Dimension Reduction (Myself)", fontdict={"fontsize": 14})
# plt.grid(ls=":")

lda = LinearDiscriminantAnalysis(n_components=2)
lda.fit(X, y)
x_skl = lda.transform(X)
plt.subplot(122)
plt.scatter(x_new[:, 0], x_new[:, 1], marker="o", c=y)
plt.xlabel("PC1", fontdict={"fontsize": 12})
plt.ylabel("PC2", fontdict={"fontsize": 12})
plt.title("LDA Dimension Reduction (Sklearn)", fontdict={"fontsize": 14})
plt.grid(ls=":")
# plt.subplot(224)
# plt.scatter(x_new[:, 1], x_new[:, 2], marker="o", c=y)
# plt.xlabel("PC2", fontdict={"fontsize": 12})
# plt.ylabel("PC3", fontdict={"fontsize": 12})
# plt.title("LDA Dimension Reduction (Sklearn)", fontdict={"fontsize": 14})
# plt.grid(ls=":")

plt.tight_layout()
plt.show()


 鸢尾花数据集:

降维后前两个主特征的解释方差比

[9.91212605e-01 8.78739503e-03]

红酒数据集:

降维后前两个主特征的解释方差比

[6.87478888e-01 3.12521112e-01]

使用make_classification创建数据集:

降维后前三个主特征的解释方差比

[0.47101585 0.44946339 0.07876534]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1431858.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【电路笔记】-线圈的电感

线圈的电感 文章目录 线圈的电感1、概述2、线圈的电感3、电感示例14、电感示例2 电感是指抵抗流过其的电流变化的元件属性的名称&#xff0c;即使是直的电线也会有一些电感。 1、概述 线圈的电感是指感应线圈抵抗流过其的电流的任何变化所必须的电气特性。 因此&#xff0c;电…

Qt拖拽事件,实现控件内项的相互拖拽

文章目录 1拖拽演示2 步骤3 实现 这里主要以QTableview控件为例&#xff0c;实现表格内数据的相互拖拽。 1拖拽演示 2 步骤 自定以QTableView类&#xff0c;在自定义类中重写拖拽事件&#xff1a; void dropEvent(QDropEvent *event); void dragEnterEvent(QDragEnterEvent *…

装饰你的APP:使用Lottie-Android创建动画效果

装饰你的APP&#xff1a;使用Lottie-Android创建动画效果 1. Lottie-Android简介 Lottie-Android是一个强大的开源库&#xff0c;由Airbnb开发&#xff0c;旨在帮助开发者轻松地在Android应用中添加高质量的动画效果。它基于Adobe After Effects软件中的Bodymovin插件&#x…

一种缩短轮询时间的处理办法

我们平常处理轮询任务的时候&#xff0c;会用时间片的方式来分割开&#xff0c;每个时间片处理某一个任务。 有时候有些任务并不需要有动作&#xff0c;本轮轮询到它&#xff0c;它不需要干活&#xff0c;于是这个时间片就浪费了。但如果其他时间片里面的任务又急着呢&#xff…

微信小程序使用ucharts折线图,有负数显示0刻度线

当数据有负数和正数的时候默认不会显示0刻度线&#xff0c;不方便看出正负对比 实现思路&#xff1a;显示的刻度线是根据数据的最大值和最小值自动分配到刻度线上面&#xff0c;把最大值和最小值设置为一样&#xff0c;然后平均分配给五个刻度线中间的刻度线就会为0就实现了显…

深入理解Istio服务网格(一)数据平面Envoy

一、服务网格概述(service mesh) 在传统的微服务架构中&#xff0c;服务间的调用&#xff0c;业务代码需要考虑认证、熔断、服务发现等非业务能力&#xff0c;在某种程度上&#xff0c;表现出了一定的耦合性 服务网格追求高级别的服务流量治理能力&#xff0c;认证、熔断、服…

如何在Vue应用程序中使用Vue-Router来实现路由嵌套动画效果

Vue-Router是Vue.js官方的路由管理插件&#xff0c;可以帮助我们轻松管理应用程序的路由。除了基本的路由功能外&#xff0c;Vue-Router还允许我们在切换路由时添加动画效果&#xff0c;提升用户体验。本文将介绍如何使用Vue-Router来实现路由嵌套动画效果&#xff0c;并提供具…

跟着pink老师前端入门教程-day17

2、CSS3 动画 动画&#xff08;animation&#xff09;是CSS3中就要有颠覆性的特征之一&#xff0c;可通过设置多个节点来精确控制一个或一组动画&#xff0c;常用来实现复杂的动画效果 相比较过渡&#xff0c;动画可以实现更多变化&#xff0c;更多控制&#xff0c;连续自动播…

Python3 交叉编译 numpy pandas scipy scikit-learn

1. 概述 由于需要将Python3.7 和一些软件包交叉编译到 armv7 平台硬件&#xff0c;如果是arm64位的系统&#xff0c;很多包都有预编译好的版本&#xff0c;可直接下载。本文主要在基于 crossenv(https://github.com/benfogle/crossenv)环境下交叉编译。 2. 编译环境搭建 创建…

处理SERVLET中的错误

处理SERVLET中的错误 问题陈述 一位用户在使用在线计算机应用程序时输入一个非数字字符做数字加法。servlet试图将用户输入的值转换成整数型时,引发了NumberFormException类型的异常。要创建一个Web应用程序来使用自定义错误页面处理该异常。该自定义错误页面需要向用户提供关…

【原创】点火线圈项目

一、项目介绍 此点火线圈项目主要实现对各部件的自动组装、测试、以及下料。 二、各个工位实现动作流程 1、合装移载位,这个工位通过伺服电机和气缸夹爪把上游设备加工的点火线圈插头移载到合装位。 通过伺服设置抓料位置(绝对定位)伺服电机到了抓料位后伸出气缸伸出,夹…

acwing869. 试除法求约数870. 约数个数AcWing871. 约数之和872. 最大公约数

869. 试除法求约数 思路&#xff1a; 约数和质数的求解有着共性&#xff0c; 就是都是使用 for (int i 1; i < n/i; i) 进行计算的。这样的原因是因为约数必然也是两两一组&#xff0c; 那么我们求出小的自然也就知道另一个&#xff0c;只要再判断一下n/i和i是否相同&a…

Qt PCL学习(一):环境搭建

参考 (QT配置pcl)PCL1.12.1QT5.15.2vs2019cmake3.22.4vtk9.1.0visual studio2019Qt5.15.2PCL1.12.1vtk9.1.0cmake3.22.2 本博客用到的所有资源 版本一览&#xff1a;Visual Studio 2019 Qt 5.15.2 PCL 1.12.1 VTK 9.1.0https://pan.baidu.com/s/1xW7xCdR5QzgS1_d1NeIZpQ?pw…

队列---数据结构

定义 队列&#xff08;Queue&#xff09;简称队&#xff0c;也是一种操作受限的线性表&#xff0c;只允许在表的一端进行插入&#xff0c;而在表的另一端进行删除。向队列中插入元素称为入队或进队&#xff1b;删除元素称为出队或离队。 队头&#xff08;Front&#xff09;&a…

小米平板6获取root权限教程

1. 绑定账号 1> 打开"设置-我的设备-全部参数-连续点击MIUI版本按钮"&#xff0c;直到提示已打开开发者模式( p s : 这里需要重点关注红框平板型号和 M I U I 版本&#xff0c;例如我这里平板型号是 X i a o m i P a d 6 &#xff0c; M I U I 版本是 14.0.10 &am…

3 编辑器(Vim)

1.完成 vimtutor。备注&#xff1a;它在一个 80x24&#xff08;80 列&#xff0c;24 行&#xff09; 终端窗口看起来效果最好。 2.下载我们提供的 vimrc&#xff0c;然后把它保存到 ~/.vimrc。 通读这个注释详细的文件 &#xff08;用 Vim!&#xff09;&#xff0c; 然后观察 …

MySQL数据库①_MySQL入门(概念+使用)

目录 1. 数据库的概念 1.1 数据库的存储介质 1.2 主流数据库 2. MySQL的基本使用 2.1 链接数据库 2.2 服务器管理 2.3 数据库&#xff0c;服务器和表关系 2.4 简单MySQL语句 3. MySQL架构 4. SQL分类 5. 存储引擎 本篇完。 1. 数据库的概念 数据库是按照数据结构来…

智能决策的艺术:探索商业分析的最佳工具和方法

文章目录 一、引言二、商业分析思维概述三、数据分析在商业实践中的应用四、如何培养商业分析思维与实践能力五、结论《商业分析思维与实践&#xff1a;用数据分析解决商业问题》亮点内容简介作者简介目录获取方式 一、引言 随着大数据时代的来临&#xff0c;商业分析思维与实…

Cox等级资料是个坑

R语言做&#xff01;初学者先进来看看&#xff01;&#xff01;&#xff01; SCI冲 COX多因素模型需要满足的条件&#xff1a; 1.各观测值间相互独立&#xff0c;即残差之间不存在自相关&#xff1b; 2.因变量和自变量之间存在线性关系&#xff1b; 3.残差的方差齐&#xf…

蓝桥杯备战——12.超声波与测频代码优化

1.优化分析 昨天我在看原理图的发现超声波模块的反馈引脚P11刚好可以使用PCA模块0的捕获功能&#xff0c;我就想着把PCA功能留给超声波&#xff0c;然后测频功能还是改成定时器0来完成&#xff0c;然后前后台功能改成定时器1。 至于我为什么要这么改呢&#xff0c;看一下我原…