当前位置: 首页 > news >正文

【数学】主成分分析(PCA)的详细深度推导过程

本文基于Deep Learning (2017, MIT),推导过程补全了所涉及的知识及书中推导过程中跳跃和省略的部分。
blog

1 概述

现代数据集,如网络索引、高分辨率图像、气象学、实验测量等,通常包含高维特征,高纬度的数据可能不清晰、冗余,甚至具有误导性。数据可视化和解释变量之间的关系很困难,而使用这种高维数据训练的神经网络模型往往容易出现过拟合(维度诅咒)。
主成分分析(PCA)是一种简单而强大的无监督机器学习技术,用于数据降维。它旨在从大型变量集中提取一个较小的数据集,同时尽可能保留原始信息和特征(有损压缩)。PCA有助于识别数据集中最显著和有意义的特征,使数据易于可视化。应用场景包括:统计学、去噪和为机器学习算法预处理数据。

  • 主成分是什么?
    主成分是构建为原始变量的线性组合的新变量。这些新变量是不相关的,并且包含原始数据中大部分的信息。

2 背景数学知识

这些知识对下一节的推导很重要。

  • 正交向量和矩阵:
    • 如果两个向量垂直,则它们是正交的。即两个向量的点积为零。
    • 正交矩阵是一个方阵,其行和列是相互正交的单位向量;每两行和两列的点积为零,每一行和每一列的大小为1。
    • 如果 A T = A − 1 A^T=A^{-1} AT=A1 A A T = A T A = I AA^T=A^TA=I AAT=ATA=I,则 A A A是正交矩阵。
    • 在机器人学中,旋转矩阵通常是一个 3 × 3 3\times3 3×3的正交矩阵,在空间变换中它会旋转向量的方向但保持原始向量的大小。
  • 矩阵、向量乘法规则:
    • ( A B ) T = B T A T (AB)^T=B^TA^T (AB)T=BTAT,两个矩阵的乘积的转置。
    • a ⃗ T b ⃗ = b ⃗ T a ⃗ \vec{a}^T\vec{b}=\vec{b}^T\vec{a} a Tb =b Ta ,两个结果都是标量,标量的转置是相同的。
    • ( A + B ) C = A C + B C (A + B)C = AC + BC (A+B)C=AC+BC,乘法是可分配的。
    • A B ≠ B A AB \neq{} BA AB=BA,乘法一般不满足交换律。
    • A ( B C ) = ( A B ) C A(BC)=(AB)C A(BC)=(AB)C,乘法满足结合律。
  • 对称矩阵:
    • A = A T A=A^T A=AT A A A是对称矩阵。
    • X T X X^TX XTX是对称矩阵,因为 ( X T X ) T = X T X (X^TX)^T=X^TX (XTX)T=XTX
  • 向量导数规则( B B B是常量矩阵):
    • d ( x T B ) / d x = B d(x^TB)/dx=B d(xTB)/dx=B
    • d ( x T x ) / d x = 2 x d(x^Tx)/dx=2x d(xTx)/dx=2x
    • d ( x T B x ) / d x = 2 B x d(x^TBx)/dx=2Bx d(xTBx)/dx=2Bx
  • 矩阵迹规则:
    • T r ( A ) = T r ( A T ) Tr(A)=Tr(A^T) Tr(A)=Tr(AT)
    • T r ( A B ) = T r ( B A ) Tr(AB)=Tr(BA) Tr(AB)=Tr(BA)
    • T r ( A ) = ∑ i λ i Tr(A)=\sum_i{\lambda_i} Tr(A)=iλi,其中 λ \lambda λ A A A的特征值。
    • 迹在循环移位下不变: T r ( A B C D ) = T r ( B C D A ) = T r ( C D A B ) = T r ( D A B C ) Tr(ABCD)=Tr(BCDA)=Tr(CDAB)=Tr(DABC) Tr(ABCD)=Tr(BCDA)=Tr(CDAB)=Tr(DABC)
  • 向量和矩阵范数:
    • 向量的 L 2 L^2 L2范数,也称为欧几里得范数: ∣ ∣ x ∣ ∣ 2 = ∑ i ∣ x i ∣ 2 ||x||_2=\sqrt{\sum_i|x_i|^2} ∣∣x2=ixi2
    • 通常使用平方的 L 2 L^2 L2范数来衡量向量的大小,可以计算为 x T x x^Tx xTx
    • Frobenius范数用于衡量矩阵的大小: ∣ ∣ A ∣ ∣ F = ∑ i , j A i , j 2 ||A||_F=\sqrt{\sum_{i,j}A^2_{i,j}} ∣∣AF=i,jAi,j2
    • Frobenius范数是所有矩阵元素的绝对平方和的平方根。
    • Frobenius范数是矩阵版本的欧几里得范数。
  • 特征值分解和特征值:
    • 方阵 A A A的特征向量是一个非零向量 v v v,使得 A A A的乘法仅改变 v v v的比例: A v = λ v Av=\lambda v Av=λv λ \lambda λ是特征值, v v v是特征向量。
    • 假设矩阵 A A A n n n个线性无关的特征向量 v ( i ) v^{(i)} v(i),我们可以将所有特征向量连接起来形成一个矩阵 V = [ v ( 1 ) , … , v ( n ) ] V=[v^{(1)},\ldots,v^{(n)}] V=[v(1),,v(n)],并通过连接所有特征值 λ = [ λ 1 , … , λ n ] T \lambda=[\lambda_1,\ldots,\lambda_n]^T λ=[λ1,,λn]T形成一个向量,那么 A A A特征分解 A = V d i a g ( λ ) V − 1 A=Vdiag(\lambda)V^{-1} A=Vdiag(λ)V1
    • 每个实对称矩阵都可以分解为 A = Q Λ Q T A=Q\Lambda Q^T A=QΛQT,其中 Q Q Q是由 A A A的特征向量组成的正交矩阵, Λ \Lambda Λ(读作’lambda’)是一个对角矩阵。
  • 拉格朗日乘数法:
    • 拉格朗日乘数法是一种在方程约束下寻找函数局部最大值和最小值的策略。
    • 一般形式: L ( x , λ ) = f ( x ) + λ ⋅ g ( x ) \mathcal{L}(x,\lambda)=f(x)+\lambda\cdot g(x) L(x,λ)=f(x)+λg(x) λ \lambda λ称为拉格朗日乘子。

