分类树、回归树原理及调参实战

分类树

from sklearn import tree
import pandas as pd
import numpy as np
# import graphviz
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
wine = load_wine()

sklearn自带的数据用字典存储

wine.target_names
array(['class_0', 'class_1', 'class_2'], dtype='<U7')
wine.feature_names
['alcohol',
 'malic_acid',
 'ash',
 'alcalinity_of_ash',
 'magnesium',
 'total_phenols',
 'flavanoids',
 'nonflavanoid_phenols',
 'proanthocyanins',
 'color_intensity',
 'hue',
 'od280/od315_of_diluted_wines',
 'proline']
wine.target
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2])
wine.data
array([[1.423e+01, 1.710e+00, 2.430e+00, ..., 1.040e+00, 3.920e+00,
        1.065e+03],
       [1.320e+01, 1.780e+00, 2.140e+00, ..., 1.050e+00, 3.400e+00,
        1.050e+03],
       [1.316e+01, 2.360e+00, 2.670e+00, ..., 1.030e+00, 3.170e+00,
        1.185e+03],
       ...,
       [1.327e+01, 4.280e+00, 2.260e+00, ..., 5.900e-01, 1.560e+00,
        8.350e+02],
       [1.317e+01, 2.590e+00, 2.370e+00, ..., 6.000e-01, 1.620e+00,
        8.400e+02],
       [1.413e+01, 4.100e+00, 2.740e+00, ..., 6.100e-01, 1.600e+00,
        5.600e+02]])
import pandas as pd
pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
01234567891011120
014.231.712.4315.6127.02.803.060.282.295.641.043.921065.00
113.201.782.1411.2100.02.652.760.261.284.381.053.401050.00
213.162.362.6718.6101.02.803.240.302.815.681.033.171185.00
314.371.952.5016.8113.03.853.490.242.187.800.863.451480.00
413.242.592.8721.0118.02.802.690.391.824.321.042.93735.00
.............................................
17313.715.652.4520.595.01.680.610.521.067.700.641.74740.02
17413.403.912.4823.0102.01.800.750.431.417.300.701.56750.02
17513.274.282.2620.0120.01.590.690.431.3510.200.591.56835.02
17613.172.592.3720.0120.01.650.680.531.469.300.601.62840.02
17714.134.102.7424.596.02.050.760.561.359.200.611.60560.02

178 rows × 14 columns

Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)

参数1:criterion 不纯度计算方式

基尼系数:"gini"和信息熵:“entropy”

两种方式的选择:  
1. 通常使用基尼系数,维度低,数据比较清晰的时候,信息熵和基尼系数没区别  
2. 信息熵对不纯度更加敏感,对不纯度的惩罚最强,所以信息熵作为指标时,决策树的生长会更加“精细”。  
因此对于高维数据或者噪音很多的数据,信息熵很容易 过拟合,基尼系数在这种情况下效果往往比较好。
3. 信息熵的计算比基尼系数缓慢一些,因为基尼系数的计算不涉及对数
4. 模型拟合程度不足的时候,尝试使用信息熵。
clf = tree.DecisionTreeClassifier(criterion="entropy")
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #返回预测的准确度accuracy
score
0.8518518518518519
# feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']

# import graphviz

# dot_data = tree.export_graphviz(clf #经过fit的模型
#                                 ,out_file="Tree.dot" #文件
#                                 ,feature_names = feature_name #特征
#                                 ,class_names=["琴酒","雪莉","贝尔摩德"] #节点类型
#                                 ,filled=True #是否用颜色来标志节点类型,和不纯度
#                                 ,rounded=True #框的形状
#                                ) 

# graph=graphviz.Source(dot_data)
# graph

属性:feature_importances_ 特征重要性评分

clf.feature_importances_
array([0.36805967, 0.        , 0.01681674, 0.06558588, 0.        ,
       0.        , 0.42692793, 0.        , 0.        , 0.12260977,
       0.        , 0.        , 0.        ])
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
[*zip(feature_name,clf.feature_importances_)]
[('酒精', 0.36805967453506444),
 ('苹果酸', 0.0),
 ('灰', 0.016816735253373225),
 ('灰的碱性', 0.06558588331982633),
 ('镁', 0.0),
 ('总酚', 0.0),
 ('类黄酮', 0.4269279334333496),
 ('非黄烷类酚类', 0.0),
 ('花青素', 0.0),
 ('颜色强度', 0.1226097734583865),
 ('色调', 0.0),
 ('od280/od315稀释葡萄酒', 0.0),
 ('脯氨酸', 0.0)]

