(Arxiv-2023)LORA-FA:针对大型语言模型微调的内存高效低秩自适应
LORA-FA:针对大型语言模型微调的内存高效低秩自适应
paper是香港浸会大学发表在Arxiv 2023的工作
paper title:LORA-FA: MEMORY-EFFICIENT LOW-RANK ADAPTATION FOR LARGE LANGUAGE MODELS FINE-TUNING
ABSTRACT
低秩自适应 (LoRA) 方法可以大大减少微调大型语言模型 (LLM) 所需的可训练参数数量,但是,它仍然需要昂贵的激活内存来更新低秩权重。减少 LoRA 层数或使用激活重新计算可能会损害微调性能或增加计算开销。在这项工作中,我们提出了 LoRA-FA,这是一种内存高效的微调方法,它可以在不降低性能和进行昂贵的重新计算的情况下减少激活内存。 LoRA-FA 选择在每个 LoRA 层中冻结 A 的向下投影权重并更新 B 的向上投影权重。它确保在 LLM 微调期间模型权重的变化位于低秩空间中,同时无需存储全秩输入激活。我们在多种模型类型(RoBERTa、T5、LLaMA)和模型规模上进行了广泛的实验。我们的结果表明,与全参数微调和 LoRA 相比,LoRA-FA 在不同任务中始终能够实现接近的微调精度。此外,与 LoRA 相比,LoRA-FA 可将总内存成本降低高达 1.4 倍。
1 INTRODUCTION
大型语言模型 (LLM) 已成为自然语言处理的基石 (Brown 等人,2020 年;Touvron 等人,2023a;OpenAI,2023 年;Anil 等人,2023 年),并且对预训练的 LLM 进行微调已被证明非常有效,可以提高其在各种下游任务中的表现 (Liu 等人,2019 年;Wei 等人,2021 年) 并使它们与人类意图保持一致 (Ouyang 等人,2022 年;Bai 等人,2022 年)。然而,对具有完整参数的 LLM 进行微调的成本过高,例如,使用 AdamW(Loshchilov & Hutter,2017)对 LLaMA-65B(Touvron et al, 2023a)模型进行微调需要超过 1TB 的 GPU 内存来存储模型参数、梯度和优化器状态(Rajbhandari et al, 2020)。
为了减少全参数微调的内存,提出了参数高效微调 (PEFT) 方法,仅更新一小部分参数,例如适配器权重 (Houlsby et al, 2019; Hu et al, 2022) 和提示权重 (Li & Liang, 2021; Lester et al, 2021)。在这些方法中,LoRA (Hu et al, 2022) 已证明其性能与全参数微调相当,并且已广泛应用于许多应用 (Dettmers et al, 2023)。
具体而言,LoRA 在线性层的权重旁边添加了一个并行的低秩适配器,如图 1(b) 所示,其中 W W W 是预训练的权重, A A A 和 B B B 是低秩权重。由于 LoRA 冻结了 W W W 并仅更新较小的矩阵 A A A 和 B B B,因此与图 1(a) 所示的全参数微调相比,其可训练参数、梯度和优化器状态的内存开销大幅减少(全参数微调可以视为更新 W W W 并冻结 A A A 和 B B B)。此外,通过将 A B A B AB 的值合并到 W W W 中,LoRA 不会引入额外的推理延迟。
图 1:(a) 全参数微调 (FT)、(b) LoRA 和 © LoRA-FA 的图示。
然而,LoRA 仍然存在局限性,因为它需要在 LoRA 层中消耗昂贵的激活内存。这是因为在前馈传递过程中需要存储 X 的大型输入激活,并在反向传播传递过程中用于构建 A 的梯度。这意味着与全参数微调相比,LoRA 无法降低激活内存成本。例如,对输入序列长度为 2048 且批大小为 4 的 LLaMA-65B 进行微调需要在所有 LoRA 层中使用超过 50GB 的激活内存(16 位格式)。为了解决这个问题,现有方法选择一部分线性层进行 LoRA 微调(Hu et al, 2022)或使用激活重新计算(Chen et al, 2016),但这会影响微调性能或效率。
在本工作中,我们提出了 LoRA with Frozen-A(LoRA-FA),该方法可以在不增加计算开销的情况下大幅减少 LoRA 的激活内存占用。具体来说,LoRA-FA 选择同时冻结预训练权重 W W W 和降维权重 A A A,仅更新升维权重 B B B,如图 1© 所示。通过这种方式,我们仅需计算 B B B 的梯度,而在前向传播过程中只需存储较小的输入 A X A X AX。
假设 W ∈ R d × d , A ∈ R d × r W \in \mathbb{R}^{d \times d}, A \in \mathbb{R}^{d \times r} W∈Rd×d,A∈Rd×r,以及 B ∈ R r × d B \in \mathbb{R}^{r \times d} B∈Rr×d,降维权重 A A A 将 d d d 维输入 X X X 映射为 r r r 维输入 X A X A XA。由于 r ≪ d r \ll d r≪d,LoRA-FA 的激活内存需求可以显著降低。例如,LoRA-FA(秩大小 r = 4 r=4 r=4)可以将 LLaMA-65B(隐藏维度 d = 8192 d=8192 d=8192)线性层的激活内存需求相比全参数微调减少 2048 倍。同时,LoRA-FA 将可训练参数的数量从 d 2 d^2 d2 降至 d r d r dr,同样减少了 2048 倍。
我们将 A A A 随机初始化为服从正态分布的矩阵(通常为秩 r r r 的矩阵),并将 B B B 初始化为零。这确保了在微调开始前,预训练模型与包含 LoRA-FA 模块的模型预测保持一致。在模型适配过程中,LoRA-FA 固定 A A A 并更新 B B B 来提升模型性能,这意味着模型权重的变化 Δ W = A B \Delta W=A B ΔW=AB 局限于初始 A A A 的列空间定义的低秩空间。
实验结果表明,LoRA-FA 已足够用于微调大语言模型(LLMs)。此外,LoRA-FA 不改变 LoRA 的前向传播和反向传播计算(除了跳过 A A A 的梯度计算),因此在微调阶段不会增加计算开销。在推理阶段,与 LoRA 类似,LoRA-FA 可以通过将低秩权重 A B A B AB 合并到 W W W 中实现,与全参数微调模型相比,不会引入额外的推理延迟。
我们对多种模型类型和规模进行了广泛的实验。我们在自然语言理解任务上对 RoBERTa(Liu 等人,2019 年)、在机器翻译任务上对 T5(Raffel 等人,2020 年)以及在 MMLU(Hendrycks 等人,2021 年)基准上对 LLaMA(Touvron 等人,2023a)进行了微调。我们发现,与全参数微调 (FT) 和 LoRA 相比,我们的 LoRA-FA 可以在许多任务中实现非常接近的模型精度。在内存开销方面,与全参数微调和 LoRA 相比,我们的 LoRA-FA 可以将总内存成本分别降低高达 2 倍和 1.4 倍。例如,LoRA-FA 将微调 LLaMA-7B 模型的内存占用从 56GB 减少到 27.5GB。这意味着我们可以使用更低的资源预算(例如,更便宜的 GPU 服务,内存更小)来实现相同的微调性能。此外,我们研究了超参数的影响,结果表明 LoRA-FA 对超参数具有很强的鲁棒性。
总之,LoRA-FA 有几个关键优势:1)通过减少可训练参数和激活的数量来提高内存效率,2)它不会增加微调阶段的计算开销,也不会增加推理阶段的延迟开销,3)与全参数微调相比,它在许多模型和任务中实现了类似的模型性能。
2 BACKGROUND
2.1 LARGE LANGUAGE MODELS
我们专注于基于 Transformer 的大型语言模型 (LLM)。Transformer 模型最早在 (Vaswani et al, 2017) 中提出,用于机器翻译任务。后来,不同的 Transformer 模型被用于语言建模 (即预训练),预训练模型适用于许多下游任务 (Kenton & Toutanova, 2019; Raffel et al, 2020; Brown et al, 2020)。
以仅解码器的 GPT (Brown et al, 2020) 模型为例,它由 L 个堆叠的 Transformer 块组成,每个块有两个子模块:多头注意力 (MHA) 和前馈网络 (FFN)。在 MHA 中,三个线性层将输入转换为查询、键和值,它们被输入到自注意力中进行交互,注意力输出被发送到另一个线性层。 在 FFN 中,我们有两个线性层和它们之间的 GeLU 激活函数。对于 MHA 和 FFN,应用层规范和残差连接来提高模型性能。在 LLM 中,这些线性层中的权重通常占模型参数的大多数,并负责大部分计算浮点运算。
2.2 LOW-RANK ADAPTATION
随着微调大型语言模型(LLMs)的全参数方法成本的不断增加,参数高效微调(PEFT)方法(尤其是 LoRA,Hu et al., 2022)被提出,通过仅更新模型参数的一小部分来减轻内存开销,同时实现与全参数微调 LLMs 可比的性能。具体来说,LoRA 在线性层的权重旁添加了一个低秩适配器,其计算公式如下:
Y = X W + α X A B Y = X W + \alpha X A B Y=XW+αXAB
其中, W ∈ R d in × d out W \in \mathbb{R}^{d_{\text{in}} \times d_{\text{out}}} W∈Rdin×dout 是预训练权重, d in d_{\text{in}} din 是输入维度, d out d_{\text{out}} dout 是输出维度。我们忽略偏置项,因为它不会影响分析。 X ∈ R b × s × d in X \in \mathbb{R}^{b \times s \times d_{\text{in}}} X∈Rb×s×din 和 Y ∈ R b × s × d out Y \in \mathbb{R}^{b \times s \times d_{\text{out}}} Y∈Rb×s×dout 分别为输入和输出张量, b b b 是批大小, s s s 是序列长度。对于 LoRA 部分, A ∈ R d in × r A \in \mathbb{R}^{d_{\text{in}} \times r} A∈Rdin×r 是降维权重, B ∈ R r × d out B \in \mathbb{R}^{r \times d_{\text{out}}} B∈Rr×dout 是升维权重, r r r 是秩大小, α > 0 \alpha > 0 α>0 是超参数(通常设置为 1 / r 1 / r 1/r)。
对于如 GPT(Brown et al., 2020)这样的 Transformer 模型,我们通常有 d in = d out = d d_{\text{in}} = d_{\text{out}} = d din=dout=d,适用于多头注意力(MHA)的四个线性层;而对于前馈网络(FFN)的第一(或第二)线性层,有 d in = d , d out = 4 d d_{\text{in}} = d, d_{\text{out}} = 4d din=d,dout=4d(或 d in = 4 d , d out = d d_{\text{in}} = 4d, d_{\text{out}} = d din=4d,dout=d),其中 d d d 是隐藏维度。默认情况下,我们在 Transformer 块的所有线性层中添加 LoRA 模块以增强微调性能(Zhang et al., 2023b)。
内存复杂度
对于全参数微调,我们需要更新线性层的权重 W W W,其元素数量为 d in × d out d_{\text{in}} \times d_{\text{out}} din×dout,GPT 类型模型的权重总数为 n = 12 d 2 L n = 12d^2L n=12d2L。对于 LoRA,仅需更新两个低秩矩阵,其元素数量为 ( d in + d out ) r \left(d_{\text{in}} + d_{\text{out}}\right)r (din+dout)r,GPT 的 LoRA 参数总数为 n r = 18 d r L n_r = 18drL nr=18drL。因此,当秩大小 r ≪ d r \ll d r≪d 时,LoRA 可以显著减少可训练参数的数量。
在16位混合精度训练环境下,全参数微调需要 2 n 2n 2n 字节用于模型权重,以及 14 n 14n 14n 字节用于梯度和优化器状态(32位 AdamW 的状态和参数副本)(Rajbhandari et al., 2020)。相比之下,LoRA 需要 2 n 2n 2n 字节用于模型权重,以及 16 n r 16n_r 16nr 字节用于适配器相关的权重、梯度和优化器状态。这意味着当 n r ≪ n n_r \ll n nr≪n(或 r ≪ d r \ll d r≪d)时,LoRA 可以将这一部分的内存开销减少约 8 倍。
然而,在激活内存开销方面,情况有所不同。全参数微调需要存储输入 X X X 以计算 W W W 的梯度,而 LoRA 需要存储输入 X X X 以计算 A A A 的梯度,同时还需要存储低秩输入 X A XA XA 以计算 B B B 的梯度。具体而言,在 16 位精度下,LoRA 和全参数微调分别需要 14 b s d L + 8 b s r L 14 b s d L + 8 b s r L 14bsdL+8bsrL 字节和 14 b s d L 14 b s d L 14bsdL 字节的激活内存,其中 b b b 是批大小, s s s 是序列长度, d d d 是隐藏维度, L L L 是层数。此外,二者在其他组件(如注意力、GeLU 和层归一化)中也会消耗激活内存(Korthikanti et al., 2023)。
因此,与全参数微调相比,LoRA 无法减少(甚至可能增加)激活内存的开销,这不幸地成为了新的内存瓶颈。
减少激活内存的挑战。有两种方法可以降低 LoRA 的激活记忆成本。首先,我们可以将 LoRA 模块添加到少数线性层中,例如 Transformer 模型中的查询和值投影 (Hu et al, 2022),因此,没有 LoRA 的其他冻结线性层不需要存储其输入激活。然而,这种方法可能会影响微调任务的性能 (Dettmers et al, 2023),并且还带来了选择使用 LoRA 进行微调的层的难度 (Zhang et al, 2023b)。其次,已经提出了激活重新计算 (Chen et al, 2016; Korthikanti et al, 2023),以在前馈传递期间仅检查每个 Transformer 块的输入,并在反向传播传递期间从此检查点开始重新计算其他必要的激活。然而,激活重新计算具有非常昂贵的重新计算成本,这会引入大约 1/3 的总计算次数。
3 LORA-FA METHOD
首先,我们介绍了 LoRA-FA 方法的设计,从低秩模型自适应的角度对其进行了解释,并分析了其在减少内存开销方面的优势。其次,我们表明 LoRAFA 可以集成到其他内存优化技术中以提高其利用率。第三,我们讨论了 LoRA-FA 与梯度压缩之间的关系。
3.1 LORA WITH FROZEN-A
LoRA 方法更新了两个低秩矩阵 A A A 和 B B B,并将 A B A B AB 作为线性层预训练冻结权重 W W W 的变化,即 W + α Δ W = W + α A B W + \alpha \Delta W = W + \alpha A B W+αΔW=W+αAB。如前所述,LoRA 不直接更新 W W W,因此能够显著减少可训练参数的数量,但仍需消耗昂贵的激活内存。
为了应对这一问题,我们提出了 LoRA with Frozen-A(LoRA-FA),在微调过程中冻结 W W W 和 A A A,仅更新 B B B。具体来说,我们将 A A A 随机初始化为服从正态分布的矩阵,通常是秩为 r r r 的矩阵,并将 B B B 初始化为零,这样 Δ W = A B \Delta W = A B ΔW=AB 初始为零,因此在微调开始前,模型预测不会受到影响。
低秩模型适配
在微调过程中,如图 1© 所示,我们冻结初始化的 A A A 和预训练的 W W W,仅更新升维权重 B B B。因此,模型适配期间的权重变化限制在低秩空间内,表示为:
Δ W = A B = Q B ˉ = ∑ i = 1 r Q : , i B ˉ i , : \Delta W = A B = Q \bar{B} = \sum_{i=1}^r Q_{:, i} \bar{B}_{i,:} ΔW=AB=QBˉ=i=1∑rQ:,iBˉi,:
其中, A = Q R A = Q R A=QR 是 A A A 的 QR 分解, Q Q Q 的 r r r 列(即 Q : , i Q_{:, i} Q:,i, i = 1 , ⋯ , r i=1, \cdots, r i=1,⋯,r)是正交单位向量,当 A A A 是秩为 r r r 的矩阵时成立。我们记 B ˉ = R B \bar{B} = R B Bˉ=RB,推导得 Δ W : , j = ∑ i = 1 r B ˉ i j Q : , i \Delta W_{:, j} = \sum_{i=1}^r \bar{B}_{i j} Q_{:, i} ΔW:,j=∑i=1rBˉijQ:,i,因此 Δ W \Delta W ΔW 的任何一列都是 r r r 个正交向量的组合。换句话说,权重变化位于由 A A A 的列空间定义的低秩空间中。
内存复杂度
我们详细分析了 LoRA-FA 的内存复杂度。对于 LoRA-FA 模块,它仅计算 B B B 的梯度,包含 d out × r d_{\text{out}} \times r dout×r 个元素。在 GPT 类型模型中,总的可训练参数为 n r / 2 = 9 d r L n_r / 2 = 9 d r L nr/2=9drL,即 LoRA 可训练参数的一半。因此,在 16 位混合精度训练中,模型权重和适配器相关状态的内存开销为 2 n + 8 n r 2n + 8n_r 2n+8nr 字节。
更重要的是,就激活内存而言,LoRA-FA 仅需存储低秩输入 X A X A XA 以计算 B B B 的梯度,这对所有 LoRA-FA 模块来说需 8 b s r L 8 b s r L 8bsrL 字节(16 位)。与全参数微调相比,LoRA-FA 通过显著减少可训练参数和输入激活的数量,在内存效率上具有明显优势。
3.2 COMBINATION WITH MEMORY OPTIMIZATIONS
LoRA-FA 可以自然地与先进的内存优化方法相结合,例如权重量化(Dettmers 等人,2023 年)、权重分片(Rajbhandari 等人,2020 年)和选择性激活重新计算(Korthikanti 等人,2023 年)。
权重量化
如前所述,16 位格式下模型权重的内存开销为 2 n 2n 2n,其中 n n n 是模型参数的数量。例如,LLaMA-65B 模型的权重内存开销为 130GB,无法装载到一块 NVIDIA A100 (80GB) GPU 上。在 LoRA-FA 中,由于模型权重在微调过程中是冻结的,我们可以将其量化为更低的位宽,以减少模型权重的内存开销,同时不影响微调性能。例如,8 位(Dettmers et al., 2022a)和 4 位量化方法(Dettmers et al., 2023)可以与 LoRA-FA 结合,将模型权重内存减少至原来的 1/2 或 1/4。
权重切分
在使用数据并行技术在多块 GPU 上训练 LLM 时,可以结合权重切分或 ZeRO 第 3 阶段(Rajbhandari et al., 2020)技术,将模型权重切分到不同的 GPU 上,从而将每块 GPU 的内存开销减少为原来的 1 / g 1 / g 1/g,其中 g g g 是 GPU 的数量。与全参数微调中使用 ZeRO 第 3 阶段不同,我们仅对模型权重进行切分,并在前向和反向传播计算中进行权重收集,而不对适配器相关权重、其梯度和优化器状态进行切分。然而,在 LoRA-FA 中,权重切分引入了代价高昂的权重收集通信开销,而数据并行技术仅需通信少量可训练参数的梯度。
选择性激活重计算
Transformer 模型的其他组件(如注意力机制、层归一化、GeLU 和 dropout)也会导致激活内存开销(Korthikanti et al., 2023)。为了解决这个问题,可以使用完整激活重计算来存储每个 Transformer 块的输入。然而,这将使 LoRA-FA 相较于 LoRA 的内存优势丧失,因为在完整激活重计算下,无需为 LoRA 层存储输入。
为了平衡激活开销和重计算开销,我们采用选择性激活重计算,仅对部分模型组件进行重计算。例如,FlashAttention(Dao et al., 2022)可以消除注意力机制中 softmax 输出的内存开销,同时通过减少高带宽内存(HBM)访问加速注意力计算。此外,我们可以通过存储随机生成器状态来精确重现 dropout 掩码,从而实现 dropout 的重计算。
3.3 RELATION TO GRADIENT COMPRESSION
我们探讨 LoRA-FA 与低秩梯度压缩(Vogels et al., 2019;Zhang et al., 2023a)之间的关系。对于一个 LoRA-FA 层(为简化,省略 α \alpha α),即 Y = X W + X A B Y = X W + X A B Y=XW+XAB, B B B 的梯度计算为:
d B = A T X T d Y = A T d W d B = A^T X^T d Y = A^T d W dB=ATXTdY=ATdW
在标准 SGD 的单步更新中, B B B 的变化为 Δ B = − η d B \Delta B = -\eta d B ΔB=−ηdB,其中 η \eta η 是学习率。因此,冻结 A A A 时, W W W 的变化为:
Δ W = A Δ B = − η A A T d W \Delta W = A \Delta B = -\eta A A^T d W ΔW=AΔB=−ηAATdW
其中, d W d W dW 是 W W W 的梯度。这表明,LoRA-FA 等价于一种低秩梯度压缩方法,用于全参数微调。在这种方法中,计算得到的权重梯度通过 A T d W A^T d W ATdW 被压缩(以减少梯度通信开销),然后通过 A ( A T d W ) A\left(A^T d W\right) A(ATdW) 被解压缩。
由于 A A A 是从正态分布初始化的,我们有:
E [ A A T d W ] = E [ A A T ] d W = r d W \mathbb{E}\left[A A^T d W\right] = \mathbb{E}\left[A A^T\right] d W = r d W E[AATdW]=E[AAT]dW=rdW
这表明这种方法几乎是无偏的梯度压缩。
然而,梯度压缩在微调大型语言模型(LLMs)时,相较于 LoRA-FA 并无优势,因为梯度压缩仍然需要更新全部参数,带来较大的内存开销,而 LoRA-FA 仅需少量可训练权重,也能在数据并行设置下减少梯度通信。此外,当使用自适应优化方法(如 AdamW)时,这两种方法会表现出不同的行为。
相关文章:

(Arxiv-2023)LORA-FA:针对大型语言模型微调的内存高效低秩自适应
LORA-FA:针对大型语言模型微调的内存高效低秩自适应 paper是香港浸会大学发表在Arxiv 2023的工作 paper title:LORA-FA: MEMORY-EFFICIENT LOW-RANK ADAPTATION FOR LARGE LANGUAGE MODELS FINE-TUNING ABSTRACT 低秩自适应 (LoRA) 方法可以大大减少微调…...
huggingface/bert/transformer的模型默认下载路径以及自定义路径
当使用 BertTokenizer.from_pretrained(bert-base-uncased) 加载预训练的 BERT 模型时,Hugging Face 的 transformers 库会从 Hugging Face Model Hub 下载所需的模型文件和分词器文件(如果它们不在本地缓存中)。 默认情况下,这些…...
从 0 开始上手 Solana 智能合约
Solana CLI 基础知识 Solana CLI 是一个命令行界面工具,提供了一系列用于与 Solana Cluster 交互的命令。 我们将介绍一些最常见的命令,但你始终可以通过运行 solana --help 查看所有可能的 Solana CLI 命令列表。 Solana CLI 配置 Solana CLI 存储了…...

(六)CAN总线通讯
文章目录 CAN总线回环测试第一种基于板载CAN测试第一步确认板载是否支持第二步关闭 CAN 接口将 CAN 接口置于非活动状态第三步 配置 CAN 接口第一步 设置 CAN 接口比特率第二步 设置 CAN 启用回环模式第三步 启用 CAN 接口 第四步 测试CAN总线回环捕获 CAN 消息发送 CAN 消息 第…...

