论文解读:Attention Is All You Need

论文:Attention Is All You Need
下载:https://arxiv.org/abs/1706.03762
中英文对照:Attention Is All You Need:中英文对照

谷歌于2017年发布论文《Attention Is All YouNeed》,提出了一个只基于attention的结构来处理序列模型相关的问题,比如机器翻译。相比传统的CNN与RNN来作为encoder-decoder的模型,谷歌这个模型摒弃了固有的方式,并没有使用任何的CNN或者RNN的结构,该模型可以高度并行的工作,相比以前串行并且无法叠加多层、效率低的问题。那么Transorformer可以高度并行的工作,所以在提升翻译性能的同时训练速度也特别快。

Abstract

主流的序列转导模型基于复杂的循环或卷积神经网络,包括一个编码器和一个解码器。最高性能的模型还通过注意机制连接编码器和解码器。我们提出了一种新的简单网络架构:Transformer,仅基于注意机制,完全摒弃了循环和卷积。在两个机器翻译任务上的实验表明,这些模型在质量上更优秀,同时更可并行化,并且需要更少的训练时间。我们的模型在WMT 2014的英德翻译任务上达到28.4 BLEU,在包括集合的现有最佳结果基础上提升了2 BLEU以上。在WMT 2014的英法翻译任务上,在8个GPU上训练3.5天后,我们的模型在单一模型中建立了新的BLEU得分纪录,达到了41.8,训练成本仅为文献中最佳模型的一小部分。我们展示了Transformer在其他任务上的泛化能力,成功地应用于英语组成结构解析,无论是使用大规模还是有限的训练数据。

1 Introduction

循环神经网络(RNN),尤其是长短期记忆(LSTM)和门控循环神经网络(GRU),已经被广泛应用于序列建模和转换问题,如语言建模和机器翻译。多个研究努力不断推动循环语言模型和编码器-解码器架构的发展。

递归模型通常会将计算过程因子化为输入和输出序列的符号位置。将位置与计算时间步骤对齐,它们会根据前一个隐状态 h t − 1 h_{t−1} ht1位置 t t t的输入生成隐状态序列 h t h_{t} ht。这种隐含的顺序性使得在训练示例中无法实现并行化,而在较长的序列长度下这一点变得至关重要,因为内存限制限制了跨示例的批处理(batching across examples)。最近的研究通过因子化技巧(factorization tricks)[21]和条件计算(conditional computation )[32]在计算效率方面取得了显著进展,同时在后者的情况下也改进了模型性能。然而,顺序计算的基本限制仍然存在。

注意机制已经成为引人注目的序列建模和转换模型的重要组成部分,适用于各种任务,可以模拟输入或输出序列中的依赖关系,而不考虑它们的距离[2, 19]。然而,在除了一些特殊情况[27]之外,这种注意机制通常与递归网络一起使用。

在这项工作中,我们提出了Transformer这是一种模型架构,完全避免使用循环,并且完全依赖于注意机制来在输入和输出之间建立全局依赖关系。 Transformer可以实现更高程度的并行化,并且在仅在8个P100 GPU上训练12小时后,能够达到最新的翻译质量水平。

2 Background

减少顺序计算的目标也是Extended Neural GPU [16]、ByteNet [18]和ConvS2S [9]的基础,它们都使用卷积神经网络作为基本构建模块,对所有输入和输出位置并行计算隐状态表示(hidden representations)在这些模型中,将两个任意输入或输出位置之间的信号相关联所需的操作次数,随着位置之间的距离增加而增加,对于ConvS2S是线性增加,对于ByteNet是对数增加。这使得学习远距离位置之间的依赖关系更加困难[12]。在Transformer中,这种增长被减少为一定数量的操作,尽管通过平均注意力加权位置来降低了有效分辨率的代价,我们通过3.2节中描述的多头注意力来抵消这种影响。

在这些模型中,将两个任意输入或输出位置之间的信号相关联所需的操作次数,随着位置之间的距离增加而增加
3.2. 我们通过3.2节中描述的多头注意力来抵消这种影响。

