MarkupLM:用于视觉丰富文档理解的文本和标记语言预训练
摘要
结合文本、布局和图像的多模态预训练在视觉丰富文档理解(VRDU)领域取得了显著进展,尤其是对于固定布局文档(如扫描文档图像)。然而,仍然有大量的数字文档,其布局信息不是固定的,且需要通过交互和动态渲染来可视化,这使得现有的基于布局的预训练方法难以应用。本文提出了MarkupLM,旨在解决使用标记语言(如HTML/XML)进行文档理解任务的挑战,在该方法中,文本和标记信息共同进行预训练。实验结果表明,预训练的MarkupLM在多个文档理解任务上显著优于现有的强基线模型。预训练的模型和代码将公开发布,网址为:https://aka.ms/markuplm。
1 引言
最近,结合文本、布局和视觉信息的多模态预训练方法已成为视觉丰富文档理解(VRDU)任务中的标准方法(Xu 等,2020, 2021a,b; Pramanik 等,2020; Łukasz Garncarek 等,2021; Hong 等,2021; Powalski 等,2021; Wu 等,2021; Li 等,2021a,b; Appalaraju 等,2021)。这些多模态模型通常使用Transformer架构(Vaswani 等,2017)对大规模未标注的扫描文档图像(Lewis 等,2006)或数字原生PDF文件进行预训练,然后在相对较小的标注训练样本上进行特定任务的微调,从而在各种文档理解任务中达到最先进的性能,包括表单理解(Jaume 等,2019; Xu 等,2021b)、收据理解(Huang 等,2019; Park 等,2019)、复杂文档理解(Gralinski 等,2020)、文档类型分类(Harley 等,2015)和文档视觉问答(Mathew 等,2020)等。无论是在学术研究任务中,还是在金融、保险等多个现实世界的商业应用中,已经取得了显著进展。
视觉丰富文档大致可以分为两类。第一类是固定布局文档,如扫描文档图像和数字原生PDF文件,在这些文档中,布局和样式信息是预渲染的,并且独立于软件、硬件或操作系统。这一特点使得现有的基于布局的预训练方法能够轻松应用于文档理解任务。而第二类是基于标记语言的文档,如HTML/XML,在这些文档中,布局和样式信息需要根据软件、硬件或操作系统的不同,进行交互式和动态的渲染,如图1所示。对于基于标记语言的文档,2D布局信息并不存在显式格式,而通常需要为不同设备(例如手机/平板/桌面)动态渲染,这使得当前的基于布局的预训练模型难以应用。因此,必须将标记结构引入文档级的预训练,以便应用于下游的VRDU任务。
为此,本文提出了MarkupLM,它通过标记语言为骨架,联合预训练文本和标记语言,用于基于标记语言的VRDU任务。与固定布局文档不同,基于标记语言的文档通过标记结构提供了文档表示学习的另一种视角,因为在预训练过程中,不能直接使用2D位置信息和文档图像信息。