参数2:random_state 随机模式

由于不纯度是基于节点进行计算的,决策树在建树时,是靠优化节点来追求一颗优化树,但最优 的节点  
并不能够保证最优的树。因此sklearn中的决策树使用了集成算法的思想,建很多的树,然后从中取最好树。  

怎样从一组数据集中建不同的树?在每次分枝时,不从使用全部特征,而是随机选取一部分特征,从中选取  
不纯度相关指标最优的作为分枝用的节点。这样,每次生成的树也就不同了。 

每次选择特征的随机性由random_state参数控制。

random_state默认None,在高维度时随机性会表现更明显,低维度的数据(比如鸢尾花数据集),
随机性几乎不会显现。
clf1= tree.DecisionTreeClassifier(criterion="entropy",random_state=30)
clf1= clf1.fit(Xtrain, Ytrain)
score1 = clf1.score(Xtest, Ytest) #返回预测的准确度
score1
0.8518518518518519

参数3: splitter 控制随机性

有两种输入值,输入”best",决策树在分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝  
(重要性可以通过属性feature_importances_查看)。  
  
输入“random",决策树在分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些  
不必要信息而降低对训练集的拟合。这也是防止过拟合的一种方式
clf2= tree.DecisionTreeClassifier(criterion="entropy"
                                    ,random_state=30
                                    ,splitter="best"
                                    )
clf2 = clf2.fit(Xtrain, Ytrain)
score2 = clf2.score(Xtest, Ytest)
score2
0.8518518518518519
# import graphviz
# dot_data = tree.export_graphviz(clf
#                                 ,feature_names= feature_name
#                                 ,class_names=["琴酒","雪莉","贝尔摩德"]
#                                 ,filled=True
#                                 ,rounded=True
#                                 )
# graph = graphviz.Source(dot_data)
# graph

主要剪枝参数

在不加限制的情况下,一棵决策树会生长到衡量不纯度的指标最优,或者没有更多的特征可用为止。  
这样的决策树往往会过拟合  

参数:
max_depth:限制树的最大深度,超过设定深度的树枝全部剪掉,在高维度低样本量时非常有效,建议从3开始尝试

参数:
min_samples_leaf:一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则分
枝就不会发生,或者,分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生。
-太小会引起过拟合,设置得太大就会阻止模型学习数据。建议从=5开始使用。
-如果 叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比来使用。
-这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差,过拟合的叶子节点出现。
-对于类别不多的分类问题,1通常就是最佳选择

参数:
max_samples_split:一个节点必须要包含至少min_samples_split个训练样本,这个节点才允许被分枝,否则
分枝就不会发生

参数:
max_features:限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃。但改方法比较暴力,是
直接限制可以使用的特征数量而强行使决策树停下的参数,在不知道决策树中的各个特征的重要性的情
况下,强行设定这个参数可能会导致模型学习不足

参数:
min_impurity_decrease:限制信息增益的大小,信息增益小于设定数值的分枝不会发生

#我们的树对训练集的拟合程度如何?
score_train = clf.score(Xtrain, Ytrain)
score_train
1.0
clf3= tree.DecisionTreeClassifier(criterion="entropy"
                                    ,random_state=30
                                    ,splitter="best"
                                    ,max_depth=3
                                #    ,min_samples_leaf=10
                                #    ,min_samples_split=25
                                    )
clf3= clf3.fit(Xtrain, Ytrain)
score3= clf3.score(Xtest, Ytest)
score3
0.8518518518518519
# dot_data = tree.export_graphviz(clf
#                                 ,feature_names= feature_name
#                                 ,class_names=["琴酒","雪莉","贝尔摩德"]
#                                 ,filled=True
#                                 ,rounded=True
#                                 )
# graph = graphviz.Source(dot_data)
# graph
import matplotlib.pyplot as plt
test = []
train=[]
for i in range(10):
    clf = tree.DecisionTreeClassifier(max_depth=i+1
                                    ,criterion="entropy"
                                    ,random_state=30
                                    ,splitter="random"
                                    )
    clf = clf.fit(Xtrain, Ytrain)
    test_score = clf.score(Xtest, Ytest)
    test.append(test_score)
    train_score = clf.score(Xtrain, Ytrain)
    train.append(train_score)
