宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

导读:本次分享介绍最近一年我们在自然语言生成上的一些模型,以及实际落地场景中的一些工作。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

今天主要介绍下面这几个工作:

  • 第一个工作是我们的先知网络,是预训练的一个生成模型。
  • 第二个是我们在生成模型当中引入一些外部的知识。
  • 接下来是我们今年在ICML的三篇工作,非自回归生成的预训练和长文本的建模,以及对于生成模型加速的实现。
  • 最后是我们为了更好地去评价一些生成模型的一个benchmark。

如果大家对于某个内容感兴趣,想要深入了解,可以去查看对应的paper。

全文将围绕以下六部分内容展开:

  • 先知网络
  • 生成模型引入外部知识
  • 非自回归的预训练
  • 长文本建模
  • 生成模型加速的一个实现
  • 生成模型的benchmark

01

先知网络

在介绍先知网络之前,简单介绍研究背景。我们起初是想把生成模型应用在广告关键词生成task上。我们背后有很多广告,每个广告都有一个keywords set,用户输入一个query,所有广告的keywords set就得到一个候选集,我们要通过这个query,到候选集里面去找相关的keywords。这本身是一个检索任务,已经有各种检索模型在线上使用了,我们想把生成模型也应用到这个task上。

下面是一个例子,query和它对应的一些keywords,这些都是在候选集里面找到的。可以看到keywords没有我们想象得那么规范,这给检索带来了很大的困难。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

最开始我们想直接输入一个query去生成keywords,每个query可以生成很多的keywords,如果这个keyword在这个候选集里面有一个exactly的match,我们就把它拿出来作为一个候选,但是生成模型的decode端是自由生成的,这样很难保证生成的keyword就在候选集里面,所以recall很低。

之后,我们尝试先把keywords build成一个trie tree,在decode端生成的时候,沿着这个trie tree,从根节点到叶子节点去生成,可以保证每一次生成的一条路径,就是一个候选集里面的对应的一个keyword,这样限制decode的时候,每一个decode出来的结果都在候选集里面。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

这个方法有一个明显的缺陷,就是像下图这个例子:

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

左上角是一些候选的keywords,我们把它build成trie tree,然后在encode “accommodation texas”的时候decode,例如我们decode的前三个词是“the best hotel”,在trie tree上的候选是in和of。如果是传统的生成模型,我们只能基于前面已经生成的“the best hotel”以及输入,去预测下一个词,判断它是in还是of,但是这个in和of后面都跟了哪些词,对于选当前这个词是很有帮助的。如果我们知道,in后面有texas,但是of后面没有,那么我们就更容易去选in,但是我们现在的生成模型不支持,只能每个step去预测下一个词是什么。基于这个考虑,我们就想是否要每一个step,基于前缀直接就可以预测后面的N个词,而不仅仅是只预测下面的一个词。

下面先介绍一下transformer。在decode端,每一个step都是用前面的信息去预测下一个词的。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

接下来这是一个bigram,就是未来的两个词的一个例子,有了前面的词之后,给它不同的position的标记,就可以去预测后面的不同的词。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

这样对于我们这个task,有了“the best hotel”,就可以同时去预测它未来不同位置可能是什么词,然后再看一下这个trie tree上每个词后面接的这些词,我们就可以同时考虑进来。

下面介绍一个我们模型的训练case,输入是accommodation texas,输出是the best hotel in texas。这里第一个step,给了BOS,然后给了不同的p,去预测不同的词,这是第一个step的loss计算。

第二个step是从第一个step里面,保留下来一个词,然后去预测。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

这是我们计算后面两个词的loss,去回传。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

这里我们加上直接到trie tree上去搜索,这是一个很大的提升,但是考虑到这套框架不仅仅是针对这种trie tree based的搜索有效,它也可以加到预训练的生成模型里面,要生成一个通用的框架。我们就采用这种预训练的方式,收集了大量无标记的语料,用mask language model的task,去预训练我们的模型。我们采用的预训练任务和mask里面是一样的,当时采用预训练任务,一个很重要的考虑是因为这个预训练任务,decode端只需要去建模encode端mask的位置,所以decode的计算量会小,预训练起来会快;其次,计算力没有那么强的情况下,也可以预训练一个这种大规模的模型。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

我们做了只有中文的、只有英文的、多语言的(用100种语言的预训练)预训练,以及在Dialog上面去预训练模型。我们的code和模型都放到了这个位置:https://github.com/microsoft/ProphetNet

