【学习笔记】统计学习方法——聚类方法

摘要: 聚类是针对给定的样本,依据它们特征的相似度或距离,将其归并到若干个“类”或“簇”的数据分析问题。一个类是样本的一个子集。直观上,相似的样本聚集在相同的类,不相似的样本分散在不同的类。这里,样本之间的相似度或距离起着重要作用。

聚类的基本概念

首先定义一个矩阵X用来表示n个样本的m个属性。
X = [ x i j ] m × n = [ x 11 x 12 ⋯ x 1 n x 21 x 22 ⋯ x 2 n ⋮ ⋮ ⋮ x m 1 x m 2 ⋯ x m n ] X = [x_{ij}]_{m\times n}= \begin{bmatrix} x_{11} & x_{12} & \cdots & x_{1n}\\ x_{21} & x_{22} & \cdots & x_{2n}\\ \vdots & \vdots & & \vdots\\ x_{m1} & x_{m2} & \cdots & x_{mn}\\ \end{bmatrix} X=[xij]m×n=x11x21xm1x12x22xm2x1nx2nxmn
这里矩阵X的定义是按照书上来的,1列代表一个样本,当然还有另外一种常见的写法是1行代表一个样本,怎么写都行。

相似度或距离

1)闵可夫斯基距离(距离越大相似度越小,距离越小相似度越大)

给定样本集合XXm维实数向量空间 R m R^m Rm中点的集合,其中 x i , x j ∈ X , x i = ( x 1 i , x 2 i , ⋯   , x m i ) T x_i,x_j\in X,x_i=(x_{1i},x_{2i},\cdots,x_{mi})^T xi,xjXxi=(x1i,x2i,,xmi)T x j = ( x 1 j , x 2 j , ⋯   , x m j ) T x_j=(x_{1j},x_{2j},\cdots,x_{mj})^T xj=(x1j,x2j,,xmj)T,样本 x i x_i xi与样本 x j x_j xj的闵可夫斯基距离定义为
d i j = ( ∑ k = 1 m ∣ x k i − x k j ∣ p ) 1 p d_{ij}=\left( \sum_{k=1}^m{\mid x_{ki}-x_{kj} \mid}^p \right)^{\frac{1}{p}} dij=(k=1mxkixkjp)p1

这里 p ≥ 1 p\ge 1 p1。当 p = 2 p=2 p=2时称为欧式距离,即
d i j = ( ∑ k = 1 m ∣ x k i − x k j ∣ 2 ) 1 2 d_{ij}=\left( \sum_{k=1}^m{\mid x_{ki}-x_{kj} \mid}^2 \right)^{\frac{1}{2}} dij=(k=1mxkixkj2)21

p = 1 p=1 p=1时称为曼哈顿距离,即
d i j = ∑ k = 1 m ∣ x k i − x k j ∣ d_{ij}= \sum_{k=1}^m |x_{ki}-x_{kj} | dij=k=1mxkixkj
p = ∞ p=\infty p=时称为切比雪夫距离,取各个坐标数值差的绝对值的最大值,即
d i j = m a x k ∣ x k i − x k j ∣ d_{ij}= \mathop{max}_k|x_{ki}-x_{kj} | dij=maxkxkixkj
接下来举个简单的例子把,假设 x 1 = ( 1 , 2 ) , x 2 = ( 5 , 6 ) x_1=(1,2),x_2=(5, 6) x1=(1,2)x2=(5,6)

那么闵可夫斯基距离为: ( 5 − 1 ) p + ( 6 − 2 ) p p \sqrt[p]{(5-1)^p+(6-2)^p} p(51)p+(62)p

欧式距离为: ( 5 − 1 ) p + ( 6 − 2 ) 2 2 = 32 2 \sqrt[2]{(5-1)^p+(6-2)^2}=\sqrt[2]{32} 2(51)p+(62)2 =232

曼哈顿距离为: ∣ 5 − 1 ∣ + ∣ 6 − 2 ∣ = 8 |5-1| + |6-2| = 8 51+62=8

切比雪夫距离为: m a x ( ∣ 5 − 1 ∣ , ∣ 6 − 2 ∣ ) = 4 max(|5-1|, |6-2|)=4 max(51,62)=4


