EnsembleLearning-机器学习基础(day5)

第一章 机器学习基础

基本的分类模型

机器学习项目分为以下步骤

  • 明确项目任务:回归/分类
  • 收集数据集并选择合适的特征。
  • 选择度量模型性能的指标。
  • 选择具体的模型并进行训练以优化模型。
  • 评估模型的性能并调参。

这里还是按照这个顺序展开

1. 明确项目任务

分类

2. 收集数据集并选择合适的特征

import pandas as pd

from sklearn import datasets
iris = datasets.load_iris()
X = iris.data
y = iris.target
feature = iris.feature_names
data = pd.DataFrame(X,columns=feature)
data['target'] = y
data.head()

各个特征的相关解释:

  • sepal length (cm):花萼长度(厘米)
  • sepal width (cm):花萼宽度(厘米)
  • petal length (cm):花瓣长度(厘米)
  • petal width (cm):花瓣宽度(厘米)

3. 选择度量模型性能的指标

度量分类模型的指标和回归的指标有很大的差异,首先是因为分类问题本身的因变量是离散变量,因此像定义回归的指标那样,单单衡量预测值和因变量的相似度可能行不通。其次,在分类任务中,我们对于每个类别犯错的代价不尽相同,例如:我们将癌症患者错误预测为无癌症和无癌症患者错误预测为癌症患者,在医院和个人的代价都是不同的,前者会使得患者无法得到及时的救治而耽搁了最佳治疗时间甚至付出生命的代价,而后者只需要在后续的治疗过程中继续取证就好了,因此我们很不希望出现前者,当我们发生了前者这样的错误的时候会认为建立的模型是很差的。为了解决这些问题,我们必须将各种情况分开讨论,然后给出评价指标。

准确率,精确率,召回率,F1score(精确率,召回率,F1score都分为宏平均,微平均),ROC等。

先看准确率,精确率,召回率,F1score
在这里插入图片描述

  • 真阳性TP:实际分类结果和预测结果一致,都是正例。
  • 真阴性TN:实际分类结果和预测结果一致,都是反例。
  • 假阳性FP:实际分类结果是负例,预测分类结果是正例。
  • 假阴性FN:实际分类结果是正例,预测分类结果是负例。

准确率acc: a c c = T P + T N T P + T N + F P + F N acc = \frac{TP + TN}{TP + TN + FP + FN} acc=TP+TN+FP+FNTP+TN。分类正确的样本数占总样本的比例。

精确率precision: p r e c i s i o n = T P T P + F P precision = \frac{TP}{TP + FP} precision=TP+FPTP。预测为正且预测正确占预测为正样本的比例。查准率这个名字更好理解。精确率直观地可以说是分类器不将负样本标记为正样本的能力.

召回率recall: r e c a l l = T P T P + F N recall = \frac{TP}{TP + FN} recall=TP+FNTP。预测为正且预测正确占实际为正样本的比例。查全率。召回率直观地说是分类器找到所有正样本的能力

F1值 2 f 1 _ s c o r e = 1 p r e c i s i o n + 1 r e c a l l \frac{2}{f1\_score} = \frac{1}{precision} + \frac{1}{recall} f1_score2=precision1+recall1,转化为 f 1 _ s c o r e = 2 P R E × R E C P R E + R E C f1\_score = 2\frac{PRE\times REC}{PRE + REC} f1_score=2PRE+RECPRE×REC。false相对减少,即Precision和Recall都相对增加,即F1对Precision和Recall都进行了加权。F1 score是两者的综合,可以解释为精确率和召回率的加权平均值,F1 score越高,说明模型越稳健。

精确率,召回率,F1值又可以分为:
宏平均(Macro Average)是指在计算均值时使每个类别具有相同的权重,最后结果是每个类别的指标的算术平均值。

微平均(Micro Average)是指计算多分类指标时赋予所有类别的每个样本相同的权重,将所有样本合在一起计算各个指标。

ROC 和 AUC
ROC曲线以假阳率为横轴,真阳率为纵轴画出来的曲线,曲线下方面积越大越好。
AUC是一种模型分类指标,且仅仅是二分类模型的评价指标。AUC是Area Under Curve的简称,那么Curve就是ROC(Receiver Operating Characteristic),翻译为"接受者操作特性曲线"。也就是说ROC是一条曲线,AUC是一个面积值。

