R机器学习:决策树算法的理解与实操

R语言与机器学习学习笔记(分类算法)(2)决策树算法 算法二:决策树算法         首先,我们来谈谈什么是决策树。我们还是以鸢尾花为例子来说明这个问题。        观察上图,我们判决鸢尾花的思考过程可以这么来描述:花瓣的长度小于2.4cm的是setosa(图中绿色的分类),长度大于1cm的呢?我们通过宽度来判别,宽度小于1.8cm的是versicolor(图中红色的分类),其余的就是virginica(图中黑色的分类) 阅读详情

今天继续给大家介绍决策树算法,决策树本身是一种非常简单直观的机器学习算法,用于做分类或回归任务。它就像我们平常做决定时的过程,通过逐步排除可能的选项,最终得出结论。

A decision tree is a flowchart-like structure used to make decisions or predictions. It consists of nodes representing decisions or tests on attributes, branches representing the outcome of these decisions, and leaf nodes representing final outcomes or predictions.

一个典型的决策树的决策过程如下图:

从上图可以看到一个树的结构包括:

  1. 根节点(Root Node): 代表决策过程要问的第一个问题。
  2. 内部节点(Internal Nodes): 代表依据特征决策的后续过程,每一个节点根据结果有不同的分支。
  3. 分支(Branches): 代表决策的结果,通常会指向下一个节点。
  4. 叶节点(Leaf Nodes): 代表最终决策结果,叶节点不会出现分支。

可以看出来决策树至少有两个优点:一是直观易懂: 决策树的结构就像一棵树,每个节点代表一个属性测试,每条边代表一个测试结果,叶子节点代表最终的分类结果。这种结构非常符合人类的思维方式,让我们很容易理解模型是如何做出决策的。二是可解释性强: 通过观察决策树,我们可以清晰地看到哪些特征对分类结果影响最大,从而帮助我们更好地理解数据。

理解决策树

决策树有一连串的节点,所有的特征属性其实都可以用来划分支,这个时候至少有两个问题需要弄明白:选择哪些特征作为节点?如何对相应特征进行划分?

选择哪个特征作为节点的时候有一个原则就是先用对模型贡献最大的特征来划分节点,贡献的评估标准有很多:

第一个熵值Entropy:这个熵值是度量数据的不纯度的amount of uncertainty or impurity,我们记住熵值越大数据越不纯就好。那么按照熵值的标准我们希望通过节点后形成的分支数据越纯越好,对应的就是熵值越小越好。

第二个信息增益Information Gain:这个是数据划分前的熵值和通过节点划分后的平均熵值的差,刚刚说了熵值越小越好,那么这个差值应该是越大越好,也就是信息增益越大越好。

it is calculated by computing the total difference between the entropy before split and average entropy after the split of dataset based on the given attribute values.

第三个的基尼纯度Gini Impurity:

Gini Index is a metric to measure how often a randomly chosen element would be incorrectly identified.

可以用以上三个标准决定使用哪个特征以及特征使用的先后顺序,具体标准总结如图:

不同的模型贡献评估标准又形成了不同的算法比如,ID3算法就是用信息增益作为贡献标准: 选择信息增益最大的属性作为划分属性。C4.5算法用信息增益率,CART算法用基尼指数: CART算法采用基尼指数作为划分属性的选择标准。

那么决策树的整个划分过程又是怎么样的呢?

我们依然来看个例子:想象一下,我们想根据天气情况决定是否去打篮球。 我们可以用决策树来表示这个决策过程,步骤如下:

第一步收集数据,首先,我们收集了一些历史天气数据以及是否打篮球的,包括:

第二步选择根节点,假设我们是用ID3算法:

  • 信息增益最大化原则(ID3算法): 我们选择能提供最多信息、最能区分不同决策的属性作为根节点。
  • 在这个例子中, 我们计算每个属性(天气、温度、风力、是否下雨)的信息增益,假设计算结果是“是否下雨”的信息增益最大。
  • 所以, 我们将“是否下雨”作为根节点。

第三步划分数据集

  • 根据根节点的取值, 将数据集分成两个子集:下雨和不下雨。