2)马哈拉诺比斯距离(距离越大相似度越小,距离越小相似度越大)

给定一个样本集合X, X = ( x i j ) m × n X={(x_{ij})}_{m\times n} X=(xij)m×n,其协方差矩阵记作S。样本 x i x_i xi与样本 x j x_j xj之间的马哈拉诺比斯距离 d i j d_{ij} dij定义为
d i j = [ ( x i − x j ) T S − 1 ( x i − x j ) ] 1 2 d_{ij}=\left[ (x_i-x_j)^TS^{-1}(x_i-x_j) \right]^{\frac{1}{2}} dij=[(xixj)TS1(xixj)]21
其中
x i = ( x 1 i , x 2 i , ⋯   , x m i ) T      x j = ( x 1 j , x 2 j , ⋯   , x m j ) T x_i=(x_{1i},x_{2i},\cdots,x_{mi})^T~~~~x_j=(x_{1j},x_{2j},\cdots,x_{mj})^T xi=(x1i,x2i,,xmi)T    xj=(x1j,x2j,,xmj)T

当S为单位矩阵时,即样本数据的各个分量相互独立且各个分量的方差为1时,上式提到的马氏距离 d i j d_{ij} dij也就是欧式距离了,所以马氏距离是欧式距离的推广。

证明如下:

当S为单位矩阵时,那么 S − 1 S^{-1} S1也是单位矩阵,即 S = S − 1 S=S^{-1} S=S1。假设 x i = ( 1 , 2 , 3 ) , x j = ( 5 , 4 , 6 ) x_i=(1,2,3),x_j=(5,4,6) xi=(1,2,3),xj=(5,4,6)则:

d i j = [ [ 1 − 5 2 − 4 3 − 6 ] T [ 1 0 0 0 1 0 0 0 1 ] [ 1 − 5 2 − 4 3 − 6 ] ] 1 2 = ( − 4 ) 2 + ( − 2 ) 2 + ( − 3 ) 2 2 d_{ij}={\left[ \begin{bmatrix} 1-5 \\ 2-4 \\ 3-6 \end{bmatrix} ^T \begin{bmatrix} 1 & 0 & 0\\ 0 & 1 & 0\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} 1-5 \\ 2-4 \\ 3-6 \end{bmatrix} \right] }^{\frac{1}{2}}\\ =\sqrt[2]{(-4)^2+(-2)^2+(-3)^2} dij=152436T10001000115243621=2(4)2+(2)2+(3)2
上式最后得到的结果也就是欧式距离的结果了。

现在来解释下什么叫做协方差矩阵:

方差和协方差的定义

在统计学中,方差是用来度量单个随机变量离散程度,而协方差则一般用来刻画两个随机变量相似程度,其中,方差的计算公式为

σ x 2 = 1 n − 1 ∑ i = 1 n ( x i − x ˉ ) 2 \sigma_x^2=\frac{1}{n-1}\sum_{i=1}^n(x_i-\bar x)^2 σx2=n11i=1n(xixˉ)2

其中, n n n表示样本量,符号 x ˉ \bar x xˉ表示观测样本的均值。

在此基础上,协方差的计算公式被定义为

σ ( x , y ) = 1 n − 1 ∑ i = 1 n ( x i − x ˉ ) ( y i − y ˉ ) \sigma(x, y)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right) σ(x,y)=n11i=1n(xixˉ)(yiyˉ)

在公式中,符号 x ˉ , y ˉ \bar{x}, \bar{y} xˉ,yˉ 分别表示两个随机变量所对应的观测样本均值,据此, 我们发现:方差 σ x 2 \sigma_{x}^{2} σx2 可视作随机变量 x x x 关于其自身的协方差 σ ( x , x ) \sigma(x, x) σ(x,x)

从方差/协方差到协方差矩阵:

根据方差的定义, 给定 d d d 个随机变量 x k , k = 1 , 2 , … , d , x_{k}, k=1,2, \ldots, d, xk,k=1,2,,d, 则这些随机变量的方差为
σ ( x k , x k ) = 1 n − 1 ∑ i = 1 n ( x k i − x ˉ k ) 2 , k = 1 , 2 , … , d \sigma\left(x_{k}, x_{k}\right)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{k i}-\bar{x}_{k}\right)^{2}, k=1,2, \ldots, d σ(xk,xk)=n11i=1n(xkixˉk)2,k=1,2,,d

