NLP基础学习6--神经网络基础

左手肿了两个手指,写博客敲代码这酸爽。。。 言归正传,这一次的学习开始转入神经网络,主要任务是:

  1. 前馈神经网络、网络层数、输入层、隐藏层、输出层、隐藏单元、激活函数的概念。
  2. 感知机相关;利用tensorflow等工具定义简单的几层网络(激活函数sigmoid),递归使用链式法则来实现反向传播。
  3. 激活函数的种类以及各自的提出背景、优缺点。(和线性模型对比,线性模型的局限性,去线性化)
  4. 深度学习中的正则化(参数范数惩罚:L1正则化、L2正则化;数据集增强;噪声添加;early stop;Dropout层)、正则化的介绍。
  5. 深度模型中的优化:参数初始化策略;自适应学习率算法(梯度下降、AdaGrad、RMSProp、Adam;优化算法的选择);batch norm层(提出背景、解决什么问题、层在训练和测试阶段的计算公式);layer norm层
    本章的内容主题参考了复旦大学邱锡鹏教授的大作《神经网络和深度学习》[3],在此特别致敬和感谢一下。

前馈神经网络

给定一组神经元,我们可以以神经元为节点来构建一个网络。不同的神经
网络模型有着不同网络连接的拓扑结构。一种比较直接的拓扑结构是前馈网络。
前馈神经网络(Feedforward Neural Network,FNN)是最早发明的简单人工神
经网络。
在前馈神经网络中,各神经元分别属于不同的层。每一层的神经元可以接
收前一层神经元的信号,并产生信号输出到下一层。第0 层叫输入层,最后一
层叫输出层,其它中间层叫做隐藏层。整个网络中无反馈,信号从输入层向输
出层单向传播,可用一个有向无环图表示。 一个简单的示意图如下:
前馈神经网络

前馈神经网络通过下面公式进行信息传播,
z ( l ) = W ( l ) ⋅ a ( l − 1 ) + b ( l ) z^{(l)} = W^{(l)} · a^{(l−1)} + b^{(l)} z(l)=W(l)a(l1)+b(l)
a ( l ) = f l ( z ( l ) ) a^{(l)} = f_l(z^{(l)}) a(l)=fl(z(l))
其中

  • L:表示神经网络的层数;
  • m ( l ) m^{(l)} m(l):表示第l 层神经元的个数;
  • f l ( ⋅ ) f_l(·) fl():表示l 层神经元的激活函数;
  • W ( l ) ∈ R m ( l ) × m ( l − 1 ) W^{(l)} \in R^{m^{(l)}×m^{(l−1)}} W(l)Rm(l)×m(l1):表示l − 1 层到第l 层的权重矩阵;
  • b ( l ) ∈ R m l b^{(l)} \in R^{m^l} b(l)Rml:表示l − 1 层到第l 层的偏置;
  • z ( l ) ∈ R m l z^{(l)} \in R^{m^l} z(l)Rml:表示l 层神经元的净输入;
  • a ( l ) ∈ R m l a^{(l)} \in R^{m^l} a(l)Rml:表示l 层神经元的输出

感知机相关

感知机模型是机器学习二分类问题中的一个非常简单的模型。它的基本结构如下图所示:
感知机
其实,感知机作为最简单的分类器,确实神经网络的基础。早期很多神经网络和机器学习的书都有很多讨论,包括其收敛性证明,推荐台湾的林轩田老师的机器学习基石的课,这一章讲的很细致。
这里我因为手疼的缘故,直接省去理论,贴代码了,最简单的minist手写识别,相当于神经网络的hello word


# coding: utf-8

# # 神经网络,TensorFlow示例
# 
# 两层(隐含层)全连接神经网络


# ## MNIST 数据库概览
# 
# MNIST手写数字数据集. 共有60,000张训练图片,10,000张测试图片. 所有图片已做过归一化与中心化,尺寸统一为28x28,像素值范围从0到1. 为了简单期间,输入时每张图片不以28x28的矩阵形式输入,而是按列排列,转为一维的长度为784=28x28的特征,输入神经网络。
# 
# ![MNIST 数据集](http://neuralnetworksanddeeplearning.com/images/mnist_100_digits.png)
# 
# 更多信息: http://yann.lecun.com/exdb/mnist/