ROC曲线为 FPR 与 TPR 之间的关系曲线,这个组合以 FPR 对 TPR,即是以代价 (costs) 对收益 (benefits),显然收益越高,代价越低,模型的性能就越好。最好就是FPR=0且TPR=1.

横轴为假阳性率(FPR):在所有的负样本中,分类器预测错误的比例:
F P R = F P F P + T N FPR = \frac{FP}{FP + TN} FPR=FP+TNFP

纵轴为真阳性率(TPR):在所有的正样本中,分类器预测正确的比例(等于Recall)
T P R = T P T P + F N TPR = \frac{TP}{TP + FN} TPR=TP+FNTP

在这里插入图片描述

4. 选择具体的模型并进行训练

4.1 逻辑回归(logistic regression)

在线性回归的基础上加上sigmoid激活函数。

4.1.1 背景

说到分类问题与回归问题的区别,在于回归问题与分类问题需要预测的因变量不一样。在回归问题中,因变量是连续性变量,我们需要预测 E ( Y ∣ X ) E(Y|X) E(YX)是一个连续的实数,但是在分类问题中,我们往往是通过已知X的信息预测Y的类别,往往是一个离散集合中的某个元素。如:是否患癌症,图片是猫还是狗等。一个很自然的想法是能否用线性回归去处理分类问题,答案是可以但不好!先来看看线性回归处理分类问题会出现什么弊端,我们仔细来看这个线性回归的例子, d e f a u l t = β 0 + β 1 B a l a n c e + β 2 I n c o m e {default = \beta_0 + \beta_1 Balance + \beta_2 Income} default=β0+β1Balance+β2Income,只要输入Balance 和 Income 以及default的数据就能用最小二乘法估计出 β 0 , β 1 {\beta_0,\beta_1} β0,β1,设定预测的default>0.5就是违约反之不违约,感觉很完美的样子,但事实真的是这样吗?假设我们需要用某个人的债务(Balance)和收入(Income)去预测是否会信用卡违约(default):

  • 我们假设有一个穷人Lisa,他的Balance和Income都很小,那么有可能会导致default的值为负数,那么这个负数代表什么意义呢?显然是没有任何意义的。
    在这里插入图片描述

当我们的分类变量是多类的时候,以0.5为界限划分分类就不可用了,那么我们应该怎么找到一个界限衡量多分类呢?

基于以上问题,现在大家是否还觉得线性回归模型作为一个分类模型是否足够优秀呢?其实,为了解决以上的问题(1)我们来想想能不能将线性回归的结果default转化为区间[0:1]上,让default转变成一个违约的概率呢?下面我们来解决这个问题吧。

4.1.2 sigmoid

sigmoid: s i g m o i d = 1 1 − e − x sigmoid = \frac{1}{1-e^{-x}} sigmoid=1ex1

在推导逻辑回归之前,我们先来认识下一组函数,这组函数具有神奇的作用,可以将是实数轴上的数转换为[0:1]区间上的概率。

首先,我们假设我们的线性回归模型为 Y = β 0 + β 1 X {Y=\beta_0+\beta_1 X} Y=β0+β1X,那么这个函数是如何将线性回归的结果转化为概率呢?这个函数就是logistic 函数,具体的形式为 p ( X ) = e β 0 + β 1 X 1 + e β 0 + β 1 X {p(X) = \dfrac{e^{\beta_0 + \beta_1X}}{1+e^{\beta_0 + \beta_1X}}} p(X)=1+eβ0+β1Xeβ0+β1X,他的函数图像如下图:(左边是线性回归,右边是逻辑函数)

在这里插入图片描述
因此,我们假设逻辑回归模型为: p ( y = 1 ∣ x ) = 1 1 + e − w T x p(y = 1|x) = \frac{1}{1+e^{-w^Tx}} p(y=1x)=1+ewTx1 .

