无约束优化算法之拟牛顿法

2024-01-20 15:40

本文主要是介绍无约束优化算法之拟牛顿法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

拟牛顿法

牛顿法在理论上有很好的效果,然而对于大规模问题,函数的海塞矩阵计算待解特别大或者难以得到,即便得到海塞矩阵我们还需要求解一个大规模线性方程组。那么能否使用海塞矩阵或其逆矩阵的近似来进行牛顿迭代呢?拟牛顿法便是这样的算法,它能够在每一步以较小的代价生成近似矩阵,并且使用近似矩阵代替海塞矩阵,而产生的迭代序列仍具有超线性收敛的性质。
拟牛顿法不计算海塞矩阵 ∇ 2 f ( x ) \nabla^2f(x) 2f(x),而是构造其近似矩阵 B k B^k Bk或其逆的近似矩阵 H k H^k Hk。我们希望 B k B^k Bk H k H^k Hk仍然保留海塞矩阵的部分性质,例如使得 d k d^k dk仍然为下降方向。

一、割线方程
回顾牛顿法的推导过程。设 f ( x ) f(x) f(x)是二阶连续可微函数,根据泰勒展开,向量值函数 ∇ f ( x ) \nabla f(x) f(x)在点 x k + 1 x^{k+1} xk+1处的近似为:
∇ f ( x ) = ∇ f ( x k + 1 ) + ∇ 2 f ( x k + 1 ) ( x − x k + 1 ) + O ( ∣ ∣ x − x k + 1 ∣ ∣ ) (1) \nabla f(x)=\nabla f(x^{k+1})+\nabla^2f(x^{k+1})(x-x^{k+1}) + O(||x-x^{k+1}||) \tag{1} f(x)=f(xk+1)+2f(xk+1)(xxk+1)+O(∣∣xxk+1∣∣)(1)
x = x k , s k = x k + 1 − x k x=x^k,s^k=x^{k+1}-x^k x=xk,sk=xk+1xk y k = ∇ f ( x k + 1 ) − ∇ f ( x k ) y^k=\nabla f(x^{k+1})-\nabla f(x^k) yk=f(xk+1)f(xk),得到
∇ 2 f ( x k + 1 ) s k + O ( ∣ ∣ s k ∣ ∣ ) = y k (2) \nabla^2f(x^{k+1})s^k+O(||s^k||)=y^k \tag{2} 2f(xk+1)sk+O(∣∣sk∣∣)=yk(2)
忽略高阶项 ∣ ∣ s k ∣ ∣ ||s^k|| ∣∣sk∣∣,我们希望海塞矩阵的近似矩阵 B k + 1 B^{k+1} Bk+1满足方程
y k = B k + 1 s k (3) y^k=B^{k+1}s^k \tag{3} yk=Bk+1sk(3)
或者其逆矩阵的近似矩阵 H k + 1 H^{k+1} Hk+1满足方程
s k = H k + 1 y k (4) s^k=H^{k+1}y^k \tag{4} sk=Hk+1yk(4)
并称(3)式与(4)式为割线方程。
在通常情况下,近似矩阵 B k + 1 B^{k+1} Bk+1 H k + 1 H^{k+1} Hk+1是由上一步迭代加上一个修正得到的,并且要求满足割线方程。这里先给出拟牛顿法的一般计算框架


拟牛顿算法的一般算法框架

  1. 给定 x 0 ∈ R x^0\in\mathbb{R} x0R,初始矩阵 B 0 ∈ R n × n B^0\in\mathbb{R^{n\times n}} B0Rn×n H 0 H^0 H0,令 k = 0 k=0 k=0
  2. while 未达到停机准则 do
  3. 计算方向 d k = − ( B k ) − 1 ∇ f ( x k ) d^k=-(B^k)^{-1}\nabla f(x^k) dk=(Bk)1f(xk) d k = − H k ∇ f ( x k ) d^k=-H^k\nabla f(x^k) dk=Hkf(xk)
  4. 通过线搜索找到合适的步长 α k > 0 \alpha_k>0 αk>0,令 x k + 1 = x k + α k d k x^{k+1}=x^k+\alpha^kd^k xk+1=xk+αkdk
  5. 更新海塞矩阵的近似矩阵 B k + 1 B^{k+1} Bk+1或其逆矩阵的近似矩阵 H k + 1 H^{k+1} Hk+1
  6. k ← k + 1 k\leftarrow k+1 kk+1
  7. end while

二、BFGS算法
在实际应用中基于 H k H^k Hk的拟牛顿法更加实用,这是因为根据 H k H^k Hk计算下降方向 d k d^k dk不需要求解线性方程组,而求解线性方程组在大规模问题上是非常耗时的。

