OpenCV与机器学习:OpenCV实现主成分分析

news/2025/3/16 23:28:31/

OpenCV实现主成分分析

  • 前言
  • 主成分分析(PCA)
    • 数据生成
    • 画图
    • cv2.PCACompute
    • 绘制主成分分析结果

前言

维数灾难是指出现一定数量的特征(或者维度)后,分类器的性能将开始下降。特征越多,数据集中的信息就越多。但是,如果考虑的特征超过了所需的特征,分类器甚至会考虑异常值或者会过拟合数据集。因此分类器的性能开始下降,而不是上升。

降维技术允许我们在不丢失太多信息的情况下,找到高维数据的一种紧凑表示。

主成分分析(PCA)

最常见的一种降维技术是主成分分析(Principal Component Analysis,PCA)。PCA所做的是旋转所有的数据点,直到数据点与解释大部分数据分布的两个轴对齐。

数据生成

np.random.multivariate_normal
首先我们使用numpy中的np.random.multivariate_normal来生成一个数据集用于降维。np.random.multivariate_normal是 NumPy 库中的一个函数,用于生成满足多元正态(也称为高斯)分布的随机样本。
多元正态分布是多个随机变量的概率分布,其中每个随机变量都服从正态分布,并且这些随机变量之间存在一定的相关性。

函数的基本用法如下:

numpy.random.multivariate_normal(mean, cov, size)
参数含义
mean一个表示分布的均值的1-D数组。
cov一个表示分布的协方差矩阵的2-D数组。
size输出的形状。如果是一个整数,则输出会有这么多样本;如果是一个元组,则输出会有相应的维度。
import numpy as npmean = [20, 20]
cov = [[12, 8], [8, 18]]
np.random.seed(42)
x, y = np.random.multivariate_normal(mean, cov, 1000).T
x.shape, y.shape

生成的数据形状如下:

((1000,), (1000,))

画图

将数据的两个维度用二维图画出来,这里使用的画图风格为ggplot(没有别的原因,就是因为这个好看)

import matplotlib.pyplot as pltplt.style.use('ggplot')
plt.figure(figsize=(35, 35))
plt.plot(x, y, 'o', zorder=5)
plt.axis([0, 35, 0, 35])
plt.xlabel('feature 1')
plt.ylabel('feature 2')

在这里插入图片描述

cv2.PCACompute

首先我们将x,y合并起来作为主成分分析的数据。

X = np.vstack((x, y)).T
X.shape
(1000, 2)

在OpenCV中,cv2.PCACompute() 函数用于计算主成分分析(PCA)的结果。PCA 是一种常用的统计方法,用于减少数据集的维度,同时保留数据中的主要变化特征。通过 PCA,你可以找到数据中的“主成分”,这些主成分定义了数据的主要变化方向。在代码中np.array([]) 是一个空的均值向量,当设置为空时PCACompute()将自动计算数据的均值。

import cv2
mu, eig = cv2.PCACompute(X, np.array([]))
eig
array([[ 0.57128392,  0.82075251],[ 0.82075251, -0.57128392]])

函数返回两个值:在投影之前减去均值(mean)和协方差矩阵的特征向量(eig)。这些特征向量指向PCA认为信息最丰富的方向。如果我们使用maplotlib在我们数据的顶部绘制这些特征向量,那么就会发现这些特征向量与数据的分布是一致的。

绘制主成分分析结果

使用plt.quiver可以绘制出特征向量,其中参数mean为数据的均值,在这里表示的时箭头的起点,eig则是特征向量,即箭头的方向。

plt.figure(figsize=(10, 6))
plt.plot(x, y, 'o', zorder=1)
plt.quiver(mean, mean, eig[:, 0], eig[:, 1], zorder=3, scale=0.2, units='xy')
plt.text(mean[0] + 5 * eig[0, 0], mean[1] + 5 * eig[0, 1], 'u1', zorder=5, fontsize=16, bbox=dict(facecolor='white', alpha=0.6))plt.text(mean[0] + 5 * eig[1, 0], mean[1] + 8 * eig[1, 1], 'u2', zorder=5, fontsize=16, bbox=dict(facecolor='white', alpha=0.6))plt.axis([0, 40, 0, 40])
plt.xlabel('feature 1')
plt.ylabel('feature 2')