自注意力,有时也称为内部注意力,是一种注意机制,用于关联单个序列的不同位置,以便计算序列的表示。自注意力已成功应用于各种任务,包括阅读理解、摘要生成、文本推理和学习与任务无关的句子表示[4, 27, 28, 22]。

端到端记忆网络是基于循环注意机制(recurrent attention mechanism)而不是序列对齐的循环(sequence aligned recurrence),并且已经显示出在简单语言问答和语言建模任务上表现良好。[34]

然而,据我们所知,Transformer 是第一个完全依赖自注意力来**计算其输入和输出表示(compute representations)**的转换模型,而不使用序列对齐的循环神经网络或卷积。在接下来的几节中,我们将描述Transformer,解释自注意力的动机,并讨论它相对于诸如[17,18]和[9]模型的优势。

3 Model Architecture

大多数具有竞争力的**神经序列转导模型(neural sequence transduction models)**都采用编码器-解码器结构。在这个结构中,编码器将输入的表示序列 ( x 1 , . . . , x n ) (x_1,...,x_n) (x1...xn)映射到一系列连续的表示 z = ( z 1 , . . . , z n ) z = (z_1,...,z_n) z=(z1...zn)。给定z,解码器则逐步生成一个输出符号序列 ( y 1 , . . . , y m ) (y1,...,ym) (y1...ym)在每一步中,模型是自回归的,即在生成下一个符号(symbols)时,它使用先前生成的符号作为额外的输入。

Transformer模型的总体架构如下,它在编码器和解码器中都采用了堆叠(overall architecture)自注意力机制(stacked self-attention)逐点全连接层(point-wise fully connected layers),如图1的左右两半所示。
在这里插入图片描述

3.1 Encoder and Decoder Stacks

编码器: 编码器由 N ( N = 6 ) N(N=6) N(N=6)个相同的层组成。每个层包含两个子层。第一个子层是一个多头自注意机制,第二个子层是一个简单的逐位置全连接前馈网络。我们采用残差连接[11]将这两个子层围绕起来,然后进行层归一化[1]。也就是说,每个子层的输出是 L a y e r N o r m ( x + S u b l a y e r ( x ) ) LayerNorm(x + Sublayer(x)) LayerNorm(x+Sublayer(x)),其中 S u b l a y e r ( x ) Sublayer(x) Sublayer(x)是子层本身实现的函数。为了方便这些残差连接,模型中的所有子层以及嵌入层产生的输出都有一个维度为 d m o d e l = 512 dmodel=512 dmodel=512

解码器: 解码器也由 N ( N = 6 ) N(N=6) N(N=6)个相同层次的堆叠组成。除了每个编码器层中的两个子层外,解码器还插入了第三个子层,它在编码器堆叠的输出上执行多头注意力机制。与编码器类似,我们在每个子层周围使用残差连接,然后进行层归一化。我们还修改了解码器堆栈中的自注意力子层,以防止位置关注后续的位置这种掩码机制与输出嵌入偏移一个位置相结合,确保位置 i i i的预测仅依赖于小于 i i i位置已知的输出。

3.2 Attention

注意力函数可以被描述为将一个查询和一组键值对映射到一个输出的函数,其中查询、键、值( query, keys, values)和输出都是向量。输出是通过对值的加权求和来计算的,其中对每个值赋予的权重是通过将查询与相应的键(corresponding key.) 进行 兼容性函数(compatibility function) 计算得到的。
在这里插入图片描述Figure 2: (left) Scaled
图2:(左侧)缩放点积注意力。 (右侧)多头注意力由多个并行运行的注意力层组成。

3.2.1 Scaled Dot-Product Attention

我们将我们的特殊注意力机制称为**“缩放点积注意力(Scaled Dot-Product Attention)”**(图2)。输入包括维度为 d k d_k dk的查询和键,以及维度为 d v d_v dv的值。我们计算查询与所有键的点积,将每个点积除以 d k \sqrt{d_k} dk ,并应用 s o f t m a x softmax softmax函数来获取值的权重。

在实践中,我们同时对一组查询计算注意力函数,将它们打包成矩阵Q。键和值也被打包成矩阵K和V。我们通过以下方式计算输出矩阵:

A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k V ) Attention(Q, K, V )= softmax(\frac{QK^T}{\sqrt{d_k}}V) Attention(Q,K,V)=softmax(dk QKTV)

最常用的两种注意力函数是加性注意力点积(乘法)注意力

  • 点积注意力与我们的算法完全相同,唯一的区别是缩放因子 1 d k \frac{1}{\sqrt{d_k}} dk 1
  • 加性注意力使用具有单个隐藏层的前馈神经网络来计算相似度函数

虽然这两种函数在理论复杂度上相似,但点积注意力在实践中更快速和更节省空间,因为它可以使用高度优化的矩阵乘法代码来实现

  • d k d_k dk 的值较小时,这两种机制的表现相似,
  • 但对于较大的 d k d_k dk值,加性注意力机制优于没有缩放的点积注意力机制[3]。

我们猜测对于较大的 d k d_k dk 值,点积的结果变得非常大,将 softmax 函数推向梯度极小的区域[4]。为了抵消这种影响,我们通过 1 d k \frac{1}{\sqrt{d_k}} dk 1 来缩放点积的结果。

3.2.2 Multi-Head Attention

多头注意力

我们发现,与使用 d m o d e l d_{model} dmodel维度的单个注意力函数相比,使用不同的学习线性投影查询、键和值线性投影到 d k d_k dk d k d_k dk d v d_v dv 维度上 h h h 次,对于性能是有益的。在每个投影版本(projected versions )的查询、键和值上,我们并行执行注意力函数,得到了 d v d_v dv 维度的输出值。这些值被串联起来,然后再次进行投影,得到最终的值,如图 2 所示。

多头注意力允许模型同时关注来自不同表示子空间在不同位置的信息。使用单个注意力头会抑制这种效果。

M u l t i H e a d ( Q , K , V ) = C o n c a t ( h e a d 1 , . . . , h e a d h ) W O MultiHead(Q, K, V ) = Concat(head _1 , ..., head _h )W^O MultiHead(Q,K,V)=Concat(head1,...,headh)WO
w h e r e h e a d i = A t t e n t i o n ( Q W i Q , K W i K , V W i V ) where head i = Attention(QW_i ^Q , KW _i ^K , V W _i ^V ) whereheadi=Attention(QWiQ,KWiK,VWiV)
其中, W i Q ∈ R d m o d e l × d k , W i K ∈ R d m o d e l × d k , W i V ∈ R d m o d e l × d v W_ i ^Q ∈ R^{d_{model} × d_k} , W_ i ^K ∈ R^{d_{model} × d_k} , W_ i^ V ∈ R^{d_{model} × d_v} WiQRdmodel×dk,WiKRdmodel×dk,WiVRdmodel×dv and W O ∈ R h d v × d m o d e l W ^O ∈ R^{ hd_v ×d_{model} } WORhdv×dmodel

在这项工作中,我们使用了 h = 8 h = 8 h=8个并行的注意力层,也就是头部(heads)。对于每个头部,我们使用了 d k = d v = d m o d e l / h = 64 d_k = d_v = d_{model} /h = 64 dk=dv=dmodel/h=64。由于每个头部的维度减小,总的计算成本具有完整维度的单头注意力相似。

3.2.3 Applications of Attention in our Model
Transformer模型在三个不同的方式中使用多头注意力:

  • 在“编码器-解码器注意力”层中,**查询(queries )来自前一个解码器层,而记忆键( memory
    keys)值(values)**来自编码器的输出。这使得解码器中的每个位置都可以关注输入序列中的所有位置。这模拟了序列到序列模型中典型的编码器-解码器注意力机制,例如
    [38, 2, 9]。

  • 编码器包含自注意力层。在自注意力层中,所有的键、值和查询来自同一个位置,即编码器中前一层的输出。编码器中的每个位置都可以关注编码器前一层的所有位置。

  • 同样,解码器中的自注意力层允许解码器中的每个位置关注解码器中的所有位置,直到该位置。我们需要防止在解码器中出现左向信息流(leftward
    information flow),以保持自回归的性质(the auto-regressive property)。

    我们在缩放点积注意力中通过屏蔽(将值设为 -∞)对应于非法连接的所有输入值来实现。参见图2。

