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

大模型基础之量化

概述

量化,Quantization,机器学习和深度学习领域是一种用于降低计算复杂度、减少内存占用、加速推理的优化方法。定义:将模型中的数据从高精度表示转换为低精度表示。主要目的是为了减少模型的存储需求和计算复杂度,同时尽量减少精度损失。具体来说:

  • 减少存储需求:大模型通常包含数亿甚至数十亿个参数,占用大量的存储空间;
  • 提高计算效率:量化后的模型在推理时的计算量更少,能够加快推理速度;
  • 降低功耗:量化后的模型需要的计算资源更少,从而降低能耗。尤其是在移动设备和嵌入式系统中,可延长设备的使用时间,减少散热需求;
  • 减少带宽需求:量化后的模型可以更快地完成传输,提高数据传输效率。

量化对象:模型的权重和激活。

方便理解的几个示意图
在这里插入图片描述
在这里插入图片描述

INT是Integer缩写,即整数类型。

FP是Floating Point缩写,浮点数类型,用于表示带有小数部分的数。由三部分组成:符号位(表示正负)、指数位和尾数位(决定浮点数精度)。
在这里插入图片描述
常见的数据类型,包括:

  • FP32:全精度,标准精度。一种高精度的浮点数,1个符号位、8个指数位和23个尾数位,总共32位。可表示非常大和非常小的数,缺点是占用的存储空间大,计算速度慢;大部分硬件都支持FP32运算,所以在训练和推理中广泛使用。
  • FP16:一种低精度的浮点数,1个符号位、5个指数位和10个尾数位,总共16位。精度比FP32低,占用存储空间少一半,计算速度也更快;容易出现上溢和下溢问题,可通过一些技巧来缓解这些问题。
  • BF16:Bfloat16,另一种16位浮点数,指数位数和FP32相同,动态范围较大,但精度比FP16低。在处理大数值时表现更好,但在精度上会有所损失。
  • FP8:1个符号位、3(或4)个指数位和4(或3)个尾数位,总共8位。主要用于深度学习中的高效计算。
  • INT8:8位整数,只能表示从-128到127的整数。存储空间更小,计算速度也更快,但精度更低。常用于模型量化。比如图像处理中的像素值,通常在0到255之间,用INT8就可以很好地表示。
  • INT4:4位整数,表示的范围更小,从-8到7。可用于对精度要求不是特别高的场景,如某些简单的神经网络层。

在这里插入图片描述

公式

量化公式如下: x q = r o u n d ( x f ∗ s c a l e + z ) x_q=round(x_f * scale+z) xq=round(xfscale+z)
其中:

  • x f x_f xf是原始的浮点数;
  • x q x_q xq是量化后的低精度浮点数;
  • z z z是零点;
  • s c a l e scale scale是缩放因子,用于将浮点数映射到低精度范围;
  • r o u n d round round表示四舍五入到最近的值。

计算缩放因子前,需要找到权重或激活的最小值(min)和最大值(max)。 s c a l e = ( m a x − m i n ) / ( 2 n − 1 ) scale=(max-min)/(2^n-1) scale=(maxmin)/(2n1) z = r o u n d ( − m i n / s c a l e ) z=round(-min/scale) z=round(min/scale),确保浮点数0映射到整数0,避免负数溢出。
在这里插入图片描述
有量化公式,自然还有反量化公式: x f = ( x q − z ) / s c a l e x_f=(x_q-z)/scale xf=(xqz)/scale

应用