下面我们来具体推导下逻辑回归模型:
假设数据Data { ( x i , y i ) } ,      i = 1 , 2 , . . . , N ,      x i ∈ R p , y i ∈ { 0 , 1 } \{(x_i,y_i) \},\;\;i = 1,2,...,N,\;\;x_i \in R^p,y_i \in \{0,1 \} {(xi,yi)},i=1,2,...,N,xiRp,yi{0,1},设 p 1 = p ( y = 1 ∣ x ) = σ ( w T ) = 1 1 + e − w T x p_1 = p(y=1|x) = \sigma(w^T) = \frac{1}{1+e^{-w^Tx}} p1=p(y=1x)=σ(wT)=1+ewTx1。因为y只可能取0或者1,因此假设数据服从0-1分布,也叫伯努力分布,即:当y=1时, p ( y ∣ x ) = p 1 p(y|x)=p_1 p(yx)=p1,当y=0时, p ( y ∣ x ) = 1 − p 1 p(y|x)=1-p_1 p(yx)=1p1,可以写成 p ( y ∣ x ) = p 1 y ( 1 − p 1 ) 1 − y p(y|x) = p_1^y(1-p_1)^{1-y} p(yx)=p1y(1p1)1y,可以带入y=0和y=1进去验证,结果和前面的结论一模一样。
(没完成---------------------)

4.2 基于概率的分类模型

4.2.1 线性判别分析:

线性判别分析是一个比较久远的算法,我将会从两个方向去描述这个算法,因为我觉得每位读者都有自己喜欢的那个理解的方向,分别是基于贝叶斯公式降维分类的思想。

(a)基于贝叶斯公式对线性判别分析的理解

贝叶斯定理:

  1. P ( Y = k ∣ X = x ) = π k f k ( x ) ∑ l = 1 K π l f l ( x ) {P(Y=k|X=x) = \dfrac{{\pi}_kf_k(x)}{\sum\limits_{l=1}^K{\pi}_lf_l(x)}} P(Y=kX=x)=l=1Kπlfl(x)πkfk(x)
    假设观测有 K , k ∈ K {K,k \in K} K,kK类, π k {\pi_k} πk为随机选择的观测来自第 k {k} k类的先验概率,也就是样本里面第 k {k} k类的样本个数除以总样本的个数: π k = n k n {\pi_k = \dfrac{n_k}{n}} πk=nnk
  2. f k ( x ) = P ( X = x ∣ Y = k ) {f_k(x) =P(X=x|Y=k)} fk(x)=P(X=xY=k),表示第 k {k} k类观测的X的密度函数,说的直白一点就是在 Y = k {Y=k} Y=k的样本里, X = x {X=x} X=x的样本个数,即 f k ( x ) = P ( X = x ∣ Y = k ) = n ( X = x , Y = k ) n ( Y = k ) {f_k(x) = P(X=x|Y=k) = \dfrac{n_{(X=x,Y=k)}}{n_{(Y=k)}}} fk(x)=P(X=xY=k)=n(Y=k)n(X=x,Y=k)
  3. ∑ l = 1 K π l f l ( x ) = P ( X = x ) = n ( X = x ) n {\sum\limits_{l=1}^K{\pi}_lf_l(x)}=P(X=x)=\dfrac{n_{(X=x)}}{n} l=1Kπlfl(x)=P(X=x)=nn(X=x),也就是样本中 X = x {X=x} X=x的概率

在讨论贝叶斯定理后,我们回到分类问题,这个定理跟我们的分类问题有什么关联呢?没错,这个公式 P ( Y = k ∣ X = x ) = π k f k ( x ) ∑ l = 1 K π l f l ( x ) {P(Y=k|X=x) = \dfrac{{\pi}_kf_k(x)}{\sum\limits_{l=1}^K{\pi}_lf_l(x)}} P(Y=kX=x)=l=1Kπlfl(x)πkfk(x)给出了给定样本条件下, Y = k {Y=k} Y=k这个类别下的概率,这给分类问题提供了一条思路,那就是计算这个 P ( Y = k ∣ X = x ) {P(Y=k|X=x)} P(Y=kX=x),而且我们的逻辑回归就是这么干的,但是在 P ( Y = k ∣ X = x ) = π k f k ( x ) ∑ l = 1 K π l f l ( x ) {P(Y=k|X=x) = \dfrac{{\pi}_kf_k(x)}{\sum\limits_{l=1}^K{\pi}_lf_l(x)}} P(Y=kX=x)=l=1Kπlfl(x)πkfk(x)这个公式中,分母 ∑ l = 1 K π l f l ( x ) = P ( X = x ) {{\sum\limits_{l=1}^K{\pi}_lf_l(x)} = P(X=x)} l=1Kπlfl(x)=P(X=x)当样本给定的时候是一个与分类 k {k} k无关的常数,所以我们的问题可以简化为只需要计算分子 π k f k ( x ) {{\pi}_kf_k(x)} πkfk(x),进而比较哪个类别的概率最大就知道属于哪个类别了,因此我们的分类思路就出来啦,这个思路不同于逻辑回归,逻辑回归需要计算具体的 P ( Y = k ∣ X = x ) {P(Y=k|X=x)} P(Y=kX=x)概率值,而我们现在的思路是通过贝叶斯定理计算贝叶斯定理的分子,比较分子最大的那个类别为最终类别。

