【预训练语言模型】第 1 章:模型基础知识

 🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎

📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​

📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】  深度学习【DL】

​​

 🖍foreword

✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。

如果你对这个系列感兴趣的话,可以关注订阅哟👋

文章目录

预训练

One-Hot 表示

计数向量(Count Vector)

TF-IDF 向量化

什么是词嵌入?

词嵌入的不同方法

Word2vec

CBOW

 skip gram

GloVe 

句子嵌入(Sentence Embeddings)

ELMo

通用句编码器(Universal Sentence Encoder)

BERT

BERT 基础模型

结论


文档分类、情感分析、聚类和文档摘要等 NLP 任务需要处理和理解文本数据。这些任务的实施取决于人工智能系统如何处理和理解数据。这样做的一种方法是使用一些统计方法,如词频-逆文档频率(TF-IDF)、计数向量等,将文本表示转换为数值形式,但这些方法不考虑句子的含义并且只处理句子中单词的出现。

随着时间的推移,已经开发了几种语义方法,如解析树、上下文语法、本体等,但这些方法需要大量的人力来准备标记的训练数据。在过去的几年里,计算能力的广泛可用性使得使用基于神经网络的方法来完成这些任务成为可能。

预训练

预先训练

我们有两个相似的任务 A 和 B,任务 A 已经完成了得到了一个模型 A

任务 B(数据量小)

用到了一个特性:CNN 浅层参数通用

任务 B 就可以使用模型 A 的浅层参数,后面的参数通过任务 B 训练--》1. 冻结(浅层参数不变)2. 微调(变)

任务 B(大数据)可以训练出模型 B(我还可以使用模型 A 的浅层参数,节省训练时间,节省成本)

One-Hot 表示

One-hot表示是文本表示的最常见和最基本的方法之一。它涉及使用二进制编码(即 0 和 1)来表示单词。它也可以用于分类属性的表示。

例如,假设数据集将颜色作为特征之一,具有三个可能的值:红色、蓝色和绿色。因此,此功能将转换为三个新列,每个颜色值一个,如下所示。

红色

蓝色

绿色

1

1

0

0

2

0

1

0

3

0

0

1

例如,第一个数据点在 红色 列中的值为 1,在其他列中为 0。这意味着最初该数据点具有 红色 颜色列的值。红色在 one-hot 编码中表示为 [1 0 0],蓝色 1 占据第二位,绿色 1 占据第三位。这是一个三维向量。one-hot 表示扩展了特征向量,因为颜色的每个类别现在本身就是一个特征。

现在,当我们谈论文本句子的 one-hot 编码时,它不关心句子中单词的出现顺序,实际上忽略了单词的语义含义。这种方式在语料比较小,需要用到一些传统的 NLP 方法的场景下效果最好。

例如,要使用 one-hot 表示来表示文本句子,请遵循以下步骤。

  1. 计算语料库中存在的唯一单词的总数。

  2. 根据单词是否出现在句子中,分配 0 或 1。 

考虑一下“今天天空晴朗”这句话。词汇包括诸如The、sky、is、clear和today等词。如图1-1所示的 one-hot 表示形式表示,它会形成一个五维向量。

 图1-1  One-hot 表示

计数向量(Count Vector)

在上一节中,我们看到了如何根据单词的出现而不是根据它们的出现频率来生成句子的 one-hot 表示。单个句子的计数向量是根据特定单词在句子中出现的次数生成的。语料库中的独特词构成了词汇表。

例如,考虑这两个句子。

  • 句子 1: The blue bird is flying in the clear blue sky.

  • 句子 2: The sky is clear today.

该语料库有两个句子,词汇集 [bird, blue, flying, is, in, the, sky, clear, today] 包含九个术语。对于词汇集中的每个单词,它在句子中的出现频率是确定的。这样就形成了对应于那个句子的计数向量。从这些代表句子的计数向量中,我们得到计数矩阵。此处显示了两个例句的计数矩阵。

is

bird

blue

flying

In

the

sky

clear

today

Sentence 1

1

1

2

1