包括:

  • 模型训练加速:在模型训练过程中,使用低精度数据类型如 FP16 或 FP8 可以显著加快训练速度。例如,NVIDIA 的 Hopper 架构 GPU 支持 FP8 精度的 Tensor Core 计算,与传统的 FP32 训练相比,FP8 训练速度可以提升 2-3 倍。这种加速对于大规模模型的训练尤为重要,因为它可以大幅减少训练时间和计算资源的消耗。
    以大模型训练为例,Inflection AI 的 Inflection2 模型采用了 FP8 混合精度在 5000 个 NVIDIA Hopper 架构 GPU 上进行训练,累计浮点运算次数高达约 1025 FLOPs。与同属训练计算类别的 Google 旗舰模型 PaLM 2 相比,在多项标准人工智能性能基准测试中,Inflection-2 展现出了卓越的性能。
  • 模型推理优化
    在模型推理阶段,量化可以显著降低模型的存储需求和计算复杂度。例如,将 FP32 模型量化为 INT8,存储需求可以减少 75%,推理速度可以提升数倍。这对于在边缘设备或移动设备上部署模型尤为重要,因为这些设备的计算资源和存储空间通常有限。
    例如,Google 与 NVIDIA 团队合作,将 TensorRT-LLM 应用于 Gemma 模型,并结合 FP8 技术进行了推理加速。使用 Hopper GPU 进行推理时,FP8 对比 FP16 在吞吐量上能够带来 3 倍以上的收益。
  • 模型压缩与部署
    量化还可以用于模型的压缩和部署。通过将高精度模型量化为低精度模型,可以减少模型的大小,从而更容易将模型部署到资源受限的环境中。例如,零一万物基于 NVIDIA 软硬结合的技术栈,完成了在大模型的 FP8 训练和验证。其大模型的训练吞吐相对 BF16 得到了 1.3 倍的性能提升。
    量化后的模型不仅在存储和计算上具有优势,还可以通过特定的硬件加速来进一步提升性能。例如,NVIDIA 的 Transformer Engine 已经集成到 PyTorch、JAX、PaddlePaddle 等基础深度学习框架中,为量化模型的推理提供了高效的硬件支持。

优势与局限

优势

  • 计算效率提升:低精度量化可以显著加快计算速度,减少计算资源的消耗。如,FP16和FP8的计算吞吐量比FP32高出数倍。这种加速效果在大规模模型训练和推理中尤为明显。
  • 存储需求降低:量化可以大幅减少模型的存储需求。如将FP32模型量化为INT8,存储需求可减少75%。这对于在资源受限的环境中部署模型非常有帮助。
  • 功耗降低:低精度计算需要的计算资源更少,从而降低了能耗。在移动设备和嵌入式系统中,功耗是一个重要考虑因素。量化后的模型可以延长设备的使用时间,同时减少散热需求。
  • 模型优化:量化促使模型在训练和推理过程中进行优化和压缩,进一步降低部署成本。例如,FP8 的使用可以促使模型在训练过程中进行更细致的量化,从而提高模型的效率。

局限性

  • 精度损失:量化会带来一定的精度损失,尤其是在低精度格式下。例如,FP8 的精度比 FP16 和 FP32 低,可能会在某些任务中导致性能下降。虽然通过合理选择缩放因子可以在一定程度上减少精度损失,但完全避免精度损失是不可能的。
  • 硬件支持有限:并非所有硬件都支持低精度计算。如FP8和FP16的计算需要特定的硬件支持,如NVIDIA的Hopper架构GPU。如果硬件不支持低精度计算,量化的优势将无法充分发挥。
  • 复杂性增加:量化过程本身会增加模型的复杂性。例如,在量化过程中需要计算缩放因子,并且需要对模型进行校准和调整。这可能会增加模型开发和部署的难度。
  • 适用场景有限:量化并不适用于所有场景。例如,在需要高精度计算的任务中,如某些科学计算或金融建模任务,量化可能会导致不可接受的精度损失。

未来趋势

