高斯混合模型GMM聚类的步骤和推导

0. 引言

  由于最近要做聚类算法方面的内容,看了很多资料,在高斯混合模型(GMM)这里一直没有一个让我完全推导清楚的、理解的文章。经过三天打鱼两天晒网 不懈努力,总算是有一点自己的理解,我希望尽量通俗地把GMM讲明白,同时也希望尽量详细地对公式进行推导和解释。因此,我会先给出GMM算法的总体步骤,保证拿上先可以直接使用,然后再进行具体的推导和解释。文中可能有一些自己理解不严谨的地方,还请大家指正。

1. 算法初窥

  已知样本集是 D = { x 1 , x 2 , . . . , x m } D=\{x_1,x_2,...,x_m\} D={x1,x2,...,xm},要将这些样本聚成 k k k 类。我们认为样本服从混合高斯分布:
p M ( x ) = ∑ i = 1 k α i ⋅ p ( x ∣ μ i , Σ i ) p_M(\bm{x})=\sum_{i=1}^k \alpha_i \cdot p(\bm{x}|\bm{\mu_i}, \bm{\Sigma_i}) pM(x)=i=1kαip(xμi,Σi)
  其中 p ( x ∣ μ i , Σ i ) = 1 ( 2 π ) n / 2 ∣ Σ i ∣ 1 / 2 e x p { − 1 2 ( x − μ i ) T Σ i − 1 ( x − μ i ) } p(\bm{x}|\bm{\mu_i}, \bm{\Sigma_i})=\frac{1}{_{(2\pi)^{n/2}|\bm{\Sigma_i}|^{1/2}}}exp\{-\frac{1}{2}(\bm{x}-\bm{\mu_i})^T\bm{\Sigma_i}^{-1}(\bm{x}-\bm{\mu_i})\} p(xμi,Σi)=(2π)n/2Σi1/21exp{21(xμi)TΣi1(xμi)}是一个多元高斯分布,即一个混合成分;
   α i \alpha_i αi表示混合系数,即选择第 i i i 个混合成分的概率。

第一步 初始化高斯混合分布的模型参数 α i , μ i , Σ i \alpha_i,\bm{\mu_i},\bm{\Sigma_i} αi,μi,Σi
第二步 计算 x j x_j xj由各混合成分生成的后验概率,即观测数据 x j x_j xj由第 i i i 个分模型生成的概率 p ( z j = i ∣ x j ) p(z_j=i|\bm{x_j}) p(zj=ixj),并记为 γ j i \gamma_{ji} γji
     γ j i = α i ⋅ p ( x j ∣ μ i , Σ i ) ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) \gamma_{ji}=\frac{\alpha_i\cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})}{_{\sum_{l=1}^{^k}\alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})}} γji=l=1kαlp(xjμl,Σl)αip(xjμi,Σi)

