机器学习笔记之最优化理论与方法(十)无约束优化问题——共轭梯度法背景介绍

机器学习笔记之最优化理论与方法——共轭梯度法背景介绍

  • 引言
    • 背景:共轭梯度法
    • 线性共轭梯度法
      • 共轭方向
      • 共轭VS正交
      • 共轭方向法
      • 共轭方向法的几何解释

引言

本节将介绍共轭梯度法,并重点介绍共轭方向法的逻辑与几何意义。

背景:共轭梯度法

关于最小化二次目标函数: min ⁡ f ( x ) = min ⁡ 1 2 x T Q x + C T x \begin{aligned}\min f(x) = \min \frac{1}{2} x^T \mathcal Q x + \mathcal C^T x\end{aligned} minf(x)=min21xTQx+CTx,其中 Q ∈ R n × n ; Q ≻ 0 \mathcal Q \in \mathbb R^{n \times n};\mathcal Q \succ 0 QRn×n;Q0,且 C ∈ R n \mathcal C \in \mathbb R^n CRn。很明显:由于 Q \mathcal Q Q正定矩阵,那么该函数是凸二次函数

关于该函数的最优解:令 ∇ f ( x ) ≜ 0 \nabla f(x) \triangleq 0 f(x)0,有:
凸函数的局部最优解(极值点)也是它的全局最优解
∇ f ( x ) = Q x + C ≜ 0 \nabla f(x) = \mathcal Q x + \mathcal C \triangleq 0 f(x)=Qx+C0
可以看出: Q x + C = 0 \mathcal Q x + \mathcal C = 0 Qx+C=0是一个包含 n n n个方程的线性方程组

  • 如果 n n n的规模较小时,关于解方程组,可以使用其他工具进行解决。例如:高斯消去法
  • 相反,当 n n n的规模较大时,对应的增广矩阵规模同样很大,使用高斯消去法解方程组的成本较高

共轭梯度法初始就是针对方程组的一种迭代求解方法。随着最优化问题的推广,关于目标函数 f ( x ) f(x) f(x)也不仅仅局限在二次函数。对于这类 min ⁡ f ( x ) \min f(x) minf(x)的方法也被称作非线性共轭梯度法
对于上述方程组问题的迭代求解方法也被称作线性共轭梯度法

线性共轭梯度法