相反,MarkupLM利用基于树的标记结构来建模文档中不同单元之间的关系。与其他多模态预训练的基于布局的模型类似,MarkupLM有四个输入嵌入层:(1)文本嵌入层,表示令牌序列信息;(2)XPath嵌入层,表示从根节点到当前节点的标记标签序列信息;(3)1D位置嵌入层,表示序列顺序信息;(4)用于下游任务的段落嵌入层。MarkupLM的整体架构如图2所示。XPath嵌入层可以视为与LayoutLM系列模型(Xu 等,2020,2021a,b)相比,替代了2D位置嵌入。为了有效地预训练MarkupLM,我们使用了三种预训练策略。第一种是掩码标记语言建模(MMLM),用于联合学习文本和标记的上下文信息。第二种是节点关系预测(NRP),其中根据标记树的层次结构定义关系。第三种是标题-页面匹配(TPM),其中“ … ”中的内容会随机替换为另一个页面的标题,以便让模型学习它们是否相关。通过这种方式,MarkupLM可以通过语言和标记层级结构的角度更好地理解上下文信息。我们在Web-based结构化阅读理解(WebSRC)数据集(Chen 等,2021)和结构化Web数据提取(SWDE)数据集(Hao 等,2011)上评估了MarkupLM模型。实验结果表明,预训练的MarkupLM在这些任务上显著优于多个强基线模型。
本文的贡献总结如下:
-
我们提出了MarkupLM,以解决文档表示学习中布局信息不是固定、需要动态渲染的问题。首次在单一框架中对文本和标记信息进行预训练,用于VRDU任务。
-
MarkupLM集成了新的输入嵌入层和预训练策略,已在基于HTML的下游任务中取得了良好的效果。
-
预训练的MarkupLM模型和代码将公开发布,网址为:https://aka.ms/markuplm。
2 MarkupLM
MarkupLM 利用标记语言中的 DOM 树和 XPath 查询语言,获取基于标记语言的文档中的标记流以及自然语言文本(第 2.1 节)。我们提出了一个基于 Transformer 的模型,新增了一个 XPath 嵌入层,用于接收标记序列输入(第 2.2 节),并通过三种不同层次的目标进行预训练,包括掩码标记语言建模(MMLM)、节点关系预测(NRP)和标题-页面匹配(TPM)(第 2.3 节)。

2.1 DOM 树与 XPath
DOM(文档对象模型)树是标记语言文档(如 HTML 或 XML)在 DOM 视图中的树形结构对象,其中每个节点是一个表示文档部分的对象。
XPath(XML 路径语言)是一种查询语言,用于从基于标记语言的文档中选择节点,它基于 DOM 树,可以方便地定位文档中的节点。在典型的 XPath 表达式中,例如 /html/body/div/li[1]/div/span[2],文本表示节点的标签名称,而下标表示当多个节点具有相同标签名称并且属于同一父节点时,该节点的序号。
我们在图 3 中展示了一个 DOM 树和 XPath 示例,并附有相应的源代码,通过它我们可以清晰地识别文档中所有节点的关系,并且可以看到它们的 XPath 表达式。
2.2 模型架构
为了利用现有的预训练模型并适应基于标记语言的任务(如网页任务),我们使用 BERT(Devlin 等,2019)架构作为编码器骨架,并在原始嵌入层中添加了一个新的输入嵌入层,称为 XPath 嵌入层。MarkupLM 的总体结构和新提出的 XPath 嵌入层如图 2 和图 4 所示。
XPath 嵌入层
对于第 i 个输入标记 x i x_i xi,我们获取其对应的 XPath 表达式,并通过 “/” 将其拆分,得到 XPath 各级节点信息的列表:
x p i = [ ( t 0 i , s 0 i ) , ( t 1 i , s 1 i ) , ⋯ , ( t d i , s d i ) ] x p i = [ ( t 0 i , s 0 i ) , ( t 1 i , s 1 i ) , ⋯ , ( t d i , s d i ) ] xpi=[(t0i,s0i),(t1i,s1i),⋯ ,(tdi,sdi)]xp_i = [(t_0^i, s_0^i), (t_1^i, s_1^i), \cdots, (t_d^i, s_d^i)] xpi=[(t0i,s0i),(t1i,s1i),⋯ ,(tdi,sdi)]xpi=[(t0i,s0i),(t1i,s1i),⋯,(tdi,sdi)]
其中 d 是该 XPath 的深度,$(t_j^i, s_j^i) $表示 XPath 单元在第 j 层的标签名称和下标。需要注意的是,对于没有下标的单元,我们将 s j i s_j^i sji 设为 0。为了便于进一步处理,我们对 $xp_i $进行截断和填充,使其统一长度为 L。