未来,模型量化将在精度优化、硬件适配、动态适应性以及与其他技术的结合等方面取得更大的突破。

  • 精度优化
    • 混合精度量化:结合浮点型和整型运算的优点,对模型的不同部分使用不同的量化精度。这种方法可以在保证推理速度的同时减少精度损失,提高量化模型的性能。例如,对于一些对精度要求较高的层,可以使用较高的量化精度,而对于一些对精度要求较低的层,可以使用较低的量化精度。这种灵活的量化方式能够更好地平衡精度和效率。
    • 量化算法的改进:以更好地处理数据分布不均匀的情况。例如,通过引入更复杂的映射函数或优化算法,可以进一步提高量化精度。此外,研究人员还将探索新的量化方法,如非线性量化,以适应不同类型的数据分布。
  • 硬件适配
    • 专用硬件的优化:随着硬件技术的发展,专用硬件加速器将更好地支持模型量化。例如,未来的 GPU 和 FPGA 将提供更高效的量化操作支持,减少量化过程中的计算开销。这将使得量化模型在硬件上的运行更加高效,进一步提高推理速度。
    • 跨平台适配:未来,量化算法将更加注重跨平台适配。这意味着同一个量化模型可以在不同的硬件平台上高效运行,无需针对每个平台进行单独的优化。例如,通过开发通用的量化框架和接口,可以实现量化模型在移动设备、嵌入式系统和数据中心等不同场景下的无缝部署。
  • 动态适应性
    • 动态量化技术的改进:以更好地适应输入数据的变化。例如,通过引入更高效的量化参数计算方法,可以减少动态量化过程中的计算开销。此外,研究人员还将探索新的动态量化策略,如自适应量化,以进一步提高量化精度。
    • 动态模型的支持:例如,对于动态神经网络,量化算法将能够根据模型结构的动态变化实时调整量化参数。这将使得量化模型在处理动态任务时能够更好地保持精度和效率。
  • 与其他技术的结合
    • 与模型剪枝的结合:例如,通过先对模型进行剪枝,去除冗余的参数和连接,然后再进行量化,可以进一步减少模型的存储空间和计算复杂度。这种组合优化方法能够更好地提高模型的部署效率。
    • 与知识蒸馏的结合:例如,通过将量化模型作为学生模型,将原始浮点模型作为教师模型,进行知识蒸馏,可以进一步提高量化模型的精度。这种结合方式能够更好地平衡量化模型的精度和效率。

算法

分类

按阶段可分为:PTQ和QAT

PTQ:训练后量化(Post-Training Quantization)

  • 定义:在模型训练完成后,直接对模型的权重和激活值进行量化。不需要对原始训练过程进行修改,简单易行,适合在实际生产环境中快速部署量化模型。
  • 优点:过程简单,不需要额外的训练资源,对部署人员的技术要求较低。例如,对于一些已经训练好的大型模型,如ResNet50,使用PTQ可以在短时间内完成量化,使其更适合在移动设备上运行。
  • 缺点:由于没有在训练阶段对量化误差进行建模,量化后的模型精度可能会有一定的损失。可通过一些优化手段,如校准(calibration)和量化策略的选择,在一定程度上缓解精度下降的问题。

QAT:量化感知训练(Quantization Aware Training)

  • 定义:在模型训练过程中引入量化操作,使模型在训练阶段就对量化误差进行学习和适应。通过模拟量化过程,让模型在训练时就考虑到量化带来的影响,从而在量化后能够更好地保持精度。
  • 优点:通常能够获得较低的精度损失,适合对模型精度要求较高的场景。例如,在一些需要高精度的图像识别任务中,使用 QAT 可以在量化后仍然保持较高的准确率。
  • 缺点:需要对训练过程进行修改,增加训练的复杂性和计算成本。此外,QAT 的实现相对复杂,对研究人员的技术水平要求较高。

在这里插入图片描述
QAT:
在这里插入图片描述

按量化方式可分为:对称量化(Symmetric Quantization)和非对称量化(Asymmetric Quantization)

对称量化

  • 定义:对称量化是将浮点数的最大绝对值映射到量化后的最大值,将最大绝对值的负值映射到量化后的最小值。例如,对于 int8 量化,将浮点数的最大绝对值映射到 127,其负值映射到 -128。
  • 优点:计算简单,易于实现。在数据分布较为均匀的情况下,对称量化能够较好地利用量化范围,保持数据的精度。例如,当模型的权重或激活值在零点附近均匀分布时,对称量化的效果较好。
  • 缺点:对于数据分布不均匀的情况,对称量化可能无法充分利用量化范围,导致精度损失较大。例如,当数据主要集中在正数或负数区域时,对称量化可能会浪费一部分量化范围,影响量化效果。