关于上述优化问题: min ⁡ f ( x ) = 1 2 x T Q x + C T x ; Q ≻ 0 \begin{aligned}\min f(x) = \frac{1}{2} x^T \mathcal Q x + \mathcal C^T x;\mathcal Q \succ 0\end{aligned} minf(x)=21xTQx+CTx;Q0

  • 假设正定矩阵 Q \mathcal Q Q是一个对角矩阵 B = ( b 1 b 2 ⋱ b n ) n × n \mathcal B = \begin{pmatrix} b_1 & \quad & \quad & \quad \\ \quad & b_2 & \quad & \quad\\ \quad & \quad & \ddots & \quad \\ \quad & \quad & \quad & b_n \end{pmatrix}_{n \times n} B= b1b2bn n×n,那么此时可以发现: f ( x ) = 1 2 x T B x + C T x \begin{aligned}f(x) = \frac{1}{2}x^T \mathcal B x + \mathcal C^T x \end{aligned} f(x)=21xTBx+CTx的二次项部分仅包含 x x x内各分量的平方项,而不包含各分量的交叉项
    n = 2 n=2 n=2为例,对应目标函数图像以及在 x 1 , x 2 x_1,x_2 x1,x2方向上的投影(等值线)示例如下。
    目标函数图像以及投影图像
    很明显,可以看出:描述等值线的椭圆,其长轴与短轴分别与坐标轴平行。如果通过迭代的方式进行求解,可以根据无约束优化问题——常用求解方法(上)中介绍的坐标轴交替下降法进行求解。图像表示如下:
    由于更新方向被确定——与坐标轴方向平行。因此仅需要计算各维度达到最小步长即可。因而仅需要 2 2 2步就可以找到最优解。
    坐标轴交替下降法示例
    同理,如果是 x ∈ R n x \in \mathbb R^n xRn,需要将所有的轴均迭代一遍即可找到最优解。
  • 如果 Q \mathcal Q Q是一个一般形式的正定矩阵: Q = ( q 11 q 12 ⋯ q 1 n q 21 q 22 ⋯ q 2 n ⋮ ⋮ ⋱ ⋮ q n 1 q n 2 ⋯ q n n ) n × n ; Q ≻ 0 \mathcal Q = \begin{pmatrix} q_{11} & q_{12} & \cdots & q_{1n} \\ q_{21} & q_{22} & \cdots & q_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ q_{n1} & q_{n2} & \cdots & q_{nn} \end{pmatrix}_{n \times n};\mathcal Q \succ 0 Q= q11q21qn1q12q22qn2q1nq2nqnn n×n;Q0。这里依然以 n = 2 n=2 n=2为例,对应的目标函数 f ( x ) f(x) f(x)决策变量 x x x各分量的等值线示例如下:
    由于交叉项 q m n ( m ≠ n ) q_{mn}(m \neq n) qmn(m=n)的存在,对应椭圆图像的长轴与短轴不再与坐标轴平行。
    等值线图像示例
    针对这种一般情况二次型函数 min ⁡ f ( x ) = 1 2 x T Q x + C T x \begin{aligned}\min f(x) = \frac{1}{2} x^T \mathcal Q x + \mathcal C^T x\end{aligned} minf(x)=21xTQx+CTx,可以通过二次型的线性替换,从而将函数转化为标准型函数:
    其中 D \mathcal D D是由 Q \mathcal Q Q特征值组成的对角阵;而 P \mathcal P P则表示由特征值对应特征向量组成的正交阵
    Q = P T D P D = ( λ 1 λ 2 ⋱ λ n ) n × n \mathcal Q = \mathcal P^T \mathcal D \mathcal P \quad \mathcal D = \begin{pmatrix} \lambda_1 & \quad & \quad & \\ \quad & \lambda_2 &\quad & \\ \quad & \quad & \ddots & \\ \quad & \quad & \quad & \lambda_n \end{pmatrix}_{n \times n} Q=PTDPD= λ1λ2λn n×n
    替换后的函数 f ( x ) f(x) f(x)可表示为:
    x ^ = P x \hat {x} = \mathcal P x x^=Px反之 x = P T x ^ x = \mathcal P^T \hat x x=PTx^
    f ( x ) = 1 2 x T Q x + C T x = 1 2 x T P T D P x + C T x = 1 2 ( P x ) T D ( P x ) + C T x = 1 2 [ x ^ ] T D x ^ + C T ( P T x ^ ) = 1 2 [ x ^ ] T D x ^ + ( P C ) T x ^ = f ^ ( x ^ ) \begin{aligned} f(x) & = \frac{1}{2} x^T \mathcal Q x + \mathcal C^T x \\ & = \frac{1}{2} x^T \mathcal P^T \mathcal D \mathcal P x + \mathcal C^T x \\ & = \frac{1}{2}(\mathcal P x)^T \mathcal D (\mathcal P x) + \mathcal C^T x \\ & = \frac{1}{2} [\hat x]^T \mathcal D \hat {x} +\mathcal C^T (\mathcal P^T \hat x )\\ & = \frac{1}{2} [\hat x]^T \mathcal D \hat {x} + (\mathcal P \mathcal C)^T \hat x \\ & = \hat {f}(\hat x) \end{aligned} f(x)=21xTQx+CTx=21xTPTDPx+CTx=21(Px)TD(Px)+CTx=21[x^]TDx^+CT(PTx^)=21[x^]TDx^+(PC)Tx^=f^(x^)
    此时,该公式又变回第一类标准型。同样可以通过坐标轴交替下降法新目标函数 f ^ ( x ^ ) \hat f(\hat x) f^(x^)进行求解。如果找到了关于 x ^ \hat x x^的最优解,可以通过 x = P T x ^ x = \mathcal P^T \hat x x=PTx^找到 x x x的最优解。