第三步 计算新的模型参数:

     μ i ′ = ∑ j = 1 m γ j i x j ∣ ∑ j = 1 m γ j i ∣ \bm{\mu_i'}=\frac{\sum_{_{j=1}}^m\gamma_{ji}\bm{x_j}^{\color{white}{|}}}{\sum_{_{j=1}}^m\gamma_{ji}^{\color{white}{|}}} μi=j=1mγjij=1mγjixj

     Σ i ′ = ∑ j = 1 m γ j i ( x j − μ i ′ ) ( x j − μ i ′ ) T ∣ ∑ j = 1 m γ j i ∣ \bm{\Sigma_i'}=\frac{\sum_{_{j=1}}^m\gamma_{ji}(\bm{x_j}-\bm{\mu_i'})(\bm{x_j}-\bm{\mu_i'})^{T^{\color{white}{|}}}}{\sum_{_{j=1}}^m\gamma_{ji}^{\color{white}{|}}} Σi=j=1mγjij=1mγji(xjμi)(xjμi)T

     α i ′ = ∑ j = 1 m γ j i ∣ m \alpha_i'=\frac{\sum^{m}_{_{j=1}}\gamma_{ji}^{\color{white}{|}}}{m} αi=mj=1mγji

第四步 按照新的模型参数重复2,3步,直到满足停止条件
第五步 将每个样本按照 λ j = arg max ⁡ i ∈ { 1 , 2 , . . . , k } γ j i \lambda_j=\argmax\limits_{i\in\{1,2,...,k\}} \gamma_{ji} λj=i{1,2,...,k}argmaxγji划入对应的簇。即对每个样本来自哪个分模型的概率大就划入哪个分模型的簇中,最终就得到了 k k k 个聚类

2. 高斯混合模型的引入

  与k-means聚类不同,高斯混合聚类是采用概率模型来刻画聚类结构。实际上我们可以采用任意不同的概率分布模型来进行刻画,高斯分布是最普遍的一种,如下:
  高斯分布:
p ( x ) = 1 ( 2 π ) n / 2 ∣ Σ ∣ 1 / 2 e x p [ − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ] p(\bm{x})=\frac{1}{(2\pi)^{n/2}|\bm{\Sigma}|^{1/2}}exp[-\frac{1}{2}(\bm{x}-\bm{\mu})^T\bm{\Sigma}^{-1}(\bm{x}-\bm{\mu})] p(x)=(2π)n/2Σ1/21exp[21(xμ)TΣ1(xμ)]
  而单高斯分布模型有其局限性,不能完全反映数据分布的特点,因此我们用多个高斯分布的线性叠加来刻画实际样本,其中一个高斯分模型称为一个混合成分。

理论上来说,当叠加的高斯分模型数量足够多时,可以表征任意一种分布。(这其实很好理解,类比足够多微小线段可以逼近任意一条曲线、足够多复指数信号可以描述任意信号…是一样的道理)

  高斯混合分布:
p M ( x ) = ∑ i = 1 k α i ⋅ p ( x ∣ μ i , Σ i ) p_M(\bm{x})=\sum_{i=1}^k \alpha_i \cdot p(\bm{x}|\bm{\mu_i}, \bm{\Sigma_i}) pM(x)=i=1kαip(xμi,Σi)
我们认为,手里拿到的样本就是根据这个概率分布抽取得到的(或者说“生成的”)
例如,对于第 j j j个样本 x j \bm{x_j} xj,就根据 p M ( x j ) = ∑ i = 1 k α j i ⋅ p ( x j ∣ μ i , Σ i ) p_M(\bm{x_j})=\sum_{i=1}^k \alpha_{ji} \cdot p(\bm{x_j}|\bm{\mu_i}, \bm{\Sigma_i}) pM(xj)=i=1kαjip(xjμi,Σi) 得到。

T I P S : \bm{TIPS:} TIPS:

  1. 这里的 p ( x ) p(x) p(x) p M ( x ) p_M(x) pM(x)指的是概率密度函数,不是概率,在有些概率书上为了区别,用 f ( x ) f(x) f(x)表示,这里都用 p ( x ) p(x) p(x)表示,但心里要清楚其含义。
  2. 接上条,所以 p ( x ∣ μ i , Σ i ) p(\bm{x}|\bm{\mu_i},\bm{\Sigma_i}) p(xμi,Σi)不是条件概率,而是概率密度," ∣ μ i , Σ i |\mu_i,\Sigma_i μi,Σi"只是明确一下这个概率密度函数包含的参变量。实际上它表示的就是上面单高斯分布的 p ( x ) p(x) p(x)
  3. x \bm{x} x是一条样本,但是有 n n n个维度,因此是一个 n n n维向量。
  4. α i > 0 \alpha_i>0 αi>0是在生成这条样本时,选择通过第 i i i个分模型来生成的概率,且 ∑ i = 1 k α i = 1 \sum_{i=1}^k\alpha_i=1 i=1kαi=1。(不能说成"样本来自第 i i i个分模型的概率",因为这里是一个先验的情况,如果这样说就成了后验了)
  5. μ i , Σ i \bm{\mu}_i,\bm{\Sigma}_i μi,Σi是第 i i i个分模型的参数。其中, μ i \bm{\mu}_i μi表示均值,是一个 n n n维向量, Σ i \bm{\Sigma}_i Σi表示协方差矩阵,是一个 n × n n×n n×n方阵。

3. 按照高斯混合模型进行聚类划分

  上面说了我们认为手里拿到的样本就是通过高斯混合模型抽取得到的,那么反过来我们要怎么把这些样本用高斯混合模型划分成不同的类别呢?
  一个很直接的想法自然是按照模型的混合成分划成 k k k 类,一个数据最可能从哪个分模型得来就认为属于哪一类。
  在这里,我们要引入一个隐变量 z j ∈ { 1 , 2 , . . . , k } z_j\in\{1,2,...,k\} zj{1,2,...,k} 表示得到样本 x j \bm{x_j} xj的高斯分模型。

注:

  1. 有的书上用一维向量来表示,即若认为样本 x j \bm{x_j} xj来自第2个高斯分模型,则 z j = [ 0 , 1 , 0 , 0 , . . . , 0 ] z_j=[0,1,0,0,...,0] zj=[0,1,0,0,...,0]。 这里直接用数字来表示来自第几个分模型。
  2. 根据 z j z_j zj的含义很容易看出, P ( z j = i ) P(z_j=i) P(zj=i)表示 x j \bm{x_j} xj是通过第 i i i个分模型生成的概率,就是高斯混合模型中的参数 α j i \alpha_{ji} αji

  前面我们说了, α \alpha α是一个先验概念,是从模型到样本的过程。而现在我们在已经拿到了样本的情况下反推其来自哪个分模型,是逆向过程,因此我们用 p M ( z j = i ∣ x j ) p_M(z_j=i|\bm{x_j}) pM(zj=ixj)来表示样本 x j \bm{x_j} xj来自第 i i i个分模型的后验概率,并简记为 γ j i \gamma_{ji} γji。有:
p M ( z j = i ∣ x j ) = P ( z j = i ) ⋅ p M ( x j ∣ z j = i ) p M ( x j ) = α i ⋅ p ( x j ∣ μ i , Σ i ) ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) \begin{aligned} p_M(z_j=i|\bm{x_j}) & = \frac{P(z_j=i) \cdot p_M(\bm{x_j}|z_j=i)} {p_M(\bm{x_j})} \\ & =\frac{\alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})} {\sum_{l=1}^{k} \alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})} \end{aligned} pM(zj=ixj)=pM(xj)P(zj=i)pM(xjzj=i)=l=1kαlp(xjμl,Σl)αip(xjμi,Σi)