(没完成---------------------)

(b)降维分类的思想理解线性判别分析

基于数据进行分类时,一个很自然的想法是:将高维的数据降维至一维,然后使用某个阈值将各个类别分开。下面用图的形式展示:
在这里插入图片描述
图中,数据的维度是二维的,我们的想法是把数据降维至一维,然后用阈值就能分类。这个似乎是一个很好的想法,我们总是希望降维后的数据同一个类别自身内部方差小,不同类别之间的方差要尽可能大。这也是合理的,因为同一个类别的数据应该更加相似,因此方差小;不同类别的数据之间应该很不相似,这样才能更容易对数据进行分类,我们简称为:类内方差小,类间方差大,在计算机语言叫 “松耦合,高内聚”。在做具体的推导之前,我们对数据的形式和一些基本统计量做一些描述:

特征 X = ( x 1 , x 2 , . . . , x N ) T X = (x_1,x_2,...,x_N)^T X=(x1,x2,...,xN)T,因变量 Y = ( y 1 , y 2 , . . . , y N ) T Y = (y_1,y_2,...,y_N)^T Y=(y1,y2,...,yN)T,其中, y i ∈ { + 1 , − 1 } y_i \in \{+1,-1 \} yi{+1,1},类别c1的特征 X c 1 = { x i ∣ y i = + 1 } X_{c_1} = \{x_i|y_i=+1 \} Xc1={xiyi=+1},同理,类别c2的特征 X c 2 = { x i ∣ y i = − 1 } X_{c_2} = \{x_i|y_i=-1 \} Xc2={xiyi=1},属于c1类别的数据个数为 N 1 N_1 N1,属于类别c2的数据个数为 N 2 N_2 N2,其中, N 1 + N 2 = N N_1+N_2 = N N1+N2=N

  • 特征X投影在w方向至一维: z i = w T x i ,      ∣ ∣ w ∣ ∣ = 1 z_i = w^Tx_i,\;\;||w|| = 1 zi=wTxi,w=1
  • 全样本投影的均值 z ˉ = 1 N ∑ i = 1 N z i = 1 N ∑ i = 1 N w T x i \bar{z} = \frac{1}{N}\sum\limits_{i=1}^{N}z_i = \frac{1}{N}\sum\limits_{i=1}^{N}w^Tx_i zˉ=N1i=1Nzi=N1i=1NwTxi
  • 全样本投影的协方差 S z = 1 N ∑ i = 1 N ( z i − z ˉ ) ( z i − z ˉ ) T = 1 N ∑ i = 1 N ( w T x i − z ˉ ) ( w T x i − z ˉ ) T S_z = \frac{1}{N}\sum\limits_{i=1}^{N}(z_i-\bar{z})(z_i-\bar{z})^T = \frac{1}{N}\sum\limits_{i=1}^{N}(w^Tx_i-\bar{z})(w^Tx_i-\bar{z})^T Sz=N1i=1N(zizˉ)(zizˉ)T=N1i=1N(wTxizˉ)(wTxizˉ)T
  • c1样本投影的均值 z 1 ˉ = 1 N 1 ∑ i = 1 N 1 z i = 1 N 1 ∑ i = 1 N 1 w T x i \bar{z_1} = \frac{1}{N_1}\sum\limits_{i=1}^{N_1}z_i = \frac{1}{N_1}\sum\limits_{i=1}^{N_1}w^Tx_i z1ˉ=N11i=1N1zi=N11i=1N1wTxi
  • c1样本投影的协方差 S z 1 = 1 N 1 ∑ i = 1 N 1 ( z i − z 1 ˉ ) ( z i − z 1 ˉ ) T = 1 N 1 ∑ i = 1 N 1 ( w T x i − z 1 ˉ ) ( w T x i − z 1 ˉ ) T S_{z_1} = \frac{1}{N_1}\sum\limits_{i=1}^{N_1}(z_i-\bar{z_1})(z_i-\bar{z_1})^T = \frac{1}{N_1}\sum\limits_{i=1}^{N_1}(w^Tx_i-\bar{z_1})(w^Tx_i-\bar{z_1})^T Sz1=N11i=1N1(ziz1ˉ)(ziz1ˉ)T=N11i=1N1(wTxiz1ˉ)(wTxiz1ˉ)T
  • c2样本投影的均值 z 2 ˉ = 1 N 2 ∑ i = 1 N 2 z i = 1 N 2 ∑ i = 1 N 2 w T x i \bar{z_2} = \frac{1}{N_2}\sum\limits_{i=1}^{N_2}z_i = \frac{1}{N_2}\sum\limits_{i=1}^{N_2}w^Tx_i z2ˉ=N21i=1N2zi=N21i=1N2wTxi
  • c2样本投影的协方差 S z 2 = 1 N 2 ∑ i = 1 N 2 ( z i − z 2 ˉ ) ( z i − z 2 ˉ ) T = 1 N 2 ∑ i = 1 N 2 ( w T x i − z 2 ˉ ) ( w T x i − z 2 ˉ ) T S_{z_2} = \frac{1}{N_2}\sum\limits_{i=1}^{N_2}(z_i-\bar{z_2})(z_i-\bar{z_2})^T = \frac{1}{N_2}\sum\limits_{i=1}^{N_2}(w^Tx_i-\bar{z_2})(w^Tx_i-\bar{z_2})^T Sz2=N21i=1N2(ziz2ˉ)(ziz2ˉ)T=N21i=1N2(wTxiz2ˉ)(wTxiz2ˉ)T
  • 类间差距: ( z ˉ 1 − z ˉ 2 ) 2 (\bar{z}_1-\bar{z}_2)^2 (zˉ1zˉ2)2
  • 类内方差: S 1 + S 2 S_1 + S_2 S1+S2