线性共轭梯度法是用来针对线性方程组 ∇ f ( x ) = Q x + C ≜ 0 \nabla f(x) = \mathcal Q x + \mathcal C \triangleq 0 f(x)=Qx+C0的求解问题。如果针对上述逻辑,必然需要先将正交矩阵 P \mathcal P P求解出来。但相反,由于 P \mathcal P P是由特征值对应特征向量组成的正交矩阵,而求解特征向量依然要解方程组 Q x + C ≜ 0 \mathcal Q x + \mathcal C \triangleq 0 Qx+C0
很明显,这形成了一个闭环:想要通过 P \mathcal P P求解方程组,而 P \mathcal P P自身也要通过求解方程组来获取。

共轭梯度法的思路是:想要通过获取一系列的 n n n向量 d 0 , d 1 , ⋯ , d n − 1 ∈ R n d_0,d_1,\cdots,d_{n-1} \in \mathbb R^n d0,d1,,dn1Rn,其组成的矩阵 S = ( d 0 , d 1 , ⋯ , d n − 1 ) n × n \mathcal S = (d_0,d_1,\cdots,d_{n-1})_{n \times n} S=(d0,d1,,dn1)n×n,使其替代上面描述的正交矩阵 P n × n \mathcal P_{n \times n} Pn×n,从而帮助 Q \mathcal Q Q完成对角化
Q = S T D S \mathcal Q = \mathcal S^T \mathcal D \mathcal S Q=STDS
从而通过上述思路,求解最优解: x = S T x ^ x = \mathcal S^T \hat {x} x=STx^

关于向量组 d 0 , d 1 , ⋯ , d n − 1 d_0,d_1,\cdots,d_{n-1} d0,d1,,dn1,向量之间的关系被定义为共轭关系

共轭方向

共轭方向的定义表示为:考虑正定矩阵 Q \mathcal Q Q以及非零向量 d i , d j ( i ≠ j ) d_i,d_j(i \neq j) di,dj(i=j),若满足:
( d i ) T Q d j = 0 (d_i)^T \mathcal Q d_j = 0 (di)TQdj=0
则称向量 d i , d j d_i,d_j di,dj关于矩阵 Q \mathcal Q Q共轭。如果向量组 D = { d 0 , d 1 , ⋯ , d k } \mathcal D = \{d_0,d_1,\cdots,d_k\} D={d0,d1,,dk}关于矩阵 Q \mathcal Q Q共轭,即向量之间两两共轭
∀ d i , d j ∈ D ; i ≠ j ⇒ ( d i ) T Q d j = 0 \forall d_i,d_j \in \mathcal D;i \neq j \Rightarrow (d_i)^T \mathcal Q d_j = 0 di,djD;i=j(di)TQdj=0

共轭VS正交

