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

Nougat 深度剖析

Nougat 深度剖析

项目地址:https://github.com/facebookresearch/nougat

论文地址:Nougat: Neural Optical Understanding for Academic Documents

0 背景

近日,MetaAI又放了大招,他们提出了一种全新的端到端的OCR模型,该模型基于自回归的方法,旨在实现给定图片后输出对应的Markdown标记。一个模型实现版面分析、文本检测、文本识别、公式识别等功能。笔者从论文、源码、测试对Nougat进行深度学习与理解。下面一起来看Nougat是如何做的吧!

在这里插入图片描述

1 方法大意

1.1 模型架构

该模型采用了常规的“编码器-解码器”(encoder-decoder)架构,下面对其进行详细说明:

编码器(Encoder)

  • 模型:使用了 SwinTransformer 模型1 作为编码器。
  • 输入:接收来自PDF图像的输入,其分辨率为DPI96,并去除白边,然后将图像padding到指定的尺寸 ( H , W ) = ( 896 , 672 ) (H, W)=(896, 672) (H,W)=(896,672)
  • 输出:编码器的输出是图像patch的embedding序列。

解码器(Decoder)

  • 模型:采用了 mBART 模型的解码器部分2 作为解码器。
  • 输入:图片patch的embedding序列
  • 输出:token概率向量。(最长自回归解码长度为4096)

以上可见Nougat的encoder与decoder都用了较大transformer架构,整体pipeline得参数量达 350 M 350M 350M
在这里插入图片描述

1.2 数据工程

Nougat将OCR的问题定义为: 图片 ⟶ m a r k d o w n \text{图片} \longrightarrow \mathrm{markdown} 图片markdown

核心关键是:如何用一种cheap的方法构造(图片,对应的markdown)pair。于我而言,这是这篇文章最有价值、最值得借鉴学习的地方。

1.2.1 数据源

目前并无大规模的pdf图片与对应markdown标记pair的数据集。Nougat从arXiv、PMC (PubMed Central), IDL(Industry Documents Library)三个来源构建数据集。其中PMC与IDL的数据由于语义信息不充足仅用于预训练阶段,来使模型具备基础的ocr能力。arXiv数据有tex源码,能拿到所有需要的语义信息,用于预训练和微调阶段。

数据源Pages简介使用阶段
arXiv750w有tex源码,信息最充足预训练+微调
PMC (PubMed Central)53.6w有xml源码。但xml文件经常将公式、表格存为图片,导致语义信息不足。预训练
IDL3 (Industry Documents Library)44.6W仅有text信息,缺失format信息,语义信息不充足。预训练

1.2.2 图文对构建pipeline

1.2.2.1 思路介绍