后续我们重点关注在以 H k H^k Hk为目标的拟牛顿计算方法
这里给出秩2的BFGS公式推导过程,我们采用待定系数法推导公式,设
B k + 1 = B k + a u u T + b v v T B^{k+1}=B^k+auu^T+bvv^T Bk+1=Bk+auuT+bvvT
其中 u , v ∈ R n , a , b ∈ R u,v\in\mathbb{R^n},a,b\in\mathbb{R} u,vRn,a,bR。根据割线方程(3)有
B k + 1 s k = ( B k + a u u T + b v v T ) s k = y k B^{k+1}s^k=(B^k+auu^T+bvv^T)s^k=y^k Bk+1sk=(Bk+auuT+bvvT)sk=yk
整理可得
( a ⋅ u T s k ) u + ( b ⋅ v T s k ) v = y k − B k s k (a\cdot u^Ts^k)u+(b\cdot v^Ts^k)v=y^k-B^ks^k (auTsk)u+(bvTsk)v=ykBksk
我们通过选取 u u u v v v让以上等式成立即可。实际上 u u u v v v有非常多的取法,一种最直接的取法是让上面灯饰左右两边分别对应相等,即
u = y k , a ⋅ u T s k = 1 , v = B k s k , b ⋅ v T s k = − 1 \begin{aligned} u=y^k,a\cdot u^Ts^k=1,\\ v=B^ks^k,b\cdot v^Ts^k=-1 \end{aligned} u=yk,auTsk=1,v=Bksk,bvTsk=1
因此得到更新方式
B k + 1 = B k + y k ( y k ) T ( s k ) T y k − B k s k ( B k s k ) T ( s k ) T B k s k (5) B^{k+1}=B^k+\frac{y^k(y^k)^T}{(s^k)^Ty^k}-\frac{B^ks^k(B^ks^k)^T}{(s^k)^TB^ks^k} \tag{5} Bk+1=Bk+(sk)Tykyk(yk)T(sk)TBkskBksk(Bksk)T(5)
(5)式被成为基于 B k B^k Bk的BFGS公式,同理假设 H k = ( B k ) − 1 H^k=(B^k)^{-1} Hk=(Bk)1,可推出基于 H k H^k Hk的BFGS公式
H k + 1 = ( I − ρ k s k ( y k ) ) T H k ( I − ρ k s k ( y k ) ) + ρ k s k ( s k ) T (6) H^{k+1}=(I-\rho_ks^k(y^k))^TH^k(I-\rho_ks^k(y^k))+\rho_ks^k(s^k)^T \tag{6} Hk+1=(Iρksk(yk))THk(Iρksk(yk))+ρksk(sk)T(6)
其中 ρ k = 1 ( s k ) T y k \rho_k=\frac{1}{(s^k)^Ty^k} ρk=(sk)Tyk1。容易看出,若要BFGS公式更新产生的矩阵 H k + 1 H^{k+1} Hk+1正定,一个充分条件式不等式 ( s k ) T y k > 0 (s^k)^Ty^k>0 (sk)Tyk>0成立且上一步更新矩阵 H k H^k Hk正定,在问题求解过程中,不等式不一定会得到满足,此时应该使用Wolfe准则的线搜索来迫使不等式成立。
BFGS公式式目前最有效的拟牛顿更新格式之一,它有比较好的理论性质,实现起来也并不复杂,通过对(6)式进行改动可得到优先内存的BFGS格式(L-BFGS),它是常用的处理大规模优化问题的拟牛顿算法。

BFGS算法实现与数值实验

BFGS代码实现

function [fmin, xmin] = BFGS(func, gfunc, x0, epsilon)HOld = eye(length(x0));maxIter = 500;
xOld = x0;
iIter = 1;while iIter < maxItergOld = feval(gfunc, xOld);dk = -HOld * gOld;[~, ~, alpha] = armijo_rule(func, gfunc, xOld, 0.2, dk);xNew = xOld + alpha * dk;gNew = feval(gfunc, xNew);if norm(gNew, 2) < epsilonxmin = xNew;break;endgDiff = gNew - gOld;xDiff = xNew - xOld;I = eye(length(xNew));rho = 1 / ((xDiff)' * gDiff);HNew = (I - rho * gDiff * xDiff')' * HOld * (I - rho * gDiff * xDiff') ...+ rho * xDiff * xDiff';HOld = HNew;xOld = xNew;iIter = iIter + 1;
endif iIter == maxIterfprintf('exceed maximum iteration, and not found xmin\n');xmin = xNew;
endfmin = feval(func, xmin);end