将 XPath 表达式转换为 XPath 嵌入的过程如图 4 所示。对于每个$ (t_ji,s_ji)$,我们将其分别输入到第 j 层标签单元嵌入表和第 j 层下标单元嵌入表中,并将两者相加得到第 j 层的单元嵌入 u e j i ue_j^i ueji。我们将这两个嵌入的维度设为 d u d_u du。
u e j i = T a g U n i t E m b j ( t j i ) + S u b s U n i t E m b j ( s j i ) u e j i = TagUnitEmb j ( t j i ) + SubsUnitEmb j ( s j i ) ue_j^i=TagUnitEmb_j(t_j^i)+SubsUnitEmb_j(sji)ue_j^i = \text{TagUnitEmb}_j(t_j^i) + \text{SubsUnitEmb}_j(s_j^i) ueji=TagUnitEmbj(tji)+SubsUnitEmbj(sji)ueji=TagUnitEmbj(tji)+SubsUnitEmbj(sji)
我们将所有单元嵌入连接起来,以获得 $x_i $完整 XPath 的中间表示 r i r_i ri。
r i = [ u e 0 i ; u e 1 i ; ⋯ ; u e L i ] r i = [ u e 0 i ; u e 1 i ; ⋯ ; u e L i ] ri=[ue0i;ue1i;⋯ ;ueLi]r_i = [ue_0^i; ue_1^i; \cdots; ue_L^i] ri=[ue0i;ue1i;⋯ ;ueLi]ri=[ue0i;ue1i;⋯;ueLi]