由于线性判别分析的目标是同一类别内方差小,不同类别之间距离大,因此损失函数定义为:

J ( w ) = ( z ˉ 1 − z ˉ 2 ) 2 s 1 + s 2 = w T ( x ˉ c 1 − x ˉ c 2 ) ( x ˉ c 1 − x ˉ c 2 ) T w w T ( s c 1 + s c 2 ) w        w ^ = a r g m a x w    J ( w ) J(w) = \frac{(\bar{z}_1-\bar{z}_2)^2}{s_1+s_2} = \frac{w^T(\bar{x}_{c_1}-\bar{x}_{c_2})(\bar{x}_{c_1}-\bar{x}_{c_2})^Tw}{w^T(s_{c_1}+s_{c_2})w}\\ \;\;\; \hat{w} = argmax_w\;J(w) J(w)=s1+s2(zˉ1zˉ2)2=wT(sc1+sc2)wwT(xˉc1xˉc2)(xˉc1xˉc2)Tww^=argmaxwJ(w)
记: S b = ( x ˉ c 1 − x ˉ c 2 ) ( x ˉ c 1 − x ˉ c 2 ) T ,    S w = ( s c 1 + s c 2 ) S_b = (\bar{x}_{c_1}-\bar{x}_{c_2})(\bar{x}_{c_1}-\bar{x}_{c_2})^T,\;S_w = (s_{c_1}+s_{c_2}) Sb=(xˉc1xˉc2)(xˉc1xˉc2)T,Sw=(sc1+sc2),因此 J ( w ) = w T S b w w T S w w J(w) = \dfrac{w^TS_bw}{w^TS_ww} J(w)=wTSwwwTSbw
让J(w)对w求导等于0,求出: w = S w − 1 ( x ˉ c 1 − x ˉ c 2 ) w = S_w^{-1}(\bar{x}_{c_1}-\bar{x}_{c_2}) w=Sw1(xˉc1xˉc2)

4.2.2 朴素贝叶斯:

在线性判别分析中,我们假设每种分类类别下的特征遵循同一个协方差矩阵,每两个特征之间是存在协方差的,因此在线性判别分析中各种特征是不是独立的。但是,朴素贝叶斯算法对线性判别分析作进一步的模型简化,它将线性判别分析中的协方差矩阵中的协方差全部变成0,只保留各自特征的方差,也就是朴素贝叶斯假设各个特征之间是不相关的。在之前所看到的偏差-方差理论中,我们知道模型的简化可以带来方差的减少但是增加偏差,因此朴素贝叶斯也不例外,它比线性判别分析模型的方差小,偏差大。虽然简化了模型,实际中使用朴素贝叶斯的案例非常多,甚至多于线性判别分析,例如鼎鼎大名的新闻分类,垃圾邮件分类等。

4.3 决策树

与前面内容所讲的决策树回归大致是一样的,只是在回归问题中,选择分割点的标准是均方误差,但是在分类问题中,由于因变量是类别变量而不是连续变量,因此用均方误差显然不合适。那问题是用什么作为选择分割点的标准呢?我们先来分析具体的问题:

决策树的构建两个阶段:构造与剪枝。构造过程中选择root节点就是这个选择分割点。有ID3,C4.5,CART。

在回归树中,对一个给定的观测值,因变量的预测值取它所属的终端结点内训练集的平均因变量。与之相对应,对于分类树来说,给定一个观测值,因变量的预测值为它所属的终端结点内训练集的最常出现的类。分类树的构造过程与回归树也很类似,与回归树一样,分类树也是采用递归二叉分裂。但是在分类树中,均方误差无法作为确定分裂节点的准则,一个很自然的替代指标是分类错误率。分类错误率就是:此区域内的训练集中非常见类所占的类别,即:

E = 1 − m a x k ( p ^ m k ) E = 1-max_k(\hat{p}_{mk}) E=1maxk(p^mk)
上式中的 p ^ m k \hat{p}_{mk} p^mk代表第m个区域的训练集中第k类所占的比例。但是在大量的事实证明:分类错误率在构建决策树时不够敏感,一般在实际中用如下两个指标代替:

4.3.1 基尼系数:

G = ∑ k = 1 K p ^ m k ( 1 − p ^ m k ) G = \sum\limits_{k=1}^{K} \hat{p}_{mk}(1-\hat{p}_{mk}) G=k=1Kp^mk(1p^mk)
在基尼系数的定义中,我们发现这个指标衡量的是K个类别的总方差。不难发现,如果所有的 p̂ mk 的取值都接近0或者1,基尼系数会很小。因此基尼系数被视为衡量结点纯度的指标----如果他的取值小,那就意味着某个节点包含的观测值几乎来自同一个类别。
由基尼系数作为指标得到的分类树叫做:CART。

4.3.2 交叉熵:

可以替代基尼系数的指标是交叉熵,定义如下:
D = − ∑ k = 1 K p ^ m k l o g    p ^ m k D = -\sum\limits_{k=1}^{K} \hat{p}_{mk}log\;\hat{p}_{mk} D=k=1Kp^mklogp^mk
显然,如果所有的 p ^ m k \hat{p}_{mk} p^mk都接近于0或者1,那么交叉熵就会接近0。因此,和基尼系数一样,如果第m个结点的纯度越高,则交叉熵越小。事实证明,基尼系数和交叉熵在数值上时很接近的。
在这里插入图片描述
决策树分类算法的完整步骤:

  1. 选择最优切分特征j以及该特征上的最优点s:
    遍历特征j以及固定j后遍历切分点s,选择使得基尼系数或者交叉熵最小的(j,s)
  2. 按照(j,s)分裂特征空间,每个区域内的类别为该区域内样本比例最多的类别。
  3. 继续调用步骤1,2直到满足停止条件,就是每个区域的样本数小于等于5。
  4. 将特征空间划分为J个不同的区域,生成分类树。

4.3 支持向量机SVM

支持向量机SVM是20世纪90年代在计算机界发展起来的一种分类算法,在许多问题中都被证明有较好的效果,被认为是适应性最广的算法之一。
在这里插入图片描述
(没完成---------------------)

4.4 非线性支持向量机

那我们应该如何处理非线性问题呢?答案就是将数据投影至更加高的维度!

(没完成---------------------)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值