新一代智能工控系统网络安全合规解决方案
01.新一代智能工控系统概述 新一代智能工控系统是工业自动化的核心,它通过集成人工智能、工业大模型、物联网、5G等技术,实现生产过程的智能化管理和控制。这些系统具备实时监控、自动化优化、灵活调整等特点,能够提升生产效率、保证产品质量…...

Vivado中Tri_mode_ethernet_mac的时序约束、分析、调整——(一)时序约束的基本概念
1、基本概念 推荐阅读,Ally Zhou编写的《Vivado使用误区与进阶》系列文章,熟悉基本概念、tcl语句的使用。 《Vivado使用误区与进阶》电子书开放下载!! 2、Vivado中的语法例程 1)语法例程 约束的语句可以参考vivado…...

车载网络:现代汽车的数字心跳
在汽车领域,“智能汽车”一词毫不夸张。如今的汽车已不再是原始的机械工程,而是通过先进的车载网络无缝连接的精密数字生态系统。这些滚动计算机由复杂的电子控制单元(ECU)网络提供动力,ECU是负责管理从发动机性能到信息娱乐系统等一切事务的…...

python基础和redis
1. Map函数 2. filter函数 numbers generate_numbers() filtered_numbers filter(lambda x: x % 2 0, numbers) for _ in range(5):print(next(filtered_numbers)) # 输出: 0 2 4 6 83. filter map 和 reduce 4. picking and unpicking 5. python 没有函数的重载࿰…...

