机器学习:决策树算法:ID3、C4.5、CART、CHAID:原理、应用场景及优缺点

一、ID3算法

  1. 原理

    • 信息熵(Entropy):信息熵用于衡量数据集的混乱程度。对于数据集 D D D,包含 n n n个类别标签,其信息熵 H ( D ) H(D) H(D)计算公式为:
      H ( D ) = − ∑ k = 1 n p k log ⁡ 2 p k H(D)=-\sum_{k = 1}^{n}p_k\log_2p_k H(D)=k=1npklog2pk
      其中 p k p_k pk是数据集中属于第 k k k类样本的比例。例如,在一个简单的天气分类数据集中(晴天、雨天、多云),若晴天样本占比 p 1 = 0.4 p_1 = 0.4 p1=0.4,雨天 p 2 = 0.3 p_2 = 0.3 p2=0.3,多云 p 3 = 0.3 p_3 = 0.3 p3=0.3,则信息熵 H ( D ) = − 0.4 log ⁡ 2 0.4 − 0.3 log ⁡ 2 0.3 − 0.3 log ⁡ 2 0.3 H(D)=-0.4\log_20.4 - 0.3\log_20.3-0.3\log_20.3 H(D)=0.4log20.40.3log20.30.3log20.3
    • 信息增益(Information Gain):用于衡量特征对数据集纯度的提升程度。假设数据集 D D D,属性 a a a V V V个不同取值 { a 1 , a 2 , ⋯   , a V } \{a^1,a^2,\cdots,a^V\} {a1,a2,,aV}。使用属性 a a a D D D进行划分,得到 V V V个子集 { D 1 , D 2 , ⋯   , D V } \{D^1,D^2,\cdots,D^V\} {D1,D2,,DV}。信息增益 g ( D , a ) g(D,a) g(D,a)计算公式为:
      g ( D , a ) = H ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ H ( D v ) g(D,a)=H(D)-\sum_{v = 1}^{V}\frac{|D^v|}{|D|}H(D^v) g(D,a)=H(D)v=1VDDvH(Dv)
      例如,在一个判断水果是苹果还是香蕉的数据集中,有“颜色”这个属性(红、绿)。若红色样本中苹果占比高,绿色样本中香蕉占比高,通过这个属性划分数据集后纯度提升,信息增益较大。
    • 构建树时,从根节点开始,计算每个特征的信息增益,选择信息增益最大的特征作为当前节点的划分特征。对于划分后的子集,重复此步骤,直到满足停止条件(如所有样本属于同一类别、没有可用于划分的特征或子集样本数量小于阈值)。
  2. 应用场景

    • 适用于处理离散型特征的分类问题。例如,在文本分类中,根据文章中的词汇(离散特征)判断文章所属类别(如体育类、科技类)。
  3. 优点

    • 算法简单易懂,容易实现。计算信息熵和信息增益的概念直观,能够很好地处理离散特征。
    • 对小规模数据表现良好,能快速构建决策树。
  4. 缺点

    • 倾向于选择取值较多的属性,可能导致过拟合。例如,一个特征有很多不同的值,每个值对应的类别比较单一,这个特征会被优先选择,但可能只是巧合,对新数据的泛化能力差。
    • 只能处理离散型属性,无法直接处理连续型属性。

二、C4.5算法

  1. 原理

    • 信息增益比(Gain Ratio):为了克服ID3算法倾向于选择取值较多属性的问题,C4.5算法引入信息增益比。首先计算属性 a a a的固有值 H a ( D ) H_a(D) Ha(D)
      H a ( D ) = − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ log ⁡ 2 ∣ D v ∣ ∣ D ∣ H_a(D)=-\sum_{v = 1}^{V}\frac{|D^v|}{|D|}\log_2\frac{|D^v|}{|D|} Ha(D)=v=1VDDvlog2DDv
      信息增益比 g R ( D , a ) g_R(D,a) gR(D,a)计算公式为:
      g R ( D , a ) = g ( D , a ) H a ( D ) g_R(D,a)=\frac{g(D,a)}{H_a(D)} gR(D,a)=Ha(D)g(D,a)
      例如,在一个植物分类数据集中,有一个特征“叶子形状”有多种取值。通过计算信息增益比,可以更平衡地考虑这个特征的划分效果。
    • 树的构建过程与ID3类似,从根节点开始,计算每个特征的信息增益比,选择信息增益比最大的特征作为划分特征,在划分后的子集上重复此步骤,直到满足停止条件。
  2. 应用场景

    • 同ID3一样,主要用于分类问题,尤其在处理离散型特征的分类任务时表现出色。例如,在医疗诊断中,根据患者的症状(离散特征)判断疾病类型。
  3. 优点

    • 克服了ID3算法对取值较多属性的偏好,使得决策树的构建更加合理。
    • 能够处理离散型和连续型属性。对于连续型属性,先将其离散化,再进行处理。
  4. 缺点

    • 计算信息增益比相对复杂,算法效率比ID3稍低。
    • 连续型属性的离散化过程可能会丢失信息,影响决策树的性能。