plt.plot(range(1,11),test,color="red",label="test_score")
plt.plot(range(1,11),train,color="blue",label="train_score")
plt.legend()
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0EfxgHou-1587534022405)(output_36_0.png)]

目标权重参数

参数:  
    class_weight:完成样本标签平衡的参数。默认为None,此模式表示自动给所有标签相同的权重。  
    有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了,因此这时候剪枝,  
    就需要搭配min_weight_fraction_leaf这个基于权重的剪枝参数来使用  
参数:  
    min_weight_fraction_leaf:改参数比不知道样本权重(比如min_samples_leaf)更少偏向主导类。  
    如果样本是加权的,则使用基于权重的预修剪标准来更容易优化树结构,这确保叶节点至少包含样  
    本权重的总和的一小部分

接口:

apply():返回每个测试样本所在的叶子节点的索引  
clf.apply(Xtest)
array([ 4, 13, 30, 30,  4, 30, 21, 30, 15, 13, 15, 30,  4,  9, 30,  4,  4,
       15, 30, 21,  4, 30, 15, 20, 13, 13, 30,  4, 20, 15, 21, 10,  4, 21,
        4, 15, 13, 20,  4, 29, 13, 29, 21, 20, 20, 20, 29,  4, 10,  4, 10,
        9,  4,  9], dtype=int64)



predict():返回每个测试样本的分类/回归结果
clf.predict(Xtest)
array([2, 1, 0, 0, 2, 0, 0, 0, 1, 1, 1, 0, 2, 1, 0, 2, 2, 1, 0, 0, 2, 0,
       1, 1, 1, 1, 0, 2, 1, 1, 0, 2, 2, 0, 2, 1, 1, 1, 2, 0, 1, 0, 0, 1,
       1, 1, 0, 2, 2, 2, 2, 1, 2, 1])



注意:所有接口中要求输入X_train和X_test的部分,输入的特征矩阵必须至少是一个二维矩阵。
sklearn不接受任何一维矩阵作为特征矩阵被输入。如果你的数据的确只有一个特征,那必须用reshape(-1,1)来给
矩阵增维;如果你的数据只有一个特征和一个样本,使用reshape(1,-1)来给你的数据增维。

回归树

from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
boston = load_boston()
boston.data
array([[6.3200e-03, 1.8000e+01, 2.3100e+00, ..., 1.5300e+01, 3.9690e+02,
        4.9800e+00],
       [2.7310e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 3.9690e+02,
        9.1400e+00],
       [2.7290e-02, 0.0000e+00, 7.0700e+00, ..., 1.7800e+01, 3.9283e+02,
        4.0300e+00],
       ...,
       [6.0760e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02,
        5.6400e+00],
       [1.0959e-01, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9345e+02,
        6.4800e+00],
       [4.7410e-02, 0.0000e+00, 1.1930e+01, ..., 2.1000e+01, 3.9690e+02,
        7.8800e+00]])