3 详细PCA推导

需求描述

我们有 m m m个点的输入数据,表示为 x ( 1 ) , . . . , x ( m ) {x^{(1)},...,x^{(m)}} x(1),...,x(m) R n \mathbb{R}^{n} Rn的实数集中。因此,每个点 x ( i ) x^{(i)} x(i)是一个列向量,具有 n n n维特征。

需要对输入数据进行有损压缩,将这些点编码以表示它们的较低维度版本。换句话说,我们想要找到编码向量 c ( i ) ∈ R l c^{(i)}\in \mathbb{R}^{l} c(i)Rl ( l < n ) (l<n) (l<n)来表示每个输入点 x ( i ) x^{(i)} x(i)。我们的目标是找到产生输入的编码向量的编码函数 f ( x ) = c f(x)=c f(x)=c,以及相应的重构(解码)函数 x ≈ g ( f ( x ) ) x\approx g(f(x)) xg(f(x)),根据编码向量 c c c计算原始输入。

解码的 g ( f ( x ) ) g(f(x)) g(f(x))是一组新的点(变量),因此它与原始 x x x是近似的。存储 c ( i ) c^{(i)} c(i)和解码函数比存储 x ( i ) x^{(i)} x(i)更节省空间,因为 c ( i ) c^{(i)} c(i)的维度较低。

解码矩阵

我们选择使用矩阵 D D D作为解码矩阵,将编码向量 c ( i ) c^{(i)} c(i)映射回 R n \mathbb{R}^{n} Rn,因此 g ( c ) = D c g(c)=Dc g(c)=Dc,其中 D ∈ R n × l D\in \mathbb{R}^{n\times l} DRn×l。为了简化编码问题,PCA将 D D D的列约束为彼此正交。

衡量重构的表现