感兴趣可以下载。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

在中文上,是在这几个任务上面去做,一个是输入question能直接生成answer;输入description,去生成question;以及输入一个document,去生成summary。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

可以看到,我们中文版的预训练模型,在不同的task上还是有一些提升。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

在英文上,我们输入一个文本,生成multi sentence的summary,生成single sentence的headline,以及给一个article,一个answer span,去生成对应的question的生成任务。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

以下是在CNN Dailymail上的生成性能。和BART对比,我们跟它用的预训练的语料是差不多的,但是我们只训练了14个epoch,它训练了40个,而且在相同epoch的情况下,我们decode端的计算量要比它小,它还原整个句子,输入是512个token,输出也是512个token;我们输入是512个token,输出只是这个里面的15%的token,所以decode端的计算量要小很多。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

下面是在不同任务上面的结果:

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

以下是在QG task上的结果:

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

QG task在预训练之前,是我们之前做的很难的一个task,我们当时感觉生成question直接应用到线上还是很困难的,但是有了预训练之后,这个task就有了很大幅度的提升。

接下来就是多语言,我们用100种语言的语料去预训练模型,在英文语料上fine tune,然后直接在其他语言上inference,还做了news headline生成和question生成。

以下是我们在中文对话和英文对话上的一些结果:

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

以下是ProphetNet在没有预训练的情况下,直接和transformer对比的结果,以及预训练的时候,预测未来的词的个数不同,结果有什么变化。可以看到在增加gram的个数的时候,从1gram到2gram的时候有一个还算可以的提升,3gram的时候提升得小一点,但是还是会有一些。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

以下是在Ads keywords项目上的一个实验结果,我们用260 milion keywords,作为候选集,然后用1 milion训练语料去训练模型,最后用10k test set。所有的生成都接了trie,只有第一个BM25是直接检索的,BM25的优势是不需要训练,直接检索,但是它的performance很差,可以看到加上之后可以对recall有大幅度的提升,这是在真实的项目数据集上做的实验。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

这是我们的第一个工作,我们从头预训练了一个生成模型,取得了不错的性能。

--

02

生成模型引入外部知识

我们在生成模型当中引入一些外部的知识,做实验的task用了CommonGen语料。考虑我们的任务是输入query,然后生成keywords,query本身不是孤立的,它有很多点击的信息,这些信息是否可以都用进来,帮助我们去生成keywords。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

为了验证引入外部的一些信息来辅助生成这个方法,我们用CommonGen语料集。这个语料集的任务是,输入一个concept set,输出日常的一些场景,cover这些concept的一个句子。做这件事情需要知道背后的concept之间的关系,也就是common sense的knowledge,再通过它们之间的关系去生成一个句子,就像如果给了一个树和一个苹果,苹果长上在树上,肯定没有问题,但是树长在苹果上,就有问题了,它们都是通顺的,但要输出合理的句子。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

一个简单的想法,就是可以通过这些concept,去引入一些外部的知识。这些知识里面,可能覆盖了concept之间的一些合理的组合,也可以通过得到的这些东西,把最后要生成的句子里面一些丢失的关键信息,从这个prototype里面获取到。直接的方法,就是输入concept set,然后输出就是decode的target sentence,而我们拿concept set,去open domain的一些无标记的语料里面,找来和这个concept相关的一些信息,然后把这些信息加到我们的模型里面,辅助它去生成它的target。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

得到这些辅助信息后,如何将其引入到模型中?获取到的这些信息,对于生成有很多有帮助的东西,但也会有很多noise带进来。为了把有用的信息加进来,把没用的信息尽量去除掉,我们设计了不同的方法,包括scaling model和prototype position indicator。

scaling model有一个模块去判断,得到prototype里面这些token的重要性。prototype position indicator是判断这些外部信息中包含的concept在句子中出现的位置,即其他词相对它的位置距离,也一定程度上反映了这些词的重要性,然后把position indicator加进去。

接下来这个问题就可以定义成下面这样,有一个concept set、prototype,以及target,我们要build的model就是根据concept set和prototype去生成这个target。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

我们的模型包括三个部分,第一个部分是embedding,因为引入了prototype,输入就包含两部分,一个是concept,一个是prototype。我们分别给它们加了group embedding,加到concept和prototype里面。另外我们加入了encoder端和scaling model帮助过滤,把有用的信息尽量提取出来,帮助生成。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