1

2

1

0

0

Sentence 2

1

0

0

0

0

1

1

1

1

矩阵中的行代表句子,列表示矩阵中相应单词的单词向量。矩阵的大小为 S × T,其中 S 是句子的数量,T 是术语或单词的数量。

句子的计数向量表示有助于我们完成多项任务,包括:

  • 确定句子之间的相似性

  • 查询相关文件的识别

  • 文件摘要

作为一个例子,我们展示了如何在数学上计算句子之间的相似性。句子 1 的计数向量是 [1 1 2 1 1 2 1 0 0],句子 2 的计数向量是 [1 0 0 0 0 1 1 1 1]。余弦相似度可以使用以下数学表达式计算。

Sim =

 

这里,xy是两个计数向量。|| x || 是向量x的欧几里得范数。

所以,

||x|| = ​ = 3.60

||y|| = ​ = 2.24

Sim = 4/ (3.6 * 2.24) = 0.49

这个计算意味着这两个句子彼此相似,相似度得分为 49% (0.49)。相似度值总是介于 0 和 1 之间,其中 1 表示最大相似度,0 表示没有相似度

TF-IDF 向量化

One-hot表示和计数向量方法是最基本的方法,它们实际上不考虑特定单词在句子和语料库中的重要性。对于某些 NLP 项目(例如搜索引擎),了解查询中的单词对语料库中文档中的单词的重要性以确定文档与该查询的相关性非常重要。一些经常出现的英语单词(例如,“is”、“the”、“a”等)将出现在所有文档中。即使它们的数量更高,它们在执行与 NLP 相关的任务时也没有用。为了克服计数向量的这个缺点,使用了 TF-IDF。TF-IDF 是各种应用程序中最流行的技术之一,因为它能够对通常出现得更频繁的单词进行加权。

在 TF-IDF 中,我们以类似于之前方法的方式形成词汇表。词汇表由整个语料库中的唯一单词组成。现在为词汇集中的每个单词计算词频。词或词 t 的词频 (TF) 对应于它在文档中出现的所有次数 d 对应于文档中词的数量。

TF = (词条 t 在文档中出现的次数 / 文档中词条的数量)

我们通过计算存在该术语的文档数来计算逆文档频率 (IDF) 。IDF 告诉我们一个术语或单词提供了多少信息。它会告诉您一个词是否在所有文档中通用。IDF 是文档总数与出现术语 t 的文档数之比的对数值。

IDF = log(N/n)   其中 N 是语料库中的文档总数,n 是出现术语 t 的文档数

TF-IDF 是 TF 和 IDF 的产物。

TF-IDF (t, document) = TF (t, document) * IDF(t)

例如,让我们使用前面的两个例句,其中 句子1 和 句子 2 对应两个文档。

句子 1 中单词“blue”的 TF = 2

IDF = log (2/1) = 0.3

句子 1 中单词“blue”的 TF-IDF = 2*0.3 = 0.6

类似地,句子 2 中单词“is”的 TF-IDF 值为 0,因为它的 IDF 分数为 0。这意味着单词“is”没有任何重要性,因为它在所有文档中都很常见。

TF-IDF 、计数向量和 one-hot 编码等方法很容易计算,但它们不能捕获文档中的语义(或单词出现的顺序)。使用这些方法表示的单词或句子不提供任何上下文信息。尽管可以使用它们执行许多 NLP 任务,但总体结果是平庸的,尤其是在训练数据稀疏的情况下。因此,需要一种更好的技术来捕获有用的语言信息,同时提高几乎所有 NLP 问题的泛化能力和性能。

在下一节中,我们将讨论一种这样的方法,即词嵌入,其中词的向量表示包含上下文信息。

什么是词嵌入?

词嵌入是一种词表示,其中词嵌入到实数向量中。嵌入可以通过神经网络、概率模型或单词共现矩阵的降维等方法生成,如图1-2所示。它们使机器学习算法能够理解具有相似含义的单词。

图1-2 词嵌入