armijo-rule代码实现

function [fnew, xnew, alpha] = armijo_rule(func, gfunc, x0, alpha0, dk)c1 = 1e-3;
alpha = alpha0;
gamma = 0.8;iIter = 0;
iterMax = 200;
alphaMin = 1e-5;while iIter < iterMax xnew = x0 + alpha * dk;fnew = feval(func, xnew);f0 = feval(func, x0);if fnew <= f0 + c1 * feval(gfunc, x0)' * dkbreak;endif alpha < alphaMinbreak;endalpha = gamma * alpha;iIter = iIter + 1;   
endif iIter == iterMaxalpha = alphaMin;fprintf('reach maximum iteration, and not found suitable alpha.\n');
endxnew = x0 + alpha * dk;
fnew = feval(func, xnew);end

算例
(0) f 0 = x 1 2 + 2 x 2 2 − 2 x 1 x 2 − 4 x 1 f_0 = x_1^2+2x_2^2-2x_1x_2-4x_1 f0=x12+2x222x1x24x1
(1) f 1 = x 2 2 + x 2 2 − x 1 x 2 − 10 x 1 − 4 x 2 f_1 =x_2^2+x_2^2-x_1x_2-10x_1-4x_2 f1=x22+x22x1x210x14x2
(2) f 2 = x 1 2 − 2 x 1 x 2 + 2 x 2 2 − 4 x 1 f_2 =x_1^2-2x_1x_2+2x_2^2-4x_1 f2=x122x1x2+2x224x1
(3) f 3 = x 1 2 − 2 x 1 x 2 + 3 x 2 2 − 4 x 1 − 5 x 2 f_3 = x_1^2 -2x_1x_2+3x_2^2-4x_1-5x_2 f3=x122x1x2+3x224x15x2

数值实验代码

% test bfgs% example 
x0 = [1, 1]';
epsilon = 1e-6;[fmin, xmin] = BFGS('bfgsTestFun0', 'bfgsTestGfun0', x0, epsilon);
fprintf('fmin = %f, xmin = (%f, %f)\n', fmin, xmin(1), xmin(2));
[x, f] = fminsearch('bfgsTestFun0', x0);
fprintf('build-in search: fmin = %f, xmin = (%f, %f)\n', f, x(1), x(2));% exercise
% ex 4-4 (1)
x0 = [1, 1]';
epsilon = 1e-6;[fmin, xmin] = BFGS('bfgsTestFun1', 'bfgsTestGfun1', x0, epsilon);
fprintf('fmin = %f, xmin = (%f, %f)\n', fmin, xmin(1), xmin(2));
[x, f] = fminsearch('bfgsTestFun1', x0);
fprintf('build-in search: fmin = %f, xmin = (%f, %f)\n', f, x(1), x(2));% ex 4-4 (2)
x0 = [1, 1]';
epsilon = 1e-6;[fmin, xmin] = BFGS('bfgsTestFun2', 'bfgsTestGfun2', x0, epsilon);
fprintf('fmin = %f, xmin = (%f, %f)\n', fmin, xmin(1), xmin(2));
[x, f] = fminsearch('bfgsTestFun2', x0);
fprintf('build-in search: fmin = %f, xmin = (%f, %f)\n', f, x(1), x(2));% ex 4-4 (3)
x0 = [1, 1]';
epsilon = 1e-6;[fmin, xmin] = BFGS('bfgsTestFun3', 'bfgsTestGfun3', x0, epsilon);
fprintf('fmin = %f, xmin = (%f, %f)\n', fmin, xmin(1), xmin(2));
[x, f] = fminsearch('bfgsTestFun3', x0);
fprintf('build-in search: fmin = %f, xmin = (%f, %f)\n', f, x(1), x(2));
function f = bfgsTestFun0(x)f = x(1)^2 + 2 * x(2)^2 - 2 * x(1) * x(2) - 4 * x(1);end
function f = bfgsTestFun1(x)f = x(1)^2 + x(2)^2 - x(1) * x(2) - 10 * x(1) - 4 * x(2);end
function f = bfgsTestFun2(x)f = x(1)^2 - 2 * x(1) * x(2) + 2 * x(2)^2 - 4 * x(1);end
function f = bfgsTestFun3(x)f = x(1)^2 - 2 * x(1) * x(2) + 3 * x(2)^2 - 4 * x(1) - 5 * x(2);end
function g = bfgsTestGfun0(x)g = [2 * x(1) - 2 * x(2) - 4; ...-2 * x(1) + 4 * x(2)];end
function g = bfgsTestGfun1(x)g = [2 * x(1) - x(2) - 10;...2 * x(2) - x(1) - 4];end
function g = bfgsTestGfun2(x)g = [2 * x(1) - 2 * x(2) - 4;...-2 * x(1) + 4 * x(2)];end
function g = bfgsTestGfun3(x)g = [2 * x(1) - 2 * x(2) - 4;...-2 * x(1) + 6 * x(2) - 5];end