在这里插入图片描述
PCA告诉我们的是,我们预先确定的x轴和y轴对于描述我们选择的数据并不是那么有意义。因为所选数据的分布角度大约是45度,所以选择u1和u2作为坐标轴比选择x和y更有意义。

为了证明这一点,我们可以使用cv2.PCAProject旋转数据

X2 = cv2.PCAProject(X, mu, eig)
plt.plot(X2[:, 0], X2[:, 1], 'o')
plt.xlabel('first principal component')
plt.ylabel('second principal component')
plt.axis([-20, 20, -10, 10])

在这里插入图片描述
以上就是主成分分析用于调整数据分布的用法,除此之外我们还可以使用PCA进行降维操作,我们只需要选择相应的特征向量并与原数据相乘即可。

做法如下:

new_eig = eig[:, :选取的维度]
X_new = X.dot(new_eig)

http://www.ppmy.cn/news/1373683.html

相关文章

c++ pimpl惯用法

介绍 Pimpl(Pointer to implementation) 是一种减少代码依赖和编译时间的C编程技巧,其基本思想是将一个外部可见类(visible class)的实现细节(一般是所有私有的非虚成员)放在一个单独的实现类(implementation class)中,而在可见类…

【nodejs】“__dirname is not defined”错误修复

▒ 目录 ▒ 🛫 问题描述环境 1️⃣ 原理CommonJS vs ESM错误原因 2️⃣ 禁用 ESM 模式并改用 CommonJS方案一:项目方案二:单文件 3️⃣ 在 ESM 模式下自实现__dirname📖 参考资料 🛫 问题 描述 从网上找了一份代码&am…

LT6813/ADBMS1818底层驱动---均衡控制

1、LT6813采用内部均衡的原理 2、平衡控制结构体 根据数据库中读取的控制值设置平衡。要为单元设置平衡,必须将相应的位写入配置寄存器中。LTC 驱动程序仅执行数据库中 BMS 写入的数据。 参数 ltc_stateLTC 状态机的状态pSpi接口指向 SPI 配置的指针pTxBuff &…

大数据开发(Hadoop面试真题-卷六)

大数据开发(Hadoop面试真题) 1、MapReduce为什么一定要有环型缓冲区?2、MapReduce为什么一定要有Shuffle过程?3、Reduce怎么知道去哪里拉Map结果集?4、MapReduce Shuffle的排序算法?5、MapReduce shuffle为…

c++虚函数的理解

在C中,虚函数是实现多态性的关键。多态性是指允许不同类型的对象对同一消息做出响应,也就是说,你可以用同一段代码对不同的对象进行操作。 虚函数是通过在基类中使用关键字virtual声明的成员函数。如果在派生类中重新定义基类中的虚函数&…

前端开发报错:Cannot find module ‘@angular-devkit/schematics‘ Require stack:

1、背景 由于近期需要搭建angular ng-zorro-mobile ionic 框架集成项目,但是在开发过程中遇到了报错: Cannot find module angular-devkit/schematics Require stack 2、原因 这里产生的原因是因为我当时遇到另外一个问题,误导我以为是版…

什么是ElasticSearch的深度分页问题?如何解决?

在ElasticSearch中进行分页查询通常使用from和size参数。当我们对ElasticSearch发起一个带有分页参数的查询(如使用from和size参数)时,ElasticSearch需要遍历所以匹配的文档直到达到指定的起始点(from),然后返回从这一点开始的size个文档 在这个例子中: 1.from 参数定义…

vue3 对于watch的再次理解 给响应式变量赋相同值时watch不会被触发。

问题 当我给响应式变量赋相同值时watch不会被触发。 之前一直对于watch的理解是会被频繁触发,值变化就会被执行,反之computed会缓存相同值。 看官方文档也没有相关说明,加上赋相同值的场景占少数 结论 在 Vue 3 中,watch 函数默…