其中, 为方便书写, x k i \quad x_{k i} xki 表示随机变量 x k x_{k} xk 中的第 i i i 个观测样本, n \quad n n 表示样本量,每个随机变量所对应的观测样本数量均为 n n n


对于这些随机变量,我们还可以根据协方差的定义,求出两两之间的协方差, 即
σ ( x m , x k ) = 1 n − 1 ∑ i = 1 n ( x m i − x ˉ m ) ( x k i − x ˉ k ) \sigma\left(x_{m}, x_{k}\right)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{m i}-\bar{x}_{m}\right)\left(x_{k i}-\bar{x}_{k}\right) σ(xm,xk)=n11i=1n(xmixˉm)(xkixˉk)
因此, 协方差矩阵为
Σ = [ σ ( x 1 , x 1 ) ⋯ σ ( x 1 , x d ) ⋮ ⋱ ⋮ σ ( x d , x 1 ) ⋯ σ ( x d , x d ) ] ∈ R d × d \Sigma=\left[\begin{array}{ccc} \sigma\left(x_{1}, x_{1}\right) & \cdots & \sigma\left(x_{1}, x_{d}\right) \\ \vdots & \ddots & \vdots \\ \sigma\left(x_{d}, x_{1}\right) & \cdots & \sigma\left(x_{d}, x_{d}\right) \end{array}\right] \in \mathbb{R}^{d \times d} Σ=σ(x1,x1)σ(xd,x1)σ(x1,xd)σ(xd,xd)Rd×d
其中,对角线上的元素为各个随机变量的方差, 非良角线上的元素为两两随机变量之间的协方差, 根据协方差的定义,我们可以认定:矩阵 Σ \Sigma Σ 为对称矩阵(symmetric matrix),其大小为 d × d d \times d d×d


3)相关系数(相关系数的绝对值越接近于1,表示样本越相似;越接近于0,表示样本越不相似)

样本 x i x_i xi与样本 x j x_j xj之间的相关系数定义为
r i j = ∑ k = 1 m ( x k i − x ˉ i ) ( x k j − x ˉ j ) [ ∑ k = 1 m ( x k i − x ˉ i ) 2 ∑ k = 1 m ( x k j − x ˉ j ) 2 ] 1 2 r_{i j}=\frac{\sum_{k=1}^{m}\left(x_{k i}-\bar{x}_{i}\right)\left(x_{k j}-\bar{x}_{j}\right)}{\left[\sum_{k=1}^{m}\left(x_{k i}-\bar{x}_{i}\right)^{2} \sum_{k=1}^{m}\left(x_{k j}-\bar{x}_{j}\right)^{2}\right]^{\frac{1}{2}}} rij=[k=1m(xkixˉi)2k=1m(xkjxˉj)2]21k=1m(xkixˉi)(xkjxˉj)
其中
x ˉ i = 1 m ∑ k = 1 m x k i , x ˉ j = 1 m ∑ k = 1 m x k j \bar{x}_{i}=\frac{1}{m} \sum_{k=1}^{m} x_{k i}, \quad \bar{x}_{j}=\frac{1}{m} \sum_{k=1}^{m} x_{k j} xˉi=m1k=1mxki,xˉj=m1k=1mxkj

4)夹角余弦(夹角余弦越接近于1,表示样本越相似;越接近于0,表示样本越不相似)

样本 x i x_i xi与样本 x j x_j xj之间的夹角余弦定义为
s i j = ∑ k = 1 m x k i x k j [ ∑ k = 1 m x k i 2 ∑ k = 1 m x k j 2 ] 1 2 s_{i j}=\frac{\sum_{k=1}^{m} x_{k i} x_{k j}}{\left[\sum_{k=1}^{m} x_{k i}^{2} \sum_{k=1}^{m} x_{k j}^{2}\right]^{\frac{1}{2}}} sij=[k=1mxki2k=1mxkj2]21k=1mxkixkj

类或簇

类或簇的四个定义:

1)设 T T T 为给定的正牧, 若集合 G 中任意两个样本 x i , x j , x_{i}, x_{j}, xi,xj,
d i j ⩽ T d_{i j} \leqslant T dijT
则称G为一个类或簇。

2)设 T 为给定的正牧,若对集合 G 的任意样本 x i , x_{i}, xi, 一定存在 G 中的另 个样本 x j , x_{j}, xj, 使得
d i j ⩽ T d_{i j} \leqslant T dijT
则称G为一个类或簇。

3)设 T T T 为给定的正数,若对集合 G G G 中任意一个样本 x i , G x_{i}, G xi,G 中的另一个 样本 x j x_{j} xj 满足
1 n G − 1 ∑ x j ∈ G d i j ⩽ T \frac{1}{n_{G}-1} \sum_{x_{j} \in G} d_{i j} \leqslant T nG11xjGdijT
 其中  n G  为  G  中样本的个数, 则称  G  为一个类或籍。  \text { 其中 } n_{G} \text { 为 } G \text { 中样本的个数, 则称 } G \text { 为一个类或籍。 }  其中 nG  G 中样本的个数则称 G 为一个类或籍。 

4)设 T 和 V 为给定的两个正牧,如果集合 G 中任意两个样本 x i , x j x_{i}, x_{j} xi,xj 的 距离 d i j d_{i j} dij 满足
1 n G ( n G − 1 ) ∑ x i ∈ G ∑ x j ∈ G d i j ⩽ T d i j ⩽ V \begin{array}{l} \frac{1}{n_{G}\left(n_{G}-1\right)} \sum_{x_{i} \in G} \sum_{x_{j} \in G} d_{i j} \leqslant T \\ d_{i j} \leqslant V \end{array} nG(nG1)1xiGxjGdijTdijV
则称 G 为一个类或籍。

类的三个特征:

1)类的均值 x ˉ G \bar{x}_{G} xˉG, 又称为类的中心
x ˉ G = 1 n G ∑ i = 1 n G x i \bar{x}_{G}=\frac{1}{n_{G}} \sum_{i=1}^{n_{G}} x_{i} xˉG=nG1i=1nGxi
式中 n G n_{G} nG 是类 G G G 的样本个数。

2)类的直径 (diameter) D G D_{G} DG
类的直径 D_ 是类中任意两个样本之间的最大距离, 即
D G = max ⁡ x i , x j ∈ G d i j D_{G}=\max _{x_{i}, x_{j} \in G} d_{i j} DG=xi,xjGmaxdij
3)类的样本散布矩阵 A G A_G AG与样本协方差矩阵 S G S_G SG

类的样本散布矩阵 A G A_G AG
A G = ∑ i = 1 n G ( x i − x ˉ G ) ( x i − x ˉ G ) T A_{G}=\sum_{i=1}^{n_{G}}\left(x_{i}-\bar{x}_{G}\right)\left(x_{i}-\bar{x}_{G}\right)^{\mathrm{T}} AG=i=1nG(xixˉG)(xixˉG)T
样本协方差矩阵 SG 为
S G = 1 m − 1 A G = 1 m − 1 ∑ i = 1 n C ( x i − x ˉ G ) ( x i − x ˉ G ) T \begin{aligned} S_{G} &=\frac{1}{m-1} A_{G} \\ &=\frac{1}{m-1} \sum_{i=1}^{n_{C}}\left(x_{i}-\bar{x}_{G}\right)\left(x_{i}-\bar{x}_{G}\right)^{\mathrm{T}} \end{aligned} SG=m11AG=m11i=1nC(xixˉG)(xixˉG)T
其中 m 为样本的维数(样本属性的个数)。

类与类之间的距离

设类 G p G_{p} Gp 包含 n p n_{p} np 个样本, G q G_{q} Gq 包含 n q n_{q} nq 个样本, 分别用 x ˉ p \bar{x}_{p} xˉp x ˉ q \bar{x}_{q} xˉq 表示 G p G_{p} Gp G q G_{q} Gq 的 均值,即类的中心。

1)最短距离或单连接

