BERT模型引入及详解

参考

  • 视频:

    • ELMo 模型(双向 LSTM 模型解决词向量多义问题
  • 博客:

    • BERT模型
    • BERT详解:概念、原理与应用
    • 一文读懂BERT

ELMo模型

参考:

  • 视频:
    • ELMo模型(双向LSTM模型解决词向量多义问题)
  • 博客:
    • 【自然语言处理】ELMo, GPT等经典模型的介绍与对比

引入

Word Embedding中,词语都是由一个唯一的词向量进行表示的,不根据句子改变而改变

也就是说,Word Embedding表示词的方法是静态的,无法对多义词进行处理

对于这个例子,尽管不同序列中的bank的上下文不同,但经语言模型训练时,无论什么序列经过Word2Vec,都是对bank这个词进行预测,因此占用的是嵌入矩阵中的同一行参数;这样会导致不同的语义被压缩到同一个Word Embedding空间,进而导致Word Embedding无法区分多义词

核心思想

事先用语言模型训练好了一个单词的Word Embedding,但是它此时还无法区分多义词语义,这没关系

当使用Word Embedding时,此时单词已经具有特定的上下文,这个时候我可以根据上下文单词的语义再去调整单词的 Word Embedding 表示,这样经过调整后的 Word Embedding 更能表达单词在这个上下文中的具体含义

ELMo模型的核心思想就是:根据当前上下文对Word Embedding进行动态调整

注意:ELMo是对Word2Vec的改进,模型的主要任务还是在于词向量而不是预测生成

不只是训练一个嵌入矩阵Q,还要把当前词的上下文信息融入到这个Q矩阵

两阶段过程

  • 利用语言模型做预训练
  • 做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding作为新特征补充到下游任务中

架构

预训练过程

分为三部分:

  • Embedding模块 - 提取单词特征
  • 双层双向LSTM模块
    • 第一层:提取句法特征
    • 第二层:提取语义特征
  • 词向量表征模块
    • 使用若干参数融合每一层提取到的特征信息
Embedding模块

使用CNN去提取输入序列的文字特征,得到一个静态的Word Embedding作为整个网络的底层输入

双层双向LSTM模块

当前预训练语言模型的任务是:
根据当前词wiw_iwi的上下文去正确预测单词wiw_iwi,wiw_iwi之前的单词序列Context-before称为上文,wiw_iwi之后的单词序列Context-after称为下文

图中左侧的双层LSTM称为前向LSTM网络,输入顺序从左至右,输入除了wi以外的上文除了w_i以外的上文除了wi以外的上文

对于n个w,语言模型通过前k−1个w来计算第k个w出现的概率,构成双层前向LSTMP(w1,w2,⋯,wn)=∏k=1nP(wk∣w1,⋯,wk−1)\begin{align} 对于n个w,语言模型通过前k-1个w来计算第k个w出现的概率,构成双层前向LSTM\\ P(w_1,w_2,\cdots,w_n) = \prod_{k=1}^{n}P(w_k | w_1,\cdots,w_{k-1}) \end{align} 对于nw,语言模型通过前k1w来计算第kw出现的概率,构成双层前向LSTMP(w1,w2,,wn)=k=1nP(wkw1,,wk1)

图中右侧的双层LSTM称为反向LSTM网络,输入顺序从右至左,输入除了wi以外的逆序下文除了w_i以外的逆序下文除了wi以外的逆序下文

语言模型通过后n−k个w来计算第k个w出现的概率,构成双层反向LSTMP(w1,w2,⋯,wn)=∏k=1nP(wk∣wk+1,⋯,wn)\begin{align} 语言模型通过后n-k个w来计算第k个w出现的概率,构成双层反向LSTM\\ P(w_1,w_2,\cdots,w_n) = \prod_{k=1}^{n}P(w_k | w_{k+1},\cdots,w_{n}) \end{align} 语言模型通过后nkw来计算第kw出现的概率,构成双层反向LSTMP(w1,w2,,wn)=k=1nP(wkwk+1,,wn)
ELMo的训练目标是最大化下面这个函数

∑k=1n(P(wk∣w1,⋯,wk−1;Θx,Θ→LSTM,Θs)+P(wk∣wk+1,⋯,wn;Θx,Θ←LSTM,Θs))Θx:词的输入表示参数(CNN中的参数)Θ→LSTM:双层前向LSTM的参数Θ←LSTM:双层反向LSTM的参数Θs:输出层参数\begin{align} \sum_{k=1}^{n}(P(w_k|w_1,\cdots,w_{k-1};\Theta_{x},{\overrightarrow{\Theta}_{LSTM}},\Theta_{s})+P(w_k|w_{k+1},\cdots,w_{n};\Theta_{x},{{\overleftarrow{\Theta}}_{LSTM}},\Theta_{s}))\\ \Theta_{x}:词的输入表示参数(CNN中的参数)\\ \overrightarrow{\Theta}_{LSTM}:双层前向LSTM的参数\\ \overleftarrow{\Theta}_{LSTM}:双层反向LSTM的参数\\ \Theta_{s}:输出层参数\\ \end{align} k=1n(P(wkw1,,wk1;Θx,ΘLSTM,Θs)+P(wkwk+1,,wn;Θx,ΘLSTM,Θs))Θx:词的输入表示参数(CNN中的参数)ΘLSTM:双层前向LSTM的参数ΘLSTM:双层反向LSTM的参数Θs:输出层参数

词向量表征模块

对于每个w,通过一个L层的双向LSTM网络,可以计算出2L+1个表示向量对于第k个词wk,第j层的双向LSTM网络Rk={xkLM,hk,jLM→,hk,jLM←∣j=1,⋯,L}={hk,j∣j=1,2,⋯,L}hk,jLM→:第j层正向LSTM对wk的隐藏状态hk,jLM←:第j层反向LSTM对wk的隐藏状态\begin{align} 对于每个w,通过一个L层的双向LSTM网络,可以计算出2L+1个表示向量\\ 对于第k个词w_k,第j层的双向LSTM网络\\ R_k = \{{x_k^{LM},\overrightarrow{h_{k,j}^{LM}},\overleftarrow{h_{k,j}^{LM}}}\ \ |\ \ j=1,\cdots,L\} = \{h_{k,j}\ \ |\ \ j=1,2,\cdots,L\}\\ \overrightarrow{h_{k,j}^{LM}}:第j层正向LSTM对w_k的隐藏状态\\ \overleftarrow{h_{k,j}^{LM}}:第j层反向LSTM对w_k的隐藏状态 \end{align} 对于每个w,通过一个L层的双向LSTM网络,可以计算出2L+1个表示向量对于第k个词wk,j层的双向LSTM网络Rk={xkLM,hk,jLM,hk,jLM    j=1,,L}={hk,j    j=1,2,,L}hk,jLM:j层正向LSTMwk的隐藏状态hk,jLM:j层反向LSTMwk的隐藏状态

Feature-based Pre-Training

上图展示了下游任务的使用过程

比如我们的下游任务是QA,此时对于问句X:

  • 将这个X作为预训练好的ELMo网络的输入,这样X中的每个单词在ELMo网络中都能获取对应的3个embedding
  • 分别给予这3个embedding权重a,这个权重可以学习得来;
  • 根据各自权重累加求和,将三个 embedding 整合成一个
  • 将整合后的embedding作为X句在自己任务中的对应单词的输入,以此作为补充的新特征给下游任务使用

因为 ELMo 给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为 “Feature-based Pre-Training”

GPT模型

GPT(Generative Pre-Training)是指生成式的预训练模型

不同于ELMo模型的基于特征融合的预训练方法,GPT采用了一种叫 Fine-tuning(微调) 的预训练方法

GPT也采用两阶段过程:

  • 阶段1:利用语言模型进行预训练
  • 阶段2:通过Fine-tuning模型解决下游任务

预训练

这个结构乍一看,和ELMo模型很像,但是有以下不同:

  • 特征抽取器使用了双层Transfomer,而不是双层LSTM,有利于学习长序列和并行运行
  • GPT使用单向语言模型;特征抽取时不同时使用上文下文,仅使用上文预测;而ELMo的双层双向LSTM则是同时使用上文和下文进行预测

缺点:从现在来看,使用单向语言模型,没有融合单词的下文,在一些应用场景受限,比如完成阅读理解任务,这个任务允许同时看到上文和下文来进行决策

Fine-tuning解决下游任务

  • 对于下游网络来说,要将网络结构改造成与GPT一样的网络结构
  • 做下游任务时,利用第一步预训练好的参数去初始化下游任务网络(与GPT结构一样)的网络结构,这样一来,预训练学到的语言学知识就被引入到当前任务中了
  • 用当前任务再去训练这个网络,对参数进行Fine-tuning,使这个网络更适合解决当前问题

那么到底什么是Fine-tuning呢?

Fine-tuning

其实上面解决下游任务的过程已经对Fine-tuning简单地描述了一遍

Fine-tuning其实就是在已经训练好的模型的基础上,针对特定任务,再对模型的部分/全部参数进行训练,以使模型更适应当前任务(很像迁移学习)

优点
  • 解决小规模数据集的训练问题
  • 节省训练时间和成本
  • 提升模型在目标任务上的性能

BERT模型

参考

  • 视频:
  • 博客:
    • BERT模型
    • BERT详解:概念、原理与应用
    • 一文读懂BERT

定义

BERT模型(Bidirectional Encoder Representations from Transformers)是一种基于 Transformer 架构的预训练语言模型

它的特殊之处并不是说它有什么很突出的创新点,而是集大成者

所谓集大成者:

  • 借鉴了ELMo模型双向双层LSTM同时使用上文下文预测的思路
  • GPT类似,使用Transformer作为特征提取器
  • 采用了Word2VecCBOW模型

结构 & 对比

  • ELMo使用从左向右和从右向左的两个LSTM网络,分别以 P(wi∣w1,⋯,wi−1)和 P(wi∣wi+1,⋯,wn)P(w_i|w_1,\cdots,w_{i-1})\ 和\ P(w_i|w_{i+1},\cdots,w_{n})P(wiw1,,wi1)  P(wiwi+1,,wn)作为目标函数独立训练,将训练得到的特征向量用拼接实现双向编码,其实本质上还是相当于单向编码
  • GPT使用Transformer Decoder作为Transformer Block,以P(wi∣w1,⋯,wi−1)P(w_i|w_1,\cdots,w_{i-1})P(wiw1,,wi1)为目标函数,使用Transformer Block代替LSTM进行特征提取,实现了单向编码,是一个标准的预训练语言模型
  • BERT也是一个标准的预训练语言模型,以P(wi∣w1,⋯,wn)P(w_i|w_1,\cdots,w_n)P(wiw1,,wn)作为目标函数进行训练;使用Transformer Encoder作为Transformer Block,将GPT的单向编码改为双向编码;也就是说,BERT舍弃了文本生成能力,换来了更强的语义理解能力

BERT的模型其实就是Transformer Encoder的堆叠,在模型参数上,官方一开始提供了两个版本:

BERTBASE:L=12,H=768,A=12BERTLARGE:L=24,H=1024,A=16L:TransformerBlock的层数H:特征向量的维度A:多头自注意力机制的头数\begin{align} BERT_{BASE}:L=12,H=768,A=12\\ BERT_{LARGE}:L=24,H=1024,A=16\\ L:Transformer\ Block的层数\\ H:特征向量的维度\\ A:多头自注意力机制的头数\\ \end{align} BERTBASE:L=12,H=768,A=12BERTLARGE:L=24,H=1024,A=16L:Transformer Block的层数H:特征向量的维度A:多头自注意力机制的头数

无监督训练

方法

BERT也采用二阶段预训练方法:

  • 第一阶段:使用易获取的大规模无标签语料,训练基础语言模型
  • 第二阶段:使用指定任务的少量带标签数据进行Fine-tuning
任务
  • 使用语言掩码模型(MLM)方法训练词的语义理解能力
  • 用下句预测(NSP)方法训练句子之间的理解能力,从而更好支持下游任务

语言掩码模型MLM

由来

BERT作者认为自左向右和自右向左的单向编码器拼成的双向编码器,在性能,参数规模,效率等方面都不如深度双向编码器

这就是为什么BERT使用Transformer Encoder作为特征提取器,而不是使用从左至右编码和从右至左编码的两个Transformer Decoder

由于无法使用标准语言模型的训练模式(?),BERT使用MLM进行训练模型,MLM借鉴了完形填空CBOW的思想

回答:传统的语言模型(基于循环神经网络构建的语言模型)都是单向的,比如ELMo(两个单向拼接成一个双向);而BERT是双向语言模型,所以需要使用全新的训练方式

  • AR模型(自回归模型)
    • 根据上文预测下一个单词,或根据下文预测前一个单词,只能考虑单侧信息
  • AE模型(自编码模型)
    • 从损坏的输入数据中预测重构原始数据,可以使用上下文信息,BERT采用的就是AE模型
做法

在原始句子中,随机抽取15%的token进行掩盖,用其上下文去判断[mask]位置被掩盖的token原本应该是什么

由于BERT使用AE模型,MLM的做法会有个问题,15%的掩盖率其实很高了,会导致掩码词在下游任务Fine-tuning阶段从未被见过,导致了预训练和Fine-tuning的不一致

简单理解就是:在预训练学习阶段,模型已经习惯了[mask],那么MLM学到的一些表达就可能依赖于[mask];但是在下游任务中[mask]可能从未出现,这就导致了一些表达无法很好的迁移

为了解决这个问题,对于被选取的作为掩码词的15%的token,不是全用[mask]代替,而是采取以下做法来解决上述弊端:

  • 对于80%的训练样本:
    • 将选取的token直接替换成[mask]
	用[]表示选取中的token比如:我好饿啊,我想吃[饭]↓我好饿啊,我想吃[mask]
  • 对于10%的训练样本:
    • 选中的词原封不动,为了缓解训练文本和预测文本的偏差带来的性能损失
  • 对于最后10%的训练样本:
    • 将选中的词随机替换成一个新词,这样是为了让BERT学会根据上下文纠错
	用[]表示选取中的token比如:我好饿啊,我想吃[饭]↓我好饿啊,我想吃电脑

这样的好处是:编码器不知道哪些词是需要预测的,哪些词是错误的,因此被迫学习每一个token的表示向量

下句预测NSP

在很多自然语言处理的下游任务(如问答,自然语言推断)中,都基于两个句子做逻辑推理,但模型本身并不具备直接捕获句
子之间语义联系的能力,或者说,单词预测的训练(比如GPT,ELMo,都是基于上下文对单词预测)达不到句子关系这个层级

为了学会捕捉句子之间的语义联系,BERT 采用了下句预测(NSP)作为无监督预训练的一部分。

NSP的具体做法是:BERT的输入由两个句子(A,B)组成,其中:

  • 50%的概率为这两个句子是连续的,即B是真实文本中A的下一句话
  • 另外50%的概率为这两个句子是随机抽取的

句子的形式:

[CLS] A [SEP] B [SEP]
[SEP]标签表示分隔符
[CLS]标签用于类别预测,结果为1时,表示输入连续句对(isNext),为0时表示随机句对(notNext)

通过训练[CLS]编码后的输出标签,BERT可以学会捕捉两个输入句对的文本语义

eg:

Input: [CLS]The man went to [MASK] [SEP] He bought a bottle of Coke[SEP]
Label: isNextInput: [CLS]The man [MASK] to store[SEP] I'm going to sleep[SEP]
Label: notNext
输入表示

BERT的预训练方法有以上两种,但是实际使用中通常是两种方法混合使用

由于BERT模型通过Transformer Encoder堆叠组成,因此BERT的输入需要两套embedding操作:

  • Token Embeddings
    • 将各个词转换为固定维度的向量表示;
      • 在BERT中,每个单词会先进行Tokenization后再输入Token Embeddings层中
      • 插入两个特殊的Token,在Tokenization的结果开头加上[CLS],结尾加上[SEP]
      • 最终转换为768维的向量
  • Position Embeddings
    • 不同于Transformer中用三角函数固定表示每个位置的位置编码,BERT中的位置编码是预训练过程中通过学习得来的,训练思想类似于Word2Vec中嵌入矩阵Q
  • Segment Embeddings
    • 用于区分一个单词属于句子对中的哪个句子
      • 赋0:第一个句子中的各个Token
      • 赋1:第二个句子中的各个Token

这3个向量都是768维的,最后将其按元素相加,得到最终的Input Embedding

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93256.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93256.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/93256.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源 Arkts 鸿蒙应用 开发(十六)自定义绘图控件--波形图

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。 相关链接: 开源 Arkts …

【linux】自定义shell——bash命令行解释器小程序

小编个人主页详情<—请点击 小编个人gitee代码仓库<—请点击 linux系列专栏<—请点击 倘若命中无此运&#xff0c;孤身亦可登昆仑&#xff0c;送给屏幕面前的读者朋友们和小编自己! 目录前言一、交互问题&#xff0c;获取命令行二、字串的分隔问题&#xff0c;解析命…

【Python】Python爬虫学习路线

文章目录Python爬虫学习路线&#xff1a;从入门到实战的全景指南一、地基&#xff1a;Python核心基础1. 基础语法与数据结构2. 面向对象编程&#xff08;OOP&#xff09;3. 正则表达式&#xff08;Regex&#xff09;4. 模块与包管理二、工具链&#xff1a;Python爬虫核心库1. 网…

VUE+SPRINGBOOT从0-1打造前后端-前后台系统-用户管理

在现代Web应用开发中&#xff0c;前后端分离架构已经成为主流模式。本文将通过一个完整的用户管理系统案例&#xff0c;详细介绍如何使用Vue.js Element UI构建前端界面&#xff0c;结合Spring Boot实现后端服务&#xff0c;实现前后端分离开发。该系统包含用户信息的增删改查…

基于uni-app+vue3实现的微信小程序地图范围限制与单点标记功能实现指南

一、功能概述本文将分步骤讲解如何使用uni-app框架在微信小程序中实现以下功能&#xff1a;显示基础地图绘制特定区域范围&#xff08;以郑州市为例&#xff09;实现点击地图添加标记点限制标记点只能在指定区域内添加显示选中位置的坐标信息二、分步骤实现步骤1&#xff1a;搭…

C# 反射和特性(关于应用特性的更多内容)

关于应用特性的更多内容 至此&#xff0c;我们演示了特性的简单使用&#xff0c;都是为方法应用单个特性。本节将讲述特性的其他使 用方式。 多个特性 可以为单个结构应用多个特性。 多个特性可以使用下面任何一种格式列出。 独立的特性片段一个接一个。通常&#xff0c;它们彼…

【iOS】KVC原理及自定义

目录 前言 KVC定义及API KVC的使用 基本类型 集合类型 访问非对象类型——结构体 集合操作符 层层嵌套 KVC底层原理 设值过程 取值过程 自定义KVC setter方法 getter方法 KVC异常小技巧 自动转换类型 设置空值 未定义的key 前言 在平时的开发中我们经常用到K…

完整设计 之 智能合约系统:主题约定、代理协议和智能合约 (临时命名)----PromptPilot (助手)答问之2

摘要&#xff08;CSDN的AI助手生成的&#xff09;智能合约系统架构设计摘要本设计构建了一个多层次智能合约系统&#xff0c;包含150字以内的核心架构&#xff1a;三级架构体系&#xff1a;元级&#xff08;序分&#xff09;&#xff1a;MetaModel合约定义系统核心原则模型级&a…

Java基础 8.16

1.final关键字基本介绍final中文意思&#xff1a;最后的&#xff0c;最终的final可以修饰类、属性、方法和局部变量在某些情况下&#xff0c;程序员可能有以下需求&#xff0c;就会使用到final当不希望类被继承时,可以用final修饰当不希望父类的某个方法被子类覆盖/重写(overri…

YOLOv8目标检测网络结构理论

目录 YOLOv8的网络结构图&#xff1a; Backbone 卷积块&#xff08;Conv Block&#xff09; Conv2d层 BatchNorm2d层 SiLU激活函数 瓶颈块(Bottleneck Block) C2f 模块结构 Neck SPPF(空间金字塔池化快速) PAN - FPN Head 结构1.卷积层和激活函数: 2.预测层(Predi…

docker部署hadoop集群

Docker部署hadoop集群下载资源构建镜像启动容器搭建集群配置ssh免密节点职责安排修改配置文件启动集群测试上传下载执行wordcount程序补充配置历史服务器日志聚集单节点启动Java客户端使用HDFSMapReduce下载资源 java华为镜像下载地址&#xff1a;Index of java-local/jdk (hu…

常用的T-SQL命令

文章目录1. 数据库操作2. 表操作3. 数据插入、更新、删除4. 数据查询5. 存储过程6. 事务处理7、如何使用T-SQL在表中设置主键和外键&#xff1f;1. 设置主键&#xff08;PRIMARY KEY&#xff09;方法1&#xff1a;创建表时定义主键方法2&#xff1a;通过ALTER TABLE添加主键2. …

C++面试题及详细答案100道( 31-40 )

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

给纯小白的 Python 操作 Excel 笔记

&#x1f9f0; 1. 先装工具电脑键盘按 Win R&#xff0c;输入 cmd&#xff0c;回车&#xff0c;把下面一行粘进去回车&#xff0c;等它跑完。 bashpip install openpyxl——————————————————&#x1f6e0;️ 2. 打开一个空白的 Excel 打开 Jupyter Notebook…

HTML 常用属性介绍

目录 HTML 属性 HTML 属性速查表 一、通用属性&#xff08;所有元素适用&#xff09; 二、链接与引用相关属性 三、表单与输入控件属性 四、媒体与多媒体属性 五、事件属性&#xff08;常用 JavaScript 事件&#xff09; 六、其他常用属性 核心通用属性 id 属性 cla…

HTML5练习代码集:学习与实践核心特性

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;HTML5作为新一代网页标准&#xff0c;对Web开发提供了更丰富的功能和工具。本练习代码集专门针对HTML5的核心特性&#xff0c;包括语义化标签、离线存储、多媒体支持、图形绘制等&#xff0c;以及CSS3的3D效果和…

【RH134知识点问答题】第 10 章:控制启动过程

目录 1. 请简要说明 RHEL9 的启动过程。 2. 系统重启和关机的命令分别是什么? 3. Systemd target 是什么&#xff1f; 4. 重置丢失的 root 密码需要哪些步骤&#xff1f; 5. 如何让系统日志在重启后持久保留 1. 请简要说明 RHEL9 的启动过程。 答&#xff1a;①开机自检…

Apollo10.0学习之固态雷达与IMU的外参标定

固态雷达&#xff08;如Livox、禾赛等非旋转式激光雷达&#xff09;与IMU&#xff08;惯性测量单元&#xff09;的外参标定&#xff08;Extrinsic Calibration&#xff09;是自动驾驶、机器人定位&#xff08;如LIO-SAM、FAST-LIO&#xff09;的关键步骤。1. 标定原理 外参标定…

HTML5实现古典音乐网站源码模板1

文章目录 1.设计来源1.1 网站首页1.2 古典音乐界面1.3 著名人物界面1.4 古典乐器界面1.5 历史起源界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;http…

40 C++ STL模板库9-容器2-vector

C STL模板库9-容器2-vector 文章目录C STL模板库9-容器2-vector一、基础概念1. 类型成员&#xff08;Type Members&#xff09;2. 模板参数二、构造函数1. 语法2. 示例三、元素访问1. 函数说明2. 示例代码四、容量操作1. 函数说明2. 关键点说明3. 关键操作解析4. 操作示例五、修…