【数学】主成分分析(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.”

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

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

相关文章

开源项目one-api的k8s容器化部署(上)-- 制作镜像及部署准备

一、背景 最近需要对开源项目one-api进行k8s容器化部署&#xff0c;主要分以下几个步骤&#xff1a; 制作docker镜像申请mysql和redis数据库docker-compose部署方式k8s部署方式 整个的篇幅比较长&#xff0c;将会分成上下两篇来阐述。 二、制作docker镜像 开源项目one-api…

2024 年(第 12 届)“泰迪杯”C 题:竞赛论文的辅助自动评阅

一、问题背景 近年来我国各领域各层次学科竞赛百花齐放&#xff0c;层出不穷&#xff0c;学生参与度也越来越高。随着参赛队伍的增加&#xff0c;评阅论文的工作量急剧增加&#xff0c;这对评阅论文的人力要求也越来越大。因此引入机器辅助评阅成为竞赛主办方的现实需求。 在…

Linux的学习之路:9、冯诺依曼与进程(1)

摘要 本章主要是说一下冯诺依曼体系结构和进程的一部分东西。 目录 摘要 一、冯诺依曼体系结构 二、操作系统的概念 三、设计OS的目的 四、管理 五、进程的基本概念 六、PCB 七、在Linux环境下查看进程 八、使用代码创建进程 九、思维导图 一、冯诺依曼体系结构 如…

Linux adduser命令教程:如何添加新用户(附实例详解和注意事项)

Linux adduser命令介绍 adduser是Linux系统中的一个命令行工具&#xff0c;用于创建新的用户。它是useradd这个底层工具的一个更友好的前端。当添加新用户时&#xff0c;它还会在/home目录下创建用户目录。 Linux adduser命令适用的Linux版本 adduser命令在大多数Linux发行版…

5G Frequency Bands 频率分布

连接&#xff1a;https://www.5g-networks.net/5g-technology/5g-frequency-bands/

每日一题:两数之和

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意顺序返回…

uniapp:uview-plus的一些记录

customStyle 并不是所有的组件都有customStyle属性来设置自定义属性&#xff0c;有的还是需要通过::v-deep来修改内置样式 form表单 labelStyle 需要的是一个对象 :labelStyle"{color: #333333,fontSize: 32rpx,fontWeight: 500}"dateTimePicker选择器设置默认值…

最新视频理解大模型之MiniGPT4-video

前言 随着大模型的爆火&#xff0c;多模态大模型也随之卷了起来&#xff0c;基本每隔一小段时间就会冒出一个新模型。 今天给大家带来一个最新发现的关于视频理解的多模态大模型。 它的名字是MiniGPT4-video&#xff0c;可以看的出来其是MiniGPT4的一个分支&#xff1b;Mini…

root管理员用户启动kibana报错

问题描述: CentOS7.9.2009环境,以root管理员用户启动kibana7.11.1程序报如下错误: Kibana should not be run as root. Use --allow-root to continue. [root@elasticsearch bin]# whoami root [root@elasticsearch bin]# pwd /usr/local/kibana-7.11.1-linux-x86_64/bi…

STM32利用软件I2C通讯读MPU6050的ID号

今天的读ID号是建立在上篇文章中有了底层的I2C通讯的6个基本时序来编写的。首先需要完成的就是MPU6050的初始化函数 然后就是编写 指定地址写函数&#xff1a; 一&#xff1a;开始 二&#xff1a;发送 从机地址读写位&#xff08;1&#xff1a;读 0&#xff1…

ESP-IDF移植lvgl 驱动 ST7789

文章目录 1 前言2 准备3 移植LVGL3.1 工程准备3.2 修改 CMakeLists.txt文件编译 LVGL3.3 编译LVGL 4 编译 ST7789 LCD驱动5 发现问题 1 前言 本教程开始学习 LVGL的&#xff0c;开始之前要把环境配置好&#xff0c;首先就需要移植 lvgl&#xff0c;使用的是 esp32 环境&#xf…

【Vue】前端Crypto-js加密库md5加密转成二进制/十六进制/Base64格式

MD5是一种常用的哈希函数&#xff0c;用于生成数据的消息摘要&#xff0c;在前端开发中&#xff0c;我们经常需要对数据进行加密&#xff0c;以确保数据的安全性。 Crypto-js是一个常用的JavaScript加密库&#xff0c;它提供了MD5算法的实现&#xff0c;并且支持将加密结果转换…

C++_ 头指针在链表的操作中用来标识链表的起始位置

链表&#xff08;linked list&#xff09;是一种常见的数据结构&#xff0c;用于存储一系列元素。它由一系列节点组成&#xff0c;每个节点包含数据和指向下一个节点的指针。 在 C 中&#xff0c;可以使用结构体来表示链表节点&#xff0c;然后使用指针将这些节点连接起来。 -…

kafka学习记录

文章目录 windows单机版kafka搭建步骤主题的增删改查操作消息的生产与消费 Windows集群版kafka搭建步骤 prettyZoo 尚硅谷Kafka教程&#xff0c;2024新版kafka视频&#xff0c;零基础入门到实战 【尚硅谷】Kafka3.x教程&#xff08;从入门到调优&#xff0c;深入全面&#xff0…

分库分表-简单了解

通过下面这些文章&#xff0c;我知道了什么是分库分表&#xff0c; 以及 什么时候需要分库分表&#xff0c; 还有分库分表带来的问题。 我说MySQL单表超过2000w就要分库分表&#xff0c;面试官让我回去等通知&#xff1f; 目前还没有学习到分布式&#xff0c;微服务&#xf…

plsql developer 一键格式化sql/美化sql

PL/SQL 格式化工具 以 Oracle SQL Developer 为例&#xff0c;使用一键格式化的步骤如下&#xff1a; 打开 Oracle SQL Developer。在“文件”菜单中&#xff0c;选择“打开文件”&#xff0c;然后选择你的 PL/SQL 文件。打开文件后&#xff0c;你可以通过右键菜单选择“格式…

vue3 知识点的补充 之 第一节

01 vue2与vue3的区别 vue2 采用object.defuneProperty()实现 对数组不友好 重写了数组的方法&#xff0c;同时无法监听数组length长度的改变。对于对象只能劫持设置好的数据 新增需要使用vue.set vue3 采用proxy进行代理&#xff0c;不需要重写数组的方法 同时可以监听数组长度…

gdb相关指令

背景知识 通过上图&#xff0c;可以看到&#xff0c;gcc 和 g 默认形成的可执行程序是release的&#xff01;&#xff01;&#xff01;故无法直接被调试。因此带 -g 选项表示使用 Debug 模式进行编译&#xff0c;而且我们可以看到&#xff0c;Debug 模式下编译形成的可执…

OSCP靶场--ClamAV

OSCP靶场–ClamAV 考点 1.nmap扫描 ##┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC 192.168.153.42 -p- -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-13 10:01 EDT Nmap scan report for 192.168.153.42 Host is up (0.24s latency). N…

ssl认证 生成证书的代码 java

网上流行的 InstallCert.java&#xff0c;应该出自于官网。但现在也找不到了&#xff0c;只能找到2011年的一篇文章&#xff08;在文章底下的参考链接&#xff09;。 以下是生成证书的代码&#xff1a; import java.io.BufferedReader; import java.io.File; import java.io.…