最后,为了匹配其他嵌入的维度,我们将中间表示 $r_i 输入到一个前馈神经网络( F F N )层,以得到最终的 X P a t h 嵌入 输入到一个前馈神经网络(FFN)层,以得到最终的 XPath 嵌入 输入到一个前馈神经网络(FFN)层,以得到最终的XPath嵌入xe_i$。
x e i = W 2 [ R e L U ( W 1 r i + b 1 ) ] + b 2 , x e i = W 2 [ ReLU ( W 1 r i + b 1 ) ] + b 2 xe_i=W_2[ReLU(W1ri+b1)]+b_2,xe_i = W_2 \left[ \text{ReLU}(W_1ri + b_1) \right] + b_2 xei=W2[ReLU(W1ri+b1)]+b2,xei=W2[ReLU(W1ri+b1)]+b2
其中,
W 1 ∈ R 4 d h × L d u , b 1 ∈ R 4 d h , W_1∈R^{4d_h×Ld_u},b_1∈R^{4d_h}, W1∈R4dh×Ldu,b1∈R4dh,
W 2 ∈ R d h × 4 d h , b 2 ∈ R d h , W_2∈R^{d_h×4d_h},b_2∈R^{d_h}, W2∈Rdh×4dh,b2∈Rdh,
其中 d h d_h dh 是 MarkupLM 的隐藏层大小。为了简化转换过程,我们也尝试用一个线性变换替代 FFN 层。然而,这一微小的修改使得训练过程变得更加不稳定,并稍微影响了性能,因此我们保留了原始设计。
2.3 预训练目标
为了有效捕捉基于标记语言文档的复杂结构,我们提出了三个不同层次的预训练目标,包括标记级别(MMLM)、节点级别(NRP)和页面级别(TPM)。
掩码标记语言建模
受之前工作(Devlin 等,2019;Xu 等,2020,2021a)的启发,我们提出了一种标记级别的预训练目标——掩码标记语言建模(MMLM),旨在通过标记线索增强语言建模能力。基本上,给定文本和标记输入序列,我们随机选择并替换一些标记为 [MASK],该任务要求模型通过所有标记线索恢复被掩盖的标记。
节点关系预测
虽然 MMLM 任务可以帮助模型提升标记语言建模能力,但模型仍然无法理解由 XPath 嵌入提供的 XPath 信息的语义。利用自然结构的 DOM 树,我们提出了一种节点级别的预训练目标——节点关系预测(NRP),以显式建模一对节点之间的关系。我们首先定义了一组有向节点关系 R∈{self,parent,child,sibling,ancestor,descendent,others}R \in {\text{self}, \text{parent}, \text{child}, \text{sibling}, \text{ancestor}, \text{descendent}, \text{others}}。然后,我们结合每个节点,获取节点对。对于每一对节点,根据节点关系集分配相应的标签,模型需要预测分配的关系标签,使用来自每个节点第一个标记的特征。
标题-页面匹配
除了标记提供的细粒度信息外,句子级别或主题级别的信息也可以在基于标记语言的文档中得到利用。对于基于 HTML 的文档,元素 <title> 可以很好地总结 <body>,这为高级语义提供了监督。为了有效利用这些自监督信息,我们提出了页面级别的预训练目标——标题-页面匹配(TPM)。给定一个基于标记语言的文档的 <body> 元素,我们随机替换 <title> 元素中的文本,并要求模型预测该标题是否被替换,使用 [CLS] 标记的表示进行二分类。
2.4 微调
我们遵循常见预训练语言模型(Devlin 等,2019;Liu 等,2019)的方案,并介绍了两个下游任务的微调方法,包括阅读理解和信息抽取。
对于阅读理解任务,我们将其建模为提取式 QA 任务。问题和上下文被连接在一起作为输入序列,当长度超过阈值时需要进行切片。对于问题中的标记,对应的 XPath 嵌入与 [PAD] 标记相同。我们将每个标记的最后隐藏状态输入到一个二分类线性分类层,以获取起始和结束位置的两个分数,并根据这些分数进行跨度预测,遵循 SQuAD(Rajpurkar 等,2016)中的常规做法。
对于信息抽取任务,我们将其建模为标记分类任务。我们将每个标记的最后隐藏状态输入到一个线性分类层,该层具有 n+1n + 1 个类别,其中 nn 是我们需要抽取的属性数量,额外的类别用于标记那些不属于这些属性的标记。
3 实验
在本工作中,我们将 MarkupLM 框架应用于基于 HTML 的网页,这是最常见的标记语言场景之一。我们使用现有的网页数据集 Common Crawl(CC)进行大规模无标注 HTML 数据的预训练,并在基于网页的结构化阅读理解和信息抽取任务上评估预训练模型。
3.1 数据
Common Crawl
Common Crawl(CC)数据集包含以原始网页数据、元数据提取和文本提取形式存储的数PB网页数据。我们选择了其一个快照,并使用 fasttext(Joulin 等,2017)提供的预训练语言检测模型来筛选非英语页面。具体来说,当模型预测为英语且分类器得分大于 0.6 时,我们才保留页面,其他页面则丢弃。此外,我们仅保留可能包含文本的标签(如 <div>、<span>、<li>、<a> 等),删除那些不包含文本的标签(如 <script>、<style> 等)以节省存储空间。经过预处理后,我们从 CC 中提取了 2400 万个英文网页作为 MarkupLM 的预训练数据。
WebSRC
Web-based Structural Reading Comprehension(WebSRC)数据集(Chen 等,2021)包含 44万个问答对,这些问答对来自 6500 个网页及其相应的 HTML 源代码、截图和元数据。WebSRC 中的每个问题都需要对网页进行一定的结构化理解才能回答,答案要么是网页上的文本片段,要么是“是/否”类型的回答。在向文本输入中添加额外的“是/否”标记后,WebSRC 可以建模为典型的提取式阅读理解任务。按照原论文(Chen 等,2021),我们选择该数据集的评估指标为精确匹配(EM)、F1 得分(F1)和路径重叠得分(POS)。我们使用官方拆分获取训练集和开发集。需要注意的是,WebSRC 的作者并未公开他们的测试集,因此我们所有的结果都是从开发集获得的。
SWDE
Structured Web Data Extraction(SWDE)数据集(Hao 等,2011)是一个真实世界的网页集合,用于从网页中自动抽取结构化数据。它涉及 8 个垂直领域,80 个网站(每个垂直领域 10 个网站),共计 124,291 个网页(每个网站 200 - 2000 个网页)。任务是从网页中提取与一组给定属性(取决于网页所属的垂直领域)对应的值,比如在图书页面中提取作者的值。遵循之前的工作(Hao 等,2011;Lin 等,2020;Zhou 等,2021),我们选择页面级别的 F1 得分作为该数据集的评估指标。
由于没有官方的训练-测试拆分,我们遵循之前的工作(Hao 等,2011;Lin 等,2020;Zhou 等,2021)对每个垂直领域独立进行训练和评估。在每个垂直领域,我们选择 kk 个连续的种子网站作为训练数据,剩余的 10 - k 个网站作为测试集。需要注意的是,在这个少样本抽取任务中,测试阶段的 10 - k 个网站的页面在训练阶段没有被访问过。这个设置抽象了真实应用场景,其中仅为特定网站提供少量标注数据,我们的目标是在更大规模的未见网站集上推断出属性。最终结果是通过对每个垂直领域的 8 个垂直领域和每个垂直领域的 10 个种子网站排列进行平均得到的,共进行 80 次实验。对于数据的预处理和后处理,我们遵循 Zhou 等(2021)的方法以进行公平比较。