根据上述共轭梯度法的思路,以及共轭方向定义的描述,观察:共轭与正交之间的关系

  • 如果向量组 D { d 0 , d 1 , ⋯ , d k } \mathcal D \{d_0,d_1,\cdots,d_k\} D{d0,d1,,dk}关于单位矩阵 I \mathcal I I共轭:此时向量 d i , d j ∈ D d_i,d_j \in \mathcal D di,djD之间的共轭关系退化为正交关系
    ∀ d i , d j ∈ D , i ≠ j ( d i ) T I d j = 0 ⇒ ( d i ) T d j = 0 \forall d_i,d_j \in \mathcal D,i \neq j \quad (d_i)^T \mathcal Id_j = 0 \Rightarrow (d_i)^T d_j = 0 di,djD,i=j(di)TIdj=0(di)Tdj=0

  • 如果向量组 D { d 0 , d 1 , ⋯ , d k } \mathcal D \{d_0,d_1,\cdots,d_k\} D{d0,d1,,dk}关于正定矩阵 Q \mathcal Q Q共轭:令 Q = M T Λ M \mathcal Q = \mathcal M^T \Lambda \mathcal M Q=MTΛM,并令 Λ = λ 2 \Lambda = \lambda^2 Λ=λ2,有:

    • 由于 M \mathcal M M是正交矩阵: M M T = I \mathcal M \mathcal M^T = \mathcal I MMT=I,因而可以在展开过程中插入一个 M M T \mathcal M \mathcal M^T MMT
    • P = M T λ M \mathcal P = \mathcal M^T \lambda \mathcal M P=MTλM
      Q = M T Λ M = M T λ 2 M = ( M T λ M ) ( M T λ M ) = ( M T λ M ) 2 = P 2 \begin{aligned} \mathcal Q & = \mathcal M^T \Lambda \mathcal M \\ & = \mathcal M^T \lambda^2 \mathcal M \\ & = (\mathcal M^T\lambda \mathcal M) (\mathcal M^T \lambda \mathcal M) \\ & = (\mathcal M^T \lambda \mathcal M)^2 \\ & = \mathcal P^2 \end{aligned} Q=MTΛM=MTλ2M=(MTλM)(MTλM)=(MTλM)2=P2

    从而将 Q \mathcal Q Q分解成 P 2 \mathcal P^2 P2的形式。并且 P = M T λ M \mathcal P = \mathcal M^T \lambda \mathcal M P=MTλM也是一个正定矩阵 P 2 = P ⋅ P = P T P \mathcal P^2 = \mathcal P \cdot \mathcal P = \mathcal P^T \mathcal P P2=PP=PTP
    关于向量 d i , d j d_i,d_j di,dj共轭: ( d i ) T Q d j = 0 (d_i)^T \mathcal Q d_j = 0 (di)TQdj=0可表示为:
    ( d i ) T Q d j = ( d i ) T P 2 d j = ( d i ) T P T P d j = ( P d i ) T ( P d j ) = 0 \begin{aligned} (d_i)^T \mathcal Q d_j & = (d_i)^T \mathcal P^2 d_j \\ & = (d_i)^T \mathcal P^T \mathcal P d_j \\ & = (\mathcal P d_i)^T (\mathcal P d_j) = 0 \end{aligned} (di)TQdj=(di)TP2dj=(di)TPTPdj=(Pdi)T(Pdj)=0
    也就是说:向量 d i , d j d_i,d_j di,dj经过正交矩阵 P \mathcal P P的投影结果: P d i , P d j \mathcal Pd_i,\mathcal Pd_j Pdi,Pdj之间是正交关系
    关于向量投影的描述详见主成分分析(最大投影方差)

  • 根据正交的性质,两两正交的向量组,其内部向量必然线性无关两两共轭的向量组,其内部向量同样线性无关。由于决策变量 x ∈ R n x \in \mathbb R^n xRn,因而对应的两两共轭向量组内最多包含 n n n两两共轭的向量。
    再多一个,必然出现向量之间不共轭的情况。

共轭方向法