3.3 Position-wise Feed-Forward Networks

除了注意力子层之外,我们的编码器和解码器中的每个层都包含一个全连接的前馈网络,它分别对每个位置进行相同的处理。这个前馈网络由两个线性变换组成,它们之间有一个 R e L U ReLU ReLU激活函数。
F F N ( x ) = m a x ( 0 , x W 1 + b 1 ) W 2 + b 2 FFN(x) = max(0, xW _1 + b _1 )W _2 + b _2 FFN(x)=max(0,xW1+b1)W2+b2
在不同位置上,尽管线性变换是相同的,但它们使用的参数会在各个层之间不同。可以将其描述为具有核大小为1的两个卷积。输入和输出的维度为 d m o d e l = 512 d _{model} = 512 dmodel=512,而内部层的维度为 d f f = 2048 d_{ f f }= 2048 dff=2048

3.4 Embeddings and Softmax

与其他**序列转换模型(sequence transduction models)类似,我们使用学习到的嵌入(embeddings)将输入标记(input tokens )输出标记(output tokens)**转换为维数为 d m o d e l d _{model} dmodel的向量。我们还使用常规的学习到的线性变换和softmax函数将解码器输出转换为预测的下一个标记的概率。在我们的模型中,我们在两个嵌入层和预softmax线性变换之间共享相同的权重矩阵,类似于[30]。在嵌入层中,我们将这些权重乘以 d m o d e l \sqrt{d _{model}} dmodel

3.5 Positional Encoding

位置编码

由于我们的模型不包含循环和卷积,为了让模型利用序列的顺序,我们需要注入一些关于相对或绝对位置的信息。为此,我们将“位置编码(positional encodings)”添加到编码器和解码器堆栈底部(at the bottoms of the encoder and decoder stacks.)的输入嵌入中。位置编码具有与嵌入相同的模型维度 d m o d e l d _{model} dmodel,因此可以将两者相加。关于位置编码,有很多选择,可以是可学习的,也可以是固定的[9]。
在这里插入图片描述
表1:不同层类型的最大路径长度、每层复杂性和最小顺序操作次数。n是序列长度,d是表示维数,k是卷积的核大小,r是限制自注意中邻域的大小。

在这项工作中,我们使用不同频率的正弦和余弦函数:
P E ( p o s , 2 i ) = s i n ( p o s / 1000 0 2 i / d m o d e l ) P E _{(pos,2i)} = sin(pos/10000 ^{2_i/d_{model} }) PE(pos,2i)=sin(pos/100002i/dmodel)
P E ( p o s , 2 i + 1 ) = c o s ( p o s / 1000 0 2 i / d m o d e l ) P E_{ (pos,2i+1) }= cos(pos/10000 ^{2_i/d_{model} } ) PE(pos,2i+1)=cos(pos/100002i/dmodel)

其中 p o s pos pos是位置(position), i i i 是尺寸(dimension)。也就是说,位置编码中的每个维度对应于一个正弦波。波长从 2 π 2π 2π 10000 ⋅ 2 π 10000·2π 100002π形成了一个几何级数(a geometric progression)。我们选择了这个函数,是因为我们假设它可以让模型更容易学会通过相对位置进行注意力,因为对于任何固定的偏移量 k , P E p o s + k k,P E_{pos+k} kPEpos+k 可以表示为 P E p o s P E_{pos} PEpos的线性函数。

我们也尝试使用学习的位置嵌入 [9],并发现这两个版本的结果几乎相同(参见表3行(E))。我们选择了正弦版本,因为它可能允许模型对训练期间遇到的序列长度之外的序列长度进行外推。

4 Why Self-Attention

为什么使用自注意力机制

在这一部分中,我们将自注意力层与常用的用于将一个变长符号表示序列 ( x 1 , . . . , x n ) (x _1 , ..., x_ n ) (x1,...,xn)映射到另一个等长序列$(z_1 , …, z _n ) 的循环和卷积层进行比较,其中 x i , z i y ∈ R d x _i , z_i y∈ R^d xi,ziyRd,例如典型的序列转换编码器或解码器中的隐藏层。我们考虑到以下三个要点来说明我们使用自注意力的原因。