在继续之前,我们需要弄清楚如何生成最优的编码点 c ∗ c^{*} c,我们可以测量输入点 x x x与其重构 g ( c ∗ ) g(c^*) g(c)之间的距离,使用 L 2 L^2 L2范数(或欧几里得范数): c ∗ = arg ⁡ min ⁡ c ∣ ∣ x − g ( c ) ∣ ∣ 2 c^{*}=\arg\min_c||x-g(c)||_2 c=argminc∣∣xg(c)2。由于 L 2 L^2 L2范数是非负的,并且平方操作是单调递增的,所以我们可以转而使用平方的 L 2 L^2 L2范数:
c ∗ = arg ⁡ min ⁡ c ∣ ∣ x − g ( c ) ∣ ∣ 2 2 c^{*}={\arg\min}_c||x-g(c)||_2^2 c=argminc∣∣xg(c)22 向量的 L 2 L^2 L2范数是其分量的平方和,它等于向量与自身的点积,例如 ∣ ∣ x ∣ ∣ 2 = ∑ ∣ x i ∣ 2 = x T x ||x||_2=\sqrt{\sum|x_i|^2}=\sqrt{x^Tx} ∣∣x2=xi2 =xTx ,因此平方的 L 2 L^2 L2范数可以写成以下形式:
∣ ∣ x − g ( c ) ∣ ∣ 2 2 = ( x − g ( c ) ) T ( x − g ( c ) ) ||x-g(c)||_2^2 = (x-g(c))^T(x-g(c)) ∣∣xg(c)22=(xg(c))T(xg(c)) 由分配率:
= ( x T − g ( c ) T ) ( x − g ( c ) ) = x T x − x T g ( c ) − g ( c ) T x + g ( c ) T g ( c ) =(x^T-g(c)^T)(x-g(c))=x^Tx-x^Tg(c)-g(c)^Tx+g(c)^Tg(c) =(xTg(c)T)(xg(c))=xTxxTg(c)g(c)Tx+g(c)Tg(c) 由于 x T g ( c ) x^Tg(c) xTg(c) g ( c ) T x g(c)^Tx g(c)Tx是标量,标量等于其转置, ( g ( c ) T x ) T = x T g ( c ) (g(c)^Tx)^T=x^Tg(c) (g(c)Tx)T=xTg(c),所以:
= x T x − 2 x T g ( c ) + g ( c ) T g ( c ) =x^Tx-2x^Tg(c)+g(c)^Tg(c) =xTx2xTg(c)+g(c)Tg(c) 为了找到使上述函数最小化的 c c c,第一项可以省略,因为它不依赖于 c c c,所以:
c ∗ = arg ⁡ min ⁡ c − 2 x T g ( c ) + g ( c ) T g ( c ) c^*={\arg\min}_c-2x^Tg(c)+g(c)^Tg(c) c=argminc2xTg(c)+g(c)Tg(c) 然后用 g ( c ) g(c) g(c)的定义 D c Dc Dc进行替换:
= arg ⁡ min ⁡ c − 2 x T D c + c T D T D c ={\arg\min}_c-2x^TDc+c^TD^TDc =argminc2xTDc+cTDTDc 由于 D D D的正交性和单位范数约束:
c ∗ = arg ⁡ min ⁡ c − 2 x T D c + c T I l c c^*={\arg\min}_c-2x^TDc+c^TI_lc c=argminc2xTDc+cTIlc = arg ⁡ min ⁡ c − 2 x T D c + c T c = {\arg\min}_c-2x^TDc+c^Tc =argminc2xTDc+cTc

目标函数

现在目标函数是 − 2 x T D c + c T c -2x^TDc+c^Tc 2xTDc+cTc,我们需要找到 c ∗ c^* c来最小化目标函数。使用向量微积分,并令其导数等于0:
∇ c ( − 2 x T D c + c T c ) = 0 \nabla_c(-2x^TDc+c^Tc)=0 c(2xTDc+cTc)=0 根据向量导数规则:
− 2 D T x + 2 c = 0 ⇒ c = D T x -2D^Tx+2c=0 \Rightarrow c=D^Tx 2DTx+2c=0c=DTx

找到编码矩阵 D D D

所以编码器函数是 f ( x ) = D T x f(x)=D^Tx f(x)=DTx。因此我们可以定义 PCA 重构操作为 r ( x ) = g ( f ( x ) ) = D ( D T x ) = D D T x r(x)=g(f(x))=D(D^Tx)=DD^Tx r(x)=g(f(x))=D(DTx)=DDTx