在这里插入图片描述

非对称量化

  • 定义:非对称量化通过收缩因子(scale)和零点(zero point)将浮点数的最小值和最大值分别映射到量化后的最小值和最大值。例如,对于 int8 量化,将浮点数的最小值映射到 -128,最大值映射到 127。
  • 优点:能够更好地处理数据分布不均匀的情况,适用于各种数据分布形态。例如,当数据主要集中在正数区域时,非对称量化可以通过调整零点和收缩因子,将量化范围更多地分配给正数区域,从而更好地保留数据信息。
  • 缺点:计算相对复杂,需要引入零点的概念。在某些情况下,非对称量化可能会引入额外的计算开销,尤其是在硬件实现时。例如,一些专用的硬件加速器可能对非对称量化支持不够完善,导致性能下降。

PyTorch

作为主流的深度学习框架,PyTorch提供完善的支持:
Dynamic PTQ:

import torch
from torch.quantization import quantize_dynamic
# 加载预训练模型
model = torch.load('model.pth')
model.eval()
# 动态量化(量化Linear和LSTM层)
quantized_model = quantize_dynamic(model, {torch.nn.Linear, torch.nn.LSTM},  # 指定量化层类型dtype=torch.qint8
)

Static PTQ:

from torch.quantization import prepare, convert
# 准备校准数据集
def calibrate(model, data_loader):model.eval()with torch.no_grad():for inputs in data_loader:model(inputs)
# 配置量化参数
model.qconfig = torch.quantization.get_default_qconfig('fbgemm')
model_prepared = prepare(model)          # 插入Observer节点
calibrate(model_prepared, data_loader)  # 校准激活值范围
quantized_model = convert(model_prepared)  # 转换为量化模型

QAT:

from torch.quantization import prepare_qat, FakeQuantize
# 定义QAT模型
model.qconfig = torch.quantization.get_default_qat_qconfig('fbgemm')
model_prepared = prepare_qat(model)     # 插入伪量化节点
# 训练阶段(模拟量化误差)
optimizer = torch.optim.SGD(model_prepared.parameters(), lr=0.01)
for inputs, labels in train_loader:outputs = model_prepared(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()
# 转换至最终量化模型
quantized_model = convert(model_prepared)

算法简介

对称量化算法

一种简单且广泛应用的量化方法,其核心思想是将浮点数的最大绝对值映射到量化后的最大值,将最大绝对值的负值映射到量化后的最小值。优点:计算简单,易于实现,且在数据分布较为均匀的情况下能够较好地保持数据精度。例如,当模型的权重或激活值在零点附近均匀分布时,对称量化的效果较好。

公式:
x i n t = r o u n d ( x / s ) x_{int}=round(x/s) xint=round(x/s)
x Q = c l a m p ( − N l e v e l / 2 , N l e v e l / 2 − 1 , x i n t ) x_Q=clamp(-N_{level}/2,N_{level}/2-1,x_{int}) xQ=clamp(Nlevel/2,Nlevel/21,xint)(有符号)
x Q = c l a m p ( 0 , N l e v e l − 1 , x i n t ) x_Q=clamp(0,N_{level}-1,x_{int}) xQ=clamp(0,Nlevel1,xint)(无符号)
其中, x x x是原始浮点数, s s s是缩放因子, N l e v e l N_{level} Nlevel是量化后的数值范围。

缺点:对于数据分布不均匀的情况,例如数据主要集中在正数或负数区域,对称量化可能会浪费一部分量化范围,导致精度损失较大。例如,当数据主要集中在正数区域时,对称量化可能会将一部分量化范围分配给负数区域,而这些负数区域的数据实际上很少出现,从而影响量化效果。

非对称量化算法

通过收缩因子和零点将浮点数的最小值和最大值分别映射到量化后的最小值和最大值。例如,在int8量化中,浮点数的最小值被映射到 -128,最大值被映射到 127。

公式:
x i n t = r o u n d ( x / s ) + z x_{int}=round(x/s)+z xint=round(x/s)+z
x Q = c l a m p ( 0 , N l e v e l − 1 , x i n t ) x_Q=clamp(0,N_{level}-1,x_{int}) xQ=clamp(0,Nlevel1,xint)
其中, x x x是原始浮点数, s s s是缩放因子, z z z是零点, N l e v e l N_{level} Nlevel是量化后的数值范围。

优点是能够更好地处理数据分布不均匀的情况,适用于各种数据分布形态。例如,当数据主要集中在正数区域时,非对称量化可以通过调整零点和收缩因子,将量化范围更多地分配给正数区域,从而更好地保留数据信息。缺点:计算相对复杂,需要引入零点的概念。在某些情况下,非对称量化可能会引入额外的计算开销,尤其是在硬件实现时。例如,一些专用的硬件加速器可能对非对称量化支持不够完善,导致性能下降。

动态量化算法

一种在推理过程中动态调整量化参数的方法。与静态量化不同,动态量化不需要在量化前对整个数据集进行校准,而是根据输入数据的实时分布动态调整量化范围。

公式:
x i n t = r o u n d ( x / s ) x_{int}=round(x/s) xint=round(x/s)
x Q = c l a m p ( − N l e v e l / 2 , N l e v e l / 2 − 1 , x i n t ) x_Q=clamp(-N_{level}/2,N_{level}/2-1,x_{int}) xQ=clamp(Nlevel/2,Nlevel/21,xint)(有符号)
x Q = c l a m p ( 0 , N l e v e l − 1 , x i n t ) x_Q=clamp(0,N_{level}-1,x_{int}) xQ=clamp(0,Nlevel1,xint)(无符号)
其中, x x x是原始浮点数, s s s是动态计算的缩放因子, N l e v e l N_{level} Nlevel是量化后的数值范围。

优点是能够根据输入数据的实时分布动态调整量化范围,从而更好地适应输入数据的变化,提高量化精度。例如,在处理不同批次的输入数据时,动态量化可以根据每个批次的数据分布动态调整量化参数,避免因数据分布差异导致的精度损失。缺点:由于需要在推理过程中动态计算量化参数,这会增加计算开销,尤其是在硬件实现时。动态量化可能会导致量化后的模型在不同输入数据下表现出不同的精度,这需要在实际应用中进行仔细的测试和调整。

静态量化算法

一种在量化前对整个数据集进行校准的方法。通过校准过程,可确定最优的量化参数,从而在推理过程中保持固定的量化范围。

公式:
x i n t = r o u n d ( x / s ) x_{int}=round(x/s) xint=round(x/s)
x Q = c l a m p ( − N l e v e l / 2 , N l e v e l / 2 − 1 , x i n t ) x_Q=clamp(-N_{level}/2,N_{level}/2-1,x_{int}) xQ=clamp(Nlevel/2,Nlevel/21,xint)(有符号)
x Q = c l a m p ( 0 , N l e v e l − 1 , x i n t ) x_Q=clamp(0,N_{level}-1,x_{int}) xQ=clamp(0,Nlevel1,xint)(无符号)
其中, x x x是原始浮点数, s s s是通过校准过程确定的缩放因子, N l e v e l N_{level} Nlevel是量化后的数值范围。

优点是量化参数固定,计算简单,适合在硬件上实现。例如,通过校准过程确定的量化参数可以在推理过程中保持不变,从而减少计算开销,提高推理速度。缺点:由于量化参数在量化前已经确定,无法根据输入数据的变化动态调整,这可能会导致在某些情况下精度损失较大。例如,当输入数据的分布与校准数据的分布差异较大时,静态量化可能会导致量化后的模型精度下降。

零点量化

Zero-Point Quantization,通过线性映射,将原始数据的最小值和最大值对应到目标数据类型的最小值和最大值。将 FP16 数值转换为 Int8 时,就会用到这种量化方法。下图展示了这一过程。

绝对最大值量化

Max Absolute Quantization,absmax,对称量化方法,将原始数据中的最大绝对值映射到目标数据类型的有符号范围。通过找到数据中正负范围内的绝对最大值,然后使用这个最大值来确定量化的缩放因子。

GPTQ

Group-wise Precision Tuning Quantization,分组精确调整量化,首次成功地将BLOOM或OPT-175B等175B规模的大模型量化为4-bit。

GPTQ采用逐行量化(per-row quantization),即独立地量化权重矩阵的每一行,以找到最优的量化权重,从而最小化量化误差。为了实现高精度量化,GPTQ 利用 Hessian 矩阵计算剩余权重的最优更新,从而减少量化带来的信息损失。需要注意的是,GPTQ 保留嵌入层(embedding layer)和输出层(output layer)为 FP16 以维持模型精度。

AWQ

Activation-aware Weight Quantization,激活感知权重量化,

选择

选择哪种量化算法,需要综合考虑精度、推理速度、存储空间等多方面因素。

相关文章:

大模型基础之量化

概述 量化,Quantization,机器学习和深度学习领域是一种用于降低计算复杂度、减少内存占用、加速推理的优化方法。定义:将模型中的数据从高精度表示转换为低精度表示。主要目的是为了减少模型的存储需求和计算复杂度,同时尽量减少…...

游戏引擎学习第286天:开始解耦实体行为

回顾并为今天的内容定下基调 我们目前正在进入实体系统的一个新阶段,之前我们已经让实体的移动系统变得更加灵活,现在我们想把这个思路继续延伸到实体系统的更深层次。今天的重点,是重新审视我们处理实体类型(entity type&#x…...

win10-django项目与mysql的基本增删改查

以下都是在win10系统下,django项目的orm框架对本地mysql的表的操作 models.py----->即表对应的类所在的位置 在表里新增数据 1.引入表对应的在models.py中的类class 2.在views.py中使用函数:类名.objects.create(字段名值,字段名"值"。。。…...

Windows 本地部署MinerU详细教程

📖 项目概述 MinerU是一款由OpenDataLab开发的开源PDF转Markdown工具,可以高质量地提取PDF文档内容,生成结构化的Markdown格式文本。本指南将帮助您在本地部署并使用MinerU。 ⭐ 功能特性 MinerU具有以下核心功能: ✨ 文档处理…...

动态范围调整(SEF算法实现)

一、背景介绍 继续在整理对比度调整相关算法,发现一篇单帧动态范围提升的算法:Simulated Exposure Fusion,论文表现看起来很秀,这里尝试对它进行了下效果复现。 二、实现流程 1、基本原理 整体来说,大致可以分为两步…...

SpringCloud微服务开发与实战

本节内容带你认识什么是微服务的特点,微服务的拆分,会使用Nacos实现服务治理,会使用OpenFeign实现远程调用(通过黑马商城来带你了解实际开发中微服务项目) 前言:从谷歌搜索指数来看,国内从自201…...

WAS和Tomcat的对比

一、WAS和Tomcat的对比 WebSphere Application Server (WAS) 和 Apache Tomcat 是两款常用的 Java 应用服务器,但它们有许多显著的区别。在企业级应用中,它们扮演不同的角色,各自有其特点和适用场景。以下是它们在多个维度上的详细对比&…...

Rust 数据结构:String

Rust 数据结构:String Rust 数据结构:String什么是字符串?创建新字符串更新字符串将 push_str 和 push 附加到 String 对象后使用 运算符和 format! 宏 索引到字符串字符串在内存中的表示字节、标量值和字形簇 分割字符串遍历字符串的方法 R…...

IntelliJ IDEA打开项目后,目录和文件都不显示,只显示pom.xml,怎样可以再显示出来?

检查.idea文件夹 如果项目目录中缺少.idea文件夹,可能导致项目结构无法正确加载。可以尝试删除项目根目录下的.idea文件夹,然后重新打开项目,IDEA会自动生成新的.idea文件夹和相关配置文件,从而恢复项目结构。 问题解决&#xff0…...

Hot100-链表-JS

160.相交链表 160. 相交链表 已解答 简单 相关标签 相关企业 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整…...

事件驱动架构:从传统服务到实时响应的IT新风潮

文章目录 事件驱动架构的本质:从请求到事件的范式转变在EDA中: 事件驱动架构的演进:从消息队列到云原生标配核心技术:事件驱动架构的基石与工具链1. 消息队列:事件传递的枢纽2. 消费者:异步处理3. 事件总线…...

网络流量分析 | NetworkMiner

介绍 NetworkMiner 是一款适用于Windows(也适用于Linux/Mac)的开源网络取证分析工具。它可被用作被动网络嗅探器/数据包捕获工具,也可被用于检测操作系统、会话、主机名、开放端口等,还能被用于解析pcap文件进行离线分析。点击此…...

弦理论的额外维度指的是什么,宇宙中有何依据

弦理论中的额外维度是解释微观世界与宏观宇宙矛盾的关键假设之一。它们并非科幻中的平行宇宙,而是通过严谨的数学框架提出,并可能留下可观测的宇宙学痕迹。以下是具体解析: 一、弦理论为何需要额外维度? 数学自洽性要求 弦理论中…...

std::tuple 用法

std::tuple 是 C11 引入的模板类&#xff0c;用来存储多个不同类型的值&#xff0c;类似于 Python 的元组。你可以把它看作是一种“组合多个变量在一个对象中”的方式。 ✅ 基本用法 #include <tuple> #include <iostream>int main() {std::tuple<int, std::st…...

深入理解 Git 分支操作的底层原理

在软件开发的世界里&#xff0c;Git 已经成为了版本控制的标配工具。而 Git 分支功能&#xff0c;更是极大地提升了团队协作和项目开发的效率。我们在日常开发中频繁地创建、切换和合并分支&#xff0c;但是这些操作背后的底层原理是怎样的呢&#xff1f;在之前的博客探秘Git底…...

Excel MCP: 自动读取、提炼、分析Excel数据并生成可视化图表和分析报告

最近&#xff0c;一款Excel MCP Server的开源工具火了&#xff0c;看起来功能很强大&#xff0c;咱们今天来一探究竟。 基础环境 最近两年&#xff0c;大家都可以看到AI的发展有多快&#xff0c;我国超10亿参数的大模型&#xff0c;在短短一年之内&#xff0c;已经超过了100个&…...

C语言:深入理解指针(4)

目录 一、字符指针变量 二、数组指针变量 三、二维数组传参的本质 四、函数指针变量 五、typedef 类型重命名 六、函数指针数组 一、字符指针变量 我们常见的字符指针变量是这样的&#xff1a; char a w; char* p &a; char arr[] "abcd"; char* pa ar…...

Gensim 是一个专为 Python 设计的开源库

Gensim 是一个专为 Python 设计的开源库&#xff0c;其核心代码和生态系统均基于 Python 构建&#xff0c;目前官方仅支持 Python 语言。如果你需要在其他编程语言中实现类似功能&#xff08;如词向量训练、主题模型等&#xff09;&#xff0c;通常需要使用对应语言的替代库或通…...

质量管理工程师面试总结

今天闲着无聊参加了学校招聘会的一家双选会企业&#xff0c;以下是面试的过程。 此次面试采用的是一对多的形式。&#xff08;此次三个求职者&#xff0c;一个面试官&#xff09; 面试官&#xff1a;开始你们每个人先做个自我介绍吧。 哈哈哈哈哈哈哈哈&#xff0c;其实我们…...

python 爬虫框架介绍

文章目录 前言一、Requests BeautifulSoup&#xff08;基础组合&#xff09;二、Scrapy&#xff08;高级框架&#xff09;三、PySpider&#xff08;可视化爬虫&#xff09;四、Selenium&#xff08;浏览器自动化&#xff09;五、Playwright&#xff08;新一代浏览器自动化&…...

window 显示驱动开发-使用有保证的协定 DMA 缓冲区模型

Windows Vista 的显示驱动程序模型保证呈现设备的 DMA 缓冲区和修补程序位置列表的大小。 修补程序位置列表包含 DMA 缓冲区中命令引用的资源的物理内存地址。 在有保证的协定模式下&#xff0c;用户模式显示驱动程序知道 DMA 缓冲区和修补程序位置列表的确切大小&#xff0c;…...

蓝牙协议架构与调试工具详解(含 BLE、HCI 命令、调试命令)

本文介绍蓝牙协议从物理层到应用层的完整通信流程&#xff0c;并详解了 Linux 下主流蓝牙调试工具的使用方法&#xff0c;适用于嵌入式蓝牙驱动开发、BLE调试、通信协议分析等场景。 &#x1f527; 1. 蓝牙架构概览 ✅ 芯片架构 单模芯片&#xff1a;仅支持 BLE 或 Classic 蓝…...

预测模型开发与评估:基于机器学习的数据分析实践

在当今数据驱动的时代&#xff0c;预测模型已成为各行各业决策制定的核心工具。本文将分享我在COMP5310课程项目中开发预测模型的经验&#xff0c;探讨从数据清洗到模型优化的完整过程&#xff0c;并提供详细的技术实现代码。 ## 研究问题与数据集 ### 研究问题 我们的研究聚焦…...

提高表达能力

你遇到的这种情况其实很常见&#xff0c;背后的原因可能涉及思维模式、心理状态和表达习惯的综合作用。以下是具体分析和解决方案&#xff1a; 1. 原因分析&#xff1a;为什么讨论时流畅&#xff0c;独自表达却卡壳&#xff1f; 外部反馈缺失&#xff1a;讨论时对方的提问、反…...

【更新】全国省市县-公开手机基站数据集(2006-2025.3)

手机基站是现代通信网络中的重要组成部分&#xff0c;它们为广泛的通信服务提供基础设施。随着数字化进程的不断推进&#xff0c;手机基站的建设与布局对优化网络质量和提升通信服务水平起着至关重要的作用&#xff0c;本分享数据可帮助分析移动通信网络的发展和优化。本次数据…...

基于MNIST数据集的手写数字识别(CNN)

目录 一&#xff0c;模型训练 1.1 数据集介绍 1.2 CNN模型层结构 1.3 定义CNN模型 1.4 神经网络的前向传播过程 1.5 数据预处理 1.6 加载数据 1.7 初始化 1.8 模型训练过程 1.9 保存模型 二&#xff0c;模型测试 2.1 定义与训练时相同的CNN模型架构 2.2 图像的预处…...

MYSQL创建索引的原则

创建索引的原则包括&#xff1a; 表中的数据量超过10万以上时考虑创建索引。 选择查询频繁的字段作为索引&#xff0c;如查询条件、排序字段或分组字段。 尽量使用复合索引&#xff0c;覆盖SQL的返回值。 如果字段区分度不高&#xff0c;可以将其放在组合索引的后面。 对于…...

运行Spark程序-在shell中运行

Spark Shell运行程序步骤 启动Spark Shell 根据语言选择启动命令&#xff1a; Scala版本&#xff08;默认&#xff09;&#xff1a;执行spark-shellPython版本&#xff1a;执行pyspark 数据加载示例 读取本地文本文件&#xff1a; // Scala版本 val textData sc.textFile(…...

idea Maven 打包SpringBoot可执行的jar包

背景&#xff1a;当我们需要坐联调测试的时候&#xff0c;需要对接前端同事&#xff0c;则需要打包成jar包直接运行启动服务 需要将项目中的pom文件增加如下代码配置&#xff1a; <build><plugins><plugin><groupId>org.springframework.boot</gr…...

HarmonyOs开发之——— ArkWeb 实战指南

HarmonyOs开发之——— ArkWeb 实战指南 谢谢关注!! 前言:上一篇文章主要介绍HarmonyOs开发之———合理使用动画与转场:CSDN 博客链接 一、ArkWeb 组件基础与生命周期管理 1.1 Web 组件核心能力概述 ArkWeb 的Web组件支持加载本地或在线网页,提供完整的生命周期回调体…...