第四步继续划分子集

  • 对于每个子集, 我们再次计算每个属性的信息增益,选择信息增益最大的属性作为划分属性。
  • 假设对于“不下雨”这个子集, “温度”的信息增益最大。
  • 那么, 我们将“不下雨”这个子集根据“温度”划分成“温度高”和“温度不高”两个子集。
  • 对于“下雨”这个子集, 由于样本太少或其他原因,我们可能直接将其作为叶子节点,即“不下篮球”。

就这么一个思考过程决策树就出来了,决策树也就相应出来了:

所以一个常规的树的生成总结起来就是下面四步

  1. 计算每个属性的信息增益、信息增益率或基尼指数。
  2. 选择增益最大的属性作为划分属性。
  3. 根据该属性的不同取值,将数据集划分成若干个子集。
  4. 对每个子集递归地重复上述过程,直到满足停止条件。

决策树的剪枝

大家也可以想想按照上面决策树的生成流程我一直划分一直划分下去,总是可以非常精确的,这就会产生过拟合问题,为了防止过拟合,通常需要对决策树进行剪枝。剪枝的方法主要分为预剪枝和后剪枝。

  • 预剪枝: 在树生成过程中提前停止分支生长。比如我们可以设置最大深度、设置节点包含的最小样本数、设置信息增益阈值。
  • 后剪枝: 先生成一棵完整的树,然后自底向上地剪掉一些分支。比如错误率降低剪枝 (Reduced-Error Pruning, REP) *代价复杂度剪枝 (Cost-Complexity Pruning, CCP)都属于后剪枝。

决策树实操

我们依然用iris数据集进行演示,上篇讲朴素贝叶斯的文章也是用的这个数据集,大家可以对比着看下结果。以Species作为因变量,其余变量作为自变量构建决策树代码如下:

tree_model<- ctree(Species ~ ., iris_train)
plot(tree_model)

运行代码得到决策树如图:

训练好的模型在验证集中的表现如下:

针对连续特征的回归树

刚刚讲的决策树都是针对分类结局的,决策树也可以用于连续结局,叫做回归树。

比如我现在有数据集,结局是年薪(连续变量),两个预测变量,一个是工作年限,一个是工作经验HmRun,通过数据可以形成一个如下图所示的决策树:

那么对于一个工作年限为8年,工作经验为10的个体来说,模型预测其年薪结果就为577.6

上面过程也有两个问题,一个是特征分割的条件标准,另一个问题是叶节点的值是如何来的。

选择最佳划分特征和划分点: 对于每个特征,遍历所有可能的划分点,计算划分后的子节点的均方误差(或其他指标),选择使均方误差最小的特征和划分点作为特征以及对应特征的划分点,回归树的叶节点输出的是该节点包含的所有训练样本目标值的平均值或中位数。

When the dependent variable is continuous, its value can be predicted using regression trees. These predict using the average values of ȳ within each subset

看一个回归树的例子,我现在有数据如下:

我想用数据集中的特征来预测medv: 房价中位数,做一个回归树,代码如下:

fit <- rpart(medv ~ ., data = Boston, method = "anova")
rpart.plot(fit, type = 4, extra = 101)

运行代码后输出结果如下:

这个是没有剪枝前的模型,我们看下模型的效果:

predictions <- predict(fit, newdata = Boston)
mse <- mean((predictions - Boston$medv)^2)
print(mse)

运行后可以得到模型的mse是16.24467,我们对模型进行剪枝过后再看变成下图:

相应的模型的mse也变成了10.3362。说明剪枝确实提高了拟合效果。

通过上面的叙述相信大家对剪枝带来的直观效果有印象了,继续带大家捋捋这个剪枝到底怎么减的。

Pruning剪枝实操

如果回归决策树的分支过多,容易造成过拟合。剪枝主要分为两种方法:预剪枝和后剪枝。

1. 预剪枝(Pre-Pruning):