3.2 设置
预训练 XPath 嵌入中选择的标签和下标的大小分别为 216 和 1,001,XPath 表达式的最大深度( L L L)为 50,标签单元和下标单元嵌入的维度( d u d_u du)为 32。MMLM 中的标记掩蔽概率和 TPM 中的标题替换概率均为 15%,并且我们不会掩蔽输入序列中与网页标题对应的标记。在 NRP 中,每个样本选择的最大节点对数为 1,000,并且我们将带有非“其他”(例如:self, parent 等)标签的节点对比例限制为 80%,以保持平衡。我们从 RoBERTa 初始化 MarkupLM,并在 8 个 NVIDIA A100 GPU 上训练 30 万步。我们将总批次大小设置为 256,学习率为 5e-5,预热比例为 0.06。选择的优化器是 AdamW(Loshchilov 和 Hutter,2019),其中 ϵ \epsilon ϵ= 1 e − 6 , β 1 = 0.9 , β 2 = 0.98 1e-6,\beta_1=0.9,\beta_2=0.98 1e−6,β1=0.9,β2=0.98,权重衰减为 0.01,使用 6% 预热步骤的线性衰减学习率调度器。我们还应用了 FP16、梯度检查点(Chen 等,2016)和 deepspeed(Rasley 等,2020)来减少 GPU 内存消耗并加速训练。