第一个要点是每层的总计算复杂度第二个要点是可以并行计算的计算量,即所需的最小顺序操作数量。

第三个要点是网络中长程依赖的路径长度。学习长程依赖是许多序列转换任务中的一个关键挑战。影响学习此类依赖的一个关键因素是前向和后向信号在网络中必须穿越的路径长度。这些路径在输入和输出序列的任意组合位置之间越短,学习长程依赖就越容易[12]。因此,我们还比较由不同层类型组成的网络中任意两个输入和输出位置之间的最大路径长度。

如表1所示,自注意力层将所有位置连接到一个常数数量的顺序执行操作,而循环层则需要 O ( n ) O(n) O(n)个顺序操作。在计算复杂度方面,当序列长度n小于表示维度d时,自注意力层比循环层更快,而这通常是机器翻译中现有模型使用的句子表示形式,例如词元和字节对表示法。为了提高处理非常长序列的任务的计算性能,自注意力可以限制只考虑大小为 r r r的邻域。输入序列围绕相应输出位置进行了居中处理。这将增加最大路径长度为 O ( n / r ) O(n/r) O(n/r)。我们计划在未来的工作中进一步研究这种方法。

一个宽度为k < n的单个卷积层无法连接所有的输入和输出位置。这需要一个 O ( n / k ) O(n/k) O(n/k)的卷积层堆栈,在连续内核的情况下,或者在扩张卷积[18]的情况下,需要 O ( l o g k ( n ) ) O(log_ k (n)) O(logk(n)),从而增加网络中任意两个位置之间最长路径的长度。卷积层的复杂性通常比递归层高,有一个因子k。然而,可分离卷积[6]可以显著降低复杂性,达到 O ( k ⋅ n ⋅ d + n ⋅ d 2 ) O(k · n · d + n · d ^2 ) O(knd+nd2)。然而,即使当 k = n k = n k=n时,可分离卷积的复杂性仍然等于自注意层和逐点前馈层的组合,这是我们模型中采用的方法。

作为附加好处,自注意力可以产生更可解释的模型。我们检查模型的注意力分配,并在附录中提供和讨论示例。不仅每个注意头明显学会了执行不同的任务,许多注意头似乎还展现出与句子的句法和语义结构相关的行为。

5 Training

本节描述了我们模型的训练制度。

5.1 Training Data and Batching

我们在标准的WMT 2014英德数据集上进行了训练,该数据集包含约450万个句子对。句子使用字节对编码进行编码[3],其中共享的源-目标词汇表约为37000个标记。对于英法语言对,我们使用了数量显着更大的WMT 2014英法数据集,其中包含3600万个句子,并将标记分为一个32000个词片词汇表[38]。句子对按照近似的序列长度进行分组。每个训练批次包含一组句子对,其中包含大约25000个源标记和25000个目标标记。

5.2 Hardware and Schedule

我们使用了一台装有8个NVIDIA P100 GPU的机器来进行模型训练。对于我们的基本模型,使用了本文中描述的超参数,每个训练步骤大约需要0.4秒的时间。我们对基本模型进行了总计100,000步或者12小时的训练。对于大型模型(在表格3最后一行中描述),每个训练步骤需要1.0秒的时间。大型模型进行了总计300,000步或者3.5天的训练。

5.3 Optimizer

我们使用了Adam优化器[20],其中 β 1 = 0.9 , β 2 = 0.98 , ε = 1 0 − 9 β_1 = 0.9,β_2 = 0.98,ε = 10^-9 β1=0.9β2=0.98ε=109。根据以下公式,我们在训练过程中变化学习率:
l r a t e = d − 0.5 , m i n ( s t e p n u m − 0.5 , s t e p n u m ⋅ w a r m u p s t e p s − 1.5 ) lrate = d^{ −0.5}, min(step_num ^{-0.5},step_num · warmup_steps^{-1.5}) lrate=d0.5,min(stepnum0.5,stepnumwarmupsteps1.5)

这指的是在前 warmup_steps 次训练步骤中线性增加学习率,然后随着步骤数量的逆平方根成比例地递减学习率。我们使用了 w a r m u p s t e p s = 4000 warmup_steps = 4000 warmupsteps=4000