与one-hot 表示相比,词嵌入通常是低维(通常为 50-600 维)和密集的词或句子表示 。当使用 one-hot 表示时,特征向量随着词汇集的大小而增加。另一方面,词嵌入更有效。他们有概括的能力。语义相似的词更有可能具有相似的向量表示。因此,与 one-hot 表示相比,这些向量在与 NLP 任务(例如文档摘要、句子或文档相似性等)一起使用时将为您提供更相关的结果。

词嵌入也称为分布式表示或分布式语义模型或​​语义向量空间。这里的“语义”一词突出了词嵌入的重要性,因为它旨在将具有相似含义的词分类在一起。例如,网球、足球和游泳等运动应该放在靠近的地方,而与动物相关的词则远离这些词。在更广泛的意义上,词嵌入将创建与运动相关的词的向量表示,这些向量表示将远离动物词的向量表示。主要目标是让具有相似上下文的单词占据最近的空间位置。

嵌入通常是在较低维度上确实表示单词的向量。神经网络目前也被用于生成词的嵌入。它提高了从最后一组文本数据中学习或概括表示的能力。神经网络模型可以学习有关词汇集中单词的丰富特征,​​同时降低文本数据的维度。词嵌入被证明在 NLP 任务、文本分类、文档聚类等方面非常有用。有各种可用的神经网络词嵌入模型,例如 Word2vec、GloVe、ELMo 和 BERT,其中 BERT 已被证明是目前最先进的 NLP 任务的最佳选择。

词嵌入的不同方法

有不同的方法来生成词的嵌入,并且它们的实现方法不同。接下来我们将详细讨论其中的一些。

Word2vec

Word2vec是一种浅的、两层的词嵌入神经网络技术,其中词在向量空间中表示。在输入层和输出层之间只有一个隐藏层的神经网络称为浅层神经网络。Word2vec 是一个两层网络,一个输入层,一个隐藏层和一个输出层。它以文本语料库作为输入,并给出一组向量作为输出。特征向量表示语料库的单词。表示词的向量称为神经词嵌入。

该向量表示维护文档或语料库中单词之间的语义关系。具有相似含义的词将在向量空间中彼此非常靠近,而不同的词则位于很远的地方。语义关系是通过 Word2vec 重构单词的语言上下文来实现的。语境可以理解为句子的主要目标。例如,在“今天是几号?”这句话中,一个人想知道今天的日期,这实际上是句子的上下文。主要上下文可以通过语言周围的单词和句子来揭示。当给定足够的文本语料库时,可以在 Word2vec 的帮助下准确猜测一个词与其他词的关联。

Word2vec 能够针对输入文本数据中的相邻单词训练单词。它可以通过两种方式实现:连续词袋(CBOW)和skip gram。这是 Word2vec 的两个实现,用于创建词嵌入表示。在 CBOW 中,上下文用于预测目标词,而在 skip gram 中,一个词用于预测目标上下文。

CBOW

CBOW架构 尝试使用上下文窗口词来预测目标词。中心词或目标词是在周围词或源上下文词的帮助下预测的。Word2vec 模型是无监督模型,这意味着我们只需要提供输入语料库,而不需要任何关于输出的额外信息。为了获得 CBOW 词嵌入,该模型遵循监督分类方法,将语料库作为输入 X 并预测目标词 Y。

神经网络的输入将是给定窗口大小中上下文词的 one-hot 编码向量的总和。对数损失函数将用作损失函数。

softmax 函数被用作最后一层的激活函数。这将为您提供所有单词的概率分布。softmax 函数的方程如下所示:

例如,考虑“This beautiful painting belongs to Queen Elizabeth. ”这句话。以下是一些考虑到上下文窗口大小为 2 的训练数据示例。
  • [(painting, belongs), Queen Elizabeth]

  • [(This, beautiful), painting].

输入层将具有上下文词的单热表示(即“This”和“beautiful”),输出层将显示语料库中所有词的概率分布,其中“painting”一词的概率分数将为最高的一个。

图1-3显示了 Word2vec嵌入 的两种变体的架构。
图 1-3  CBOW 和 skip gram模型的架构

 skip gram