定义类 G p G_{p} Gp 的样本与 G q G_{q} Gq 的样本之间的最短距离为两类之间的距离
D p q = min ⁡ { d i j ∣ x i ∈ G p , x j ∈ G q } D_{p q}=\min \left\{d_{i j} \mid x_{i} \in G_{p}, x_{j} \in G_{q}\right\} Dpq=min{dijxiGp,xjGq}
2)最长距离或完全连接

定义类 G p G_{p} Gp 的样本与 G q G_{q} Gq 的样本之间的最长距离为两类之间的距离
D p q = max ⁡ { d i j ∣ x i ∈ G p , x j ∈ G q } D_{p q}=\max \left\{d_{i j} \mid x_{i} \in G_{p}, x_{j} \in G_{q}\right\} Dpq=max{dijxiGp,xjGq}
3)中心距离

定义类 G p G_{p} Gp 与类 G q G_{q} Gq 的中心 x ˉ p \bar{x}_{p} xˉp x ˉ q \bar{x}_{q} xˉq 之间的距离为两类之同的距离
D p q = d x p x q D_{p q}=d_{x_{p} x_{q}} Dpq=dxpxq
(4)半均距隨
定义类 G p G_{p} Gp 与类 G q G_{q} Gq 任套两个样本之但距离的平均值为两类之间的距离
D p q = 1 n p n q ∑ x i ∈ G p ∑ x j ∈ G q d i j D_{p q}=\frac{1}{n_{p} n_{q}} \sum_{x_{i} \in G_{p}} \sum_{x_{j} \in G_{q}} d_{i j} Dpq=npnq1xiGpxjGqdij

聚类算法

层次聚类

输入: n n n 个样本组成的样本集合及样本之间的距离: 输出: 对样本集合的一个层次化聚类。

(1)计算 n 个样本两两之间的欧氏距离 { d i j } , \left\{d_{i j}\right\}, {dij}, 记作矩阵 D = [ d i j ] n × n D=\left[d_{i j}\right]_{n \times n} D=[dij]n×n
(2)构造 n 个类,每个类只包含一个样本。
(3)合并类间距离最小的两个类,其中最短距离为类间距离,构建一个新类。
(4)计算新类与当前各类的距离。若类的个数为 1,终止计算, 否则回到步 (3)。

可以看出聚合层次政类算法的复杂度是 O ( n 3 m ) , O\left(n^{3} m\right), O(n3m), 其中 m m m 是样本的维数,n 是样本个数。

k均值聚类

输入: n n n 个样本的集合 X:

输出: 样本集合的款类 C”。

(1)初始化。令 t = 0 , t=0, t=0, 随 机选择 k k k 个样本点作为初始聚类中心 m ( 0 ) = m^{(0)}= m(0)= ( m 1 ( 0 ) , ⋯   , m l ( 0 ) , ⋯   , m k ( 0 ) ) \left(m_{1}^{(0)}, \cdots, m_{l}^{(0)}, \cdots, m_{k}^{(0)}\right) (m1(0),,ml(0),,mk(0))
(2)对样本进行麥类。对固定的类中心 m ( t ) = ( m 1 ( t ) , ⋯   , m l ( t ) , ⋯   , m k ( t ) ) , m^{(t)}=\left(m_{1}^{(t)}, \cdots, m_{l}^{(t)}, \cdots, m_{k}^{(t)}\right), m(t)=(m1(t),,ml(t),,mk(t)), 其中
m l ( t ) m_{l}^{(t)} ml(t) 为类 G l G_{l} Gl 的中心,计算每个样本到类中心的距离,将每个样本指派到与其最近的 中心的类中,构成聚类结果 C ( t ) C^{(t)} C(t)
(3)计算新的类中心。对聚类结果 C ( t ) , ^{(t)}, (t), 计算当前各个类中的样本的均值,作为新
的类中心 m ( t + 1 ) = ( m 1 ( t + 1 ) , ⋯   , m l ( t + 1 ) , ⋯   , m k ( t + 1 ) ) m^{(t+1)}=\left(m_{1}^{(t+1)}, \cdots, m_{l}^{(t+1)}, \cdots, m_{k}^{(t+1)}\right) m(t+1)=(m1(t+1),,ml(t+1),,mk(t+1))
(4)如果迭代收琉或符合停止条件,输出 C ∗ = C ( t ) C^{*}=C^{(t)} C=C(t)。否则, ⇔ t = t + 1 , \Leftrightarrow t=t+1, t=t+1, 返回步 (2)