依然针对凸二次函数的优化问题: min ⁡ f ( x ) = 1 2 x T Q x + C T x , Q ≻ 0 \begin{aligned}\min f(x) = \frac{1}{2} x^T \mathcal Q x + \mathcal C^T x,\mathcal Q \succ 0 \end{aligned} minf(x)=21xTQx+CTx,Q0,通过迭代的方式求解 x x x最优解

  • 给定:初始点 x 0 x_0 x0以及一组关于 Q \mathcal Q Q的共轭方向 d 0 , d 1 , ⋯ , d n − 1 d_0,d_1,\cdots,d_{n-1} d0,d1,,dn1,令:
    坐标轴交替下降法的思路如出一辙,只不过方向选择由原来两两正交的坐标轴作为方向替换为两两共轭的向量作为方向
    x k + 1 = x k + α k ⋅ d k x_{k+1} = x_k + \alpha_k \cdot d_k xk+1=xk+αkdk
  • 其中 α k \alpha_k αk满足:
    即当前迭代步骤的最优解,之所以选择最优解,因为该函数是凸函数,对应的最优解必然是全局最优解。
    α k = arg ⁡ min ⁡ α ϕ ( α ) = arg ⁡ min ⁡ α f ( x k + α ⋅ d k ) \alpha_k = \mathop{\arg\min}\limits_{\alpha} \phi(\alpha) = \mathop{\arg\min}\limits_{\alpha} f(x_k + \alpha \cdot d_k) αk=αargminϕ(α)=αargminf(xk+αdk)
    计算 ∇ ϕ ( α k ) ≜ 0 \nabla \phi(\alpha_k) \triangleq 0 ϕ(αk)0,有:
    ∇ ϕ ( α k ) = ∇ f ( x k + α k ⋅ d k ) T d k = [ Q ( x k + α k ⋅ d k ) + C ] T d k = ( Q x k + C ) T d k + α k ( d k ) T Q d k ≜ 0 \begin{aligned} \nabla \phi(\alpha_k) & = \nabla f(x_k + \alpha_k \cdot d_k)^T d_k \\ & = [\mathcal Q(x_k + \alpha_k \cdot d_k) + \mathcal C]^T d_k \\ & = (\mathcal Q x_k + \mathcal C)^T d_k + \alpha_k (d_k)^T \mathcal Q d_k \triangleq 0 \\ \end{aligned} ϕ(αk)=f(xk+αkdk)Tdk=[Q(xk+αkdk)+C]Tdk=(Qxk+C)Tdk+αk(dk)TQdk0
    最终有:
    α k = − ( Q x k + C ) T d k ( d k ) T Q d k = − [ ∇ f ( x k ) ] T d k ( d k ) T Q d k \alpha_k = -\frac{(\mathcal Q x_k + \mathcal C)^T d_k}{(d_k)^T \mathcal Q d_k} = -\frac{[\nabla f(x_k)]^T d_k}{(d_k)^T \mathcal Q d_k} αk=(dk)TQdk(Qxk+C)Tdk=(dk)TQdk[f(xk)]Tdk

整个的算法过程并不麻烦,但需要一个前提:将共轭方向 d 0 , d 1 , ⋯ , d n − 1 d_0,d_1,\cdots,d_{n-1} d0,d1,,dn1提前给出。因而不同共轭方向的选择方式对应其相应的共轭方向法。
与牛顿法的描述相似:针对 Hessian Matrix \text{Hessian Matrix} Hessian Matrix可能不是正定矩阵的一类情况,分为修正法, SR-1,DFP,BFGS \text{SR-1,DFP,BFGS} SR-1,DFP,BFGS等等方法;同理,共轭方向法为一类方法,而共轭梯度法只是其中一种方法。

共轭方向法的几何解释

观察关于初始点 x 0 x_0 x0第一次迭代 x 0 ⇒ x 1 x_0 \Rightarrow x_1 x0x1
x 1 = x 0 + ∑ i = 0 n − 1 α i ⋅ d i x_1 = x_0 + \sum_{i=0}^{n-1} \alpha_i \cdot d_i x1=x0+i=0n1αidi
如果将 n n n共轭方向组成矩阵,记作 S = ( d 0 , d 1 , ⋯ , d n − 1 ) n × n \mathcal S = (d_0,d_1,\cdots,d_{n-1})_{n \times n} S=(d0,d1,,dn1)n×n,由于共轭方向两两线性无关,因而 S \mathcal S S必然是可逆矩阵。该矩阵存在如下性质:

  • 关于 S T Q S = [ ( d 0 ) T ⋮ ( d n − 1 ) T ] Q ( d 0 , ⋯ , d n − 1 ) = [ ( d i ) T Q d j ] n × n \mathcal S^T \mathcal Q \mathcal S = \begin{bmatrix} (d_0)^T \\ \vdots \\ (d_{n-1})^T \end{bmatrix} \mathcal Q (d_0,\cdots,d_{n-1}) = [(d_i)^T \mathcal Q d_j]_{n \times n} STQS= (d0)T(dn1)T Q(d0,,dn1)=[(di)TQdj]n×n,根据共轭方向的定义,当 i ≠ j i \neq j i=j时,必然有: ( d i ) T Q d j = 0 (d_i)^T \mathcal Q d_j = 0 (di)TQdj=0;相反,当 i = j i = j i=j时,由于 Q \mathcal Q Q正定矩阵,因而 ( d i ) T Q d j > 0 (d_i)^T \mathcal Q d_j >0 (di)TQdj>0恒成立。从而 S T Q S \mathcal S^T \mathcal Q \mathcal S STQS不仅是一个正定矩阵,甚至是一个对角阵
    从而达到利用 S \mathcal S S Q \mathcal Q Q进行对角化的目的。
  • 由于 S \mathcal S S可逆,根据逆矩阵的性质,必然有: S − 1 S = S − 1 ( d 0 , d 1 , ⋯ , d n − 1 ) = I \mathcal S^{-1} \mathcal S = \mathcal S^{-1}(d_0,d_1,\cdots,d_{n-1}) = \mathcal I S1S=S1(d0,d1,,dn1)=I(单位矩阵)。将该式展开,有:
    I = S − 1 ( d 0 , d 1 , ⋯ , d n − 1 ) = ( S − 1 d 0 , S − 1 d 1 ⋯ S − 1 d n − 1 ) \begin{aligned} \mathcal I & = \mathcal S^{-1}(d_0,d_1,\cdots,d_{n-1}) \\ & = (\mathcal S^{-1} d_0,\mathcal S^{-1} d_1 \cdots \mathcal S^{-1} d_{n-1}) \end{aligned} I=S1(d0,d1,,dn1)=(S1d0,S1d1S1dn1)
    其中展开后矩阵中的元素 S − 1 d i ( i = 0 , 1 , 2 , ⋯ , n − 1 ) \mathcal S^{-1} d_i(i=0,1,2,\cdots,n-1) S1di(i=0,1,2,,n1)表示单位坐标向量 e i + 1 = ( 0 , 0 , ⋯ , 1 ⏟ i + 1 , ⋯ , 0 ) T e_{i+1} = (0,0,\cdots,\underbrace{1}_{i+1},\cdots,0)^T ei+1=(0,0,,i+1 1,,0)T