# Import MNIST data,准备MNIST输入数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)

import tensorflow as tf



# Hyper Parameters,超参
learning_rate = 0.1
num_steps = 500
batch_size = 128
display_step = 100

# Network Parameters,网络参数
n_hidden_1 = 256 # 1st layer number of neurons
n_hidden_2 = 256 # 2nd layer number of neurons
num_input = 784 # MNIST data input (img shape: 28*28)
num_classes = 10 # MNIST total classes (0-9 digits)

# tf Graph input,TensorFlow图模型结构的输入定义
X = tf.placeholder("float", [None, num_input])
Y = tf.placeholder("float", [None, num_classes])


# Store layers weight & bias,定义需要学习的网络参数,即网络权值
weights = {
    'h1': tf.Variable(tf.random_normal([num_input, n_hidden_1])),
    'h2': tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
    'out': tf.Variable(tf.random_normal([n_hidden_2, num_classes]))
}
biases = {
    'b1': tf.Variable(tf.random_normal([n_hidden_1])),
    'b2': tf.Variable(tf.random_normal([n_hidden_2])),
    'out': tf.Variable(tf.random_normal([num_classes]))
}



# Create model,定义神经网络基本结构
def neural_net(x):
    # Hidden fully connected layer with 256 neurons
    layer_1 = tf.add(tf.matmul(x, weights['h1']), biases['b1'])
    # Hidden fully connected layer with 256 neurons
    layer_2 = tf.add(tf.matmul(layer_1, weights['h2']), biases['b2'])
    # Output fully connected layer with a neuron for each class
    out_layer = tf.matmul(layer_2, weights['out']) + biases['out']
    return out_layer


# Construct model,初始化所定义神经网络结构的实例
logits = neural_net(X)

# Define loss and optimizer,定义误差函数与优化方式
loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
    logits=logits, labels=Y))
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
train_op = optimizer.minimize(loss_op)

# Evaluate model (with test logits, for dropout to be disabled),定义检验模型效果的方式
correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

# Initialize the variables (i.e. assign their default value),初始化所有定义的网络变量
init = tf.global_variables_initializer()



# Start training,开启session,将所有定义编译成实际的TensorFlow图模型并运行
with tf.Session() as sess:

    # Run the initializer
    sess.run(init)

    for step in range(1, num_steps+1):
        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # Run optimization op (backprop),进行前向传播,后向传播,以及优化
        sess.run(train_op, feed_dict={X: batch_x, Y: batch_y})
        if step % display_step == 0 or step == 1:
            # Calculate batch loss and accuracy,计算每一批数据的误差及准确度
            loss, acc = sess.run([loss_op, accuracy], feed_dict={X: batch_x,
                                                                 Y: batch_y})
            print("Step " + str(step) + ", Minibatch Loss= " +                   "{:.4f}".format(loss) + ", Training Accuracy= " +                   "{:.3f}".format(acc))

    print("Optimization Finished!")

    # Calculate accuracy for MNIST test images,计算测试数据上的准确度
    print("Testing Accuracy:",         sess.run(accuracy, feed_dict={X: mnist.test.images,
                                      Y: mnist.test.labels}))


minist

激活函数

激活函数在神经元中非常重要的,是增强网络的非线性表示能力和学习能
力的关键,一般需要具备以下几点性质:

  1. 连续并可导(允许少数点上不可导)的非线性函数。可导的激活函数可以
    直接利用数值优化的方法来学习网络参数。
  2. 激活函数及其导函数要尽可能的简单,有利于提高网络计算效率。
  3. 激活函数的导函数的值域要在一个合适的区间内,不能太大也不能太小,
    否则会影响训练的效率和稳定性

Sigmoid 型激活函数

Sigmoid 型函数是指一类S 型曲线函数,为两端饱和函数。常用的Sigmoid
型函数有Logistic 函数和Tanh 函数。

Logistic 函数