k 均值聚类算法的复杂度是 O ( m n k ) , O(m n k), O(mnk), 其中 m m m 是样本维数,n 是样本个数,k 是类别个数。

代码

# 定义聚类数的节点

class ClusterNode:
    def __init__(self, vec, left=None, right=None, distance=-1, id=None, count=1):
        """
        :param vec: 保存两个数据聚类后形成新的中心
        :param left: 左节点
        :param right:  右节点
        :param distance: 两个节点的距离
        :param id: 用来标记哪些节点是计算过的
        :param count: 这个节点的叶子节点个数
        """
        self.vec = vec
        self.left = left
        self.right = right
        self.distance = distance
        self.id = id
        self.count = count
        
 def euler_distance(point1: np.ndarray, point2: list) -> float:
    """
    计算两点之间的欧拉距离,支持多维
    """
    distance = 0.0
    for a, b in zip(point1, point2):
        distance += math.pow(a - b, 2)
    return math.sqrt(distance)

# 层次聚类(聚合法)

class Hierarchical:
    def __init__(self, k):
        self.k = k
        self.labels = None
        
    def fit(self, x):
        nodes = [ClusterNode(vec=v, id=i) for i, v in enumerate(x)]
        distances = {}
        point_num, feature_num = x.shape
        self.labels = [-1] * point_num
        currentclustid = -1
        while(len(nodes)) > self.k:
            min_dist = math.inf
            nodes_len = len(nodes)
            closest_part = None
            for i in range(nodes_len - 1):
                for j in range(i+1, nodes_len):
                    d_key = (nodes[i].id, nodes[j].id)
                    if d_key not in distances:
                        distances[d_key] = euler_distance(nodes[i].vec, nodes[j].vec)
                    d = distances[d_key]
                    if d < min_dist:
                        min_dist = d
                        closest_part = (i, j)
                        
            part1, part2 = closest_part
            node1, node2 = nodes[part1], nodes[part2]
            new_vec = [ (node1.vec[i] * node1.count + node2.vec[i] * node2.count ) / (node1.count + node2.count)
                        for i in range(feature_num)]
            new_node = ClusterNode(vec=new_vec,
                                   left=node1,
                                   right=node2,
                                   distance=min_dist,
                                   id=currentclustid,
                                   count=node1.count + node2.count)
            currentclustid -= 1
            del nodes[part2], nodes[part1]
            nodes.append(new_node)
            
        self.nodes = nodes
        self.calc_label()
        
    def calc_label(self):
        """
        调取聚类的结果
        """
        for i, node in enumerate(self.nodes):
            # 将节点的所有叶子节点都分类
            self.leaf_traversal(node, i)

    def leaf_traversal(self, node: ClusterNode, label):
        """
        递归遍历叶子节点
        """
        if node.left == None and node.right == None:
            self.labels[node.id] = label
        if node.left:
            self.leaf_traversal(node.left, label)
        if node.right:
            self.leaf_traversal(node.right, label)
            
# kmeans

class MyKmeans:
    def __init__(self, k, n=20):
        self.k = k
        self.n = n
        
    def fit(self, x, centers=None):
        # 第一步,随机选择 K 个点, 或者指定
        if centers is None:
            idx = np.random.randint(low=0, high=len(x), size=self.k)
            centers = x[idx]
        #print(centers)
        
        inters = 0
        while inters < self.n:
            #print(inters)
            #print(centers)
            points_set = {key: [] for key in range(self.k)}

            # 第二步,遍历所有点 P,将 P 放入最近的聚类中心的集合中
            for p in x:
                nearest_index = np.argmin(np.sum((centers - p) ** 2, axis=1) ** 0.5)
                points_set[nearest_index].append(p)

            # 第三步,遍历每一个点集,计算新的聚类中心
            for i_k in range(self.k):
                centers[i_k] = sum(points_set[i_k])/len(points_set[i_k])
                
            inters += 1

        
            
        return points_set, centers
        
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值