skip gram 模型是一种无 监督学习技术,可以在目标词周围找到最相关的词。在这种情况下,使用目标词预测词。它与 CBOW 方法相反。这里目标词是输入,上下文词是输出。这是一种相对困难的技术,因为要预测多个上下文词。从 skip gram 模型架构(图1-3)中可以看出,输入是目标词 W(t),输出是上下文词的向量表示。

这通常按照以下方法计算。这个输入向量和权重矩阵之间的点积是由一个隐藏层得到的。类似地,在输出层中,在隐藏层的输出向量和输出层的权重矩阵之间计算点积。然后使用 softmax 激活函数计算单词在 W(t) 上下文中的概率。

隐藏层是权重矩阵,其中行对输出词有贡献。例如,如果权重矩阵的维度为 4 × 4,并且输入是 one-hot 编码词,那么将从与输入向量中的那个对应的矩阵中选择一行。

[0 0 1 0] ×  = [6 15 3 2]

这个词向量是在隐藏层被馈送到输出层之后获得的,输出层产生介于 0 和 1 之间的输出。输出层是一个 softmax 回归分类器,它给出了输出词在输入附近的上下文位置 的概率目标词。

图1-4显示了使用 skip gram 的词嵌入示例。

图 1-4  神经网络架构

GloVe 

GloVe(全局向量) 是一种无监督技术,用于全局语料库中单词的向量表示。词向量是通过考虑语料库的全局和局部统计数据获得的。局部统计对应于词的局部上下文信息,而全局统计由词共现捕获。

尽管 Word2vec 的性能相当令人满意,但仍然需要一种更好的方法,因为 Word2vec 只考虑周围的单词,这有时可能无法捕捉到单词与其他单词的有用关系。在 Word2vec 的情况下学习的语义只依赖于本地信息,并受相邻单词的影响。另一方面,在 GloVe 中,可以借助整个语料库的结构来获得单词的含义。这构成词频和同现计数。该模型主要依赖于直觉,即单词到单词的共现概率可以有助于编码某种形式的含义,从而使其比 Word2vec 具有额外的优势。

GloVe 在这些聚合的全局词-词共现统计数据上进行训练,并最大限度地减少最小二乘误差。这导致了词向量空间的有意义的线性子结构。例如,“男人”和“女人”在都描述人类的上下文中是相似的,但这两个词也是对立的。为了尽可能多地捕捉这两个词所指定的含义,我们需要一个更大的信息语料库。这两个词的区分是基于性别的,可以通过其他词对来指定,例如丈夫-妻子、兄弟-姐妹等。