Logistic 函数定义为
σ ( x ) = 1 1 + e x p ( − x ) \sigma(x) = \frac{1}{1 + exp(−x)} σ(x)=1+exp(x)1

Logistic 函数可以看成是一个“挤压”函数,把一个实数域的输入“挤压”
到(0, 1)。当输入值在0 附近时,Sigmoid 型函数近似为线性函数;当输入值靠近
两端时,对输入进行抑制。输入越小,越接近于0;输入越大,越接近于1。这
样的特点也和生物神经元类似,对一些输入会产生兴奋(输出为1),对另一些
输入产生抑制(输出为0)。和感知器使用的阶跃激活函数相比,Logistic 函数
是连续可导的,其数学性质更好。
因为Logistic 函数的性质,使得装备了Logistic 激活函数的神经元具有以下
两点性质:1)其输出直接可以看作是概率分布,使得神经网络可以更好地和统
计学习模型进行结合。2)其可以看作是一个软性门(Soft Gate),用来控制其
它神经元输出信息的数量。

Tanh 函数

Tanh 函数是也一种Sigmoid 型函数。其定义为
t a n h ( x ) = e x p ( x ) − e x p ( − x ) e x p ( x ) + e x p ( − x ) tanh(x) = \frac{exp(x) − exp(−x)}{exp(x) + exp(−x)} tanh(x)=exp(x)+exp(x)exp(x)exp(x)

Tanh 函数可以看作是放大并平移的Logistic 函数,其值域是(−1, 1),即 t a n h ( x ) = 2 σ ( 2 x ) − 1 tanh(x) = 2σ(2x) − 1 tanh(x)=2σ(2x)1
在这里插入图片描述

修正线性单元 Relu