以下是group embedding,对concept和prototype分别有一个special的embedding加到它们的token里面。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

接下来就是scaling model的部分,这一部分是在encoder端。我们得到的prototype和target之间overlap的这些词,我们认为它们比较重要,没有overlap的词,就认为它不是特别重要,这样就有了一个0-1的label。在encoder端我们会对它进行训练,学习这种重要词和不重要词的预测,然后把这个weight加到最终的词在输入decoder端之前它的表示里面。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

接下来是prototype position indicator,我们直接把embedding在encoder端输出的时候,跟着输出的信息一起输入到decoder端,比如对于concept里面的词,因为它直接就是concept,所以它的相对位置距离就是零。对于prototype里面的词,它距离最近的concept的距离,有的相对距离是一,有的是二,就把这种位置信息和encoder的输出一起引入到decoder里。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

然后我们进行实验,我们通过不同的方法,去不同的语料集里面去获取prototype,一个是in domain的,一个是out of domain。in domain是构造这个候选语料集的时候,和CommomGen的target在一个domain里面的语料。out of domain就是open domain,我们直接用wikipedia的语料作为外部的数据集。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

最后是实验结果,无论是在in domain还是out of domain,都可以看到模型引入这个信息之后,都有比较大的提升。这是因为原本的语料体系里面给的baseline没有预训练,所以比较差,加入预训练之后在这个任务上面有了一个明显的提升。信息引入进来之后,也进一步再去提升,in domain肯定会更好,out of domain也有明显效果。这是我们在CommonGen上面的一个工作。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

接下来介绍我们在ICML上的几个工作。

--

03

非自回归的预训练

第一个是非自回归的预训练。前面介绍的这些模型,都是基于预训练的,而且模型比较大,而生成模型的decode端一般用的都是自回归的,每一个step都在decode端去生成一个词,token by token地去生成,它的latency一般都会比较高。在广告Keywords生成的时候,很难把它online使用起来,只能在offline去生成。怎样让它能够online去生成,有不同类型的方法,可以考虑去distill一个小的模型,或者用deep encoder,shallow decoder。因为latency主要在decoder端,所以让它的decode端比较浅层,encode端比较深层,但是无论怎样去做,只要是auto regressive的,总归要token by token地去生成,而online使用的时候,对于它的限制,我们这边就是10毫秒,10毫秒这种latency的需求还很难满足。从2018年到现在,非自回归在机器翻译上面已经被研究了很多,我们考虑怎样把非自回归的引入到这个task里面,并且用我们这种预训练的方式来提升它的性能,就提出了BANG。

在介绍BANG之前,先回顾一下我们的这种auto regressive的方法。例如输入是一个x0到x3的序列,输出是y0到y3,在auto regressive 的方法里面,输入直接对x进行encode,然后decoder端是token by token的,就是每一个token去生成的时候都基于前面已经生成的部分,以及encoder端的输入,这样latency会比较高。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

非自回归的方法里,每个token都不再基于前面的已经生成的token,而是基于输入和一个mask,就是在decoder端直接全部输入mask和position,然后直接去预测target,这种方式的latency确实会低,但是它的performance会有明显的下降。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

我们用各种方法对它的性能进行提升,包括用auto regressive的方式去distill,或者design一些semi auto regressive的方法。我们设计了一种新的semi auto regressive的方式,对auto regressive到non-auto regressive之间进行过渡。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

在decoder端,auto regressive是一个token一个token地去生成,non-auto regressive是一次性去生成。我们的semi-auto regressive,前几个token,直接auto regressive地去生成,后几个token,non-auto regressive地去生成。一个motivation是:要生成十个词的一个句子的时候,前五个词一旦生成好了之后,可能后半句就比较确定了,就更容易去生成,所以我们就让前几个词用auto regressive的方法,后面几个词相对容易的,用non-auto regressive的方法。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

BANG里面把auto regressive所有的都token by token地生成,non-auto regressive所有的token都一次性生成,并且把semi-auto regressive中间变化的整个过程,全都考虑到同一个模型里面,例如生成y3的时候,可以只把y2遮住,去预测y3,也可以把y2、y1遮住,也可以把y前面全遮住,这就是non-auto regressive。我们会在训练过程中,把所有情形全都考虑进来。这样的一个好处是模型在学一个hard的任务时,可以让它把简单的任务先学一下,也会帮助我们把整个hard的task学好。同时这也是一个多任务,因为semi-auto regressive的任务其实是非常多的,让不同的auto regressive、semi-auto regressive来帮助non-auto regressive。