预剪枝是在树的构建过程中进行的。它通过提前停止树的生长来达到剪枝的目的。具体方法包括:

  • 限制树的深度(max_depth): 设置树的最大深度,当树达到指定深度时就停止生长。例如,设置max_depth=3意味着树最多有3层。
  • 限制节点包含的最小样本数(min_samples_split): 规定一个节点如果要分裂,至少需要包含多少个样本。如果一个节点包含的样本数少于这个阈值,则该节点不再分裂。
  • 限制叶节点包含的最小样本数(min_samples_leaf): 规定一个叶节点至少需要包含多少个样本。如果一个节点分裂后,某个子节点包含的样本数少于这个阈值,则该分裂不进行。
  • 限制叶节点的最小权重总和(min_weight_fraction_leaf): 与min_samples_leaf类似,但使用样本权重的总和而不是样本数。
  • 设定分裂的阈值(如信息增益、基尼指数的阈值): 当分裂带来的增益小于设定的阈值时,停止分裂。

举例说明预剪枝:假设我们设置min_samples_split=10。这意味着只有当一个节点包含至少10个样本时,它才会被考虑分裂。如果一个节点只包含8个样本,即使它可以被分裂成更“纯”的子节点,也不会进行分裂,从而避免了树的过度生长。

2. 后剪枝(Post-Pruning):

后剪枝是先让树完整地生长,然后再自底向上地对树进行修剪。它通过删除一些子树或将子树替换为叶节点来简化树的结构。常用的后剪枝方法包括:

  • 降低错误剪枝(Reduced Error Pruning): 将数据集分成训练集和验证集。首先使用训练集构建完整的树,然后从底向上遍历每个非叶节点,尝试将其子树替换为叶节点。如果替换后在验证集上的错误率降低或保持不变,则进行替换;否则,不进行替换。
  • 代价复杂度剪枝(Cost-Complexity Pruning): 为树的每个非叶节点定义一个代价复杂度因子(α),它衡量了剪枝带来的误差减少量与剪掉的叶节点数量之间的权衡。通过调整α的值,可以得到一系列不同复杂度的树。然后使用交叉验证等方法选择最佳的α值,并根据该值对树进行剪枝。

举例说明后剪枝:假设我们构建了一棵完整的树,其中一个非叶节点A有两个子节点B和C。我们尝试将节点A的子树(包括B和C)替换为一个叶节点,该叶节点的值为B和C包含的所有样本目标值的平均值。如果替换后在验证集上的均方误差降低了,则进行替换;否则,保留原来的子树。

故决策树剪枝的主要思想是防止模型在训练集中出现过拟合现象,使模型在测试集中的表现更好。预剪枝的逻辑我们其实很清楚了,现在我们以代价复杂度剪枝为例子看看后剪枝到底是如何操作的:

首先我们得有一个代价函数,如下图:

代价函数通常由两部分组成: 误差项SSR: 反映模型在训练集上的预测误差。 复杂度项: 反映决策树的复杂度,通常用叶子节点的数量来表示。通过调整这两项的权重,α是调节参数,可以控制模型的拟合程度和复杂度。

剪枝过程:

  1. 从底向上遍历决策树的内部节点。
  2. 对于每个内部节点,计算剪枝前后的代价。
  3. 如果剪枝后代价降低,则进行剪枝,将该节点及其子树替换为一个叶子节点。
  4. 叶子节点的类别通常由该子树中样本最多的类别决定。

通常我们会使用交叉验证法求解最佳α取值,α约小决策树越长。不同的α取值将影响我们选择哪种亚决策树的决策。

交叉验证剪枝实操

我们依然是用鸢尾花数据集进行展示如何用交叉验证得到最优cp(代价复杂度因子(α))值从而完成剪枝提高模型的准确度。

下面的代码做了决策树模型,绘制cp值与交叉验证误差的关系图。并展示了剪枝前的模型:

fit <- rpart(Species ~ ., data = iris)
plotcp(fit)
rpart.plot(fit, type = 4, extra = 101)

代码运行结果如下:

接下来进行剪枝,并输出剪枝后的模型评估结果:

# 使用1-SE规则选择cp值
bestcp <- fit$cptable[which.min(fit$cptable[,"xerror"] + fit$cptable[,"xstd"]), "CP"]
# 剪枝
fit.pruned <- prune(fit, cp = bestcp)
predicted.classes <- fit.pruned %>% predict(iris,type = "class")
tab_tree <- table(predicted.classes, iris$Species)
caret::confusionMatrix(tab_tree)  

运行代码输出结果如下:

可以看到模型整体的正确性变成了96,这可确实比前面的算法提升了嘞,之前可是只有93哦。

R语言实现决策树 1.决策树 (1)决策树定义     分类决策树模型是一种描述对实例进行分类的树形结构。决策树是一种由节点和有向边组成的树形结构,节点分为     三种:             ①根节点:没有入边,但有零条或多条出边,包括全部实例的集合;             ②内部节点:恰有一条入边和两条或多条出边,表示一个特征或属性;             ③叶节点:恰有一条入边,但没有出边, 阅读详情

相关推荐

【R的机器学习】决策树性能提升

上一章用iris数据集进行了决策树分析,理论上来说,Kappa值是0.8991,已经非常高了,我们下面研究下方法,看看有没有什么优化空间。首先看C5.0的函数参数C5.0(x, y, trials = 1, rules= FALSE, weights = NULL, control = C5.0Control(), costs = NULL, ...)C5.0(y

Yunru_Yang的博客 3971

分类算法3:决策树及R语言实现

决策树是一种基本的分类与回归方法,这里只介绍用于分类的决策树。前面已经说过,只要是分类,它的本质就是出发于特征,结束于类别。 决策树主要3步骤: step1:特征选择; step2:决策树的生成; step3:决策树的修剪。 决策树思想主要来源于由Quinlan在1986年提出的ID3算法和1993年提出的C4.5算法,以及有Breiman等人在1984年提出的CART算法。 决策树定义: 分类决...

qq_38865429的博客 9905

人工智能AI 与 机器学习ML 的关键区别

人工智能(AI)是指计算机系统能够执行通常需要人类智能才能完成的任务。包括理解自然语言、识别图像、解决复杂问题和做出决策。AI的目标是创建能够模仿或超越人类智能的系统。弱人工智能(弱AI):也称为窄AI,专注于特定任务。例如,语音助手(如Siri和Alexa)和推荐系统(如Netflix和Amazon的推荐算法)。强人工智能(强AI):也称为通用AI,具有执行任何人类智能任务的能力。目前,强AI仍处于理论阶段,尚未实现。机器学习(ML)是人工智能的一个子领域。

王教主的博客 5944

机器学习方法:15分钟带你吃透决策树模型

【本文的阅读时间约15分钟,希望大家耐心观看】这是机器学习方法系列科普文章,由浙中大公卫徐老师撰写,往期推文可以看集合。在众多机器学习模型中,决策树是最为简单直观的一种算法。它就像我们平常做决定时的过程,逐步排除可能的选项,最终得出结论。今天这篇文章中,我们将结合图例讲解讲解决策树的结构、数学原理、具体构建和优化过程,让大家在理解时不至于太抽象,同时我们也会提供构建决策树预测模型的数据和代码,感...

郑老师统计 2936

7篇1章9节:认识决策树,构建CART算法的决策树模型

在本文中,我们将深入探讨决策树算法的各个方面,首先概述决策树的基本概念,介绍其不同类型,并分析其优势与局限性。接着,我们将详细讲解如何构建CART算法的决策树模型,包括模型的构建、可视化以及剪枝技术等关键步骤。此外,还将探讨一些常用的决策树算法改进方法,以提升模型的性能和稳定性。

MD Code 1053

R语言构建决策树模型的算法步骤和流程

至此,我们完成了使用rpart包构建决策树模型的算法步骤和流程。当然,在实际应用中可能需要进一步调优和验证模型的鲁棒性,但以上步骤提供了一个基本的框架来构建决策树模型。在R语言中,可以使用不同的包来构建决策树模型,如rpart、tree和randomForest等。其中formula表示模型的公式,data表示训练数据集,方法表示决策树的构建方法。构建完决策树模型后,可以使用plot函数将模型可视化,以便更好地理解模型的结构和规则。构建完决策树模型后,可以使用该模型对新样本进行预测,并评估模型的性能。

ByteWhiz的博客 345

机器学习sklearn中决策树模型参数释义

''' scikit-learn中有两类决策树,它们均采用优化的CART决策树算法。 ''' from sklearn.tree import DecisionTreeRegressor ''' 回归决策树 ''' DecisionTreeRegressor(criterion="mse", splitter="best", ...

随遇而安_小强的博客 2万+

女神也用的约会决策:决策树算法实践

一、决策树 决策树是机器学习中强大的有监督学习模型。决策树本质上是一个二叉树的流程图,其中每个节点根据某个特征变量将一组观测值拆分。 决策树的目标是将数据分成多个组,这样一个组中的每个元素都属于同一个类别。决策树也可以用来近似连续的目标变量。在这种情况下,树将进行拆分,使每个组的均方误差最小。 决策树的一个重要特性可解释性好,即使你不熟悉机器学习技术,也可以理解决策树在做什么。 1. CART概述 所谓CART算法,全名叫Classification and Regression Tree,即分类与回归树。

叶庭云 成为自己的光 4192

机器学习:15分钟带你吃透决策树模型

今天这篇文章中,我们将结合图例讲解讲解决策树的结构、数学原理、具体构建和优化过程,让大家在理解时不至于太抽象,同时我们也会提供构建决策树预测模型的数据和代码,感兴趣的不妨尝试一下。CP列是决策树的成本复杂性参数,nsplit是决策树的分裂次数,rel error列是整个数据集上的平均误差,xerror列是通过交叉验证法得到的验证集的平均误差。此外,决策树模型是树状结构模型的总称,根据分支的样本集合纯度度量指标的不同分为不同算法,其中具有标志性的是。是根据 “基尼指数”来度量数据子集的“纯度”的。

weixin_41560800的博客 1478

R语言实战:构建决策树模型

R语言实战:构建决策树模型决策树是一种常用的机器学习算法,它能够从多个特征中推断出决策结果。在本篇文章中,我们将使用R语言来构建一个决策树模型,并通过实例来展示其应用。

TechChamp的博客 480

R语言实现决策树模型及调优与解释

本文介绍了如何使用R语言构建决策树模型,并进行调优和解释。通过准备数据、构建模型、可视化决策树、调优模型和解释模型等步骤,我们可以更好地理解和应用决策树算法。希望本文对你在R语言中构建决策树模型有所帮助!

HackDyno的博客 637

决策树模型

在本教程中,我们提供了回归算法的高级概述,并展示了如何使用 scikit-learn 库实现这些算法。我们还使用 matplot lib 来可视化一些结果。

2401_82469710的博客 471

用rpart.plot包可视化R语言中最终的决策树模型结构

例如,可以使用type参数来选择节点的显示类型,使用extra参数添加额外的文本或符号,使用fallen.leaves参数将叶子节点放置在树的底部等等。在R语言中,rpart包提供了构建决策树模型的功能,而rpart.plot包则是用于可视化最终的决策树模型结构。接下来,我们使用一个示例数据集来构建一个简单的决策树模型。通过可视化决策树,我们可以更好地理解模型的决策过程,并对模型的性能和预测结果进行解释和验证。接下来,我们可以使用rpart.plot包中的rpart.plot函数来可视化决策树模型的结构。

TechPulseZ的博客 1240

【机器学习】回归决策树

回归决策树1. 原理概述2. 算法描述3. 简单实例3.1 实例计算过程3.2 回归决策树和线性回归对比4. 小结 1. 原理概述 上篇文章已经讲到,关于数据类型,我们主要可以把其分为两类,连续型数据和离散型数据。在面对不同数据时,决策树也 可以分为两大类型: 分类决策树和回归决策树。 前者主要用于处理离散型数据,后者主要用于处理连续型数据。 不管是回归决策树还是分类决策树,都会存在两个核心问题: 如何选择划分点? 如何决定叶节点的输出值? ⼀个回归树对应着输入空间(即特征空间)的⼀个划分以及在划分单元

全网粉丝30W+,优快云、稀土掘金人工智能领域签约作者,人工智能、大模型、Python 爬虫,商务合作,请私信沟通。 1万+

R语言中的决策树模型构建与分析

本文深入探讨了在R语言中使用rpart包拟合决策树模型的过程。通过一个具体的贷款数据集例子,展示了如何利用rpart控制参数来拟合模型,并通过图形化的方式解释了树模型的结构和分类规则。文章详细解释了递归分割算法的工作原理,并探讨了如何使用Gini不纯度和熵等度量来评估决策树的性能。

weixin_42596011的博客 477

微信支付开发之平台给用户转账到零钱的功能

请求消息中应包含商家批次单号、转账名称、appid、转账总金额、转账总笔数、转账openid、收款用户姓名等信息。批次已受理成功,若发起批量转账的30分钟后,转账批次单仍处于该状态,可能原因是商户账户余额不足等。【转账场景ID】 该批次转账使用的转账场景,如不填写则使用商家的默认场景,如无默认场景可为空,可前往“商家转账到零钱-前往功能”中申请。【转账总笔数】 一个转账批次单最多发起一千笔转账。【商家批次单号】 商户系统内部的商家批次单号,要求此参数只能由数字、大小写字母组成,在商户系统内部唯一。

程序员weixin_sodomany的博客 3455

机器学习系列(9)_机器学习算法一览(附Python和R代码)

写这篇文章的目的,就是希望它可以让有志于从事数据科学和机器学习的诸位在学习算法的路上少走些路。我会在文章中举例一些机器学习的问题,你们也可以在思考解决这些问题的过程中得到启发。我也会写下对于各种机器学习算法的一些个人理解,并且提供R和Python的执行代码。读完这篇文章,读者们至少可以行动起来亲手试试写一个机器学习的程序。

寒小阳 4万+

【Android】汽车电源管理:深入解析CarPowerManager与Suspend To RAM的交互机制

本文深入解析了Android Automotive OS中CarPowerManager与Suspend To RAM(深度睡眠)的交互机制。详细阐述了从车辆发出睡眠请求,到CarPowerManagementService协调应用状态,最终通过内核进入低功耗睡眠的完整流程,并探讨了唤醒机制、开发者实践及功耗优化策略,为车机应用开发与系统优化提供关键指导。

weixin_28339967的博客 292

决策树 Decision Tree

本文主要简单介绍了决策树的基本概念,优缺点,应用场景,决策树建模时的注意事项,python的实现方法,案例和模型参数等。

JasonH2021的博客 5396

华科软院研究生第一学期的事项(奖学金、学业、考试等)

奖助 研究生补助 每月500,全年共6000元 每个月月底学院会打到银行卡里 碰上开学、过年会延后发放 17年10月底发了9、10两个月的钱 18年3月底发了2、3月的钱 学业奖学金 17届全日制每人都有 按照考研最后综合成绩排名 前16 10000 前80 8000 其他 4000 大概11月底发 注意:第一年如果有挂科的话,第二年就不能参加学业奖学金评...

sjdeak的博客 3707

一文详解声码器

声码器(Vocoder)是语音信号处理领域的核心技术,其本质是通过“分析 - 参数化 - 合成” 的闭环流程,实现语音的高效编码、转换或生成。它不仅是早期语音通信的关键工具,更是现代 AI 语音技术(如 TTS、语音转换)的核心组件。以下从原理、技术分类、关键模块、应用及发展趋势展开详细解析。

weixin_41413777的博客 1355

决策树算法

学习打卡内容: 理解决策树以及决策树的几种算法 总结决策树模型结构 理解决策树递归思想 学习信息增益 学习信息增益率 学习ID3算法优缺点 学习C4.5算法优缺点 理解C4.5算法在ID3算法上有什么提升 学习C4.5算法在连续值上的处理 学习决策树如何生成 代码实现决策树 划分数据集代码 选择最好的数据集划分方式代码 创建树的函数代码 ...

StarCoder_WangYue的博客 645

手把手教你使用ConvNeXt训练自己数据集和推理,ConvNeXt模型训练(CVPR 2022),一个能挑战 Vision Transformer 的卷积神经网络,含完整代码和数据集

手把手教你使用ConvNeXt训练自己数据集和推理,ConvNeXt模型训练(CVPR 2022),一个能挑战 Vision Transformer 的卷积神经网络,含完整代码和数据集

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 1458
上一篇: R机器学习:朴素贝叶斯算法的理解与实操
下一篇: R数据分析:工具变量回归的做法和解释,实例解析
公众号Codewar原创作者
博客等级 码龄7年 2025粉丝 185原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

公众号Codewar原创作者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值