主成分分析(PCA)和基于核函数的主成分分析(KPCA)入门

文章目录

  • 1 前言
  • 2 PCA的原理
    • 2.1 什么是投影
    • 2.2 投影后的方差
    • 2.3 转化为求特征值的问题
    • 2.4 符号的表示
  • 3 KPCA的原理
  • 4 PCA和KPCA在Python中的使用
    • 4.1 PCA的使用
    • 4.2 KPCA的使用
  • 5 参考文献

1 前言

主成分分析是在做特征筛选时的重要手段,这个方法在大部分的书中都只是介绍了步骤方法,并没有从头到尾把这个事情给说清楚。本文的目的是把PCA和KPCA给说清楚。主要参考了YouTube上李政轩的Principal Component Analysis and Kernel Principal Component Analysis这个视频(强烈推荐看一下)。

2 PCA的原理

2.1 什么是投影

主成分分析所做的工作就是将数据集从高维投影到低维,从而用极少的几个特征来涵盖大部分的数据集信息。
所谓的投影,就是下图所示的这样。投影

图1:向量投影图

xjx_jxj投影到vvv上的向量为

xj′=(∣∣xj∣∣cosθ)v∣∣v∣∣x_j'=(||x_j||cos\theta)\dfrac{v}{||v||}xj=(xjcosθ)vv

其中,θ\thetaθxjx_jxjvvv的夹角。
由于向量之间的内积为

<xj,v>=∣∣xj∣∣⋅∣∣v∣∣⋅cosθ<x_j, v>=||x_j|| \cdot ||v|| \cdot cos\theta<xj,v>=xjvcosθ

故有

xj′=<xj,v>∣∣v∣∣2vx_j' = \dfrac{<x_j,v>}{||v||^2}vxj=v2<xj,v>v

如果我们把vvv设置成单位向量的话(即∣∣v∣∣=1||v||=1v=1)就有

xj′=<xj,v>vx_j' = <x_j,v>vxj=<xj,v>v

也就是说我们只要求出<xj,v><x_j,v><xj,v>就可以知道xjx_jxj投影到vvv上的大小了。
又由于在坐标当中,内积可以表示为

<xj,v>=xjT⋅v=vT⋅xj<x_j, v>=x_j^T \cdot v=v^T \cdot x_j<xj,v>=xjTv=vTxj

故可以用vT⋅xjv^T \cdot x_jvTxj来表示投影后的数值大小。

2.2 投影后的方差

主成分分析认为,沿某特征分布的数据的方差越大,则该特征所包含的信息越多,也就是所谓的主成分。
我们已经知道了可以用vT⋅xjv^T \cdot x_jvTxj来表示投影后的数值大小,那么我们现在就可以算出投影后的方差大小了。注意我们么已经把数据标准化过了,所以vT⋅xv^T \cdot xvTx的均值为vT⋅0=0v^T \cdot 0=0vT0=0

σ2=1N−1∑i=1N(vTxi−0)2=1N−1∑i=1N(vTxi)(vTxi)\sigma^2 = \dfrac{1}{N - 1}\sum_{i=1}^{N}(v^Tx_i-0)^2=\dfrac{1}{N - 1}\sum_{i=1}^{N }(v^Tx_i)(v^Tx_i)σ2=N11i=1N(vTxi0)2=N11i=1N(vTxi)(vTxi)

注意到vTxiv^Tx_ivTxi是一个数值,不是向量,故有vTxi=(vTxi)Tv^Tx_i=(v^Tx_i)^TvTxi=(vTxi)T于是

σ2=1N−1∑i=1NvTxixiTv=vT(1N−1∑i=1NxixiT)v=vTCv\sigma^2=\dfrac{1}{N - 1}\sum_{i=1}^{N}v^Tx_ix_i^Tv=v^T(\dfrac{1}{N- 1}\sum_{i=1}^{N}x_ix_i^T)v=v^TCvσ2=N11i=1NvTxixiTv=vT(N11i=1NxixiT)v=vTCv

其中,C=1N−1∑i=1NxixiTC=\dfrac{1}{N - 1}\sum_{i=1}^{N}x_ix_i^TC=N11i=1NxixiT是一个m×mm \times mm×m的矩阵,mmm为特征的个数。
好了,如果我们要找到最大的方差,也就是要找到一个向量vvv使得方差最大。