另外一点就是这样学了之后,这个模型很自然地直接support这三种inference,只考虑performance,对latency的需求不高,那么就用auto regressive的方式;如果latency要求很高,performance可以低一点,可以用non-auto regressive;当然可以用semi-auto regressive的,综合前两个之间,进行任意调节,可以随意地调节前面多少个词去auto regressive,多少个词去non auto regressive,可以在latency和performance之间随意调节。

decode端这种不同的auto regressive,non-auto regressive和semi-auto regressive,它们的输入是不同的,用transformer没有办法直接去训练,因为这几个task的输入不同,我们就对XLNet里提出的n-stream self attention进行了一些改进,design了一个cross visible n-stream self attention的机制来同时高效地去训练不同的输入,把它们在一次decode当中去进行有效的训练。

我们用了无标记语料去预训练模型,然后在三个下游task上去进行evaluation,包括用SQuAD for Question Generation、XSum for Summarization,还有PersonaChat for Response Generation。

因为这个模型支持不同的inference,我们也对比了不同的baseline,在non-auto regressive和semi-auto regressive的方法下,都有非常大的提升,这里我们也引入了预训练。

以下是我们和auto regressive的latency的比较,我们比这种方法直接transformer去做,速度提升了十倍,在不同task上面得到相同的结论。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

--

04

长文本建模

再介绍另外一个工作,就是Poolingformer,这是我们在长文本建模上的一个工作。在介绍这个工作之前,先介绍一下transformer,输入一个序列,每一个token我们是做full self attention,每个token都会和其他的所有token进行计算attention,这样计算复杂度就是的。当输入的序列长度特别大的时候,例如输入一万个token的时候,计算量非常大,已有的常见的一些预训练的模型都是限制它的最大输入长度是512个token,像BERT、Roberta。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

对于这种长文本,我们怎样去进行建模,在做谷歌的一个NQ task的时候,就是一些很长的文本,我们基于Roberta,把长文本先切片,然后分片建模,最后综合。这样在出来这种长文本建模之前,我们当时在那个榜上做得还挺好的,后来就有了很多各种各样的长文本建模的模型。这里我举了两个例子,一个是Longformer,一个是Linformer,大家一个核心的想法是,怎样去压缩计算量,然后用这种sparse attention的方式。之前transformer里面,每个token都直接去看所有的其他token,直接去算attention,然后在Longformer里面,每个token不去直接看所有的token,每个token周边的这些token很重要,其他token可以引入一个global token,去把其他的一些信息也考虑进来。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

Linformer是:query不变,要计算的token是这些,但是对于整体的这些K和V,就是其他的这些token,先进行压缩,然后直接去看压缩之后就好了。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

我们的方法比较简单,我们设计了一个二级的window,通过实验下来,一级window很重要,每个token周边的这些token是一定要直接看的,比如第一级window,我们就直接window内部做full self attention,对于稍微远一些的token,就直接通过pooling的方式。二级window里面,例如有1000个token,先压缩成100个,然后只看压缩之后的,在二级window以外的就不看了,这样一个模型是,是一个常数,它就是的计算量。当比较小的时候,我们看不出来,当不断变大的时候,节约的计算量还是很多的。

下面是对比不同的长文本建模,计算量、计算复杂度,我们和Longformer 、BigBird都是的。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

我们也在谷歌NQ榜和TyDi QA榜上。谷歌的NQ是输入一个question,给一个Wikipedia,然后到wikipedia里面找一个span作为answer,就是short answer。如果找passage作为answer,就是long answer,这样两个榜。TyDi QA就是我理解的一个多语言的NQ。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

下面是在document level的summarization上,我们用arXiv for summarization这个dataset,去验证我们的模型。前四种方法都基于直接transformer的,最大输入长度是512个token。接下来这两种,一个BigBird,一个LongFormer。16k就是最大输入长度是16000个token,4k就是4000。可以看到,我们这个方法在这个task上性能不错,并且对比4k和16k,它的输入长度变大了之后,性能也有明显的提升。