修正线性单元(Rectified Linear Unit,ReLU)是目前深层神经网络中经常使用的激活函数。ReLU实际上是一个斜坡(ramp)函数,定义为
R e L U ( x ) = { x x &gt; = 0 0 x &lt; 0 = m a x ( 0 , x ) . ReLU(x) =\left\{ \begin{aligned} x &amp; &amp; x&gt;=0 \\ 0&amp; &amp; x&lt;0 \end{aligned} \right. = max(0, x). ReLU(x)={x0x>=0x<0=max(0,x).

优点: 采用ReLU 的神经元只需要进行加、乘和比较的操作,计算上更加高效。
ReLU函数被认为有生物上的解释性,比如单侧抑制、宽兴奋边界(即兴奋程度
也可以非常高)。在生物神经网络中,同时处于兴奋状态的神经元非常稀疏。人
脑中在同一时刻大概只有1 ∼ 4%的神经元处于活跃状态。Sigmoid 型激活函数
会导致一个非稀疏的神经网络,而ReLU却具有很好的稀疏性,大约50% 的神
经元会处于激活状态。 在优化方面,相比于Sigmoid 型函数的两端饱和,ReLU函数为左饱和函数,且在x > 0 时导数为1,在一定程度上缓解了神经网络的梯度消失问题,加速梯度下降的收敛速度。
缺点: ReLU 函数的输出是非零中心化的,给后一层的神经网络引入偏置偏移,
会影响梯度下降的效率。此外,ReLU神经元在训练时比较容易“死亡”。在训
ReLU 神经元指采用ReLU练时,如果参数在一次不恰当的更新后,第一个隐藏层中的某个ReLU神经元在 作为激活函数的神经元。所有的训练数据上都不能被激活,那么这个神经元自身参数的梯度永远都会是0,在以后的训练过程中永远不能被激活。这种现象称为死亡ReLU问题(Dying ReLU Problem),并且也有可能会发生在其它隐藏层。
在实际使用中,为了避免上述情况,有几种ReLU的变种也会被广泛使用,如 Leaky ReLU,Parametric ReLU,Exponential Linear Unit,Softplus。当然除此之外,还有用swish函数和分段线性的maxout做激活函数,具体可以参考[1]。

正则化

正则化(Regularization)是通过限制模型复杂度,从而避免过拟合,提
高泛化能力的方法,这里主要总结一下L1/2正则化、数据集增强、噪声添加、early stop和Dropout。

ℓ1 和ℓ2 正则化

ℓ1 和ℓ2 正则化是机器学习中最常用的正则化方法,通过约束参数的ℓ1 和ℓ2
范数来减小模型在训练数据集上的过拟合现象。
通过加入ℓ1 和ℓ2 正则化,优化问题可以写为:
θ ∗ = a r g m i n θ 1 N ∑ L ( y ( n ) , f ( x ( n ) , θ ) + λ ℓ p ( θ ) θ^∗ = argmin_θ \frac{1}{N} \sum \mathcal{L}(y(n), f(x(n), θ)+ λℓ_p(θ) θ=argminθN1L(y(n),f(x(n),θ)+λp(θ)
其中, ℓ p ℓ_p p 为范数函数,p 的取值通常为{1, 2} 代表ℓ1 和ℓ2 范数,λ 为正则化系数。从概率角度看,ℓ1 正则对应着稀疏先验,ℓ2正则对应着高斯先验。ℓ1 范数的约束通常会使得最优解位于坐标轴上,而从使得最终的参数为稀疏性向量。

数据集增强

深层神经网络一般都需要大量的训练数据才能获得比较理想的效果。在数
据量有限的情况下,可以通过数据增强(Data Augmentation)来增加数据量,
提高模型鲁棒性,避免过拟合。目前,数据增强还主要应用在图像数据上,在
文本等其它类型的数据还没有太好的方法。
图像数据的增强主要是通过算法对图像进行转变,引入噪声等方法来增加
数据的多样性。增强的方法主要有几种:

  • 旋转(Rotation):将图像按顺时针或逆时针方向随机旋转一定角度;
  • 翻转(Flip):将图像沿水平或垂直方法随机翻转一定角度;
  • 缩放(Zoom In/Out):将图像放大或缩小一定比例;
  • 平移(Shift):将图像沿水平或垂直方法平移一定步长;
  • 加噪声(Noise):加入随机噪声。

Early stop

提前停止(early stop)对于深层神经网络来说是一种简单有效的正则化方
法。由于深层神经网络的拟合能力非常强,因此比较容易在训练集上过拟合。在使用梯度下降法进行优化时,我们可以使用一个和训练集独立的样本集合,称
为验证集(validation set),并用验证集上的错误来代替期望错误。当验证集
上的错误率不再下降,就停止迭代。 然而在实际操作中,验证集上的错误率变化曲线并不一定是平衡曲线,很可能是先升高再降低。因此,提前停止的具体停止标准需要根据实际任务上进行优化

Dropout

当训练一个深层神经网络时,我们可以随机丢弃一部分神经元(同时丢弃
其对应的连接边)来避免过拟合,这种方法称为丢弃法(Dropout Method)。每次选择丢弃的神经元是随机的。最简单的方法是设置一个固定的概率p。对每一个神经元都一个概率p 来判定要不要保留。对于一个神
经层y = f(Wx+b),我们可以引入一个丢弃函数d(·) 使得y = f(Wd(x)+b)。
丢弃函数d(·) 的定义为:
d ( x ) = { m ⊙ x 训 练 阶 段 p x 测 试 阶 段 d(x) =\left\{ \begin{aligned} m\odot x &amp; &amp; 训练阶段 \\ px&amp; &amp; 测试阶段 \end{aligned} \right. d(x)={mxpx
其中 m ∈ { 0 , 1 } d m \in \{0, 1\}^d m{0,1}d是丢弃掩码(dropout mask),通过以概率为p 的贝努力分布随机生成。p 可以通过验证集来选取一个最优的值。或者p 也可以设为0.5,这
对大部分的网络和任务有比较有效。在训练时,激活神经元的平均数量为原来
的p 倍。而在测试时,所有的神经元都是可以激活的,这会造成训练和测试时
网络的输出不一致。为了缓解这个问题,在测试时需要将每一个神经元的输出
乘以p,也相当于把不同的神经网络做了平均。

集成学习的解释:每做一次丢弃,相当于从原始的网络中采样得到一个子网络。
如果一个神经网络有n个神经元,那么总共可以采样出2n 个子网络。每次迭代
都相当于训练一个不同的子网络,这些子网络都共享原始网络的参数。那么,最
终的网络可以近似看作是集成了指数级个不同网络的组合模型。
当然对于Dropout 还有贝叶斯解释,大家可以看[1]和[3]。

深度模型中的优化

参数初始化

神经网络的训练过程中的参数学习是基于梯度下降法进行优化的。梯度下
降法需要在开始训练时给每一个参数赋一个初始值。这个初始值的选取十分关
键。在感知器和logistic 回归的训练中,我们一般将参数全部初始化为0。但是
这在神经网络的训练中会存在一些问题。因为如果参数都为0,在第一遍前向
计算时,所有的隐层神经元的激活值都相同。这样会导致深层神经元没有区分
性。这种现象也称为对称权重现象。
为了打破这个平衡,比较好的方式是对每个参数都随机初始化,这样使得
不同神经元之间的区分性更好。
如果要高质量地训练一个网络,给参数选取一个合适的初始化区间
是非常重要的。一般而言,参数初始化的区间应该根据神经元的性质进行差异
化的设置。如果一个神经元的输入连接很多,它的每个输入连接上的权重就应
该小一些,以避免神经元的输出过大(当激活函数为ReLU 时)或过饱和(当
激活函数为sigmoid 函数时)。
经常使用的初始化方法有Gaussian 分布初始化 和 Xavier 初始化方法, 后者可以参考文献 [4].

自适应学习率算法

优化算法,写起来就非常的多,这里我手指实在疼痛,偷个懒,贴几个总结。后面有空,我在专门写一个专题。
优化总结
下图给出了这几种优化方法在MNIST数据集上收敛性的比较
优化方法比较

batch norm

在深层神经网络中,中间某一层的输入是其之前的神经层的输出。因此,其
之前的神经层的参数变化会导致其输入的分布发生较大的差异。在使用随机梯
度下降来训练网络时,每次参数更新都会导致网络中间每一层的输入的分布发
生改变。越深的层,其输入的分布会改变得越明显。就像一栋高楼,低楼层发
生一个较小的偏移,都会导致高楼层较大的偏移。
从机器学习角度来看,如果某个神经层的输入分布发生了改变,那么其参
数需要重新学习,这种现象叫做内部协变量偏移(Internal Covariate Shift)
协变量偏移:在传统机器学习中,一个常见的问题的协变量偏移(Covariate
Shift)。协变量是一个统计学概念,是可能影响预测结果的统计变量。
在机器学习中,协变量可以看作是输入。一般的机器学习算法都要求输
入在训练集和测试集上的分布是相似的。如果不满足这个假设,在训练
集上学习到的模型在测试集上的表现会比较差。

为了解决内部协变量偏移问题,就要使得每一个神经层的输入的分布在训
练过程中要保持一致。最简单直接的方法就是对每一个神经层都进行归一化操
作,使其分布保存稳定。
批量归一化(Batch Normalization,BN)方法是一种有效的逐层归一化方法,可以对神经网络中任意的中间层进行归一化操作。对于一个深层神经网络,令第l 层的净输入为 z ( l ) z^(l) z(l),神经元的输出为 a ( l ) a^(l) a(l)。为了减少内部协变量偏移问题,就要使得净输入 z ( l ) z^(l) z(l) 的分布一致,比如都归一化到标准正态分布为了提高归一化效率,一般使用标准归一化,将净输入 z ( l ) z^(l) z(l)的每一维都归一到标准正态分布
z ^ ( l ) = z ( l ) − E [ z ( l ) ] v a r ( z ( l ) ) + ϵ \hat{z}^{(l)} = \frac{z^{(l)} − E[z^{(l)}] }{\sqrt{var(z^{(l)}) + ϵ}} z^(l)=var(z(l))+ϵ z(l)E[z(l)]
var(z(l)) + ϵ
因为目前主要的训练方法是基于小批量的随机梯度下降方法,所以准确
地计算 z ( l ) z^(l) z(l) 的期望和方差是不可行的。因此, z ( l ) z^(l) z(l) 的期望和方差通常用当前小批量样本集的均值和方差近似估计。
给定一个包含K 个样本的小批量样本集合,第l 层神经元的净输入 z ( 1 , l ) z^{(1,l)} z(1,l),
· · · , z ( K , l ) z^{(K,l)} z(K,l) 的均值和方差为:
μ β = 1 K ∑ k = 1 K z ( k , l ) μ_\beta = \frac{1}{K} \sum_{k=1}^K z^{(k,l)} μβ=K1k=1Kz(k,l)
σ β 2 = 1 K ∑ k = 1 K ( z ( k , l ) − μ β ) ⊙ ( z ( k , l ) − μ β ) σ_{\beta}^2 = \frac{1}{K} \sum_{k=1}^K (z^{(k,l)} − μ_\beta) \odot (z^{(k,l)} − μ_\beta) σβ2=K1k=1K(z(k,l)μβ)(z(k,l)μβ)
对净输入z(l) 的标准归一化会使得其取值集中的0 附近,如果使用sigmoid
型激活函数时,这个取值区间刚好是接近线性变换的区间,减弱了神经网络的
非线性性质。因此,为了使得归一化不对网络的表示能力造成负面影响,我们
可以通过一个附加的缩放和平移变换改变取值区间
z ^ ( l ) = z ( l ) − μ β σ β 2 + ϵ ⊙ γ + β \hat{z}^{(l)} = \frac{ z^{(l)} − μ_\beta} {\sqrt{σ_{\beta}^2+ ϵ}}⊙ γ + β z^(l)=σβ2+ϵ z(l)μβγ+β
≜ B N γ , β ( z ( l ) ) \triangleq BN_{γ,β}(z^{(l)}) BNγ,β(z(l))

其中γ 和β 分别代表缩放和平移的参数向量.
批量归一化操作可以看作是一个特殊的神经层,加在每一层非线性激活函
数之前,即 a ( l ) = f ( B N γ , β ( z ( l ) ) ) = f ( B N γ , β ( W a ( l − 1 ) ) ) a(l) = f(BN_{γ,β}(z^{(l)})) =f(BN_{γ,β}(Wa^{(l−1)})) a(l)=f(BNγ,β(z(l)))=f(BNγ,β(Wa(l1)))

layer norm

批量归一化是对一个中间层的单个神经元进行归一化操作,因此要求小批
量样本的数量不能太小,否则难以计算单个神经元的统计信息。此外,如果一
个神经元的净输入的分布在神经网络中是动态变化的,比如循环神经网络,那
么就无法应用批量归一化操作

层归一化(Layer Normalization) 是和批量归一化非常类似的方法。和批量归一化不同的是,层归一化是对一个中间层的所有神经元进行归一化。层归一化定义为:
z ^ ( l ) = z ( l ) − μ l σ l 2 + ϵ ⊙ γ + β \hat{z}^{(l)} = \frac{ z^{(l)} − μ^{l}} {\sqrt{σ^{l^2}+ ϵ}}⊙ γ + β z^(l)=σl2+ϵ z(l)μlγ+β
≜ L N γ , β ( z ( l ) ) \triangleq LN_{γ,β}(z^{(l)}) LNγ,β(z(l))
其中γ 和β 分别代表缩放和平移的参数向量,和 z ( l ) z^{(l)} z(l)维数相同

在标准循环神经网络中,循环神经层的净输入一般会随着时间慢慢变大或变小,从而导致梯度爆炸或消失。而层归一化的循环神经网络可以有效地缓解这种状况。
,

参考文献

  1. Goodfellow I, Bengio Y, Courville A. Deep learning[M]. MIT press, 2016.
  2. 红色石头Will, 一看就懂的感知机算法PLA,CSDN(https://blog.csdn.net/red_stone1/article/details/80491895)
  3. 邱锡鹏, 《神经网络和深度学习》
  4. Xavier Glorot and Yoshua Bengio. Understanding the difficulty of training deep
    feedforward neural networks. In International conference on artificial intelligence
    and statistics, pages 249–256, 2010
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值