注:

  1. p M ( x j ∣ z j = i ) p_M(\bm{x_j}|z_j=i) pM(xjzj=i)表示按照第 i i i个高斯分模型生成 x j \bm{x_j} xj的概率密度,第 i i i个高斯分模型的参数是 μ i , Σ i \bm{\mu_i},\bm{\Sigma_i} μi,Σi,故而就等于 p ( x j ∣ μ i , Σ i ) p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i}) p(xjμi,Σi)
  2. p M ( x j ) p_M(\bm{x_j}) pM(xj)表示综合所有的混合成分后总的概率密度
  3. 上述等式第一行由贝叶斯公式得到
     贝叶斯公式: p ( A ∣ B ) = p ( A ) p ( B ∣ A ) p ( B ) p(A|B)=\frac{p(A)p(B|A)}{_{p(B)}} p(AB)=p(B)p(A)p(BA)

那么显而易见地,每个样本 x j \bm{x_j} xj的簇标记 λ j \lambda_j λj如下确定:
λ j = arg max ⁡ i ∈ { 1 , 2 , . . . , k } γ j i \lambda_j=\argmax_{i \in \{1,2,...,k\}}\gamma_{ji} λj=i{1,2,...,k}argmaxγji
即, x j \bm{x_j} xj来自哪个分模型的概率最大,就认为属于哪一类。