最后分析一下我们这个模型,例如我们用了二级window,能否用一个特别大的二级的window通过NQ上的实验,当一级window固定,二级window在不断的变大的时候,模型不是performance一直涨,这也是我们为什么不直接把二级window压缩整个序列长度,然后直接去看。压缩整个序列长度会带来的问题,一是计算量会变得大很多;其次特别远的token,可能噪声比有用的信息还要多,就可以不用直接去看了。

压缩也有一些不同的方法,包括Mean pooling、Max pooling等。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

--

05

生成模型加速的实现

再介绍我们在实现上去提速生成的一个工作,也发在了ICML。我们在做生成的时候,auto regressive decode端,每一个step去生成一个token,要生成第t个token,我们考虑输入X和前面已经生成的t-1个token。当生成第t+1个token的时候,我们多考虑的信息,就是上一步生成的yt,所以前面的部分,这两个step它们都是共享的。如果每一次都重新去计算,每个step有很多重复的计算,所以一般的实现我们都会把前面的内容cache住,每一次更新的时候都只对新增加的东西进行计算。

在 multi head attention里,我们会把所有的Key和value都cache,这样每一层都会有它自己的cache,这样就会导致模型里面cache很多内容,为了维持这种大量的cache,对cache进行操作就非常耗时。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

这里我们就提出了一个新的attention的方式,叫EL-attention。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

在之前我们实现multi head attention的时候,都是把K乘W,V乘W,K和V都是cache住的,这里我们就不cache这一部分了,这样会节省很多的cache的消耗,但是不cache,就避免不了重复的计算,这就是用快速的计算去替换大量的cache的操作,看哪一个会更快。这里我们就引入EL-attention,它是对multi head attension的一个改进。

multi head attension里面,我们通过 WQ、WK、WV,得到Q、K、V,然后再去计算attention。这里Q在每一次生成的时候,都只新增一个yt,所以Q只是一个向量,但是根据任务不同,K和V可能是不同的向量。如果输入很长,或者batch size比较大,K和V是一个很大的一个矩阵,是很多个向量,但是Q只是一个向量,如果直接去算K乘W、V乘W,计算量是很大的,但是Q乘W的计算量是小的。

这里把这个query用了EL query去替代,就是把以前直接Q乘以 WQ,替换成了Q乘 WQ,再乘以一个 WT的转置,这样得到新的Q,然后把这个新的Q放到这个attention里面,用这个Q,K和V这两个操作就不再做了,然后直接去和它们算attention。Attention算完之后,再通过这个FFNO去算,最后乘V的参数。这样其实是一个等价的变换,但是它的整个计算量会有大幅度的下降,因为Q是很小的,所以都是在一维的向量上进行矩阵操作。K和V当输入比较长或者batch size比较大的时候,它是一个很大的矩阵的操作,所以它的计算量是很大的。所以这样即便每一次重复操作,计算量也不会特别大,但是却省略了大量的cache,可以在没有任何性能下降的情况下,大幅度地提升inference的速度。

下面是之前的multi head attention和EL-attention的对比,只是在计算上,还没有加cache的操作。这个圆的面积就是每一部分所耗的时间,之前multi head attention就是这三部分加起来的面积,EL-attention就只剩下这两部分,因为K和V都不会去乘这个参数,所以在K和V上就没有时耗,就直接去计算了一个ELQ,然后去计算。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

另外把这个机制加到transformer、BART、GPT等不同的模型上,在不同的生成任务的task上面进行对比,在performance没有掉的情况下,有很明显的速度提升。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

下面是对比不同batch size或者cache 的结果。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

--

06

生成模型的benchmark

我们也构造了一个generation的evaluation benchmark,里面包括八个语料集,四个task。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用

下面是我们的Leaderboard。

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用


今天的分享就到这里,谢谢大家。

阅读更多技术干货文章、下载讲师PPT,请关注微信公众号“DataFunSummit”


分享嘉宾:宫叶云博士 微软亚洲研究院

编辑整理:王岩 中科院

出品平台:DataFunTalk


01/分享嘉宾

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用


02/报名看直播 免费领PPT

宫叶云:基于预训练的自然语言生成在搜索与广告中的应用


03/关于我们

DataFun:专注于大数据、人工智能技术应用的分享与交流。发起于2017年,在北京、上海、深圳、杭州等城市举办超过100+线下和100+线上沙龙、论坛及峰会,已邀请超过2000位专家和学者参与分享。其公众号 DataFunTalk 累计生产原创文章700+,百万+阅读,14万+精准粉丝。


欢迎转载分享评论,转载请私信。

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章