如果将决策变量 x = S ⋅ x ^ x = \mathcal S \cdot \hat {x} x=Sx^或者 x ^ = S − 1 x \hat x = \mathcal S^{-1} x x^=S1x,从而原始目标函数 f ( x ) = 1 2 x T Q x + C T x \begin{aligned}f(x) = \frac{1}{2} x^T \mathcal Q x + \mathcal C^T x\end{aligned} f(x)=21xTQx+CTx可替换为一个新函数 f ^ ( x ^ ) \hat f(\hat {x}) f^(x^)
f ^ ( x ^ ) = 1 2 [ x ^ ] T S T Q S ⏟ 对角阵 ⋅ x ^ + ( S T C ) T x ^ \hat f(\hat {x}) = \frac{1}{2} [\hat x]^T \underbrace{\mathcal S^T \mathcal Q \mathcal S}_{对角阵} \cdot \hat {x} + (\mathcal S^T \mathcal C)^T \hat {x} f^(x^)=21[x^]T对角阵 STQSx^+(STC)Tx^
此时的新函数中仅包含关于 x ^ i ( i = 1 , 2 , ⋯ , n ) \hat {x}_i(i=1,2,\cdots,n) x^i(i=1,2,,n)的平方项,而没有交叉项。从而新函数 f ^ ( x ^ ) \hat f(\hat x) f^(x^) x ^ \hat x x^特征空间中的等值线依然是一个椭圆/椭球/超椭球,其长轴与短轴同样与坐标轴平行

回归第一次迭代 x 0 + ∑ i = 0 n − 1 α i ⋅ d i x_0 + \sum_{i=0}^{n-1} \alpha_i \cdot d_i x0+i=0n1αidi,这明显是一个在原始特征空间 x x x上的操作。如果该操作映射在 x ^ \hat x x^的特征空间中会变成什么样的效果 ? ? ?
只需要将 x x x特征空间中的正交向量乘以 S − 1 \mathcal S^{-1} S1即可得到对应 x ^ \hat x x^特征空间的正交向量。
S − 1 x 0 + α 0 S − 1 d 0 + α 1 S − 1 d 1 + ⋯ + α n − 1 S − 1 d n − 1 \mathcal S^{-1}x_0 + \alpha_0 \mathcal S^{-1}d_0 + \alpha_1 \mathcal S^{-1} d_1 + \cdots + \alpha_{n-1} \mathcal S^{-1} d_{n-1} S1x0+α0S1d0+α1S1d1++αn1S1dn1
由于 e i + 1 = S − 1 d i ( i = 1 , 2 , ⋯ , n − 1 ) e_{i+1} = \mathcal S^{-1} d_i(i=1,2,\cdots,n-1) ei+1=S1di(i=1,2,,n1),整理有:
很明显,在 x ^ \hat x x^的特征空间中,相当于坐标轴交替下降法,沿着坐标轴进行搜索。
S − 1 x 0 + α 0 e 1 + α 1 e 2 + ⋯ + α n − 1 e n \mathcal S^{-1}x_0 + \alpha_0 e_1 + \alpha_1 e_2 + \cdots + \alpha_{n-1} e_{n} S1x0+α0e1+α1e2++αn1en