因此编码矩阵 D D D 也被重构过程使用。我们需要找到最优的 D D D 来最小化重构误差,即输入和重构之间所有维度特征的距离。这里使用 Frobenius 范数(矩阵范数)定义目标函数:
D ∗ = arg ⁡ min ⁡ D ∑ i , j ( x j ( i ) − r ( x i ) j ) 2 , D T D = I l D^*={\arg\min}_D\sqrt{\sum_{i,j}(x_j^{(i)}-r(x^{i})_j)^2},\quad D^TD=I_l D=argminDi,j(xj(i)r(xi)j)2 ,DTD=Il 从考虑 l = 1 l=1 l=1 的情况开始(这也是第一个主成分), D D D 是一个单一向量 d d d,并使用平方 L 2 L^2 L2 范数形式:
d ∗ = arg ⁡ min ⁡ d ∑ i ∣ ∣ ( x ( i ) − r ( x i ) ) ∣ ∣ 2 2 , ∣ ∣ d ∣ ∣ 2 = 1 d^*={\arg\min}_d{\sum_{i}||(x^{(i)}-r(x^{i}))}||_2^2, ||d||_2=1 d=argmindi∣∣(x(i)r(xi))22,∣∣d2=1 = arg ⁡ min ⁡ d ∑ i ∣ ∣ ( x ( i ) − d d T x ( i ) ) ∣ ∣ 2 2 , ∣ ∣ d ∣ ∣ 2 = 1 = {\arg\min}_d{\sum_{i}||(x^{(i)}-dd^Tx^{(i)})||_2^2}, ||d||_2=1 =argmindi∣∣(x(i)ddTx(i))22,∣∣d2=1 d T x ( i ) d^Tx^{(i)} dTx(i) 是一个标量:
= arg ⁡ min ⁡ d ∑ i ∣ ∣ ( x ( i ) − d T x ( i ) d ) ∣ ∣ 2 2 , ∣ ∣ d ∣ ∣ 2 = 1 = {\arg\min}_d{\sum_{i}||(x^{(i)}-d^Tx^{(i)}d)}||_2^2, ||d||_2=1 =argmindi∣∣(x(i)dTx(i)d)22,∣∣d2=1 标量等于其自身的转置:
d ∗ = arg ⁡ min ⁡ d ∑ i ∣ ∣ ( x ( i ) − x ( i ) T d d ) ∣ ∣ 2 2 , ∣ ∣ d ∣ ∣ 2 = 1 d^*= {\arg\min}_d{\sum_{i}||(x^{(i)}-x^{(i)T}dd)}||_2^2, ||d||_2=1 d=argmindi∣∣(x(i)x(i)Tdd)22,∣∣d2=1

使用矩阵形式表示

X ∈ R m × n X\in \mathbb{R}^{m\times n} XRm×n 表示所有描述点的向量堆叠,即 { x ( 1 ) T , x ( 2 ) T , … , x ( i ) T , … , x ( m ) T } \{x^{(1)^T}, x^{(2)^T}, \ldots, x^{(i)^T}, \ldots, x^{(m)^T}\} {x(1)T,x(2)T,,x(i)T,,x(m)T},使得 X i , : = x ( i ) T X_{i,:}=x^{(i)^T} Xi,:=x(i)T