句子嵌入(Sentence Embeddings

词嵌入 通过只考虑相邻词而不考虑其他句子来生成词的向量表示。为了捕捉句子之间的关系,句子嵌入是最好的方法。这些是文档中句子的向量表示。句子嵌入模型是必不可少的,因为它们能够捕获词嵌入模型无法捕获的上下文信息。如前所述,词嵌入表示句子或对话中词的含义。它们是 N 维向量空间中单词的表示。然而,这些方法往往会忽略必要的信息,如下面的示例所述。

两个句子可以具有相同的表示但完全不同的含义。例如:
  • 句子1: The sky is clear not cloudy today.

  • 句子2:The sky is cloudy not clear today.

在这里,句子 1 和句子 2 具有相似的表示,但它们的含义完全不同。词嵌入将无法区分这两个句子,因为这些句子中存在的词的向量表示几乎相同。句子嵌入可用于实现这种区分。

在 ML 管道中处理文本数据时,我们确实需要计算句子嵌入,以便我们能够将完整的句子嵌入到向量空间中。句子嵌入可以捕获句子之间的语义相似性或相关性,然后是段落,然后是文档。

一个句子的句子嵌入可能如下所示:
  • “The bird is flying in sky.” – [0.1, 0.7,0.4, ...]

要为一个句子生成句子嵌入,最基本的方法是对该句子中存在的所有单词执行词嵌入的平均值。

词嵌入的加权平均可用于获得句子嵌入并降低维度。除了这种方法之外,还引入了其他方法,例如 Universal Sentence Encoder 和 ELMo,它们对 NLP 相关任务 非常有用。

ELMo

ELMo (Embeddings from Language Models) 是一种深度上下文化的词嵌入。它由艾伦人工智能研究所于 2018 年开发。ELMo 使用深度双向 LSTM 模型来创建单词表示。两层双向语言模型的内部状态计算嵌入。它能够捕捉句子中单词的上下文含义变化,如图 1-5 所示。

图 1-5  ELMo 架构

与 Word2vec 不同,ELMo 会在使用它们的上下文中分析单词。它不会为单词字典创建向量;相反,向量是通过将文本传递给深度学习模型来创建的。单词的表示取决于传递给模型的整个句子语料库。它不为每个单词使用固定的嵌入;相反,在将嵌入分配给一个单词之前会查看整个句子。它能够理解单词的含义以及它所在的上下文。因此,它能够捕获含义以及上下文信息。与单词相关的上下文信息可能会根据使用该单词的句子而有所不同。这使它比 Word2vec 和 GloVe 更具优势。预训练的语言嵌入,当添加到现有模型中时,

ELMo 是基于字符的:它将字符而不是单词作为输入,这使得它能够为训练 期间未见过的单词计算有意义的表示。当在大型数据集上进行训练时,它还能够学习语言模式,这对与 NLU 相关的任务很有帮助,例如确定短语中的下一个单词。例如,在短语“今天天气多云,它可能……”中,“雨”这个词更可能出现,而不是“狗”这个词。该模型在此类场景中非常有用,可以根据上下文找到最可能的单词,如图1-6所示。

图 1-6 “blue”一词的 ELMo 特定表示

ELMo模型 是一个相当复杂的神经语言模型,它试图计算一个单词的概率,给定一些之前看到的单词历史。ELMo 架构(参见图1-5) 有一个两层的双向 LSTM 作为其主干。这种两层双向 LSTM 模型有助于模型理解句子中的下一个单词以及前一个单词。第一层和第二层由残差连接连接,当该层馈送到下一层并直接跳到层中时,这些连接可以跳过一个或多个层。它们用于使更深层次的网络更容易优化。在 ELMo 语言模型中,每个标记都使用字符嵌入转换为适当的表示。我们使用一维 CNN 获得这些字符级嵌入,以获得单词的数字表示。即使对于不在词汇集中的单词,这也允许有效的表示。然后使用各种数量和类型的过滤器通过卷积层。最后,在作为 LSTM 层的输入之前,它通过一个两层的高速网络。这种高速公路网络可以通过输入实现更顺畅的信息传输。这些对输入标记的转换允许选择形态特征、n-gram 特征等。这有助于建立强大的句子表示。

让我们假设我们正在查看输入中的第 i 个单词。以图1-5 为参考,单词“blue”的 ELMo 表示是转换后的单词表示 x i以及两个双向表示 h 1i和 h 2i的输出的组合。函数 f 对输入执行以下操作。

ELMo i task = γi . (s0 task . xi + s1 task . h1, i + s2 task . h2, k)

这里,γ i 和 s k是在特定任务模型中学习的权重因子。因此,当我们使用 ELMo 时,我们冻结权重,然后将每个标记的 ELMo i 任务连接到输入表示 。

通用句编码器(Universal Sentence Encoder

最近推出了Universal Sentence Encoder ,它已成为最流行的句子嵌入预训练模型之一。它能够将句子转换为向量表示。这种通用的句子嵌入模型可以学习丰富的语义信息,从而使用迁移学习,可以通过重新训练架构的最后一层来学习来自其他任务的句子表示。

这个句子编码器模型可以用于各种各样的 NLU 任务。编码器使用的变压器网络是在一个庞大的、多样化的数据语料库上训练的。输入文本(可以是句子、短语或短段落)被编码为高维向量。在这里,输入长度可以是可变的,但输出是一个 512 维的向量。这使得为​​广泛的下游任务(如文本分类、聚类、语义相似性等)生成句子嵌入。

TensorFlow hub 上提供了这些模型的多个版本和实现,这些模型已由 Google 使用 Tensorflow 进行训练,供 ML 工程师使用,包括这些。
  • universal-sentence-encoder-large

  • universal-sentence-encoder-lite

  • universal-sentence-encoder-multilingual

  • universal-sentence-encoder-multilingual-large

  • universal-sentence-encoder-multilingual-qa

BERT

Google 的研究人员介绍了来自 Transformers 的双向编码器表示 (BERT)。用于语言建模的双向转换器使 BERT 在各种 NLP 任务以及问答中都很受欢迎。这使得它不同于以前的模型,其中序列仅在一个方向上进行,从左到右或从右到左。

双向编码器采用两个序列进行编码,一个是正常序列,另一个是相反的序列。它由两个编码器组成,用于对两个序列进行编码。对于最终输出,两个编码结果都被考虑在内。语言模型的双向训练让他们更深入地了解语言的上下文。这对于理解文本的含义确实很重要,如图3-7所示。

例如,考虑以下两个句子:
  • 句子1:I got scared on seeing a bat flying in my room.

  • 句子2: The player held the bat firmly while smashing a ball with it.

在这里,“蝙蝠”一词在两个句子中具有不同的含义,具体取决于语言上下文。如果我们从两个方向接近句子,这一点会更好地理解。如果我们只朝一个方向移动,我们可能会错过有用的信息,并且可能无法正确获得含义。BERT 会同时考虑前后上下文,从而在做出任何预测之前减少出错的机会。训练时从两个方向收集信息,并且在所有层中共同调节来自两个方向的上下文。

图 1-7  BERT架构
只需修改输出层,预训练的 BERT 模型就可以用于各种最先进的任务。它不需要任何特定于任务的架构更改。它使用转换器来掌握文本中标记或单词的关系。变压器包括编码器和解码器。编码器读取输入文本,解码器帮助生成任务预测。Transformer 编码器能够一次读取整个单词序列,而不是从左到右顺序读取。这使得模型是双向的,并允许它从左右两侧学习单词或标记的上下文。输入到转换器的标记序列被嵌入到向量中,然后向量在神经网络中进一步处理。网络的输出是输入token对应的向量序列,如图1-8 所示。
图 1-8  BERT transformer

BERT 使用两种策略来超越单向约束。BERT 在这两个 NLP 任务上进行了预训练:掩码语言建模 (MLM)和下一句预测 (NSP)。MLM 通过从输入文本中随机屏蔽标记来帮助预训练双向转换器,而 NSP 任务联合预训练文本对表示。BERT 在训练期间最小化了这两个任务的组合损失函数。

要使用 BERT,需要遵循两个阶段:
  1. 预训练:在这一步中,模型通过不同的预训练任务在未标记的数据上进行训练。
     
  2. 微调 使用预训练参数初始化 BERT 模型,然后使用来自下游任务的数据进行微调,这可能是分类、问答等。
     

BERT 模型有两种实现方式,BERT 基础模型和 BERT 大型模型。

BERT 基础模型

BERT基础模型 是一个预训练的 BERT 模型,它有 12 层或变换器块,每层有 768 个隐藏单元,以及 1.1 亿个参数。根据它所训练的英文文本(大小写或非大小写),它可以进一步分为 BERT base-cases 和 BERT base-uncased,如图 1-9 所示。

图 1-9  BERT 基础模型和 BERT 大型模型

BERT 大型模型

BERT大模型 是一个预训练的 BERT 模型,它有 24 层或变换器块,每层有 1,024 个隐藏单元,以及 3.4 亿个参数。它还可以进一步分为 BERT large-cased 和 BERT large-uncased。该模型需要比 BERT 基础更多的内存。

结论

本章介绍了词嵌入、句子嵌入及其不同的实现方法,例如 Word2vec、GloVe、Universal Sentence Encoder 等。我们还讨论了 BERT 及其变体(即基本模型和大型模型)。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sonhhxg_柒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值