三、CART算法(分类与回归树)

  1. 原理 - 分类任务

    • 基尼指数(Gini Index):用于衡量数据集的纯度。对于数据集 D D D,基尼指数 G i n i ( D ) Gini(D) Gini(D)计算公式为:
      G i n i ( D ) = ∑ k = 1 n p k ( 1 − p k ) = 1 − ∑ k = 1 n p k 2 Gini(D)=\sum_{k = 1}^{n}p_k(1 - p_k)=1 - \sum_{k = 1}^{n}p_k^2 Gini(D)=k=1npk(1pk)=1k=1npk2
      当使用属性 a a a对数据集 D D D进行划分,属性 a a a V V V个取值,得到 V V V个子集 { D 1 , D 2 , ⋯   , D V } \{D^1,D^2,\cdots,D^V\} {D1,D2,,DV},划分后的基尼指数 G i n i _ i n d e x ( D , a ) Gini\_index(D,a) Gini_index(D,a)为:
      G i n i _ i n d e x ( D , a ) = ∑ v = 1 V ∣ D v ∣ ∣ D ∣ G i n i ( D v ) Gini\_index(D,a)=\sum_{v = 1}^{V}\frac{|D^v|}{|D|}Gini(D^v) Gini_index(D,a)=v=1VDDvGini(Dv)
      例如,在一个判断用户是否购买某产品的数据集中,计算“用户年龄”这个特征的基尼指数。根据不同年龄划分数据集后,计算每个子集的基尼指数,再根据子集大小加权求和,选择基尼指数最小的属性作为划分属性,使划分后的数据集纯度更高。
    • 构建树时,从根节点开始,计算每个特征的基尼指数,选择基尼指数最小的特征和对应的划分点进行划分。在划分后的子节点上重复此步骤,直到满足停止条件(如树的深度达到限制、节点中的样本数量小于阈值等)。
    • 原理 - 回归任务
    • 最小平方误差(MSE):对于一个节点的数据集 D D D,其目标值(如房价预测中的房价)的均值为 y ‾ \overline{y} y,则该节点的平方误差为:
      M S E = 1 ∣ D ∣ ∑ i ∈ D ( y i − y ‾ ) 2 MSE = \frac{1}{|D|}\sum_{i\in D}(y_i - \overline{y})^2 MSE=D1iD(yiy)2
      在选择划分特征和划分点时,遍历所有特征和可能的划分点,计算划分后的两个子节点的MSE之和。选择使MSE之和最小的特征和划分点进行划分。例如,在房价预测中,对于“房屋面积”这个特征,尝试不同划分点,计算划分后的MSE之和,找到最小的划分点。
  2. 应用场景

    • 既可以用于分类任务,如客户流失预测(根据客户行为特征判断是否流失),也可以用于回归任务,如房价预测、销售额预测等。
  3. 优点

    • 对于分类和回归任务都有很好的适用性,是一种通用的决策树算法。
    • 可以处理连续型和离散型数据,不需要像C4.5那样对连续型数据进行额外的离散化处理。
    • 能够自动处理缺失值,在一定程度上增强了算法的鲁棒性。
  4. 缺点

    • 对异常值比较敏感。在回归任务中,异常值可能会导致MSE计算出现较大偏差,影响树的构建。
    • 构建的树可能会比较复杂,容易出现过拟合现象,需要进行剪枝处理。