X = [ x ( 1 ) T x ( 2 ) T … x ( m ) T ] ⇒ X d = [ x ( 1 ) T d x ( 2 ) T d … x ( m ) T d ] X = \begin{bmatrix} x^{(1)^T}\\ x^{(2)^T}\\ \ldots\\ x^{(m)^T} \end{bmatrix} \Rightarrow Xd = \begin{bmatrix} x^{(1)^T}d\\ x^{(2)^T}d\\ \ldots\\ x^{(m)^T}d \end{bmatrix} X= x(1)Tx(2)Tx(m)T Xd= x(1)Tdx(2)Tdx(m)Td ⇒ X d d T = [ x ( 1 ) T d d T x ( 2 ) T d d T … x ( m ) T d d T ] \Rightarrow Xdd^T = \begin{bmatrix} x^{(1)^T}dd^T\\ x^{(2)^T}dd^T\\ \ldots\\ x^{(m)^T}dd^T\\ \end{bmatrix} XddT= x(1)TddTx(2)TddTx(m)TddT ⇒ X − X d d T = [ x ( 1 ) T − x ( 1 ) T d d T x ( 2 ) T − x ( 2 ) T d d T … x ( m ) T − x ( m ) T d d T ] \Rightarrow X-Xdd^T = \begin{bmatrix} x^{(1)^T}-x^{(1)^T}dd^T\\ x^{(2)^T}-x^{(2)^T}dd^T\\ \ldots\\ x^{(m)^T}-x^{(m)^T}dd^T\\ \end{bmatrix} XXddT= x(1)Tx(1)TddTx(2)Tx(2)TddTx(m)Tx(m)TddT 矩阵中的一行的转置:
( x ( i ) T − x ( i ) T d d T ) T = x ( i ) − d d T x ( i ) (x^{(i)^T}-x^{(i)^T}dd^T)^T=x^{(i)}-dd^Tx^{(i)} (x(i)Tx(i)TddT)T=x(i)ddTx(i) 由于 d T x ( i ) d^Tx^{(i)} dTx(i) 是标量:
= x ( i ) − d T x ( i ) d = x ( i ) − x ( i ) T d d =x^{(i)}-d^Tx^{(i)}d=x^{(i)}-x^{(i)^T}dd =x(i)dTx(i)d=x(i)x(i)Tdd 所以我们知道 X X X 的第 i i i 行的 L 2 L^2 L2 范数与原始形式相同,因此我们可以使用矩阵重写问题,并省略求和符号:
d ∗ = arg ⁡ min ⁡ d ∣ ∣ X − X d d T ∣ ∣ F 2 , d T d = 1 d^*={\arg\min}_{d}||X-Xdd^T||_F^2, \quad d^Td=1 d=argmind∣∣XXddTF2,dTd=1 利用矩阵迹规则简化 Frobenius 范数部分如下:
arg ⁡ min ⁡ d ∣ ∣ X − X d d T ∣ ∣ F 2 {\arg\min}_{d}||X-Xdd^T||_F^2 argmind∣∣XXddTF2 = arg ⁡ min ⁡ d T r ( ( X − X d d T ) T ( X − X d d T ) ) ={\arg\min}_{d}Tr((X-Xdd^T)^T(X-Xdd^T)) =argmindTr((XXddT)T(XXddT)) = arg ⁡ min ⁡ d − T r ( X T X d d T ) − T r ( d d T X T X ) + T r ( d d T X T X d d T ) ={\arg\min}_{d}-Tr(X^TXdd^T)-Tr(dd^TX^TX)+Tr(dd^TX^TXdd^T) =argmindTr(XTXddT)Tr(ddTXTX)+Tr(ddTXTXddT) = arg ⁡ min ⁡ d − 2 T r ( X T X d d T ) + T r ( X T X d d T d d T ) ={\arg\min}_{d}-2Tr(X^TXdd^T)+Tr(X^TXdd^Tdd^T) =argmind2Tr(XTXddT)+Tr(XTXddTddT) 由于 d T d = 1 d^Td=1 dTd=1
= arg ⁡ min ⁡ d − 2 T r ( X T X d d T ) + T r ( X T X d d T ) ={\arg\min}_{d}-2Tr(X^TXdd^T)+Tr(X^TXdd^T) =argmind2Tr(XTXddT)+Tr(XTXddT) = arg ⁡ min ⁡ d − T r ( X T X d d T ) ={\arg\min}_{d}-Tr(X^TXdd^T) =argmindTr(XTXddT) = arg ⁡ max ⁡ d T r ( X T X d d T ) ={\arg\max}_{d}Tr(X^TXdd^T) =argmaxdTr(XTXddT) 由于迹是循环置换不变的,将方程重写为:
d ∗ = arg ⁡ max ⁡ d T r ( d T X T X d ) , d T d = 1 d^*={\arg\max}_{d}Tr(d^TX^TXd), \quad d^Td=1 d=argmaxdTr(dTXTXd),dTd=1 由于 d T X T X d d^TX^TXd dTXTXd 是实数,因此迹符号可以省略:
d ∗ = arg ⁡ max ⁡ d d T X T X d , d T d = 1 d^*={\arg\max}_{d}d^TX^TXd,\quad d^Td=1 d=argmaxddTXTXd,dTd=1

寻找最优的 d d d

现在的问题是找到最优的 d d d 来最大化 d T X T X d d^TX^TXd dTXTXd,并且有约束条件 d T d = 1 d^Td=1 dTd=1

使用拉格朗日乘子法来将问题描述为关于 d d d 的形式:
L ( d , λ ) = d T X T X d + λ ( d T d − 1 ) \mathcal{L}(d,\lambda)=d^TX^TXd+\lambda(d^Td-1) L(d,λ)=dTXTXd+λ(dTd1) d d d 求导数(向量导数规则):
∇ d L ( d , λ ) = 2 X T X d + 2 λ d \nabla_d\mathcal{L}(d,\lambda)=2X^TXd+2\lambda d dL(d,λ)=2XTXd+2λd 令导数等于0, d d d 将是最优的:
2 X T X d + 2 λ d = 0 2X^TXd+2\lambda d=0 2XTXd+2λd=0 X T X d = − λ d X^TXd=-\lambda d XTXd=λd X T X d = λ ′ d , ( λ ′ = − λ ) X^TXd=\lambda' d,\quad(\lambda'=-\lambda) XTXd=λd,(λ=λ) 这个方程是典型的矩阵特征值分解形式, d d d 是矩阵 X T X X^TX XTX 的特征向量, λ ′ \lambda' λ 是对应的特征值。