w~自动驾驶~合集16
我自己的原文哦~ https://blog.51cto.com/whaosoft/12765612 #SIMPL 用于自动驾驶的简单高效的多智能体运动预测基准 原标题:SIMPL: A Simple and Efficient Multi-agent Motion Prediction Baseline for Autonomous Driving 论文链接:https://ar…...
最长的指定瑕疵度的元音子串
一、题目 最长的指定瑕疵度的元音子串 定义:开头和结尾都是元音字母(aeiouAEIOU)的字符串为 元音字符串 ,其中混杂的非元音字母数量为其 瑕疵度 。比如: “a” 、 "aa"是元音字符串,其瑕疵度都为0 "aiu…...

每日算法Day15【组合、组合总和III、电话号码的字母组合】
77. 组合 算法链接: 77. 组合 - 力扣(LeetCode) 类型: 回溯 难度: 中等 回溯三步法: 1、确定参数返回值 2、确定终止条件 3、单层搜索逻辑 剪枝操作: 当path容量超过k时的数据可以不用遍历,故遍历边界条件判断: …...

C语言教程——指针进阶(2)
目录 一、函数指针数组 1.1函数指针数组写法 1.2函数指针用途 二、指向函数指针数组的指针 2.1概念 三、回调函数 3.1用法 3.2qsort排序 总结 前言 我们接着上一篇的函数指针往下学习。 一、函数指针数组 1.1函数指针数组写法 我们都知道指针数组,里面可以…...
调和级数不为整数的证明
文章目录 1. 问题引入2. 证明2.1 引理12.2 引理22.3 引理3:2.4 核心证明: 3. 参考 1. 问题引入 s ( n ) 1 1 2 1 3 ⋯ 1 n , n ∈ N ∗ , n ≥ 2 s(n) 1\frac{1}{2}\frac{1}{3}\cdots\frac{1}{n}, \quad \\n \in N^*, n \ge2 s(n)12131⋯n1,…...