图文对构造的整体pipeline由下图所示。从arXiv拿到的Tex源码出发拿到全篇文章的markdown标记,与pdf每页的图片与文本

  • Branch1: T E X ⟶ L a T e X M L H T M L ⟶ P a r s e r m a r k d o w n \mathrm{TEX} \stackrel{\mathtt{LaTeXML}} \longrightarrow \mathrm{HTML} \stackrel{\mathtt{Parser}} \longrightarrow \mathrm{markdown} TEXLaTeXMLHTMLParsermarkdown
  • Branch2: T E X ⟶ P D F L a t e x P D F ⟶ M u P D F { [ p a g e 1 t e x t , p a g e 2 t e x t , ⋯ ] [ p a g e 1 i m a g e , p a g e 2 i m a g e , ⋯ ] \mathrm{TEX} \stackrel{\mathtt{PDFLatex}} \longrightarrow \mathrm{PDF} \stackrel{\mathtt{MuPDF}} \longrightarrow \begin{cases} \mathrm{[page_1 \, text, page_2 \, text, \cdots]} \\ \mathrm{[page_1 \, image, page_2 \, image, \cdots]} \end{cases} TEXPDFLatexPDFMuPDF{[page1text,page2text,][page1image,page2image,]

TEX2HTML转化工具为 LaTeXML http://dlmf.nist.gov/LaTeXML/。(tex源码自定义性过强,转为HTML主要为了消歧)

HTML2markdown 转为代码见源码位置:nougat/dataset/parser/html2md.py

目前我们只能得到全文的markdown标记与pdf图片文本对。剩下需要做的就是根据pdf的page text信息将markdown进行划分得到 p a g e m a r k d o w n \mathrm{page \, markdown} pagemarkdown

在这里插入图片描述

1.2.2.2 markdown 划分

代码位置:nougat/nougat/dataset/split_md_to_pages/split_markdown

1.2.2.2.1 预处理

预处理1 去除PDF中的图片表格:

由于图片表格在PDF的位置和tex源码的位置可能有所差异,因此作者采取的办法是先用pdffigures2工具将PDF的图片和表格移除。当划分完markdown后再在markdown的末尾加入移除的信息。

pdffigures2提取的信息如

{"figures": [{"name": "1","page": 5,"figType": "Table","regionBoundary": {"x1": 74.0,"y1": 72.0,"x2": 517.0,"y2": 507.0},"caption": "Table 1. Result comparison with representative vision-language pre-training models. † denotes using additional text premise as input.","imageText": ["BEIT-3", "[?]", "28M", "MOME", "Transformer", "84.19", "84.03", "91.51", "92.58", "-", "-", "PaLI", "[?]", "1.6B", "VIT-E-224", "84.30", "84.34", "-", "-", "-", "-", "ViLTALARGE", "4M", ...],"captionBoundary": {"x1": 50.11199951171875,"y1": 515.78271484375,"x2": 527.7859497070312,"y2": 521.1849975585938}}, {"name": "5","page": 14,"figType": "Figure","regionBoundary": {"x1": 57.0,"y1": 148.0,"x2": 538.0,"y2": 605.803955078125},"caption": "Figure 5. Case study of ViLTA on image captioning task.","imageText": ["Three", "giraffes", "are", "standing", "in", "a", "grassy", "field.", "A", "street", "game", "controller."],"captionBoundary": {"x1": 195.4810028076172,"y1": 627.4857177734375,"x2": 399.7445983886719,"y2": 632.8880004882812}},],"regionless-captions": []
}

预处理2 将pdf的text格式转化:

去除PDF text中的尾注、页码等。

预处理3 将pdf的text格式转化为latex编码:

后续的markdown划分中会依据markdown的序列与pdf text的匹配度,为了更好的匹配,最好将pdf的text用pylatexenc工具转为为latex编码。

1.2.2.2.2 markdown page 划分

叙述核心逻辑,详细细节见源码

STEP1: HTML解析的全文markdown按段落划分, 得到doc_paragraphs_full, 数据结构: List[str], 每一个元素是段落

doc_paragraphs_full: List[str] = doc.split("\n")  # 先按换行符切分,doc为markdown全文
doc_paragraph_lengths = [len(p) for p in doc_paragraphs_full if len(p) > 1]
# doc_paragraph_chars为预设的段落字符数, num_lines为段落所占的行数
num_lines = 1 + int(doc_paragraph_chars / np.mean(doc_paragraph_lengths)) 
doc_paragraphs_full = [unidecode("\n".join(doc_paragraphs_full[i : i + num_lines]))for i in range(0, len(doc_paragraphs_full), num_lines)
]  # 划分段落

STEP2: 用fitzblock拿到每页的text, 得到pdf_content, 数据结构: List[List[str]],例:pdf_content[0][0]为第一页的第一个block的文本信息。

blocks = page.get_text("blocks", flags=fitz.TEXT_DEHYPHENATE | fitz.TEXT_PRESERVE_IMAGES)

STEP3: 基于pdf_content训练page分类器

  • 分类器的数据: { pdf_content [ i ] [ j ] ∣ i ∈ { 0 , 1 , . . . , N } , j ∈ { 0 , 1 , . . . , M i } } \{\text{pdf\_content}[i][j] |i \in \{0, 1, ..., N\}, j \in \{0, 1, ..., M_i \}\} {pdf_content[i][j]i{0,1,...,N},j{0,1,...,Mi}}, N N N为页面数量, M i M_i Mi为页面 i i i中的文本block数量。随后将 pdf_content [ i ] [ j ] \text{pdf\_content}[i][j] pdf_content[i][j]用结合了TF-IDF的Bag of Word (BoW)进行向量化。
  • 分类器的标签:BoW向量对应的页面标签。
  • 分类器的模型:SVM。

STEP4: 预测markdown的所有段落文本doc_paragraphs_full所属的页面标签。

STEP5: 根据Gini impurity来refine预测的doc_paragraphs_full页面标签,使其满足阶梯状分布。
G [ a , b ] ( i ) = ( b − a ) ⋅ ( 1 − p [ a , b ] 2 ( i ) − p [ a , b ] 2 ( i + 1 ) ) , (1) G _ { [ a , b ] } ( i ) = ( b - a ) \cdot ( 1 - p _ { [ a , b ] } ^ { 2 } ( i ) - p _ { [ a , b ] } ^ { 2 } ( i + 1 ) ) , \tag{1} G[a,b](i)=(ba)(1p[a,b]2(i)p[a,b]2(i+1)),(1)

t ^ i = arg ⁡ min ⁡ t ( G [ a , t ] ( i ) + G [ t , b ] ( i ) ) (2) \hat { t } _ { i } = \mathop{\arg \min} _ { t } ( G _ { [ a , t ] } ( i ) + G _ { [ t , b ] } ( i ) ) \ \tag{2} t^i=argmint(G[a,t](i)+G[t,b](i)) (2)

p [ a , b ] ( i ) p _ { [ a , b ] } ( i ) p[a,b](i)为在 a , b a, b a,b间预测为页面 i i i的概率。 t t t为最好的分割位置。

在这里插入图片描述

STEP6: 通过STEP5得到将markdown的段落以页划分。但这是段落级别的划分,字符始末位置与PDF任有差异,需要进一步修正。核心思想为(详细实现参考代码,此处省略了很多细节,仅用于理解):

  • 从PDF text中找到当前页的初始几个单词和末尾几个单词。
  • 拿到当前页markdown的第一段,使用以编辑距离为指标的模糊匹配(库fuzzysearch)找到初始几个单词的位置,对其进行截断。
  • 拿到当前页markdown的最后一段,找到末尾几个单词的位置,进行截断。

STEP7: 在每页markdown末尾添加预处理产出的表格、图片信息。

1.2.3 训练中数据增强

训练中的数据增强没太多可以介绍的,就是一些常规的方式。

在这里插入图片描述

2 小结

Nougat描绘了这么一个愿景,用一个端到端的方式来实现过去繁琐的数据加工pipeline。但目前尝试来看,并不适用实际场景,主要有以下几点缺陷

  • 推理速度慢。虽然过去的pipeline设计多个模型,但每个模型都非常轻量化,组合起来的参数量甚至不到Nougat的1/10。
  • 定制化难。
    • 数据集构建成本高。Nougat需要构建带结构化信息的图文对,当构建完毕生产数据domain足够的图文对时,用过去的方法早已完成项目。
    • 训练成本高。主要体现在机器成本,需要更多的GPU,更长的训练时间。
    • 优化成本高。Nougat作为一种端到端的解决方法无法针对特定的badcase进行优化。比如在传统方案中,如果表格OCR这个模块效果较差单独优化即可,不会影响到其它模块。但用端到端的方案,当构建倾向表格的数据时,可能会导致其它场景出现新的badcase。

Reference


  1. Liu, Ze, et al. “Swin transformer: Hierarchical vision transformer using shifted windows.” Proceedings of the IEEE/CVF international conference on computer vision. 2021. ↩︎

  2. Liu, Yinhan, et al. “Multilingual denoising pre-training for neural machine translation.” Transactions of the Association for Computational Linguistics 8 (2020): 726-742. ↩︎

  3. Ali Furkan Biten, Rub` en Tito, Lluis Gomez, Ernest Valveny, and Dimosthenis Karatzas. OCR-IDL: OCR Annotations for Industry Document Library Dataset, February 2022. ↩︎

相关文章:

Nougat 深度剖析

Nougat 深度剖析 项目地址:https://github.com/facebookresearch/nougat 论文地址:Nougat: Neural Optical Understanding for Academic Documents 0 背景 近日,MetaAI又放了大招,他们提出了一种全新的端到端的OCR模型&#x…...

ffmpeg的使用

本文章记录ffmpeg 源码下载,编译,及使用。 一、FFMPEG 源码下载解压 源码官网地址:http://ffmpeg.org/download.html#releases 下载最新版本ffmpeg6.0。 使用命令tar xvJf ffmpeg-6.0.tar.xz 解压。 二、了解FFMPEG源码 (一&am…...

深度强化学习算法的参数更新时机

深度强化学习算法的参数更新时机 深度强化学习中往往涉及到多个神经网络来拟合策略函数、值函数等,什么时候更新参数因算法而异,与具体算法架构/算法思想紧密相关。 算法参数更新时机架构DQN先收集一定经验,然后每步更新Off Policy Value-B…...

【进阶篇】MySQL的MVCC实现机制详解

文章目录 0.前言1.基础介绍1.1. 什么是MVCC?1.1. 什么是当前读和快照读?1.1. 当前读,快照读和MVCC的关系1.1. MVCC能解决什么问题,好处是?1.1.1. 提高并发性能1.1.2. 避免死锁1.1.3. 解决脏读、不可重复读和幻读等问题1.1.4. 实现…...

Git 命令行查看仓库信息

目录 查看系统config ​编辑查看当前用户(global)配置 查看当前仓库配置信息 查看系统config git config --system --list 1 查看当前用户(global)配置 git config --global --list 1 查到的是email , name 等ssl签名信息&a…...

【爬虫】8.1. 深度使用tesseract-OCR技术识别图形验证码

深度使用tesseract-OCR技术识别图形验证码 文章目录 深度使用tesseract-OCR技术识别图形验证码1. OCR技术2. 准备工作3. 简单作用了解3.1. 验证码图片爬取-screenshot_as_png3.2. 识别测试-image_to_string3.2.1. 正确识别3.2.2. 错误识别3.2.3. 灰度调节 3.3. 识别实战-使用im…...

【PythonRS】基于GDAL修改栅格数据的DN值

遥感工作者离不开栅格数据,有时候我们可能需要修改栅格数据的值,但ENVI和ArcGIS中并没有直接修改DN值的工具,只有栅格计算器、Band math这些工具去计算整个波段的值,或者Edit Classification Image工具可以修改ENVI分类后的像元值…...

mysql课堂笔记 mac

目录 启动mac上的mysql 进入mysql mac windows 创建数据库 创建表 修改字段数据类型 修改字段名 增加字段 删除字段 启动mac上的mysql sudo /usr/local/mysql/support-files/mysql.server start 直接输入你的开机密码即可。 编辑 进入mysql mac sudo /usr/local…...

2023年数学建模国赛A 定日镜场的优化设计思路分析

构建以新能源为主体的新型电力系统,是我国实现“碳达峰”“碳中和”目标的一项重要措施。塔式太阳能光热发电是一种低碳环保的新型清洁能源技术[1]。定日镜是塔式太阳能光热发电站(以下简称塔式电站)收集太阳能的基本组件,其底座由…...

【QT】QMessageBox消息框的使用(16)

在实际项目中,弹出消息框是一个很常见的操作,包含错误信息提示、警告信息提示、关于信息提示、还包括判断信息选择等操作,那么今天通过这一节来好好了解下消息框的使用方法。 一.环境配置 1.python 3.7.8 可直接进入官网下载安装&#xf…...

XL-LightHouse 与 Flink 和 ClickHouse 流式大数据统计系统

一个Flink任务只能并行处理一个或少数几个数据流,而XL-LightHouse一个任务可以并行处理数万个、几十万个数据流; 一个Flink任务只能实现一个或少数几个数据指标,而XL-LightHouse单个任务就能支撑大批量、数以万计的数据指标。 1、XL-LightHo…...

【postgresql 基础入门】创建数据库的方法,存储位置,决定自己的数据的访问用户和范围

创建数据库 ​专栏内容: postgresql内核源码分析手写数据库toadb并发编程 ​开源贡献: toadb开源库 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君…...

科技云报道:AI时代,对构建云安全提出了哪些新要求?

科技云报道原创。 随着企业上云的提速,一系列云安全问题也逐渐暴露出来,云安全问题得到重视,市场不断扩大。 Gartner 发布“2022 年中国 ICT 技术成熟度曲线”显示,云安全已处于技术萌芽期高点,预期在2-5年内有望达到…...

如何让 Llama2、通义千问开源大语言模型快速跑在函数计算上?

:::info 本文是“在Serverless平台上构建AIGC应用”系列文章的第一篇文章。 ::: 前言 随着ChatGPT 以及 Stable Diffusion,Midjourney 这些新生代 AIGC 应用的兴起,围绕AIGC应用的相关开发变得越来越广泛,有呈井喷之势,从长远看这波应用的爆…...

Linux内核源码分析 (B.2)虚拟地址空间布局架构

Linux内核源码分析 (B.2)虚拟地址空间布局架构 文章目录 Linux内核源码分析 (B.2)虚拟地址空间布局架构一、Linux内核整体架构及子系统二、Linux内核内存管理架构 一、Linux内核整体架构及子系统 Linux内核只是操作系统当中的一部分,对下管理系统所有硬件设备&…...

Spring系列文章:Spring使用JdbcTemplate

一、简介 JdbcTemplate是Spring提供的⼀个JDBC模板类&#xff0c;是对JDBC的封装&#xff0c;简化JDBC代码。 当然&#xff0c;你也可以不⽤&#xff0c;可以让Spring集成其它的ORM框架&#xff0c;例如&#xff1a;MyBatis、Hibernate等。 第一步&#xff1a;引入依赖 <d…...

[matlab]cvx安装后测试代码

测试环境&#xff1a; windows10 x64 matlab2023a 代码来自官方网站&#xff1a;CVX: Matlab Software for Disciplined Convex Programming | CVX Research, Inc. m 20; n 10; p 4; A randn(m,n); b randn(m,1); C randn(p,n); d randn(p,1); e rand; cvx_beginva…...

【css】margin:auot什么情况下失效

margin&#xff1a;auto只对块级元素有效果&#xff0c;并且在正常文档流margin&#xff1a;automargin&#xff1a;0 auto&#xff0c;css默认在正常文档流里面margin-top和margin-bottom是0 为什么margin: auto能实现水平居中&#xff0c;而垂直居中不行&#xff1f; 一般子…...

linux的dirty page回写磁盘过程中是否允许并发写入更新page?

概述 众所周知Linux内核write系统调用采用pagecache机制加速写入过程,避免write系统调用长时间block应用进程,用户态进程执行write调用的时候,内核只是将用户态buffer copy到内核的pagecache当中,write系统调用就返回了,完全不需要等待数据完全写入存储设备,因为存储设备…...

Docker-基础命令使用

文章目录 前言命令帮助命令执行示意图docker rundocker psdocker inspectdocker execdocker attachdocker stopdocker startdocker topdocker rmdocker prune参考说明 前言 本文主要介绍Docker基础命令的使用方法。 命令帮助 Docker命令获取帮助方法 # docker -h Flag shor…...

【Python 程序设计】Python 中的类型提示【06/8】

目录 一、说明 二、什么是动态类型&#xff1f; 2.1 为什么要使用类型提示&#xff1f; 2.2 局限性 三、基本类型提示 3.1 声明变量的类型 3.2 函数注释 四、Python 中的内置类型 4.1 原子类型与复合类型 五、函数注释 5.1 如何指定函数的参数类型和返回类型 5.2 在函数签名中…...

78 # koa 中间件的实现

上上节实现了上下文的&#xff0c;上一节使用了一下中间件&#xff0c;这一节来实现 koa 的中间件这个洋葱模型。 思路&#xff1a; 储存用户所有的 callback将用户传递的 callback 全部组合起来&#xff08;redux 里的 compose&#xff09;组合成一个线性结构依次执行&#…...

国产操作系统麒麟v10中遇到的一些问题

下载pycharm&#xff1a;直接在应用商店 目标&#xff1a;主机1安装了虚拟机&#xff0c;主机2要ping通主机1安装的虚拟机。 前提&#xff1a;主机1&#xff0c;主机2在同一局域网下&#xff0c;同一网段。 网络配置 因为虚拟机的网段不在局域网网段内&#xff0c;局域网下…...

Gridea+GitPage+Gittalk 搭建个人博客

&#x1f44b;通过GrideaGitPage 搭建属于自己的博客&#xff01; &#x1f47b;GitPage 负责提供 Web 功能&#xff01; &#x1f63d;Gridea 作为本地编辑器&#xff0c;方便 push 文章&#xff01; &#x1f3f7;本文讲解如何使用 GrideaGitPage 服务域名&#xff08;可选&a…...

代码质量保障第2讲:单元测试 - 浅谈单元测试

代码质量保障第2讲&#xff1a;单元测试 - 浅谈单元测试 本文是代码质量保障第2讲&#xff0c;浅谈单元测试。单元测试&#xff08;unit testing&#xff09;&#xff0c;是指对软件中的最小可测试单元进行检查和验证。这是基础&#xff0c;所以围绕着单元测试&#xff0c;我从…...

“五度晟企通”企业发展服务平台正式发布,帮扶企业行稳致远!

在数字中国建设的大背景下&#xff0c;“五度易链”以企业实际发展需求为牵引&#xff0c;以帮扶企业行稳致远为目标&#xff0c;基于全体量产业大数据&#xff0c;运用NLP、AI等新一代信息技术&#xff0c;打造了数字化ToB企业发展服务平台“五度晟企通”&#xff0c;旨在以数…...

Java类和对象(七千字详解!!!带你彻底理解类和对象)

目录 一、面向对象的初步认知 1、什么是面向对象 2、面向对象和面向过程 &#xff08;1&#xff09;传统洗衣服的过程 &#xff08;2&#xff09;现代洗衣服过程 ​编辑 二、类的定义和使用 1、类的定义格式 三、类的实例化 1、什么是实例化 2、类和对象说明 四、t…...

机器学习笔记:node2vec(论文笔记:node2vec: Scalable Feature Learning for Networks)

2016 KDD 1 intro 利用graph上的节点相似性&#xff0c;对这些节点进行embedding 同质性&#xff1a;节点和其周围节点的embedding比较相似 蓝色节点和其周围的节点结构等价性 结构相近的点embedding相近 比如蓝色节点&#xff0c;都处于多个簇的连接处 2 随机游走 2.1 介绍…...

go基础10 -字符串的高效构造与转换

前面提到过&#xff0c;Go原生支持通过/操作符来连接多个字符串以构造一个更长的字符串&#xff0c;并且通过/操作符的字符串连接构造是最自然、开发体验最好的一种。 但Go还提供了其他一些构造字符串的方法&#xff0c;比如&#xff1a; ● 使用fmt.Sprintf&#xff1b; ● 使…...

VR钢铁实训 | 铁前事业部虚拟仿真培训软件

随着科技的发展&#xff0c;虚拟现实技术在各个行业中的应用越来越广泛。在钢铁冶炼行业中&#xff0c;VR技术也逐渐得到了应用&#xff0c;其中铁前事业部虚拟仿真培训软件就是一项非常有优势的技术。 铁前事业部虚拟仿真培训软件是广州华锐互动打造的《钢铁生产VR虚拟培训系统…...

上海自动seo/云南网站seo服务

1. 内核架构 SELinux在所有内核资源上提供增强的访问控制&#xff0c;在它目前的格式下&#xff0c;SELinux是通过LSM框架合并到内核中的。 1.1 LSM框架 LSM框架的思想是允许安全模块以插件形式进入内核&#xff0c;以便更严格地控制Linux默认的基于身份的任意访问控制&…...

免费网站设计/yahoo搜索

先调用string的c_str(),函数&#xff0c;该函数一个指向正规C字符串的指针, 内容与本字符串相同&#xff0c;然后调用atoi&#xff08;&#xff09;函数就可以了&#xff0c;下面是一个简单的测试程序&#xff1a;#include<iostream>using namespace std;int main(){stri…...

wordpress表单防止/狠抓措施落实

关系数据库系统中的数据是以规范化格式存储的。 所以&#xff0c;为了进行统计计算&#xff0c;我们需要非常高级和复杂的SQL查询。但是R可以很容易地连接到许多关系数据库&#xff0c;如&#xff1a;MySQL&#xff0c;Oracle&#xff0c;Sql Server等&#xff0c;并将它们作为…...

学网站建设培训班/做网上推广

最近在看effective-python&#xff0c;第二章函数中提到了优先排序的概念&#xff0c;具体代码如下&#xff1a;values [1, 5, 3, 9, 7, 4, 2, 8, 6]group [7, 9]def sort_priority(values, group):def helper(x):if x in group:return (0, x)return (1, x)values.sort(keyhe…...

企业网站维护怎么做/网络推广页面

相关历史文章&#xff08;阅读本文之前&#xff0c;您可能需要先看下之前的系列 &#xff09;分布式事务「2020年」必学&#xff0c;升职加薪你准备好了吗&#xff1f;事务的基本概念事务的四大特性ACID分布式事务产生的场景前言CAP理论告诉我们分布式系统最多只能满足CAP中的两…...

靠谱企业网站设计公司/什么叫友情链接

电子商务安全作业 一、单选题 1. 以下那个不是杀毒软件的正确使用方法&#xff08; &#xff09;。 A. 定期对病毒库进行升级 B. 经常针对电脑进行全盘扫描 C. 设置开机自动运行杀毒软件D. 中毒之后再下载杀毒软件来安装 2. 电子商务实践表明&#x…...