利用上述结果,让我们重新审视原方程:
d ∗ = arg ⁡ max ⁡ d d T X T X d , d T d = 1 d^*={\arg\max}_{d}d^TX^TXd, \quad d^Td=1 d=argmaxddTXTXd,dTd=1 = arg ⁡ max ⁡ d d T λ ′ d ={\arg\max}_{d}d^T\lambda' d =argmaxddTλd = arg ⁡ max ⁡ d λ ′ d T d ={\arg\max}_{d}\lambda'd^T d =argmaxdλdTd = arg ⁡ max ⁡ d λ ′ ={\arg\max}_{d}\lambda' =argmaxdλ 现在问题已经变的非常清楚了, X T X X^TX XTX 的最大特征值会最大化原方程的结果,因此最优的 d d d 是矩阵 X T X X^TX XTX 对应最大特征值的特征向量。

这个推导是针对 l = 1 l=1 l=1 的情况,只包含第一个主成分。当 l > 1 l>1 l>1 时, D = [ d 1 , d 2 , … ] D=[d_1, d_2, \ldots] D=[d1,d2,],第一个主成分 d 1 d_1 d1 是矩阵 X T X X^TX XTX 对应最大特征值的特征向量,第二个主成分 d 2 d_2 d2 是对应第二大特征值的特征向量,以此类推。


4 总结

我们有一个数据集,包含 m m m 个点,记为 x ( 1 ) , . . . , x ( m ) {x^{(1)},...,x^{(m)}} x(1),...,x(m)
X ∈ R m × n X\in \mathbb{R}^{m\times n} XRm×n 为将所有这些点堆叠而成的矩阵: [ x ( 1 ) T , x ( 2 ) T , … , x ( i ) T , … , x ( m ) T ] [x^{(1)^T}, x^{(2)^T}, \ldots, x^{(i)^T}, \ldots, x^{(m)^T}] [x(1)T,x(2)T,,x(i)T,,x(m)T]

主成分分析(PCA)编码函数表示为 f ( x ) = D T x f(x)=D^Tx f(x)=DTx,重构函数表示为 x ≈ g ( c ) = D c x\approx g(c)=Dc xg(c)=Dc,其中 D = [ d 1 , d 2 , … ] D=[d_1, d_2, \ldots] D=[d1,d2,] 的列是 X T X X^TX XTX 的特征向量,特征向量对应的特征值大小为降序排列。 D T x D^Tx DTx即是降维度之后的数据。


呼~
后续恢复元气后会分析一些PCA的应用案例。

在这里插入图片描述

“Remember, Red, hope is a good thing, maybe the best of things, and no good thing ever dies.
I will be hoping that this letter finds you, and finds you well.”

相关文章:

【数学】主成分分析(PCA)的详细深度推导过程

本文基于Deep Learning (2017, MIT)&#xff0c;推导过程补全了所涉及的知识及书中推导过程中跳跃和省略的部分。 blog 1 概述 现代数据集&#xff0c;如网络索引、高分辨率图像、气象学、实验测量等&#xff0c;通常包含高维特征&#xff0c;高纬度的数据可能不清晰、冗余&am…...

微信跳转页面时发生报错

报错如下图所示&#xff1a; 解决方法&#xff1a;&#xff08;从下面四种跳转方式中任选一种&#xff0c;哪种能实现效果就用哪个&#xff09; 带历史回退 wx.navigateTo() //不能跳转到tabbar页面 不带历史回退 wx.redirectTo() //跳转到另一个页面wx.switchTab() //只能…...

8:系统开发基础--8.1:软件工程概述、8.2:软件开发方法 、8.3:软件开发模型、8.4:系统分析

转上一节&#xff1a; http://t.csdnimg.cn/G7lfmhttp://t.csdnimg.cn/G7lfm 课程内容提要&#xff1a; 8&#xff1a;知识点考点详解 8.1&#xff1a;软件工程概述 1.软件的生存周期 2.软件过程改进—CMM Capability Maturity Model能力成熟度模型 3.软件过程改进—CMMI—…...

【简单讲解下Symfony框架】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…...

[Linux基础]ln硬链接和ln -s软链接的方法参数及区别

区别&#xff1a; 1、ln创建硬链接&#xff1b;ln -s 创建软链接 2、硬链接的两个文件指向同一个inode&#xff08;inode&#xff1a;存放着文件的目录、权限、block块编号等信息&#xff09;&#xff1b;软链接的目标文件指向源文件&#xff0c;目标文件内存储的是源文件的目…...

开源博客项目Blog .NET Core源码学习(15:App.Hosting项目结构分析-3)

本文学习并分析App.Hosting项目中前台页面的关于本站页面和点点滴滴页面。 关于本站页面 关于本站页面相对而言布局简单&#xff0c;与后台控制器类的交互也不算复杂。整个页面主要使用了layui中的面包屑导航、选项卡、模版、流加载等样式或模块。   面包屑导航。使用layui…...