boston.target
array([24. , 21.6, 34.7, 33.4, 36.2, 28.7, 22.9, 27.1, 16.5, 18.9, 15. ,
       18.9, 21.7, 20.4, 18.2, 19.9, 23.1, 17.5, 20.2, 18.2, 13.6, 19.6,
       15.2, 14.5, 15.6, 13.9, 16.6, 14.8, 18.4, 21. , 12.7, 14.5, 13.2,
       13.1, 13.5, 18.9, 20. , 21. , 24.7, 30.8, 34.9, 26.6, 25.3, 24.7,
       21.2, 19.3, 20. , 16.6, 14.4, 19.4, 19.7, 20.5, 25. , 23.4, 18.9,
       35.4, 24.7, 31.6, 23.3, 19.6, 18.7, 16. , 22.2, 25. , 33. , 23.5,
       19.4, 22. , 17.4, 20.9, 24.2, 21.7, 22.8, 23.4, 24.1, 21.4, 20. ,
       20.8, 21.2, 20.3, 28. , 23.9, 24.8, 22.9, 23.9, 26.6, 22.5, 22.2,
       23.6, 28.7, 22.6, 22. , 22.9, 25. , 20.6, 28.4, 21.4, 38.7, 43.8,
       33.2, 27.5, 26.5, 18.6, 19.3, 20.1, 19.5, 19.5, 20.4, 19.8, 19.4,
       21.7, 22.8, 18.8, 18.7, 18.5, 18.3, 21.2, 19.2, 20.4, 19.3, 22. ,
       20.3, 20.5, 17.3, 18.8, 21.4, 15.7, 16.2, 18. , 14.3, 19.2, 19.6,
       23. , 18.4, 15.6, 18.1, 17.4, 17.1, 13.3, 17.8, 14. , 14.4, 13.4,
       15.6, 11.8, 13.8, 15.6, 14.6, 17.8, 15.4, 21.5, 19.6, 15.3, 19.4,
       17. , 15.6, 13.1, 41.3, 24.3, 23.3, 27. , 50. , 50. , 50. , 22.7,
       25. , 50. , 23.8, 23.8, 22.3, 17.4, 19.1, 23.1, 23.6, 22.6, 29.4,
       23.2, 24.6, 29.9, 37.2, 39.8, 36.2, 37.9, 32.5, 26.4, 29.6, 50. ,
       32. , 29.8, 34.9, 37. , 30.5, 36.4, 31.1, 29.1, 50. , 33.3, 30.3,
       34.6, 34.9, 32.9, 24.1, 42.3, 48.5, 50. , 22.6, 24.4, 22.5, 24.4,
       20. , 21.7, 19.3, 22.4, 28.1, 23.7, 25. , 23.3, 28.7, 21.5, 23. ,
       26.7, 21.7, 27.5, 30.1, 44.8, 50. , 37.6, 31.6, 46.7, 31.5, 24.3,
       31.7, 41.7, 48.3, 29. , 24. , 25.1, 31.5, 23.7, 23.3, 22. , 20.1,
       22.2, 23.7, 17.6, 18.5, 24.3, 20.5, 24.5, 26.2, 24.4, 24.8, 29.6,
       42.8, 21.9, 20.9, 44. , 50. , 36. , 30.1, 33.8, 43.1, 48.8, 31. ,
       36.5, 22.8, 30.7, 50. , 43.5, 20.7, 21.1, 25.2, 24.4, 35.2, 32.4,
       32. , 33.2, 33.1, 29.1, 35.1, 45.4, 35.4, 46. , 50. , 32.2, 22. ,
       20.1, 23.2, 22.3, 24.8, 28.5, 37.3, 27.9, 23.9, 21.7, 28.6, 27.1,
       20.3, 22.5, 29. , 24.8, 22. , 26.4, 33.1, 36.1, 28.4, 33.4, 28.2,
       22.8, 20.3, 16.1, 22.1, 19.4, 21.6, 23.8, 16.2, 17.8, 19.8, 23.1,
       21. , 23.8, 23.1, 20.4, 18.5, 25. , 24.6, 23. , 22.2, 19.3, 22.6,
       19.8, 17.1, 19.4, 22.2, 20.7, 21.1, 19.5, 18.5, 20.6, 19. , 18.7,
       32.7, 16.5, 23.9, 31.2, 17.5, 17.2, 23.1, 24.5, 26.6, 22.9, 24.1,
       18.6, 30.1, 18.2, 20.6, 17.8, 21.7, 22.7, 22.6, 25. , 19.9, 20.8,
       16.8, 21.9, 27.5, 21.9, 23.1, 50. , 50. , 50. , 50. , 50. , 13.8,
       13.8, 15. , 13.9, 13.3, 13.1, 10.2, 10.4, 10.9, 11.3, 12.3,  8.8,
        7.2, 10.5,  7.4, 10.2, 11.5, 15.1, 23.2,  9.7, 13.8, 12.7, 13.1,
       12.5,  8.5,  5. ,  6.3,  5.6,  7.2, 12.1,  8.3,  8.5,  5. , 11.9,
       27.9, 17.2, 27.5, 15. , 17.2, 17.9, 16.3,  7. ,  7.2,  7.5, 10.4,
        8.8,  8.4, 16.7, 14.2, 20.8, 13.4, 11.7,  8.3, 10.2, 10.9, 11. ,
        9.5, 14.5, 14.1, 16.1, 14.3, 11.7, 13.4,  9.6,  8.7,  8.4, 12.8,
       10.5, 17.1, 18.4, 15.4, 10.8, 11.8, 14.9, 12.6, 14.1, 13. , 13.4,
       15.2, 16.1, 17.8, 14.9, 14.1, 12.7, 13.5, 14.9, 20. , 16.4, 17.7,
       19.5, 20.2, 21.4, 19.9, 19. , 19.1, 19.1, 20.1, 19.9, 19.6, 23.2,
       29.8, 13.8, 13.3, 16.7, 12. , 14.6, 21.4, 23. , 23.7, 25. , 21.8,
       20.6, 21.2, 19.1, 20.6, 15.2,  7. ,  8.1, 13.6, 20.1, 21.8, 24.5,
       23.1, 19.7, 18.3, 21.2, 17.5, 16.8, 22.4, 20.6, 23.9, 22. , 11.9])