四、CHAID算法

  1. 原理

    • 卡方检验(Chi - squared test):基于卡方检验来确定最佳的分类变量和分割点。对于两个分类变量 A A A B B B A A A r r r个类别, B B B c c c个类别,列联表中的每个单元格 ( i , j ) (i, j) (i,j)表示 A A A的第 i i i类和 B B B的第 j j j类的交叉频数 n i j n_{ij} nij。卡方统计量 χ 2 \chi^2 χ2计算公式为:
      χ 2 = ∑ i = 1 r ∑ j = 1 c ( n i j − E i j ) 2 E i j \chi^2=\sum_{i = 1}^{r}\sum_{j = 1}^{c}\frac{(n_{ij}-E_{ij})^2}{E_{ij}} χ2=i=1rj=1cEij(nijEij)2
      其中 E i j E_{ij} Eij是期望频数, E i j = n i ⋅ n ⋅ j n E_{ij}=\frac{n_{i\cdot}n_{\cdot j}}{n} Eij=nninj n i ⋅ n_{i\cdot} ni是第 i i i行的总和, n ⋅ j n_{\cdot j} nj是第 j j j列的总和, n n n是总的样本数。
    • 在决策树构建过程中,对于每个节点,对所有可能的分类变量进行卡方检验,计算每个变量作为分割变量时的卡方统计量。根据统计显著性水平(如 p − v a l u e = 0.05 p - value = 0.05 pvalue=0.05)来决定是否进行分割。若 p − v a l u e p - value pvalue大于设定的显著性水平,说明分割后的子节点之间没有显著差异,就不进行分割。
    • 例如,在市场调查数据中,研究消费者性别(男/女)和购买产品类型(电子产品/日用品/食品)之间的关联。通过卡方检验构建决策树,若性别和产品类型之间有显著关联,就以此为依据进行分割。
  2. 应用场景

    • 主要用于分类问题,尤其适用于处理多个分类变量之间的关系。例如,在市场细分中,根据消费者的多种属性(如年龄、性别、收入等分类变量)对市场进行细分。
  3. 优点

    • 能够有效处理分类变量之间的相互关系,挖掘变量之间的关联,使得决策树的分割更有意义。
    • 基于统计检验进行分割,具有一定的统计学理论支持,结果相对可靠。
  4. 缺点

    • 只能处理分类变量,对于连续型变量需要先进行离散化处理。
    • 计算卡方统计量和进行假设检验相对复杂,当数据量较大时,计算成本较高。

决策树算法对比与示例

一、对比

  1. 特征选择标准
    • ID3:基于信息增益选择特征。倾向于选择具有较多取值的特征,因为这样的特征可能会使信息增益较大。例如,在一个有“颜色”(红、绿、蓝)和“形状”(圆、方)的数据集用于区分两种物体时,如果“颜色”这个特征每个取值对应的类别很单一,那么它的信息增益可能会很大,容易被优先选择。
    • C4.5:使用信息增益比来克服ID3对取值较多特征的偏好。通过计算属性的固有值,将信息增益标准化。在一个包含多种植物特征的数据集里,像“叶子形状”这种有多种变化的特征不会因为取值多就被过度选择,而是综合考虑其信息增益比。
    • CART(分类):依据基尼指数选择特征。基尼指数衡量数据集的不纯度,选择使划分后基尼指数最小的特征。例如在判断客户是否购买产品的数据集,CART会考虑哪个特征能让划分后的子节点纯度更高,更关注类别分布的均匀性。
    • CHAID:以卡方检验来确定最佳分类变量和分割点。重点在于检验分类变量之间的关联性。在市场调研数据中,若研究消费者性别和购买产品类型的关系,通过卡方检验判断这种关联是否显著来决定是否以此为分割变量。
  2. 数据类型处理
    • ID3:主要处理离散型特征,对于连续型特征需要先进行离散化处理才能使用。
    • C4.5:可以处理离散型和连续型特征。对于连续型特征,先将其离散化,不过这个过程可能会丢失信息。
    • CART:能够自然地处理连续型和离散型数据。在回归任务中直接利用连续型数据计算最小平方误差,在分类任务中处理离散型数据计算基尼指数。
    • CHAID:主要用于处理分类变量,对于连续型变量要先进行离散化才能应用卡方检验。
  3. 树的构建方式
    • ID3:从根节点开始,每次选择信息增益最大的特征进行划分,直到满足停止条件。例如在一个简单的动物分类数据集(分为哺乳动物和非哺乳动物),以“是否有毛发”作为信息增益最大的特征先划分,然后在子节点继续找信息增益最大的特征划分。
    • C4.5:类似于ID3,但以信息增益比来选择划分特征。构建过程中不断寻找信息增益比最大的特征进行划分,递归构建树结构。
    • CART(分类):从根节点开始,计算每个特征的基尼指数,选择基尼指数最小的特征和对应的划分点进行划分,重复这个过程构建树。
    • CHAID:从根节点开始,对所有可能的分类变量进行卡方检验,根据统计显著性水平决定是否进行分割。若变量之间关联显著,就以此为依据进行分割,递归构建树。
  4. 过拟合情况
    • ID3:容易过拟合,因为倾向于选择取值较多的特征,可能会学到数据中的噪声。例如在一个包含很多无关特征且部分特征取值多样的数据集上,ID3可能会构建出过于复杂的树。
    • C4.5:通过信息增益比在一定程度上缓解了过拟合,但连续型特征离散化过程可能引入新问题导致过拟合。
    • CART:也可能过拟合,尤其是在数据有噪声或者树的深度没有有效控制时。不过它的剪枝方法相对成熟,可以较好地处理过拟合。
    • CHAID:如果不注意统计显著性水平的设置,可能会过度分割,导致过拟合。而且它对数据的分布和变量之间的关系比较敏感,容易在复杂的数据关系中产生过拟合。