【muzzik 分享】3D模型平面切割

# 前言 一年一度的征稿到了&#xff0c;倒腾点存货&#xff0c;3D平面切割通常用于一些解压游戏里&#xff0c;例如水果忍者&#xff0c;切菜这些&#xff0c;今天我就给大家讲讲怎么实现3D切割以及其原理&#xff0c;帮助大家更理解3D中的 Mesh(网格)&#xff0c;以及UV贴图和…...

SCI一区 | Matlab实现OOA-TCN-BiGRU-Attention鱼鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测

SCI一区 | Matlab实现OOA-TCN-BiGRU-Attention鱼鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测 目录 SCI一区 | Matlab实现OOA-TCN-BiGRU-Attention鱼鹰算法优化时间卷积双向门控循环单元融合注意力机制多变量时间序列预测预测效果基本介绍模型描述程序…...

nodejs安装常用命令

安装 Node.js 后&#xff0c;你可以在命令行中使用以下常用命令&#xff1a; node&#xff1a;启动 Node.js 的交互式解释器&#xff0c;可以直接在命令行中执行 JavaScript 代码。 npm install <package-name>&#xff1a;安装一个 Node.js 模块&#xff0c;<packag…...

使用 Prometheus 在 KubeSphere 上监控 KubeEdge 边缘节点(Jetson) CPU、GPU 状态

作者&#xff1a;朱亚光&#xff0c;之江实验室工程师&#xff0c;云原生/开源爱好者。 KubeSphere 边缘节点的可观测性 在边缘计算场景下&#xff0c;KubeSphere 基于 KubeEdge 实现应用与工作负载在云端与边缘节点的统一分发与管理&#xff0c;解决在海量边、端设备上完成应…...

OSI七层网络模型 —— 筑梦之路

在信息技术领域&#xff0c;OSI七层模型是一个经典的网络通信框架&#xff0c;它将网络通信分为七个层次&#xff0c;每一层都有其独特的功能和作用。为了帮助记忆这七个层次&#xff0c;有一个巧妙的方法&#xff1a;将每个层次的英文单词首字母组合起来&#xff0c;形成了一句…...

状态模式:管理对象状态转换的动态策略

在软件开发中&#xff0c;状态模式是一种行为型设计模式&#xff0c;它允许一个对象在其内部状态改变时改变它的行为。这种模式把与特定状态相关的行为局部化&#xff0c;并且将不同状态的行为分散到对应的状态类中&#xff0c;使得状态和行为可以独立变化。本文将详细介绍状态…...

【论文阅读】MCTformer: 弱监督语义分割的多类令牌转换器

【论文阅读】MCTformer: 弱监督语义分割的多类令牌转换器 文章目录 【论文阅读】MCTformer: 弱监督语义分割的多类令牌转换器一、介绍二、联系工作三、方法四、实验结果 Multi-class Token Transformer for Weakly Supervised Semantic Segmentation 本文提出了一种新的基于变换…...

FMix: Enhancing Mixed Sample Data Augmentation 论文阅读

1 Abstract 近年来&#xff0c;混合样本数据增强&#xff08;Mixed Sample Data Augmentation&#xff0c;MSDA&#xff09;受到了越来越多的关注&#xff0c;出现了许多成功的变体&#xff0c;例如MixUp和CutMix。通过研究VAE在原始数据和增强数据上学习到的函数之间的互信息…...

2024蓝桥A组A题

艺术与篮球&#xff08;蓝桥&#xff09; 问题描述格式输入格式输出评测用例规模与约定解析参考程序难度等级 问题描述 格式输入 无 格式输出 一个整数 评测用例规模与约定 无 解析 模拟就好从20000101-20240413每一天计算笔画数是否大于50然后天数&#xff1b; 记得判断平…...

Linux journalctl命令详解

文章目录 1.介紹2.概念设置system time基本的日志查阅方法按时过滤日志&#xff08;by Time&#xff09;显示本次启动以来的日志&#xff08;Current Boot&#xff09;按Past Boots按时间窗口按感兴趣的消息筛选按unit按进程、用户、Group ID按组件路径显示内核消息按消息优先级…...

恢复MySQL!是我的条件反射,PXB开源的力量...

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…...

Storm详细配置

一、认识Storm Apache Storm是个实时数据处理的“大能”&#xff0c;它可以实时接收、处理并转发大量数据流&#xff0c;就像一个高速运转的物流中心&#xff0c;确保数据及时、准确地到达目的地。我们要做的&#xff0c;就是把这个物流中心搭建起来&#xff0c;并且根据我们的…...