boston.feature_names
array(['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD',
       'TAX', 'PTRATIO', 'B', 'LSTAT'], dtype='<U7')

交叉验证

训练集和测试集的划分会干扰模型的结果,使用交叉验证来观察模型的稳定性。用交叉验证n次的结果
求出的均值是对模型效果的一个更好的度量
regressor = DecisionTreeRegressor(random_state=0) #实例化
cross_val_score(regressor, boston.data, boston.target, cv=10).mean()
-0.1253505322812249

回归树 模型的评估指标

regressor = DecisionTreeRegressor(random_state=0)
cross_val_score(regressor #任何实例化后的分类器
                , boston.data #不需要划分训练集和测试集的特征矩阵
                , boston.target#不需要划分训练集和测试集的标签
                , cv=10, #默认为5,通常使用默认即可
                scoring = "neg_mean_squared_error" #模型衡量指标,对于回归树默认为R平方,这里使用负的均方误差
               )
array([-16.41568627, -10.61843137, -18.30176471, -55.36803922,
       -16.01470588, -44.70117647, -12.2148    , -91.3888    ,
       -57.764     , -36.8134    ])

实例:决策树拟合一条包含噪声的正弦曲线

import numpy as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt
rng = np.random.RandomState(1) #随机数种子
X = np.sort(5 * rng.rand(80,1), axis=0) #生成0~5之间随机的x的取值
#这里生成1个 80×1的二维矩阵。因为要将数据导入分类树拟合,而sklearn不支持一维特征矩阵的输入
y = np.sin(X).ravel() #生成Y,并将标签降为一维
y[::5] += 2 * (0.5 - rng.rand(16)) #在正弦曲线上加噪声
#y[::5] 在一维array上每隔5个数取一个值
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
<matplotlib.collections.PathCollection at 0x9a6a848>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vk2P0CMx-1587534022409)(output_60_在这里插入图片描述1.png)]

regr_1 = DecisionTreeRegressor(max_depth=2)
regr_2 = DecisionTreeRegressor(max_depth=5)
regr_1.fit(X, y)
regr_2.fit(X, y)
DecisionTreeRegressor(ccp_alpha=0.0, criterion='mse', max_depth=5,
                      max_features=None, max_leaf_nodes=None,
                      min_impurity_decrease=0.0, min_impurity_split=None,
                      min_samples_leaf=1, min_samples_split=2,
                      min_weight_fraction_leaf=0.0, presort='deprecated',
                      random_state=None, splitter='best')
X_test = np.arange(0.0, 5.0, 0.01)[:, np.newaxis]
y_1 = regr_1.predict(X_test)
y_2 = regr_2.predict(X_test)
plt.figure()
plt.scatter(X, y, s=20, edgecolor="black",c="darkorange", label="data")
plt.plot(X_test, y_1, color="cornflowerblue",label="max_depth=2", linewidth=2)
plt.plot(X_test, y_2, color="yellowgreen", label="max_depth=5", linewidth=2)
plt.xlabel("data")
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GkYUwQuN-1587534022414)(output_64_0.在这里插入图片描述

可以看到,树的最大深度设置的太高,决策树就会学习的越精细,它从训练数据中学了很多细节,  
包括噪声,使模型偏离真实的正弦曲线,形成过拟合
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值