计算结果为:

>> bfgsTest
fmin = -8.000000, xmin = (3.999999, 1.999999)
build-in search: fmin = -8.000000, xmin = (3.999976, 1.999973)
fmin = -52.000000, xmin = (7.999999, 6.000000)
build-in search: fmin = -52.000000, xmin = (8.000014, 5.999992)
fmin = -8.000000, xmin = (3.999999, 1.999999)
build-in search: fmin = -8.000000, xmin = (3.999976, 1.999973)
fmin = -14.125000, xmin = (4.250000, 2.250000)
build-in search: fmin = -14.125000, xmin = (4.249959, 2.249993)

三、L-BFGS算法
拟牛顿法虽然克服了计算海塞矩阵的困难,但是它仍然无法应用在大规模优化问题上。一般来说,拟牛顿矩阵 B k B^k Bk H k H^k Hk是稠密矩阵,而存储稠密矩阵要小号 O ( n 2 ) O(n^2) O(n2)的内存,这对于大规模问题,尤其是处理高分辨率图像问题时是不可能接受的。本部分介绍有效内存的BFGS方法解决了这一问题,从而使得人们在大规模问题上也可应用拟牛顿方法加速迭代的收敛。
L-BFGS方法根据公式(5)和(6)变形而来的。为了推导方便,我们以 H k H^k Hk的更新公式(6)为基础推导相应的L-BFGS,为了方便推导,引入新的记号重写公式(6)
H k + 1 = ( V k ) T H k V k + ρ s k ( s k ) T (7) H^{k+1}=(V^k)^TH^kV^k+\rho s^k(s^k)^T \tag{7} Hk+1=(Vk)THkVk+ρsk(sk)T(7)
其中
ρ k = 1 ( y k ) T s k , V k = I − ρ k y k ( s k ) T (8) \rho^k=\frac{1}{(y^k)^Ts^k},V^k=I-\rho^ky^k(s^k)^T \tag{8} ρk=(yk)Tsk1,Vk=Iρkyk(sk)T(8)
观察到(7)式有类似地推的性质,为了我们将(7)式递归地展开 m m m次,其中 m m m是一个给定的整数:
H k = ( V k − m ⋯ V k − 1 ) T H k − m ( V k − m ⋯ V k − 1 ) + ρ k − m ( V k − m + 1 ⋯ V k − 1 ) T s k − m ( s k − m ) ( V k − m + 1 ⋯ V k − 1 ) + ρ k − m + 1 ( V k − m + 2 ⋯ V k − 1 ) T s k − m + 1 ( s k − m + 1 ) ( V k − m + 2 ⋯ V k − 1 ) + ⋯ + ρ k − 1 s k − 1 ( s k − 1 ) T (9) \begin{aligned} &H^k = \\ &(V^{k-m}\cdots V^{k-1})^TH^{k-m}(V^{k-m}\cdots V^{k-1})+\\ &\rho_{k-m}(V^{k-m+1}\cdots V^{k-1})^Ts^{k-m}(s^{k-m})^(V^{k-m+1}\cdots V^{k-1})+\\ &\rho_{k-m+1}(V^{k-m+2}\cdots V^{k-1})^Ts^{k-m+1}(s^{k-m+1})^(V^{k-m+2}\cdots V^{k-1})+\cdots + \\ &\rho_{k-1}s^{k-1}(s^{k-1})^T \end{aligned} \tag{9} Hk=(VkmVk1)THkm(VkmVk1)+ρkm(Vkm+1Vk1)Tskm(skm)Vkm+1Vk1+ρkm+1(Vkm+2Vk1)Tskm+1(skm+1)Vkm+2Vk1++ρk1sk1(sk1)T(9)
为了达到节省内存的目的,(7)式不能无限展开下去,当这会产生一个问题, H k − m H^{k-m} Hkm还是无法求出。一个自然的想法就是用 H k − m H^{k-m} Hkm的近似矩阵来代替 H k − m H^{k-m} Hkm进行计算,近似矩阵的选取方式很多,但基本原则是要保证近似矩阵具有非常简单的结构,假定我们给出了 H k − m H^{k-m} Hkm的一个近似矩阵(9)式便可以用于计算拟牛顿迭代。
在拟牛顿迭代中,实际上并不需要计算 H k H^k Hk的显示形式,只需要利用 H k ∇ f ( x k ) H^k\nabla f(x^k) Hkf(xk)来计算迭代方向 d k d^k dk。为此先直接给出一个利用展开式(9)直接求解 H k ∇ f ( x k ) H^k\nabla f(x^k) Hkf(xk)的算法。见L-BFGS双循环递归算法。改算法的设计很精妙,充分利用了(9)式的结构来尽量节省计算 H k ∇ f ( x k ) H^k\nabla f(x^k) Hkf(xk)的开销。