2.3 转化为求特征值的问题

我们可以将求最大方差的问题写成

maxvTCvs.t.∣∣v∣∣=1max \quad v^TCv \\ s.t. \quad ||v||=1maxvTCvs.t.v=1

又由于∣∣v∣∣=vTv||v||=v^Tvv=vTv ,故上式即

maxvTCvs.t.vTv=1max \quad v^TCv \\ s.t. \quad v^Tv=1maxvTCvs.t.vTv=1

利用拉格朗日乘子法可以将上述问题转化为

f(v,λ)=vTCv−λ(vTv−1)f(v,\lambda)=v^TCv-\lambda (v^Tv-1)f(v,λ)=vTCvλ(vTv1)

其中,f(v,λ)f(v, \lambda)f(v,λ)的平稳点,和我们所要求的最大方差问题是等价的,即求下述方程式的解

{∂f∂v=2Cv−2λv=0∂f∂λ=vTv−1=0\begin{cases}\dfrac{\partial f}{\partial v}=2Cv-2\lambda v=0 \\ \dfrac{\partial f}{\partial \lambda}=v^Tv-1=0 \end{cases}vf=2Cv2λv=0λf=vTv1=0

上述方程组等价于

{Cv=λv∣∣v∣∣=1\begin{cases}Cv=\lambda v \\ ||v|| =1\end{cases}{Cv=λvv=1

看到了没,Cv=λvCv=\lambda vCv=λv不就是求特征值和特征向量的方程吗!更神奇的地方在下面,我们再回到最初求最大方差的问题

vTCv=vTλv=λvTv=λv^TCv=v^T\lambda v=\lambda v^Tv=\lambdavTCv=vTλv=λvTv=λ

是不是很神奇!要求的方差就是我们这里的特征值!所以我们只需要把Cv=λvCv=\lambda vCv=λv的特征值求出来,然后按大小排个序就,选出最大的几个特征值,并求出对应的特征向量,最后用这几个特征向量来完成数据集在其上的投影vTxv^TxvTx,这样就完成了特征的筛选!

2.4 符号的表示

值得注意的是,CCC是一个m×mm \times mm×m的矩阵

C=1N−1∑i=1NxixiT=1N−1[x1,x2,...,xN][x1Tx2T...xNT]C=\dfrac{1}{N - 1}\sum_{i=1}^{N}x_ix_i^T=\dfrac{1}{N - 1}[x_1,x_2,...,x_N] \begin{bmatrix}x_1^T \\ x_2^T \\... \\ x_N^T \end{bmatrix}C=N11i=1NxixiT=N11[x1,x2,...,xN]x1Tx2T...xNT

其中,每个xix_ixi为一个列向量

xi=[xi(1)xi(2)...xi(m)]x_i=\begin{bmatrix}x_i^{(1)} \\ x_i^{(2)} \\... \\x_i^{(m)} \end{bmatrix}xi=xi(1)xi(2)...xi(m)

其中,mmm为特征的个数。
为了方便表示,我们作出如下定义

XT=[x1,x2,...,xN]X^T=[x_1,x_2,...,x_N]XT=[x1,x2,...,xN]

于是,CCC可以表示为

C=1N−1XTXC=\dfrac{1}{N - 1}X^TXC=N11XTX

3 KPCA的原理

基于核函数的主成分分析和主成分分析的步骤是一样的,只不过用核函数替代了原来的数据。这里对什么是核函数不作说明,请参考其它文章。
对于线性不可分的数据集,我们可以将其映射到高维上,再进行划分。

C=1N−1∑i=1Nϕ(xi)ϕ(xi)T=1N[ϕ(x1),...,ϕ(xN)][ϕ(x1)T...ϕ(xN)T]C=\dfrac{1}{N - 1}\sum_{i=1}^{N}\phi (x_i)\phi(x_i)^T=\dfrac{1}{N}[\phi(x_1),...,\phi(x_N)]\begin{bmatrix}\phi(x_1)^T \\ ... \\ \phi(x_N)^T \end{bmatrix}C=N11i=1Nϕ(xi)ϕ(xi)T=N1[ϕ(x1),...,ϕ(xN)]ϕ(x1)T...ϕ(xN)T

我们令

XT=[ϕ(x1),...,ϕ(xN)]X^T=[\phi(x_1),...,\phi(x_N)]XT=[ϕ(x1),...,ϕ(xN)]

那么

C=1N−1XTXC=\dfrac{1}{N - 1}X^TXC=N11XTX

在这里,ϕ(x)\phi(x)ϕ(x)我们是不知道的,所以上式是没法算的。就算知道了,计算成本也太大了。故引入核函数,我们知道核函数有

K=XXT=[ϕ(x1)T...ϕ(xN)T][ϕ(x1),⋯,ϕ(xN)]=[κ(x1,x1)...κ(x1,xN)⋮⋱⋮κ(xN,x1)⋯κ(xN,xN)]K=XX^T=\begin{bmatrix} \phi(x_1)^T \\...\\ \phi(x_N)^T \end{bmatrix} [ \phi(x_1) , \cdots ,\phi(x_N)]=\begin{bmatrix} \kappa(x_1,x_1) & ... & \kappa(x_1,x_N) \\ \vdots & \ddots & \vdots \\ \kappa(x_N, x_1) & \cdots & \kappa(x_N,x_N) \end{bmatrix}K=XXT=ϕ(x1)T...ϕ(xN)T[ϕ(x1),,ϕ(xN)]=κ(x1,x1)κ(xN,x1)...κ(x1,xN)κ(xN,xN)

上述的KKK我们根据核函数的性质是可以算出来的,现在来看看KKKCCC之间有没有关系。
如果要求KKK的特征值和特征向量的话,我们有下式

(XXT)u=λu(XX^T)u=\lambda u(XXT)u=λu

其中,uuu为矩阵KKK的特征向量,λ\lambdaλ为矩阵KKK的特征值。
我们对左右两边同时左乘一个XTX^TXT

XT(XXT)u=λXTuX^T(XX^T)u=\lambda X^TuXT(XXT)u=λXTu

(XTX)(XTu)=λ(XTu)(X^TX)(X^Tu)=\lambda (X^Tu)(XTX)(XTu)=λ(XTu)

又由于(N−1)⋅C=XTX(N - 1) \cdot C=X^TX(N1)C=XTX,所以我们发现矩阵KKKCCC的特征值是相同的,都为λ\lambdaλCCC的特征向量为XTuX^TuXTu
由于我们希望特征向量是单位向量,所以我们对其做一下单位化

v=1∣∣XTu∣∣XTu=1uTXXTuXTu=1uTKuXTu=1uTλuXTu=1λXTuv=\dfrac{1}{||X^Tu||}X^Tu=\dfrac{1}{\sqrt{u^TXX^Tu}}X^Tu=\dfrac{1}{\sqrt{u^TKu}}X^Tu=\dfrac{1}{\sqrt{u^T\lambda u}}X^Tu=\dfrac{1}{\sqrt{\lambda}}X^Tuv=XTu1XTu=uTXXTu1XTu=uTKu1XTu=uTλu1XTu=λ1XTu

在上式中,λ\lambdaλuuu可以通过矩阵KKK求得,但是XTX^TXT仍旧是不可知的。那么CCC的特征向量还是算不出来,难道费了这么大的劲,我们白算了?不急,我们接着往下看。虽然求不出vvv,但是vvv并不是我们的最终目标,我们只要知道xxxvvv上的投影就可以了

vTϕ(xj)=(1λXTu)Tϕ(xj)=1λuTXϕ(xj)=1λuT[ϕ(x1)T⋮ϕ(xN)T]ϕ(xj)=1λuT[κ(x1,xj)⋮κ(xN,xj)]v^T\phi(x_j)=(\dfrac{1}{\sqrt{\lambda}}X^Tu)^T\phi(x_j)=\dfrac{1}{\sqrt{\lambda}}u^TX\phi(x_j)=\dfrac{1}{\sqrt{\lambda}}u^T\begin{bmatrix} \phi(x_1)^T \\ \vdots \\ \phi(x_N)^T \end{bmatrix} \phi(x_j)=\dfrac{1}{\sqrt{\lambda}}u^T\begin{bmatrix} \kappa(x_1, x_j) \\ \vdots \\ \kappa(x_N, x_j) \end{bmatrix}vTϕ(xj)=(λ1XTu)Tϕ(xj)=λ1uTXϕ(xj)=λ1uTϕ(x1)Tϕ(xN)Tϕ(xj)=λ1uTκ(x1,xj)κ(xN,xj)

上式中所有的量都是可以求得的,也就说我们在没有求出特征向量的情况下,直接算出了样本在特征向量上的投影!
这样一来问题就解决了!是不是很神奇!

4 PCA和KPCA在Python中的使用

在python的sklearn包中,已经对PCA和KPCA进行了实现,我们只需要调用函数即可,非常方便。

4.1 PCA的使用

我们用的数据集是UCI上关于葡萄酒的数据集,得到数据集后对其进行预处理,使得其均值为0。

import pandas as pd
from sklearn.preprocessing import StandardScalerdf = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data', header=None)
x, y = df.iloc[:, 1:].values, df.iloc[:, 0].values
sc = StandardScaler()
x = sc.fit_transform(x)

这个时候得到的xxx是一个178×13178 \times 13178×13规模的数据集,也就是说有131313个特征,每个特征下有178178178个数据。
我们用主成分分析法将131313个特征通过线性组合得到一个222个特征的数据集。

from sklearn.decomposition import PCApca = PCA(n_components=2)
x_pca = pca.fit_transform(x)

然后我们来看下效果

import matplotlib.pyplot as pltplt.scatter(x_pca[y==1, 0], x_pca[y==1, 1], color='red', marker='^', alpha=0.5)
plt.scatter(x_pca[y==2, 0], x_pca[y==2, 1], color='blue', marker='o', alpha=0.5)
plt.scatter(x_pca[y==3, 0], x_pca[y==3, 1], color='lightgreen', marker='s', alpha=0.5)
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()

可以得到
主成分分析

图2:葡萄酒数据主成分分析后效果

很显然,此时已经可以看成是线性可分的数据集了,效果不错。

4.2 KPCA的使用

PCA的使用是有局限性的,如果遇到了,一个像下面这样的线性不可分的数据集,就比较麻烦了。

from sklearn.datasets import make_moonsx2, y2 = make_moons(n_samples=100, random_state=123)plt.scatter(x2_std[y2==0, 0], x2_std[y2==0, 1], color='red', marker='^', alpha=0.5)
plt.scatter(x2_std[y2==1, 0], x2_std[y2==1, 1], color='blue', marker='o', alpha=0.5)
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()

MoonData

图3:非线性不可分的数据集

不相信的话我们可以用PCA先试下看

x2_std = sc.fit_transform(x2)
x_spca = pca.fit_transform(x2_std)fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(14,6))
ax[0].scatter(x_spca[y2==0, 0], x_spca[y2==0, 1], color='red', marker='^', alpha=0.5)
ax[0].scatter(x_spca[y2==1, 0], x_spca[y2==1, 1], color='blue', marker='o', alpha=0.5)
ax[1].scatter(x_spca[y2==0, 0], np.zeros((50,1))+0.02, color='red', marker='^', alpha=0.5)
ax[1].scatter(x_spca[y2==1, 0], np.zeros((50,1))+0.02, color='blue', marker='o', alpha=0.5)
ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')
plt.show()

主成分分非线性可分

图4:PCA在非线性可分数据集的效果

从图中可以看出,经过主成分分析之后,数据仍旧是线性不可分的。接下来,我们用基于核函数的主成分分析来试下看。

from sklearn.decomposition import KernelPCAkpca = KernelPCA(n_components=2, kernel='rbf', gamma=15)
x_kpca = kpca.fit_transform(x2_std)fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(14,6))
ax[0].scatter(x_kpca[y2==0, 0], x_kpca[y2==0, 1], color='red', marker='^', alpha=0.5)
ax[0].scatter(x_kpca[y2==1, 0], x_kpca[y2==1, 1], color='blue', marker='o', alpha=0.5)
ax[1].scatter(x_kpca[y2==0, 0], np.zeros((50,1))+0.02, color='red', marker='^', alpha=0.5)
ax[1].scatter(x_kpca[y2==1, 0], np.zeros((50,1))+0.02, color='blue', marker='o', alpha=0.5)
ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')
plt.show()

KPCA效果

图5:KPCA在非线性可分数据集的效果

由图可知,只需要把数据集投影到经变换后的特征PC1PC1PC1上就可以实现线性划分了,这个时候只需要一个特征PC1PC1PC1就够了。

5 参考文献

[1] https://www.youtube.com/watch?v=G2NRnh7W4NQ&t=1s
[2] Raschka S. Python Machine Learning[M]. Packt Publishing, 2015.

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

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

相关文章

算法分类整理+模板①:矩阵快速幂

一直有一个想法&#xff0c;感觉自己很多基础算法不是很扎实&#xff0c;想要找个机会写一些算法的整理&#xff0c;顺便自己总结一些实用的模板。 最近偶然在训练赛中连续做了2道思维矩阵快速幂的题目&#xff0c;碰巧有时间&#xff0c;就以矩阵快速幂作为这个系列博客的开始…

爬虫小记:利用cookies跳过登陆验证码

前言 在爬取某些网页时&#xff0c;登陆界面时经常遇到的一个坎&#xff0c;而现在大多数的网站在登陆时都会要求用户填写验证码。当然&#xff0c;我们可以设计一套机器学习的算法去破解验证码&#xff0c;然而&#xff0c;验证码的形式多种多样&#xff0c;稍微变一下&#…

Nodejs 中的包、npm 、第三方模块、 package.json 以及 cnpm

一、包与 NPM 包Nodejs 中除了它自己提供的核心模块外&#xff0c;我们可以自定义模块&#xff0c;也可以使用第三方的 模块。Nodejs 中第三方模块由包组成&#xff0c;可以通过包来对一组具有相互依赖关系的模块进行 统一管理。 完全符合 CommonJs 规范的包目录一般包含如下…

神经网络中BP(back propagation)到底在干些什么

前言 想要理解神经网络的工作原理&#xff0c;反向传播(BP)是必须搞懂的东西。BP其实并不难理解&#xff0c;说白了就是用链式法则(chain rule)算算算。本文试图以某个神经网络为例&#xff0c;尽可能直观&#xff0c;详细&#xff0c;明了地说明反向传播的整个过程。 正向传…

Nodejs 新特性 async await 的使用 以及使用 async await 处理异步

1. let 和 var 2. const定义常量 3. 模板字符串 4. 属性简写 5. 方法简写 6. 箭头函数 7. 回调函数 7. Promise 8. async 和 await

leetcode 高薪_LeetCode 第 125 号问题:验证回文串

本文首发于公众号「五分钟学算法」&#xff0c;是图解 LeetCode 系列文章之一。个人网站&#xff1a;https://www.cxyxiaowu.com题目来源于 LeetCode 第 125 号问题&#xff1a;验证回文串。这道题目是 初级程序员 在面试的时候经常遇到的一道算法题&#xff0c;而且面试官喜欢…

从拉格朗日乘子法到SVM

前言 本文主要是讲了如何构建SVM的模型&#xff0c;并利用KKT条件构造其对偶型&#xff0c;从而求解问题&#xff0c;并讲述了SVM的硬间隔&#xff0c;软间隔和核函数三个境界。主要参考了周志华的《机器学习》&#xff0c;并在其中补充了自己的想法。由于内容较多&#xff0c…

nodejs 创建一个静态资源服务器 +路由

0、补充 1、Node.js 创建的第一个应用 1、引入 http 模块 var http require("http"); 2、创建服务器 接下来我们使用 http.createServer() 方法创建服务器&#xff0c;并使用 listen 方法绑定 3000 端口。 函数通过 request, response 参数来接收和响应数据。 co…

python输出字体的大小_Python密码学编程:文件的加密与解密

在之前的章节中&#xff0c;编写的程序只能操作较少的信息&#xff0c;这些信息往往是以字符串的形式直接写在代码中的。但本章中的程序可以对整个文件进行加密和解密&#xff0c;文件的大小可以包括成千上万个字符。本章要点open()方法。读、写文件。write()、close()及read()…

电脑k歌软件_金麦客专业k歌app下载|金麦客专业k歌软件 手机安卓版v1.1.5.0 下载...

金麦客专业k歌app能够让用户通过手机直接连接电视&#xff0c;从而在安卓端实现金麦客点歌的目的&#xff0c;平台包含上万高清mv资源&#xff0c;让用户在歌唱时能够更好的代入氛围中&#xff0c;并且还能通过网络直接搜歌&#xff0c;从而在线下载播放&#xff0c;用户在演唱…

Nodejs ejs模板引擎

官方网站&#xff1a;https://www.npmjs.com/package/ejs 我们学的 EJS 是后台模板&#xff0c;可以把我们数据库和文件读取的数据显示到 Html 页面上面。它 是一个第三方模块&#xff0c;需要通过 npm 安装 npm install ejs –save 或者 cnpm install ejs --saveNodejs 中使用…

linux can总线接收数据串口打包上传_关于串口,你需要知道这些!!

嵌入式设备在电路中交换信息的时候必须通过共享一个通用的协议。现在嵌入式系统中已经定义了数百种通信协议来实现数据交换&#xff0c;一般来说可以将其分为两类&#xff1a;并行或串行。并行传输数据是指同时传输多个数据位&#xff0c;它们通常需要数据线和时钟线配合工作&a…

div里嵌套了img底部会有白块问题和图片一像素问题解决

div里嵌套了img底部会有白块 因为img默认是按基线(baseline)对齐的。对比一下图片和右边的p, q, y等字母&#xff0c;你会发现这三个字母的“小尾巴”和图片下方的空白一样高。下面这张图中的黑线就是那条基线。 解决方案&#xff1a;一&#xff1a;vertical-align: bottom&…

Nodejs 中的Get、Post

Get、Post 超文本传输协议&#xff08;HTTP&#xff09;的设计目的是保证客户端机器与服务器之间的通信。 在客户端和服务器之间进行请求-响应时&#xff0c;两种最常被用到的方法是&#xff1a;GET 和 POST。 GET - 从指定的资源请求数据。&#xff08;一般用于获取数据&#…

电脑故障扫描修复软件_电脑故障分析:电脑安装软件提示没有权限的解决方法...

我们安装软件时如果没有权限就会导致安装故障&#xff0c;最近就有用户安装软件的时候出现了无法将数值写入键software的错误提示&#xff0c;请验证您对该键拥有足够的访问权限&#xff0c;或者与您的技术支持人员联系。那么遇到这种问题该怎么办呢&#xff1f;接下来就让我们…

Nodejs 路由封装 封装一个类似 express 的路由

1、模块化的方式封装 routes.js: const http require(http); const fs require(fs); const path require(path) const url require(url) const ejs require(ejs) let getFileMime function (extname) {// 把异步读取文件方法改为同步读取文件方法let data fs.readFileSy…

天翼网关 ddns设置_19,微服务网关之Zuul

这一次给大家分享微服务网关的相关知识&#xff0c;这个也是微服务架构中&#xff0c;相当重要的组件之一&#xff0c;来&#xff0c;下面听我徐徐道来1&#xff0c;API网关概览1.1&#xff0c;现有的交互模式存在什么问题&#xff1f;目前&#xff0c;是客户端会直接跟多个微服…

MongoDB 数据库创建、删除、表(集合) 创建删除、数据的增、删、改、查

一、 连接数据库 1、连接数据库 清屏命令&#xff1a;cls 查看所有数据库列表:show dbs 二、 创建数据库、查看、删除数据库 1、使用数据库、创建数据库 use itying 如果真的想把这个数据库创建成功&#xff0c;那么必须插入一个数据。 数据库中不能直接插入数据&#xff0…

从LeetCode 210. Course Schedule II 了解拓扑排序

问题简述 给定n节课&#xff0c;每节课按0~n-1编号。 在修某些课的时候需要有其它课的基础&#xff0c;必须先上先修课。现在用pair的形式来表示要先修的课&#xff0c;比如 [ [0,1], [1,2] ] 就表示在修课程1之前必须先修课程0&#xff0c;修课程2之前必须修课程1。现在需要给…

MongoDb 大数据查询优化、 MongoDB 索引、复合索引、唯一索引、 explain 分 析查询速度

一、索引基础 索引是对数据库表中一列或多列的值进行排序的一种结构&#xff0c;可以让我们查询数据库变得 更快。 MongoDB 的索引几乎与传统的关系型数据库一模一样&#xff0c;这其中也包括一些基本的查询优化技巧。 下面是创建索引的命令&#xff1a; db.user.ensureIndex…