基于微信小程序的在线学习系统springboot+论文源码调试讲解
第4章 系统设计 一个成功设计的系统在内容上必定是丰富的,在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值,吸引更多的访问者访问系统,以及让来访用户可以花费更多时间停留在系统上,则表明该系统设计得比较专…...

基于 Boost.Asio 和 Boost.Beast 的异步 HTTP 服务器(学习记录)
已完成功能: 支持 GET 和 POST 请求的路由与回调处理。 解析URL请求。 单例模式 管理核心业务逻辑。 异步 I/O 技术和 定时器 控制超时。 通过回调函数注册机制,可以灵活地为不同的 URL 路由注册处理函数。 1. 项目背景 1.1 项目简介 本项目是一个基于…...

有机物谱图信息的速查技巧有哪些?
谱图信息是化学家解读分子世界的“语言”,它们在化学研究的各个领域都发挥着不可或缺的作用。它们是理解和确定分子结构的关键,对化学家来说极为重要,每一种谱学技术都提供了不同的视角来观察分子,从而揭示其独特的化学和物理特性…...
Eureka缓存机制
一、Eureka的CAP特性 Eureka是一个AP系统,它优先保证可用性(A)和分区容错性(P),而不保证强一致性(C)。这种设计使得Eureka在分布式系统中能够应对各种故障和分区情况,保…...
【LC】78. 子集
题目描述: 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入:nums [1,2,3] 输出࿱…...

协同过滤算法私人诊所系统|Java|SpringBoot|VUE|
【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7 4⃣️:技术栈:Java、Mysql、SpringBoot、Mybatis-Plus、VUE、jquery,html 5⃣️…...
Docker部署Naocs-- 超细教程
Docker 拉取镜像 docker pull nacos/nacos-server:v2.2.0 挂载目录 如果不是root账号 前面加sudo 或者 切换root账号 su root(命令) mkdir -p /mydata/nacos/logs/ #新建logs目录 mkdir -p /mydata/nacos/conf/ #新建conf目录 启动容器…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...