二、示例

假设我们有一个数据集用于判断是否购买电脑,数据集如下:

年龄收入学生信用等级是否购买电脑
青年一般
青年
青年一般
中年
中年一般
老年一般
老年
老年一般
  1. ID3算法示例
    • 首先计算根节点的信息熵:
      • 数据集中总共有 n = 8 n = 8 n=8个样本,其中购买电脑的样本数为 n 1 = 5 n_1 = 5 n1=5,不购买电脑的样本数为 n 2 = 3 n_2 = 3 n2=3
      • 则购买电脑的样本比例 p 1 = n 1 n = 5 8 p_1=\frac{n_1}{n}=\frac{5}{8} p1=nn1=85,不购买电脑的样本比例 p 2 = n 2 n = 3 8 p_2=\frac{n_2}{n}=\frac{3}{8} p2=nn2=83
      • 根据信息熵公式 H ( D ) = − ∑ k = 1 n p k log ⁡ 2 p k H(D)=-\sum_{k = 1}^{n}p_k\log_2p_k H(D)=k=1npklog2pk,这里 n = 2 n = 2 n=2,所以根节点的信息熵为:
        H ( D ) = − 5 8 log ⁡ 2 5 8 − 3 8 log ⁡ 2 3 8 ≈ 0.954 H(D)=-\frac{5}{8}\log_2\frac{5}{8}-\frac{3}{8}\log_2\frac{3}{8}\approx0.954 H(D)=85log28583log2830.954
    • 然后计算每个特征的信息增益:
      • 年龄特征:“年龄”特征有三个取值:青年、中年、老年。
        • 青年对应的子集 D 青年 D_{青年} D青年中有 3 3 3个样本,其中购买电脑的有 1 1 1个,不购买电脑的有 2 2 2个。所以在这个子集中,购买电脑的比例 p 1 , 青年 = 1 3 p_{1,青年}=\frac{1}{3} p1,青年=31,不购买电脑的比例 p 2 , 青年 = 2 3 p_{2,青年}=\frac{2}{3} p2,青年=32
        • 根据信息熵公式, D 青年 D_{青年} D青年的信息熵为 H ( D 青年 ) = − 1 3 log ⁡ 2 1 3 − 2 3 log ⁡ 2 2 3 ≈ 0.918 H(D_{青年})=-\frac{1}{3}\log_2\frac{1}{3}-\frac{2}{3}\log_2\frac{2}{3}\approx0.918 H(D青年)=31log23132log2320.918
        • 中年对应的子集 D 中年 D_{中年} D中年中有 2 2 2个样本,都购买电脑,所以 H ( D 中年 ) = 0 H(D_{中年}) = 0 H(D中年)=0
        • 老年对应的子集 D 老年 D_{老年} D老年中有 3 3 3个样本,其中购买电脑的有 2 2 2个,不购买电脑的有 1 1 1个。所以 H ( D 老年 ) = − 2 3 log ⁡ 2 2 3 − 1 3 log ⁡ 2 1 3 ≈ 0.918 H(D_{老年})=-\frac{2}{3}\log_2\frac{2}{3}-\frac{1}{3}\log_2\frac{1}{3}\approx0.918 H(D老年)=32log23231log2310.918
        • “年龄”特征划分后的信息增益 g ( D , 年龄 ) g(D,年龄) g(D,年龄),根据公式 g ( D , a ) = H ( D ) − ∑ v = 1 V ∣ D v ∣ ∣ D ∣ H ( D v ) g(D,a)=H(D)-\sum_{v = 1}^{V}\frac{|D^v|}{|D|}H(D^v) g(D,a)=H(D)v=1VDDvH(Dv),这里 V = 3 V = 3 V=3 ∣ D 青年 ∣ = 3 |D_{青年}| = 3 D青年=3 ∣ D 中年 ∣ = 2 |D_{中年}| = 2 D中年=2 ∣ D 老年 ∣ = 3 |D_{老年}| = 3 D老年=3 ∣ D ∣ = 8 |D| = 8 D=8,所以:
          g ( D , 年龄 ) = 0.954 − ( 3 8 × 0.918 + 2 8 × 0 + 3 8 × 0.918 ) ≈ 0.042 g(D,年龄)=0.954-(\frac{3}{8}×0.918+\frac{2}{8}×0+\frac{3}{8}×0.918)\approx0.042 g(D,年龄)=0.954(83×0.918+82×0+83×0.918)0.042
      • 同样地,可以计算“收入”“学生”“信用等级”等特征的信息增益。假设经过计算“学生”特征的信息增益最大。
    • 以“学生”作为根节点的划分特征构建决策树。对于“学生”为“是”的分支,该子集中所有样本都购买电脑,所以这个分支是一个叶节点,标记为“是”。对于“学生”为“否”的分支,这个子集中包含了 4 4 4个样本,在这个子集中继续计算剩余特征(“年龄”、“收入”、“信用等级”)的信息增益,重复上述步骤进行划分,直到所有子集的样本都属于同一类别或者满足停止条件。
  2. C4.5算法示例
    • 首先计算根节点信息熵,同ID3算法, H ( D ) ≈ 0.954 H(D)\approx0.954 H(D)0.954
    • 计算每个特征的信息增益比。以“年龄”特征为例,先计算其信息增益(同ID3计算过程) g ( D , 年龄 ) ≈ 0.042 g(D,年龄)\approx0.042 g(D,年龄)0.042
    • 然后计算属性“年龄”的固有值 H a ( D ) H_a(D) Ha(D)
      • “年龄”有三个取值, ∣ D 青年 ∣ = 3 |D_{青年}| = 3 D青年=3 ∣ D 中年 ∣ = 2 |D_{中年}| = 2 D中年=2 ∣ D 老年 ∣ = 3 |D_{老年}| = 3 D老年=3 ∣ D ∣ = 8 |D| = 8 D=8
      • H a ( D ) = − 3 8 log ⁡ 2 3 8 − 2 8 log ⁡ 2 2 8 − 3 8 log ⁡ 2 3 8 ≈ 1.56 H_a(D)=-\frac{3}{8}\log_2\frac{3}{8}-\frac{2}{8}\log_2\frac{2}{8}-\frac{3}{8}\log_2\frac{3}{8}\approx1.56 Ha(D)=83log28382log28283log2831.56
      • 信息增益比 g R ( D , 年龄 ) = g ( D , 年龄 ) H a ( D ) = 0.042 1.56 ≈ 0.027 g_R(D,年龄)=\frac{g(D,年龄)}{H_a(D)}=\frac{0.042}{1.56}\approx0.027 gR(D,年龄)=Ha(D)g(D,年龄)=1.560.0420.027
    • 同样计算其他特征的信息增益比,假设“信用等级”特征的信息增益比最大。以“信用等级”作为根节点的划分特征构建决策树,后续步骤同ID3算法,在划分后的子集上继续计算信息增益比来选择划分特征,直到满足停止条件。
  3. CART算法示例(分类)
    • 计算根节点的基尼指数:
      • 数据集中购买电脑的样本比例 p 1 = 5 8 p_1=\frac{5}{8} p1=85,不购买电脑的样本比例 p 2 = 3 8 p_2=\frac{3}{8} p2=83
      • 根据基尼指数公式 G i n i ( D ) = ∑ k = 1 n p k ( 1 − p k ) = 1 − ∑ k = 1 n p k 2 Gini(D)=\sum_{k = 1}^{n}p_k(1 - p_k)=1 - \sum_{k = 1}^{n}p_k^2 Gini(D)=k=1npk(1pk)=1k=1npk2,这里 n = 2 n = 2 n=2,所以根节点的基尼指数为:
        G i n i ( D ) = 1 − ( 5 8 ) 2 − ( 3 8 ) 2 = 0.469 Gini(D)=1 - (\frac{5}{8})^2-(\frac{3}{8})^2 = 0.469 Gini(D)=1(85)2(83)2=0.469
    • 计算每个特征划分后的基尼指数。以“学生”特征为例,“学生”有“是”和“否”两个取值。
      • “学生”为“是”的子集 D 是 D_{是} D中有 4 4 4个样本,都购买电脑, G i n i ( D 是 ) = 0 Gini(D_{是}) = 0 Gini(D)=0
      • “学生”为“否”的子集 D 否 D_{否} D中有 4 4 4个样本,其中购买电脑的有 1 1 1个,不购买电脑的有 3 3 3个,购买电脑的比例 p 1 , 否 = 1 4 p_{1,否}=\frac{1}{4} p1,=41,不购买电脑的比例 p 2 , 否 = 3 4 p_{2,否}=\frac{3}{4} p2,=43 G i n i ( D 否 ) = 1 − ( 1 4 ) 2 − ( 3 4 ) 2 = 0.375 Gini(D_{否}) = 1 - (\frac{1}{4})^2-(\frac{3}{4})^2 = 0.375 Gini(D)=1(41)2(43)2=0.375
      • 划分后的基尼指数 G i n i _ i n d e x ( D , 学生 ) = 4 8 × 0 + 4 8 × 0.375 = 0.188 Gini\_index(D,学生)=\frac{4}{8}×0+\frac{4}{8}×0.375 = 0.188 Gini_index(D,学生)=84×0+84×0.375=0.188
    • 同样计算其他特征划分后的基尼指数,假设“信用等级”特征划分后的基尼指数最小。以“信用等级”作为根节点的划分特征构建决策树,对于划分后的子节点,继续计算基尼指数选择划分特征,直到满足停止条件。
  4. CHAID算法示例
    • 假设我们要研究“年龄”和“是否购买电脑”之间的关系。构建列联表如下:
      |年龄|购买电脑|不购买电脑|
      |—|—|—|
      |青年|1|2|
      |中年|2|0|
      |老年|2|1|
    • 计算卡方统计量。先计算期望频数,例如对于“青年 - 购买电脑”单元格,期望频数 E 11 = ( 1 + 2 ) × ( 1 + 2 + 2 + 1 ) 8 = 3 × 6 8 = 2.25 E_{11}=\frac{(1 + 2)×(1 + 2 + 2 + 1)}{8}=\frac{3×6}{8}=2.25 E11=8(1+2)×(1+2+2+1)=83×6=2.25
    • 然后根据卡方统计量公式 χ 2 = ∑ i = 1 r ∑ j = 1 c ( n i j − E i j ) 2 E i j \chi^2=\sum_{i = 1}^{r}\sum_{j = 1}^{c}\frac{(n_{ij}-E_{ij})^2}{E_{ij}} χ2=i=1rj=1cEij(nijEij)2计算卡方值。假设经过计算与其他特征相比,“年龄”和“是否购买电脑”的卡方值对应的 p − v a l u e p - value pvalue小于设定的显著性水平(如 0.05 0.05 0.05),则可以以“年龄”作为根节点的划分特征。
    • 对于划分后的子集,继续对其他特征进行卡方检验,决定是否进一步划分,直到满足停止条件(如所有 p − v a l u e p - value pvalue大于显著性水平)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

rubyw

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

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

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

打赏作者

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

抵扣说明:

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

余额充值