下一节将继续介绍共轭方向法
0 : 37 : 14 / 1 : 26 : 29 0:37:14/1:26:29 0:37:14/1:26:29

Reference \text{Reference} Reference
最优化理论与方法-第七讲-无约束优化问题(三)

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

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

相关文章

手摸手系列之前端Vue实现PDF预览及打印的终极解决方案

前言 近期我正在开发一个前后端分离项目,使用了Spring Boot 和 Vue2,借助了国内优秀的框架 jeecg,前端UI库则选择了 ant-design-vue。在项目中,需要实现文件上传功能,同时还要能够在线预览和下载图片和PDF文件&#x…

虹科分享 | 软件供应链攻击如何工作?如何评估软件供应链安全?

说到应用程序和软件,关键词是“更多”。在数字经济需求的推动下,从简化业务运营到创造创新的新收入机会,企业越来越依赖应用程序。云本地应用程序开发更是火上浇油。然而,情况是双向的:这些应用程序通常更复杂&#xf…

路由缓存问题 | vue-router的导航守卫

路由缓存问题 带参路由&#xff0c;当参数发生变化时&#xff0c;相同的组件实例将被复用&#xff0c;组件的生命周期钩子不会被调用&#xff0c;导致数据无法更新。 两种解决方法&#xff1a; 1. 给 RouterView绑定key值&#xff0c;即 <RouterView :key"$route.ful…

手机木马远程控制复现

目录 目录 前言 系列文章列表 渗透测试基础之永恒之蓝漏洞复现http://t.csdn.cn/EsMu2 思维导图 1&#xff0c;实验涉及复现环境 2,Android模拟器环境配置 2.1,首先从官网上下载雷电模拟器 2.2,安装雷电模拟器 2.3, 对模拟器网络进行配置 2.3.1,为什么要进行配置…

flask要点与坑

简介 Flask是一个用Python编写的Web应用程序框架&#xff0c;该框架简单易用、模块化、灵活性高。 该笔记主要记录Flask的关键要点和容易踩坑的地方 Flask 日志配置 Flask 中的自带logger模块&#xff08;也是python自带的模块&#xff09;&#xff0c;通过简单配置可以实现…

SpringMVC之JSON数据返回与异常处理机制

目录 一.SpringMVC的JSON数据返回 1.导入Maven依赖 2.配置spring-mvc.xml 3.ResponseBody注解的使用 3.1案例演示 1.List集合转JSON 2.Map集合转JSON 3.返回指定格式String 4. ResponseBody用法 5.Jackson 5.1介绍 5.2常用注解 二.异常处理机制 1.为什么要全局异常处…

Jenkins :添加node权限获取凭据、执行命令

拥有Jenkins agent权限的账号可以对node节点进行操作&#xff0c;通过添加不同的node可以让流水线项目在不同的节点上运行&#xff0c;安装Jenkins的主机默认作为master节点。 1.Jenkins 添加node获取明文凭据 通过添加node节点&#xff0c;本地监听ssh认证&#xff0c;选则凭…

详解TCP/IP协议第三篇:通信数据在OSI通信模型的上下传输

文章目录 一&#xff1a;OSI通信模型间数据传输展示 二&#xff1a;应用层到会话层解析 1&#xff1a;应用层 2&#xff1a;表现层 3&#xff1a;会话层 三&#xff1a;传输层到物理层解析 1&#xff1a;传输层 2&#xff1a;网络层 3&#xff1a;数据链路层、与物理层…