微调
对于 WebSRC,我们对 MarkupLM 进行了 5 轮微调,批次大小为 64,学习率为 1e-5,预热比例为 0.1。对于 SWDE,我们对 MarkupLM 进行了 10 轮微调,批次大小为 64,学习率为 2e-5,预热比例为 0.1。两项任务中的最大序列长度均设置为 384,其他超参数保持默认。
3.3 结果
WebSRC 的结果如表 1 所示。选择的基线模型包括 Chen 等人(2021)中的 T-PLM、H-PLM 和 V-PLM,具体细节请参考该论文。为了公平比较,我们使用 RoBERTa 重新运行了发布的基线实验。我们观察到,MarkupLM 显著超越了使用相同信息模态的 H-PLM。这强烈表明,与仅仅将更多标签标记添加到输入序列中的 H-PLM 相比,MarkupLM 更好地利用了 XPath 特征,得益于特别设计的嵌入层和预训练目标。此外,MarkupLM 还超过了之前的最先进的 V-PLM 模型,后者需要大量外部资源来渲染 HTML 源代码,并使用来自 Faster R-CNN(Ren 等,2015)的附加视觉特征,表明我们不依赖渲染的 MarkupLM 更加轻量,并且即使没有任何视觉信息,也能更好地学习结构信息。值得注意的是,向 H-PLM 和 V-PLM 中添加 HTML 标签作为输入标记会大大增加输入字符串的长度,因此需要更多的切片操作来满足语言模型的长度限制,这导致了更多的训练样本(约 860k)和更长的训练时间,而 MarkupLM 不会遇到这个问题(只有约 470k 训练样本),因此可以大大减少训练时间。
SWDE 的结果见表 2 和表 3。可以观察到,我们的 MarkupLM 也大幅超越了强基线。与之前的最先进模型 SimpDOM 不同,SimpDOM 明确地将 DOM 树节点之间的关系传入其模型,并添加了大量额外的离散特征(例如,节点是否包含数字或日期),而 MarkupLM 更加简洁,无需耗时的额外网页注释。我们还在表 3 中报告了不同垂直领域的详细统计数据。随着 k 的增长,MarkupLM 获得更多网页作为训练集,因此在得分上有明显的上升趋势。我们还可以看到不同垂直领域之间的方差,因为每个垂直领域的网页数量和类型不同。
3.4 消融研究
为了研究每个预训练目标如何影响 MarkupLM,我们在 WebSRC 上进行了一个消融研究,使用包含 100 万网页的小型训练集。在这个子实验中,我们从 BERT-base-uncased 初始化模型,其他设置保持不变。结果如表 4 所示。根据 #1 中的四个结果,我们看到新提出的训练目标都显著提升了模型的性能,其中提出的 TPM(+4.6% EM)对模型的益处大于 NRP(+2.4% EM)。同时使用这两个目标比单独使用其中任何一个都更有效,EM 提升了 5.3%。我们还可以看到,在将 BERT 替换为更强大的初始模型 RoBERTa 时,性能有所提升(+1.9% EM),从 #1d 到 #2a。最终,我们通过结合所有三个目标并在更大的数据集上进行更好的初始化,得到了最佳模型,如 #2a 和 #2b 之间的对比所示。