5.4 Regularization

我们在训练过程中采用了三种类型的正则化方法:

残差Dropout:我们对每个子层的输出应用了Dropout [33],在将其添加到子层输入并归一化之前。此外,在编码器和解码器堆栈中,我们也对嵌入和位置编码的总和应用了Dropout。对于基本模型,我们使用的Dropout率为 P d r o p = 0.1 P_drop = 0.1 Pdrop=0.1
在这里插入图片描述
表2:Transformer在2014年英语到德语和英语到法语新闻测试中获得了比以前最先进的型号更好的BLEU分数,而培训成本只是其中的一小部分。

(以下是ChatGpt生成的解释,大家可以看一下。)
该表格列出了各种神经机器翻译模型在英德和英法数据集上的BLEU分数以及它们的训练成本(以浮点运算次数FLOPs计算)。下面是对表格的分析:

  • ByteNet是一种基于卷积神经网络的翻译模型,它在英德数据集上达到了23.75的BLEU分数。该模型的训练成本并未给出。
  • Deep-Att + PosUnk是一种使用注意力机制和位置未知标记的模型,它在英法数据集上达到了39.2的BLEU分数。该模型的训练成本为1.0·1020 FLOPs。
  • GNMT + RL是一种使用增强学习训练的Google神经机器翻译系统,它在英德数据集上达到了24.6的BLEU分数,在英法数据集上达到了39.92的BLEU分数。该模型的训练成本分别为2.3·1019 FLOPs和1.4·1020 FLOPs。
  • ConvS2S是一种基于卷积神经网络的翻译模型,它在英德数据集上达到了25.16的BLEU分数,在英法数据集上达到了40.46的BLEU分数。该模型的训练成本分别为9.6·1018 FLOPs和1.5·1020 FLOPs。
  • MoE是一种使用多层感知机(MLP)的模型,它在英德数据集上达到了26.03的BLEU分数,在英法数据集上达到了40.56的BLEU分数。该模型的训练成本分别为2.0·1019 FLOPs和1.2·1020 FLOPs。
  • Deep-Att + PosUnk Ensemble是Deep-Att + PosUnk模型的集成版本,它在英法数据集上达到了40.4的BLEU分数。该模型的训练成本为8.0·1020 FLOPs。
  • GNMT + RL Ensemble是GNMT + RL模型的集成版本,它在英德数据集上达到了26.30的BLEU分数,在英法数据集上达到了41.16的BLEU分数。该模型的训练成本分别为1.8·1020 FLOPs和1.1·1021 FLOPs。
  • ConvS2S Ensemble是ConvS2S模型的集成版本,它在英德数据集上达到了26.36的BLEU分数,在英法数据集上达到了41.29的BLEU分数。该模型的训练成本分别为7.7·1019 FLOPs和1.2·1021 FLOPs。
  • Transformer是一种基于自注意力机制的翻译模型,包括base model和big model两个版本。其中,base model在英德数据集上达到了27.3的BLEU分数,在英法数据集上达到了38.1的BLEU分数。它的训练成本为3.3·1018 FLOPs。big model在英德数据集上达到了28.4的BLEU分数,在英法数据集上达到了41.8的BLEU分数。它的训练成本为2.3·1019 FLOPs。

综合来看,根据BLEU分数的表现,Transformer模型的big版本在英法翻译任务上达到了最佳性能。但是,GNMT + RL Ensemble和ConvS2S Ensemble在英法翻译任务中也表现出色。总的来说,这些模型都有不同的训练成本,选择适合任务需求和计算资源的模型将是一个权衡。

Label Smoothing During training, we employed label smoothing of value ls = 0.1 [36]. This hurts perplexity, as the model learns to be more unsure, but improves accuracy and BLEU score.
标签平滑化: 在训练过程中,我们采用了标签平滑化,其中平滑值 l s = 0.1 ls = 0.1 ls=0.1 [36]。这会降低困惑度,因为模型学会变得更加不确定,但可以提高准确率和BLEU分数。

6 Results

这部分大家可以自己看一下,不属于论文核心内容,我就不翻译了

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值