linux redis部署教程

单节点部署&#xff1a; 单节点部署 Redis 非常简单&#xff0c;只需要在一台服务器上安装 Redis 服务即可。以下是在 Linux 环境下的单节点部署步骤&#xff1a; 安装 Redis&#xff1a;打开终端&#xff0c;并执行以下命令来更新软件包列表并安装 Redis 服务器&#xff1a;…...

【Java】隐式锁(synchronized):如何解决餐厅等座的并发难题

当你走进一家熙熙攘攘的餐厅&#xff0c;准备享受一顿美味的晚餐时&#xff0c;你是否曾想过&#xff0c;这里正上演着一场场微观的线程战争&#xff1f;在这个场景中&#xff0c;每一张桌子都代表着珍贵的共享资源&#xff0c;而每一位顾客&#xff08;线程&#xff09;都在争…...

科技论文和会议录制高质量Presentation Video视频方法

一、背景 机器人领域&#xff0c;许多高质量的期刊和会议&#xff08;如IEEE旗下的TRO&#xff0c;RAL&#xff0c;IROS&#xff0c;ICRA等&#xff09;在你的论文收录后&#xff0c;需要上传一个Presentation Video材料&#xff0c;且对设备兼容性和视频质量有较高要求&#…...

Spring高手之路17——动态代理的艺术与实践

文章目录 1. 背景2. JDK动态代理2.1 定义和演示2.2 不同方法分别代理2.3 熔断限流和日志监控 3. CGLIB动态代理3.1 定义和演示3.2 不同方法分别代理&#xff08;对比JDK动态代理写法&#xff09;3.3 熔断限流和日志监控&#xff08;对比JDK动态代理写法&#xff09; 4. 动态代理…...

如何在Unity中使用设计模式

在 Unity 环境中,设计模式是游戏开发人员遇到的常见问题的通用解决方案。将它们视为解决游戏开发中特定挑战的经过验证的模板或蓝图。以下是一些简单易懂的设计模式: 1. 单例=> 单例模式确保一个类只有一个实例,并提供对该实例的全局访问点。在 Unity 中,可以使用单例模…...

基于springboot+vue+Mysql的旅游管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...

vue3+ts中判断输入的值是不是经纬度格式

vue3ts中判断输入的值是不是经纬度格式 vue代码&#xff1a; <template #bdjhwz"{ record }"><a-row :gutter"8" v-show"!record.editable"><a-col :span"12"><a-input placeholder"经度" v-model:v…...

python常用知识总结

文章目录 1. 常用内置函数1. ASCII码与字符相互转换 1. 常用内置函数 1. ASCII码与字符相互转换 # 用户输入字符 c input("请输入一个字符: ")# 用户输入ASCII码&#xff0c;并将输入的数字转为整型 a int(input("请输入一个ASCII码: "))print( c &qu…...

常用的启发式算法

A算法&#xff1a;在电子地图导航软件中&#xff0c;当你输入目的地时&#xff0c;软件就会利用A算法来计算从现在的位置到目的地的最佳路径。该算法兼顾了路径的优化以及计算速度&#xff0c;保证了结果的准确性以及反馈的实时性。 模拟退火算法&#xff1a;模拟退火算法常被…...

应该如何进行POC测试?—【DBA从入门到实践】第三期

在数据库选型过程中&#xff0c;为确保能够灵活应对数据规模的不断扩大和处理需求的日益复杂化&#xff0c;企业和技术人员会借助POC测试来评估不同数据库系统的性能。在测试过程中&#xff0c;性能、并发处理能力、存储成本以及高可用性等核心要素通常会成为大家关注的焦点&am…...

通过Clojure中的集合与序列谈谈抽象的重要

与君共勉&#xff1a;生命不息&#xff0c;学习不止&#xff0c;切忌浮躁&#xff0c;静下心来&#xff0c;每天进步一点点。 Clojure简介 Clojure是一门运行在JVM上面的Lisp方言&#xff0c;其它的Lisp方言还有Scheme、Common Lisp等。Lisp相关的著名书籍有《计算机程序的构…...

Rust---模式(Pattern)匹配

目录 模式是什么它用来做什么模式匹配和赋值为什么会有模式匹配模式匹配用在什么地方match 表达式if let表达式while let表达式for 循环let 语句函数参数不可驳模式匹配和可驳模式匹配模式是什么 在Rust中,模式(Pattern)是一种用于匹配和解构数据的语法结构。模式匹配中常用…...