4. 确定高斯混合模型参数

  上面已经说了当已知高斯混合模型时,就可以进行聚类的划分,那么如何求解这个模型,得到它的三个参数呢?
  我们在这里要用到的是EM算法(期望最大算法)。其实原理很简单:为什么我们能拿到手中的样本,而不是其他数据呢?我们认为这是由于选出这样一组样本的概率最大,所以才运气爆表,被我们拿到手。
  由上文知,按照高斯混合模型选出一个样本 x j \bm{x_j} xj的概率密度
p M ( x j ) = ∑ i = 1 k α i ⋅ p ( x j ∣ μ i , Σ i ) p_M(\bm{x_j})=\sum_{i=1}^k\alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i}) pM(xj)=i=1kαip(xjμi,Σi)
  对于手中的 m m m个样本,选到任意一个都是一个独立事件,最终的概率自然是全部相乘,即
∏ j = 1 m p M ( x j ) \prod_{j=1}^mp_M(\bm{x_j}) j=1mpM(xj)
但是,连乘不好处理,因此一般习惯对它取对数,于是样本集 D D D的最大化对数似然函数就定义如下:
L L ( D ) = ln ⁡ ( ∏ j = 1 m p M ( x j ) ) = ∑ j = 1 m ln ⁡ ( p M ( x j ) ) = ∑ j = 1 m ln ⁡ ( ∑ i = 1 k α i ⋅ p ( x j ∣ μ i , Σ i ) ) \begin{aligned} LL(D) & =\ln(\prod_{j=1}^mp_M(\bm{x_j})) \\ & =\sum_{j=1}^m \ln(p_M(\bm{x_j})) \\ & =\sum_{j=1}^m \ln(\sum_{i=1}^k \alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})) \end{aligned} LL(D)=ln(j=1mpM(xj))=j=1mln(pM(xj))=j=1mln(i=1kαip(xjμi,Σi))

  只要能求出使 L L ( D ) LL(D) LL(D)最大的参数就可以了。
  那么怎么求满足要求的参数呢?
  我们设参数 θ i = { ( α i , μ i , Σ i ) } \theta_i=\{(\alpha_i,\mu_i,\Sigma_i)\} θi={(αi,μi,Σi)}能使 L L ( D ) LL(D) LL(D)最大化,那么 L L ( D ) LL(D) LL(D)对每个参数的偏导数应该为0,但是偏导数为0求出的参数有可能只是局部最优解( L L ( D ) LL(D) LL(D)取极大值或驻点),而不是全局最优解( L L ( D ) LL(D) LL(D)取最大值)。
  经过后面的推导,我们可以发现求出的每个参数,都可以用 γ j i \gamma_{ji} γji表示。所以,我们在求出了一组模型参数后,按照这种模型得到对应的 γ j i \gamma_{ji} γji,再用得到的 γ j i \gamma_{ji} γji继续按照偏导数为0的方式求出新的参数。如此循环迭代,直到我们认为足够为止。

至于为什么每次迭代都可以使求得的参数更优,这个问题就不在本文展开叙述了,具体可以参考EM算法的相关资料。

  现在我们来具体求解每个参数:

μ : \bm{\mu}: μ:

∂ L L ( D ) ∂ μ i = 0 ⇒ ∂ ∂ μ i ∑ j = 1 m ln ⁡ ( ∑ i = 1 k α i ⋅ p ( x j ∣ μ i , Σ i ) ) = 0 ⇒ ∑ j = 1 m 1 ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) ⋅ ∂ ∂ μ i [ ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) ] = 0 \begin{aligned} & \frac{\partial LL(D)}{\partial \bm{\mu_i}}=0 \\ & \rArr \frac{\partial}{\partial \bm{\mu_i}}\sum_{j=1}^m \ln (\sum_{i=1}^k \alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i}))=0 \\ & \rArr \sum_{j=1}^m\frac{1}{\sum_{l=1}^k \alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})} \cdot \frac{\partial}{\partial \bm{\mu_i}}[\sum_{l=1}^k\alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})]=0 \end{aligned} μiLL(D)=0μij=1mln(i=1kαip(xjμi,Σi))=0j=1ml=1kαlp(xjμl,Σl)1μi[l=1kαlp(xjμl,Σl)]=0

  (这里因为对 μ i \bm{\mu_i} μi求偏导,为了避免混淆,将求和变量写成 l l l)
  对 ∂ ∂ μ i [ ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) ] \frac{\partial}{\partial \bm{\mu_i}}[\sum_{l=1}^k\alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})] μi[l=1kαlp(xjμl,Σl)]来说,只有当 l = i l=i l=i时,包含 μ i \mu_i μi的内容,其余对 μ i \mu_i μi求偏导均为0,可以舍去,则继续推导如下:

⇒ ∑ j = 1 m 1 ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) ⋅ ∂ ∂ μ i [ α i ⋅ p ( x j ∣ μ i , Σ i ) ] = 0 \rArr \sum_{j=1}^m\frac{1}{\sum_{l=1}^k \alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})} \cdot \frac{\partial}{\partial \bm{\mu_i}}[ \alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})]=0 j=1ml=1kαlp(xjμl,Σl)1μi[αip(xjμi,Σi)]=0

  其中,

∂ ∂ μ i [ α i ⋅ p ( x j ∣ μ i , Σ i ) ] = ∂ ∂ μ i { α i 1 ( 2 π ) n / 2 ∣ Σ i ∣ 1 / 2 exp ⁡ [ − 1 2 ( x j − μ i ) T Σ i − 1 ( x j − μ i ) ] } = α i exp ⁡ [ − 1 2 ( x j − μ i ) T Σ i − 1 ( x j − μ i ) ] ( 2 π ) n / 2 ∣ Σ i ∣ 1 / 2 ∂ ∂ μ i [ − 1 2 ( x j − μ i ) T Σ i − 1 ( x j − μ i ) ] = α i ⋅ p ( x j ∣ μ i , Σ i ) ⋅ ( x j − μ i ) \begin{aligned} & \frac{\partial}{\partial \bm{\mu_i}}[ \alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})] \\ & =\frac{\partial}{\partial \bm{\mu_i}}\{\alpha_i\frac{1}{(2\pi)^{n/2}|\bm{\Sigma_i}|^{1/2}} \exp[-\frac{1}{2}(\bm{x_j}-\bm{\mu_i})^T\bm{\Sigma_i}^{-1}(\bm{x_j}-\bm{\mu_i})]\} \\ & =\alpha_i\frac{\exp[-\frac{1}{2}(\bm{x_j}-\bm{\mu_i})^T\bm{\Sigma_i}^{-1}(\bm{x_j}-\bm{\mu_i})]}{(2\pi)^{n/2}|\bm{\Sigma_i}|^{1/2}} \frac{\partial}{\partial\bm{\mu_i}}[-\frac{1}{2}(\bm{x_j}-\bm{\mu_i})^T\bm{\Sigma_i}^{-1}(\bm{x_j}-\bm{\mu_i})] \\ & =\alpha_i\cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})\cdot(\bm{x_j}-\bm{\mu_i}) \end{aligned} μi[αip(xjμi,Σi)]=μi{αi(2π)n/2Σi1/21exp[21(xjμi)TΣi1(xjμi)]}=αi(2π)n/2Σi1/2exp[21(xjμi)TΣi1(xjμi)]μi[21(xjμi)TΣi1(xjμi)]=αip(xjμi,Σi)(xjμi)

这里是向量/矩阵对另一个向量求导,不是标量求导,具体可以参考矩阵求导相关资料

  因此继续推导如下:
⇒ ∑ j = 1 m α i ⋅ p ( x j ∣ μ i , Σ i ) ∑ l = 1 k α l ⋅ p ( x j ∣ μ l , Σ l ) ( x j − μ i ) = 0 ⇒ ∑ j = 1 m p M ( z j = i ∣ x j ) ( x j − μ i ) = 0 ⇒ ∑ j = 1 m γ j i ⋅ ( x j − μ i ) = 0 ⇒ ∑ j = 1 m γ j i x j = ∑ j = 1 m γ j i μ i ⇒ μ i = ∑ j = 1 m γ j i x j ∑ j = 1 m γ j i \begin{aligned} & \rArr \sum_{j=1}^m\frac{\alpha_i \cdot p(\bm{x_j}|\bm{\mu_i},\bm{\Sigma_i})}{\sum_{l=1}^k \alpha_l \cdot p(\bm{x_j}|\bm{\mu_l},\bm{\Sigma_l})} (\bm{x_j}-\bm{\mu_i})=0 \\ & \rArr \sum_{j=1}^m p_M(z_j=i|\bm{x_j})(\bm{x_j}-\bm{\mu_i})=0 \\ & \rArr \sum_{j=1}^m \gamma_{ji}\cdot (\bm{x_j}-\bm{\mu_i})=0 \\ & \rArr \sum_{j=1}^m \gamma_{ji}\bm{x_j}=\sum_{j=1}^m\gamma_{ji}\bm{\mu_i} \\ & \rArr \bm{\mu_i}=\frac{\sum_{j=1}^m \gamma_{ji}\bm{x_j}}{\sum_{j=1}^m\gamma_{ji}} \end{aligned} j=1ml=1kαlp(xjμl,Σl)αip(xjμi,Σi)(xjμi)=0j=1mpM(zj=ixj)(xjμi)=0j=1mγji(xjμi)=0j=1mγjixj=j=1mγjiμiμi=j=1mγjij=1mγjixj

  至此,参数 μ i \bm{\mu_i} μi迭代公式得到。

Σ : \bm{\Sigma}: Σ:

  同理,由
∂ L L ( D ) ∂ Σ i = 0 \frac{\partial LL(D)}{\partial \bm{\Sigma_i}}=0 ΣiLL(D)=0
  推得:
Σ i = ∑ j = 1 m γ j i ( x j − μ i ) ( x j − μ i ) T ∑ j = 1 m γ j i \bm{\Sigma_i}=\frac{\sum_{j=1}^m\gamma_{ji}(\bm{x_j}-\bm{\mu_i})(\bm{x_j}-\bm{\mu_i})^T}{\sum_{j=1}^m\gamma_{ji}} Σi=j=1mγjij=1mγji(xjμi)(xjμi)T

α : \alpha: α:

  求 α \alpha α的过程略有不同,因为除了要使 L L ( D ) LL(D) LL(D)最大化以外, α \alpha α还要满足它自身的条件: α i ≥ 0 , ∑ i = 1 k α i = 1 \alpha_i ≥0,\sum_{i=1}^k\alpha_i=1 αi0,i=1kαi=1
  这是一个有条件的极值问题,我们要用拉格朗日乘数法来求解(具体可以参考拉格朗日乘数法求极值的相关资料)
  相当于将 L L ( D ) LL(D) LL(D)求极值问题转化为 L L ( D ) + λ ( ∑ i = 1 k α i − 1 ) LL(D)+\lambda(\sum_{i=1}^k\alpha_i -1) LL(D)+λ(i=1kαi1)求极值的问题,然后依然对 α i \alpha_i αi求导为0,由此得到:
α i = 1 m ∑ j = 1 m γ j i \alpha_i=\frac{1}{m}\sum_{j=1}^m\gamma_{ji} αi=m1j=1mγji

  至此,高斯混合模型聚类的所有参数公式均已得到,之后只要不断迭代,并按照文章第3节中的划分方式来进行聚类划分即可。

  最后,可以再回头看看文章第1节的算法总结。


参考资料
  1. 周志华,机器学习,清华大学出版社,2016
  2. 李航,统计学习方法,清华大学出版社,2012








  • 27
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

虚宇宸轩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值