L-BFGS双循环递归算法

  1. 初始化 q ← ∇ f ( x k ) q\leftarrow\nabla f(x^k) qf(xk)
  2. for i = k-1,k-2, …, k-m do
  3. 计算并保存 α i ← ρ i ( s i ) T q \alpha_i\leftarrow\rho_i(s^i)^Tq αiρi(si)Tq.
  4. 更新 q ← q − α i y i q\leftarrow q-\alpha_iy^i qqαiyi.
  5. end for
  6. 初始化 r ← H ^ k − m q r\leftarrow\hat{H}^{k-m}q rH^kmq,其中 H ^ k − m \hat{H}^{k-m} H^km H k − m {H}^{k-m} Hkm的近似矩阵
  7. for i = k-m, k-m+1, …, k-1 do
  8. 计算 β ← ρ i ( y i ) T r \beta\leftarrow\rho_i(y^i)^Tr βρi(yi)Tr
  9. 更新 r ← r + ( α i − β ) s i r\leftarrow r+(\alpha_i-\beta)s^i rr+(αiβ)si
  10. end for
  11. 输出 r r r,即 H k ∇ f ( x k ) H^k\nabla f(x^k) Hkf(xk)

上述L-BFGS双循环递归算法约需要4mn次乘法运算与2mn次加法运算,若近似矩阵 H ^ k − m \hat{H}^{k-m} H^km是对角矩阵,则额外需要n次乘法运算。由于m不会很大,因此该算法的复杂度为 O ( m n ) O(mn) O(mn)。算法所需要的额外存储为临时变量 α i \alpha_i αi,它的大小是 O ( m ) O(m) O(m)。综上所述,L-BFGS双循环算法是非常高效的。
近似矩阵 H ^ k − m \hat{H}^{k-m} H^km的取法可以是对角矩阵 H ^ k − m = γ k I \hat{H}^{k-m}=\gamma_kI H^km=γkI,其中
γ k = ( s k − 1 ) T y k − 1 ( y k − 1 ) T y k − 1 \gamma_k=\frac{(s^{k-1})^Ty^{k-1}}{(y^{k-1})^Ty^{k-1}} γk=(yk1)Tyk1(sk1)Tyk1
这恰好是BB方法的第一个步长。

这里给出L-BFGS的具体算法流程


  1. 选择初始点 x 0 x^0 x0,参数 m > 0 , k ← 0 m>0,k\leftarrow 0 m>0,k0.
  2. while 未达到收敛准者 do
  3. 选择近似矩阵 H ^ k − m \hat{H}^{k-m} H^km.
  4. 使用双循环算法计算下降方向 d k = − H k ∇ f ( x k ) d^k=-H^k\nabla f(x^k) dk=Hkf(xk)
  5. 使用线搜索算法计算满足Wolfe准则的步长 α k \alpha_k αk.
  6. 更新 x k + 1 = x k + α k d k x^{k+1}=x^k+\alpha_kd^k xk+1=xk+αkdk.
  7. if k > m then
  8. 从内存空间中删除 s k − m , y k − m s^{k-m},y^{k-m} skm,ykm.
  9. end if
  10. 计算并保存 s k = x k + 1 − x k , y k = ∇ f ( x k + 1 ) − ∇ f ( x k ) s^k=x^{k+1}-x^k,y^k=\nabla f(x^{k+1})-\nabla f(x^k) sk=xk+1xk,yk=f(xk+1)f(xk)
  11. k = ← k + 1 k=\leftarrow k+1 k=←k+1
  12. end while

正因为L-BFGS方法的出现,人们可以使用拟牛顿类算法求解优化问题。虽然有关L-BFGS方法的收敛性依然有限,但实际应用中L-BFGS方法很快成为应用最广泛的拟牛顿类算法。

在这里插入图片描述

这篇关于无约束优化算法之拟牛顿法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/626508

相关文章

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语