4 相关工作
结合文本、布局和图像信息的多模态预训练在文档AI研究中取得了显著进展,并且已经成为多种VRDU任务中的事实标准方法。尽管在固定布局文档理解任务中取得了巨大进展,但现有的多模态预训练方法无法直接应用于基于标记语言的文档理解,因为基于标记语言的文档的布局信息需要动态渲染,并且可能因软件和硬件的不同而有所不同。因此,标记信息对文档理解至关重要。Ashby 和 Weir(2020)比较了 Text+Tags 方法与其 Text-Only 等效方法在五个基于网页的命名实体识别(NER)数据集上的表现,结果表明深度语言模型的标记增强是必要的。Lin 等人(2020)提出了一种新的两阶段神经方法,称为 FreeDOM。第一阶段通过结合文本和标记信息,为页面中的每个 DOM 节点学习表示。第二阶段使用关系神经网络捕捉较长距离的语义相关性。实验表明,FreeDOM 在不需要通过渲染页面或昂贵的手工特征的情况下,超越了之前的最先进的结果。Zhou 等人(2021)提出了一种新颖的可转移方法 SimpDOM,利用树结构高效地检索每个节点的有用上下文,以解决这一问题。Xie 等人(2021)介绍了一个名为 WebKE 的框架,通过扩展预训练语言模型到标记语言并编码布局语义,从半结构化网页中提取知识三元组。
然而,这些方法并没有充分利用大规模无标签数据和自监督预训练技术来丰富文档表示学习。尽我们所知,MarkupLM 是第一个在一个框架中联合学习文本和标记语言的超大规模预训练模型,用于 VRDU 任务。
5 结论与未来工作
本文提出了 MarkupLM,一种简单而有效的文本和标记语言预训练方法。通过 Transformer 架构,MarkupLM 集成了包括文本嵌入、位置嵌入和 XPath 嵌入在内的不同输入嵌入。此外,我们还提出了专门为理解标记语言设计的新预训练目标。我们在 WebSRC 和 SWDE 数据集上评估了预训练的 MarkupLM 模型。实验结果表明,MarkupLM 在这些任务中显著超越了几个最先进的基线模型。
对于未来的研究,我们将探索在更多数据和计算资源下进行 MarkupLM 的预训练,并扩展其语言能力。此外,我们还将对 MarkupLM 模型进行预训练,针对使用 XML DOM 作为骨架的数字原生 PDF 和 Office 文档进行研究。我们还将探讨 MarkupLM 与基于布局的模型(如 LayoutLM)之间的关系,以深入理解这两种模型是否可以在统一的多视图和多任务设置下进行预训练,并且这些模型之间的知识是否可以相互迁移,从而更好地理解结构信息。
相关文章:
MarkupLM:用于视觉丰富文档理解的文本和标记语言预训练
摘要 结合文本、布局和图像的多模态预训练在视觉丰富文档理解(VRDU)领域取得了显著进展,尤其是对于固定布局文档(如扫描文档图像)。然而,仍然有大量的数字文档,其布局信息不是固定的࿰…...
讯飞智作 AI 配音技术浅析(三):自然语言处理
自然语言处理(NLP)是讯飞智作 AI 配音技术的重要组成部分,负责将输入的文本转换为机器可理解的格式,并提取出文本的语义和情感信息,以便生成自然、富有表现力的语音。 一、基本原理 讯飞智作 AI 配音的 NLP 技术主要包…...
kafka服务端之日志存储
文章目录 日志布局日志索引日志清理日志删除基于时间基千日志大小基于日志起始偏移量 日志压缩总结 日志布局 Ka饮a 中的消息是以主题为基本单位进行归类的, 各个主题在逻辑 上相互独立。 每个主题又可以分为一个或多个分区, 分区的数量可以在主题创建的…...
软件工程的熵减:AI如何降低系统复杂度
软件开发的世界,如同一个不断膨胀的宇宙。随着功能的增加和时间的推移,代码库越来越庞大,系统复杂度也随之水涨船高。代码膨胀、维护困难、开发效率低下等问题困扰着无数开发者。这不禁让人联想到物理学中的“熵增”原理——一个孤立系统的熵…...
模拟开发小鹅通首页网站练习
HTML代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>小鹅通-首页</title><!-- 引入页…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_strerror 函数
声明 ngx_strerror 函数声明在 ngx_errno.h 中: u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size); 实现 在 ngx_errno.c 中: u_char * ngx_strerror(ngx_err_t err, u_char *errstr, size_t size) {size_t len;const char *ms…...
第26场蓝桥入门赛
5.扑克较量【算法赛】 - 蓝桥云课 C: #include <iostream> #include <algorithm> using namespace std;int a[100005];int main() {int n,k;cin>>n>>k;for (int i1; i<n; i)cin>>a[i], a[i] % k;sort(a1, a1n);int mx a[1]k-a…...
【CAPL实战】实现弹窗提示及操作
文章目录 前言1、TestWaitForTesterConfirmation函数2、测试举例 前言 在使用CANoe进行车载通信测试的过程中,可能因为一些条件限制,我们需要在测试执行的过程中去观察一些硬件显示或者调整相关硬件状态。比如测试过程中,需要手动去调整小电…...
基于ESP32的远程开关灯控制(ESP32+舵机+Android+物联网云平台)
目录 材料环境准备物理材料软件环境 物联网平台配置(MQTT)MQTT阿里云平台配置创建产品添加设备自定义topic esp32配置接线代码 Android部分和云平台数据流转 前言:出租屋、宿舍网上关灯问题,计划弄一个智能开关以及带一点安防能力…...
协议-ACLLite-ffmpeg
是什么? FFmpeg是一个开源的多媒体处理工具包,它集成了多种功能,包括音视频的录制、转换和流式传输处理。FFmpeg由一系列的库和工具组成,其中最核心的是libavcodec和libavformat库。 libavcodec是一个领先的音频/视频编解码器库&…...
ARM嵌入式学习--第十四天(SPI)
SPI -介绍 SPI(Serial Peripheral Interface)串行外围设备接口。是由Motorola公司开发,用来在微控制器和外围设备芯片之间提供一个低成本,易使用的接口。这样接口可以用来连接存储器、AD转换器、DA转换器、实时时钟、LCD驱动器、…...
DeepSeek-V2 论文解读:混合专家架构的新突破
论文链接:DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model 目录 一、引言二、模型架构(一)多头部潜在注意力(MLA):重塑推理效率(二)DeepSeekM…...
5分钟了解回归测试
1. 什么是回归测试(Regression Testing) 回归测试是一个系统的质量控制过程,用于验证最近对软件的更改或更新是否无意中引入了新错误或对以前的功能方面产生了负面影响(比如你在家中安装了新的空调系统,发现虽然新的空…...
路由器如何进行数据包转发?
路由器进行数据包转发的过程是网络通信的核心之一,主要涉及以下几个步骤: 接收数据包:当一个数据包到达路由器的一个接口时,它首先被暂时存储在该接口的缓冲区中。 解析目标地址:路由器会检查数据包中的目标IP地址。…...
【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(四) -> 常见组件(一)
目录 1 -> List 1.1 -> 创建List组件 1.2 -> 添加滚动条 1.3 -> 添加侧边索引栏 1.4 -> 实现列表折叠和展开 1.5 -> 场景示例 2 -> dialog 2.1 -> 创建Dialog组件 2.2 -> 设置弹窗响应 2.3 -> 场景示例 3 -> form 3.1 -> 创建…...
iOS 自动翻滚广告条(榜单条)实现方案
引言 在直播场景中,榜单信息、活动公告或者广告推广通常需要以醒目的方式展示,但由于屏幕空间有限,一次只能显示一条内容。为了让用户能够持续关注这些信息,我们可以实现一个自动翻滚的广告条(或榜单条)&a…...
TensorFlow深度学习实战(7)——分类任务详解
TensorFlow深度学习实战(7)——分类任务详解 0. 前言1. 分类任务1.1 分类任务简介1.2 分类与回归的区别 2. 逻辑回归3. 使用 TensorFlow 实现逻辑回归小结系列链接 0. 前言 分类任务 (Classification Task) 是机器学习中的一种监督学习问题,…...
动态规划问题——青蛙跳台阶案例分析
问题描述: 一只青蛙要跳上n级台阶,它每次可以跳 1级或者2级。问:青蛙有多少种不同的跳法可以跳完这些台阶? 举个例子: 假设台阶数 n 3 ,我们来看看青蛙有多少种跳法。 可能的跳法: 1. 跳1级…...
element-ui使用el-table,保留字段前的空白
项目名称项目编号1、XXXXX1111111111111111111 1.1 XXXXX11111111111111222222222 如上表格中,实现项目名称字段1.1前空白的效果。 从JAVA返回的数据带有空白,即数据库中插入的数据带有空白。 原先写法: <el-table><el-tabl…...
kamailio中路由模块汇总
功能模块描述请求路由 (request_route)主要处理进入的SIP请求,包含初步检查、NAT检测、CANCEL请求处理、重传处理等。处理通过REQINIT、NATDETECT、RELAY等子模块的调用。CANCEL处理对CANCEL请求进行处理,包括更新对话状态并检查事务。如果事务检查通过&…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
倒装芯片凸点成型工艺
UBM(Under Bump Metallization)与Bump(焊球)形成工艺流程。我们可以将整张流程图分为三大阶段来理解: 🔧 一、UBM(Under Bump Metallization)工艺流程(黄色区域ÿ…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
uniapp获取当前位置和经纬度信息
1.1. 获取当前位置和经纬度信息(需要配置高的SDK) 调用uni-app官方API中的uni.chooseLocation(),即打开地图选择位置。 <button click"getAddress">获取定位</button> const getAddress () > {uni.chooseLocatio…...