考研算法47天:01背包

问题描述 算法详细步骤 代码随想录 (programmercarl.com) ac代码 #include <iostream> using namespace std; int bag[1001]; int bagMax[1001]; int bagvalue[1001]; int main(){int n,v;cin>>n>>v;for(int i0;i<n;i){cin>>bag[i]>>bagva…

【C++杂货铺】继承由浅入深详细总结

文章目录 一、继承的概念及定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承方式和访问限定符1.2.3 继承基类成员访问方式的变化 二、基类和派生类对象赋值转换三、继承中的作用域四、派生类中的默认成员函数4.1 默认构造函数4.2 拷贝构造函数4.3 赋值运算符重载函数4.…

【C++】动态规划题目总结(随做随更)

文章目录 一. 斐波那契数列模型1. 第 N 个泰波那契数2. 三步问题3. 使用最小花费爬楼梯解法一&#xff1a;从左往右填表解法二&#xff1a;从右往左填表 一. 斐波那契数列模型 解题步骤&#xff1a; 确定状态表示&#xff08;最重要&#xff09;&#xff1a;明确dp表里的值所…

PYTHON-模拟练习题目集合

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Python的get请求报错Error: Unexpected status code 400

一句话导读&#xff1a; 最近在做研发效能提升的事情&#xff0c;其中有一块就是要对项目管理相关数据做统计&#xff0c;我们使用的是ones做的项目管理&#xff0c;ones本身带的那些报表满足不了我们的需求&#xff0c;就想着看这些数据是不是能自己拿出来做统计&#xff0c;有…

浅谈C++|多态篇

1.多态的基本概念 多态是C面向对象三大特性之一多态分为两类 1. 静态多态:函数重载和运算符重载属于静态多态&#xff0c;复用函数名 2.动态多态:派生类和虚函数实现运行时多态 静态多态和动态多态区别: 静态多态的函数地址早绑定–编译阶段确定函数地址 动态多态的函数地址晚绑…

Linux学习之平均负载的概念和查看方法

先理解一下平均负载的含义&#xff1a; 平均负载是指单位时间内&#xff0c;系统处于可运行状态和不可中断状态的进程数&#xff0c;也可以看成平均活跃进程数。 可运行状态的进程&#xff1a; 正在使用CPU或者正在等待CPU处理的进程&#xff0c;ps 命令看到的&#xff0c;处于…

黑马JVM总结(十)

&#xff08;1&#xff09;直接内存_基本使用 下面我们看一下使用了ByteBuffer直接内存&#xff0c;大文件的读写效率是非常的高 Java本身并不具备磁盘读写的能力&#xff0c;它需要调用操作系统的函数&#xff0c;需要从java的方法内部调用本地方法操作系统的方法&#xff0c…

bboss 流批一体化框架 与 数据采集 ETL

数据采集 ETL 与 流批一体化框架 特性&#xff1a; 高效、稳定、快速、安全 bboss 是一个基于开源协议 Apache License 发布的开源项目&#xff0c;主要由以下三部分构成&#xff1a; Elasticsearch Highlevel Java Restclient &#xff0c; 一个高性能高兼容性的Elasticsea…

【C刷题】day2

一、选择题 1、以下程序段的输出结果是&#xff08; &#xff09; #include<stdio.h> int main() { char s[] "\\123456\123456\t"; printf("%d\n", strlen(s)); return 0; } A: 12 B: 13 C: 16 D: 以上都不对【答案】&#xff1a; A 【解析】…

Python Opencv实践 - 视频文件写入(格式和分辨率修改)

参考资料&#xff1a; python opencv写视频——cv2.VideoWriter()_cv2.cv.videowriter(_翟羽嚄的博客-CSDN博客 import cv2 as cv import numpy as np#1. 打开原始视频 video_in cv.VideoCapture("../SampleVideos/Unity2D.mp4") video_width int(video_in.get(c…

带你了解前后端分离的秘密-Vue【vue入门】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Vue》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这个专栏…