如何通俗理解EM算法(2),软件测试面试40题

硬币结果统计
A正正反正反3正-2反
B反反正正反2正-3反
A正反反反反1正-4反
B正反反正正3正-2反
A反正正反反2正-3反

硬币A被抛了15次,在第一轮、第三轮、第五轮分别出现了3次正、1次正、2次正,所以很容易估计出PA,类似的,PB也很容易计算出来,如下:

PA = (3+1+2)/ 15 = 0.4
PB= (2+3)/10 = 0.5

问题来了,如果我们不知道抛的硬币是A还是B呢(即硬币种类是隐变量),然后再轮流抛五轮,得到如下结果:

硬币结果统计
Unknown正正反正反3正-2反
Unknown反反正正反2正-3反
Unknown正反反反反1正-4反
Unknown正反反正正3正-2反
Unknown反正正反反2正-3反

OK,问题变得有意思了。现在我们的目标没变,还是估计PA和PB,需要怎么做呢?

显然,此时我们多了一个硬币种类的隐变量,设为z,可以把它认为是一个5维的向量(z1,z2,z3,z4,z5),代表每次投掷时所使用的硬币,比如z1,就代表第一轮投掷时使用的硬币是A还是B。

  • 但是,这个变量z不知道,就无法去估计PA和PB,所以,我们必须先估计出z,然后才能进一步估计PA和PB。
  • 可要估计z,我们又得知道PA和PB,这样我们才能用极大似然概率法则去估计z,这不是鸡生蛋和蛋生鸡的问题吗,如何破?

答案就是先随机初始化一个PA和PB,用它来估计z,然后基于z,还是按照最大似然概率法则去估计新的PA和PB,如果新的PA和PB和我们初始化的PA和PB一样,请问这说明了什么?

这说明我们初始化的PA和PB是一个相当靠谱的估计!

就是说,我们初始化的PA和PB,按照最大似然概率就可以估计出z,然后基于z,按照最大似然概率可以反过来估计出P1和P2,当与我们初始化的PA和PB一样时,说明是P1和P2很有可能就是真实的值。这里面包含了两个交互的最大似然估计。

如果新估计出来的PA和PB和我们初始化的值差别很大,怎么办呢?就是继续用新的P1和P2迭代,直至收敛。

我们不妨这样,先随便给PA和PB赋一个值,比如:
硬币A正面朝上的概率PA = 0.2
硬币B正面朝上的概率PB = 0.7

然后,我们看看第一轮抛掷最可能是哪个硬币。
如果是硬币A,得出3正2反的概率为 0.2*0.2*0.2*0.8*0.8 = 0.00512
如果是硬币B,得出3正2反的概率为0.7*0.7*0.7*0.3*0.3=0.03087
然后依次求出其他4轮中的相应概率。做成表格如下(标粗表示其概率更大):

轮数若是硬币A若是硬币B
10.00512,即0.2 0.2 0.2 0.8 0.8,3正-2反**0.03087,**3正-2反
20.02048,即0.2 0.2 0.8 0.8 0.8,2正-3反0.01323,2正-3反
3**0.08192,**即0.2 0.8 0.8 0.8 0.8,1正-4反0.00567,1正-4反
40.00512,即0.2 0.2 0.2 0.8 0.8,3正-2反**0.03087,**3正-2反
5**0.02048,**即0.2 0.2 0.8 0.8 0.8,2正-3反0.01323,2正-3反

按照最大似然法则:
第1轮中最有可能的是硬币B
第2轮中最有可能的是硬币A
第3轮中最有可能的是硬币A
第4轮中最有可能的是硬币B
第5轮中最有可能的是硬币A

我们就把概率更大,即更可能是A的,即第2轮、第3轮、第5轮出现正的次数2、1、2相加,除以A被抛的总次数15(A抛了三轮,每轮5次),作为z的估计值,B的计算方法类似。然后我们便可以按照最大似然概率法则来估计新的PA和PB。

PA = (2+1+2)/15 = 0.33
PB =(3+3)/10 = 0.6

设想我们是全知的神,知道每轮抛掷时的硬币就是如本文本节开头标示的那样,那么,PA和PB的最大似然估计就是0.4和0.5(下文中将这两个值称为PA和PB的真实值)。那么对比下我们初始化的PA和PB和新估计出的PA和PB:

初始化的PA估计出的PA真实的PA初始化的PB估计出的PB真实的PB
0.20.330.40.70.60.5

看到没?我们估计的PA和PB相比于它们的初始值,更接近它们的真实值了!就这样,不断迭代 不断接近真实值,这就是EM算法的奇妙之处。

可以期待,我们继续按照上面的思路,用估计出的PA和PB再来估计z,再用z来估计新的PA和PB,反复迭代下去,就可以最终得到PA = 0.4,PB=0.5,此时无论怎样迭代,PA和PB的值都会保持0.4和0.5不变,于是乎,我们就找到了PA和PB的最大似然估计。

三、EM算法的公式推导

3.1 EM算法的目标函数

还记得1.2节开头所说的吧?

从分布是p(x|θ)的总体样本中抽取到这100个样本的概率,也就是样本集X中各个样本的联合概率,用下式表示:

假设我们有一个样本集{x(1),…,x(m)},包含m个独立的样本,现在我们想找到每个样本隐含的类别z,能使得p(x,z)最大。p(x,z)的极大似然估计如下:

clip_image024

第一步是对极大似然取对数,第二步是对每个样例的每个可能类别z求联合分布概率和。但是直接求一般比较困难,因为有隐藏变量z存在,但是一般确定了z后,求解就容易了。

对于参数估计,我们本质上还是想获得一个使似然函数最大化的那个参数θ,现在与极大似然不同的只是似然函数式中多了一个未知的变量z,见下式(1)。也就是说我们的目标是找到适合的θ和z,以让L(θ)最大。那我们也许会想,你就是多了一个未知的变量而已啊,我也可以分别对未知的θ和z分别求偏导,再令其等于0,求解出来不也一样吗?

clip_image035

本质上我们是需要最大化(1)式,也就是似然函数,但是可以看到里面有“和的对数”,求导后形式会非常复杂(自己可以想象下log(f1(x)+ f2(x)+ f3(x)+…)复合函数的求导),所以很难求解得到未知参数z和θ。

我们把分子分母同乘以一个相等的函数(即隐变量Z的概率分布Qi(z(i)),其概率之和等于1,即clip_image067),即得到上图中的(2)式,但(2)式还是有“和的对数”,还是求解不了,咋办呢?接下来,便是见证神奇的时刻,我们通过Jensen不等式可得到(3)式,此时(3)式变成了“对数的和”,如此求导就容易了。

从(2)式到(3)式,神奇的地方有两点:

  1. 当我们在求(2)式的极大值时,(2)式不太好计算,我们便想(2)式大于某个方便计算的下界(3)式,而我们尽可能让下界(3)式最大化,直到(3)式的计算结果等于(2)式,便也就间接求得了(2)式的极大值;
  2. Jensen不等式,促进神奇发生的Jensen不等式到底是什么来历呢?

3.2 Jensen不等式

设f是定义域为实数的函数

  • 如果对于所有的实数x,f(x)的二次导数clip_image002,那么f是凸函数。
  • x是向量时,如果其hessian矩阵H是半正定的(clip_image004),那么f是凸函数。
  • 如果clip_image006或者clip_image008,那么称f是严格凸函数。

Jensen不等式表述如下:

如果f是凸函数,X是随机变量,那么:E[f(X)]>=f(E[X]),通俗的说法是函数的期望大于等于期望的函数。

特别地,如果f是严格凸函数,当且仅当P(X = EX) = 1,即X是常量时,上式取等号,即E[f(X)] = f(EX)。

如下图所示

clip_image019

图中,实线f是凸函数(因为函数上方的区域是一个凸集),X是随机变量,有0.5的概率是a,有0.5的概率是b(就像抛硬币一样)。X的期望值就是a和b的中值了,可以很明显从看出,clip_image010[1]

当然,当f是(严格)凹函数当且仅当-f是(严格)凸函数,不等号方向反向,也就是clip_image021

回到公式(2),因为f(x)=log x为凹函数(其二次导数为-1/x2<0)。

clip_image035

(2)式中clip_image038就是 clip_image039的期望。为什么?回想期望公式中的Lazy Statistician规则,如下

设Y是随机变量X的函数clip_image041(g是连续函数),那么       (1) X是离散型随机变量,它的分布律为clip_image043,k=1,2,…。若clip_image045绝对收敛,则有       clip_image047       (2) X是连续型随机变量,它的概率密度为clip_image049,若clip_image051绝对收敛,则有       clip_image053

考虑到E(X)=∑x*p(x),f(X)是X的函数,则E(f(X))=∑f(x)*p(x)),又clip_image067,所以就可以得到公式(3)的不等式了:

clip_image060

OK,到这里,现在式(3)就容易地求导了,但是式(2)和式(3)是不等号啊,式(2)的最大值不是式(3)的最大值啊,而我们想得到式(2)的最大值,那怎么办呢?

上面的式(2)和式(3)不等式可以写成:似然函数L(θ)>=J(z,Q),如3.1节最后所说,我们可以通过不断的最大化这个下界J,来使得L(θ)不断提高,最终达到L(θ)的最大值。

见上图,我们固定θ,调整Q(z)使下界J(z,Q)上升至与L(θ)在此点θ处相等(绿色曲线到蓝色曲线),然后固定Q(z),调整θ使下界J(z,Q)达到最大值(θt到θt+1),然后再固定θ,调整Q(z)……直到收敛到似然函数L(θ)的最大值处的θ*。

这里有两个问题:

  1. 什么时候下界J(z,Q)与L(θ)在此点θ处相等?
  2. 为什么一定会收敛?

clip_image035

首先第一个问题,在Jensen不等式中说到,当自变量X是常数的时候,等式成立。换言之,为了让(3)式取等号,我们需要:

clip_image063

其中,c为常数,不依赖于clip_image065。对该式做个变换,并对所有的z求和,得到

因为前面提到clip_image067(对的,隐变量Z的概率分布,其概率之和等于1),所以可以推导出:

所以通过clip_image063,可求得的值(即/c),加之,所以

clip_image070

瞬间豁然开朗!至此,我们推出了在固定参数θ后,使下界拉升的Q(z)的计算公式就是条件概率,解决了Q(z)如何选择的问题。这一步就是E步,建立L(θ)的下界。

接下来的M步,就是在给定Q(z)后,调整θ,去极大化L(θ)的下界J(z,Q),毕竟在固定Q(z)后,下界还可以调整的更大。

这就是EM算法的步骤。

3.3 EM算法的流程及证明

我们来总结下,期望最大EM算法是一种从不完全数据或有数据丢失的数据集(存在隐含变量)中求解概率模型参数的最大似然估计方法。

换言之,当我们不知道隐变量z的具体取值时(比如是硬币A还是硬币B),也就不好判断硬币A或硬币B正面朝上的概率θ,既然这样,那就

1 随机初始化分布参数θ 2 然后循环重复直到收敛 {       (E步,求Q函数)对于每一个i,计算根据上一次迭代的模型参数来计算出隐性变量的后验概率(其实就是隐性变量的期望),来作为隐藏变量的现估计值:                   clip_image074       (M步,求使Q函数获得极大时的参数取值)将似然函数最大化以获得新的参数值                   clip_image075

就这样,Q(z)求出来代入到θ,θ求出来又反代回Q(z),如此不断的迭代,就可以得到使似然函数L(θ)最大化的参数θ了。

还有就是,如上节所提出的第二个问题,它会收敛吗?或者,如何怎么确保EM收敛?

这里,直接引用JerryLead做的机器学习笔记证明下,我做了相关注解、解释。

假定clip_image077clip_image079是EM第 t 次和 t+1 次迭代后的结果(对的,上标 t 表示第 t 次迭代)。如果我们证明了clip_image081,也就是说极大似然估计单调增加,那么最终我们会到达最大似然估计的最大值。

下面来证明。

选定clip_image077[2]后,我们得到E步

clip_image083

这一步保证了在给定clip_image077[2]时,Jensen不等式中的等式成立,也就是

clip_image084

然后进行M步,固定clip_image086,并将clip_image088视作变量,对上面的clip_image090求导后,得到clip_image092,这样经过一些推导会有以下式子成立:

clip_image093

解释下第(4)步,得到clip_image092[1]时,只是最大化clip_image090[1],也就是clip_image095的下界,而没有使等式成立,等式成立只有是在固定clip_image026[4],并按E步得到clip_image097时才能成立。

况且根据我们前面得到的下式,对于所有的clip_image097[1]clip_image026[5]都成立

clip_image098

第(5)步利用了M步的定义,M步就是将clip_image088[1]调整到clip_image100,使得下界最大化。因此(5)成立,(6)是之前的等式结果。

这样就证明了clip_image102会单调增加。一种收敛方法是clip_image102不再变化,还有一种就是变化幅度很小。

再次解释一下(4)、(5)、(6)。

  • 首先(4)对所有的参数都满足,而其等式成立条件只是在固定clip_image026[4],并调整好Q时成立,而第(4)步只是固定Q,调整clip_image026[4],不能保证等式一定成立。
  • (4)到(5)就是M步的定义,(5)到(6)是前面E步所保证等式成立条件。也就是说E步会将下界拉到与clip_image102一个特定值(这里clip_image088[2])一样的高度,而此时发现下界仍然可以上升,因此经过M步后,下界又被拉升,但达不到与clip_image102[2]另外一个特定值一样的高度,之后E步又将下界拉到与这个特定值一样的高度,重复下去,直到最大值。

结束了?NO,M步中,到底如何求θ的极值呢?虽说求极值的方法有很多种,但本文还是要展开下。

首先,把Q(z)求出来代入到θ,可得:

 (7)

其中:

 (8)

(9)

直接对求导还是很麻烦,不过已经可以用迭代来最大化啦。

  1. 先根据式(9),由  求条件分布
  2. 再把  带入(7)中,得到

 (10)

这就只需要最大化联合分布  了,最大化求出  后再重复这2步。

M步很显然,就是最大化那一步,E步又从何谈起呢?根据式(10)有

其实,E步就是求给定X下的条件期望,也就是后验期望,使得式(3)的琴生不等式能够取等号,是对Jensen不等式中,小的那一端进行放大,使其等于大的那一端,这是一次放大;M步最大化联合分布,通过0梯度,拉格朗日法等方法求极值点,又是一次放大。只要似然函数是有界的,只要M步中的0梯度点是极大值点,一直放大下去就能找到最终所求。

3.4 EM算法另一种理解

如果我们定义

clip_image103

从前面的推导中我们知道clip_image105,EM可以看作是J的坐标上升法,E步固定clip_image026[8],优化clip_image107,M步固定clip_image107优化clip_image026[9]

坐标上升法(Coordinate ascent):

图中的直线式迭代优化的路径,可以看到每一步都会向最优值前进一步,而且前进路线是平行于坐标轴的,因为每一步只优化一个变量。

这犹如在x-y坐标系中找一个曲线的极值,然而曲线函数不能直接求导,因此什么梯度下降方法就不适用了。但固定一个变量后,另外一个可以通过求导得到,因此可以使用坐标上升法,一次固定一个变量,对另外的求极值,最后逐步逼近极值。

对应到EM上,就是:E步:固定θ,优化Q;M步:固定Q,优化θ;交替将极值推向最大。

四、EM应用:估计pLSA的两未知参数

关于EM算法的应用其实很多,最广泛的就是GMM混合高斯模型、聚类、HMM等等。比如聚类

本文重点讲下用EM算法估计主题模型pLSA的两未知参数。

4.1 pLSA模型下生成文档

一篇文章往往有多个主题,只是这多个主题各自在文档中出现的概率大小不一样。比如介绍一个国家的文档中,往往会分别从教育、经济、交通等多个主题进行介绍。那么在pLSA中,文档是怎样被生成的呢

假设你要写M篇文档,由于一篇文档由各个不同的词组成,所以你需要确定每篇文档里每个位置上的词。

再假定你一共有K个可选的主题,有V个可选的词,咱们来玩一个扔骰子的游戏。

  • 1. 假设你每写一篇文档会制作一颗K面的“文档-主题”骰子(扔此骰子能得到K个主题中的任意一个),和K个V面的“主题-词项” 骰子(每个骰子对应一个主题,K个骰子对应之前的K个主题,且骰子的每一面对应要选择的词项,V个面对应着V个可选的词)。
  • 比如可令K=3,即制作1个含有3个主题的“文档-主题”骰子,这3个主题可以是:教育、经济、交通。然后令V = 3,制作3个有着3面的“主题-词项”骰子,其中,教育主题骰子的3个面上的词可以是:大学、老师、课程,经济主题骰子的3个面上的词可以是:市场、企业、金融,交通主题骰子的3个面上的词可以是:高铁、汽车、飞机。
  • 2. 每写一个词,先扔该“文档-主题”骰子选择主题,得到主题的结果后,使用和主题结果对应的那颗“主题-词项”骰子,扔该骰子选择要写的词。
  • 先扔“文档-主题”的骰子,假设(以一定的概率)得到的主题是教育,所以下一步便是扔教育主题筛子,(以一定的概率)得到教育主题筛子对应的某个词:大学。
  • 上面这个投骰子产生词的过程简化下便是:“先以一定的概率选取主题,再以一定的概率选取词”。事实上,一开始可供选择的主题有3个:教育、经济、交通,那为何偏偏选取教育这个主题呢?其实是随机选取的,只是这个随机遵循一定的概率分布。比如可能选取教育主题的概率是0.5,选取经济主题的概率是0.3,选取交通主题的概率是0.2,那么这3个主题的概率分布便是{教育:0.5,经济:0.3,交通:0.2},我们把各个主题z在文档d中出现的概率分布称之为主题分布,且是一个多项分布。
  • 同样的,从主题分布中随机抽取出教育主题后,依然面对着3个词:大学、老师、课程,这3个词都可能被选中,但它们被选中的概率也是不一样的。比如大学这个词被选中的概率是0.5,老师这个词被选中的概率是0.3,课程被选中的概率是0.2,那么这3个词的概率分布便是{大学:0.5,老师:0.3,课程:0.2},我们把各个词语w在主题z下出现的概率分布称之为词分布,这个词分布也是一个多项分布。
  • 所以,选主题和选词都是两个随机的过程,先从主题分布{教育:0.5,经济:0.3,交通:0.2}中抽取出主题:教育,然后从该教育主题对应的词分布{大学:0.5,老师:0.3,课程:0.2}中抽取出词:大学
  • 3. 最后,你不停的重复扔“文档-主题”骰子和”主题-词项“骰子,重复N次(产生N个词),完成一篇文档,重复这产生一篇文档的方法M次,则完成M篇文档。

上述过程抽象出来即是pLSA的文档生成模型。在这个过程中,我们并未关注词和词之间的出现顺序,所以pLSA是一种词袋方法。具体说来,该模型假设一组共现(co-occurrence)词项关联着一个隐含的主题类别。同时定义:

  • 表示海量文档中某篇文档被选中的概率。
  • 表示词在给定文档中出现的概率。
  • 怎么计算得到呢?针对海量文档,对所有文档进行分词后,得到一个词汇列表,这样每篇文档就是一个词语的集合。对于每个词语,用它在文档中出现的次数除以文档中词语总的数目便是它在文档中出现的概率
  • 表示具体某个主题在给定文档下出现的概率。
  • 表示具体某个词在给定主题下出现的概率,与主题关系越密切的词,其条件概率越大。

利用上述的第1、3、4个概率,我们便可以按照如下的步骤得到“文档-词项”的生成模型:

  1. 按照概率选择一篇文档
  2. 选定文档后,从主题分布中按照概率选择一个隐含的主题类别
  3. 选定后,从词分布中按照概率选择一个词

所以pLSA中生成文档的整个过程便是选定文档生成主题,确定主题生成词。

4.2 根据文档反推其主题分布

反过来,既然文档已经产生,那么如何根据已经产生好的文档反推其主题呢?这个利用看到的文档推断其隐藏的主题(分布)的过程(其实也就是产生文档的逆过程),便是主题建模的目的:自动地发现文档集中的主题(分布)。

换言之,人类根据文档生成模型写成了各类文章,然后丢给了计算机,相当于计算机看到的是一篇篇已经写好的文章。现在计算机需要根据一篇篇文章中看到的一系列词归纳出当篇文章的主题,进而得出各个主题各自不同的出现概率:主题分布。即文档d和单词w是可被观察到的,但主题z却是隐藏的。

如下图所示(图中被涂色的d、w表示可观测变量,未被涂色的z表示未知的隐变量,N表示一篇文档中总共N个单词,M表示M篇文档):

上图中,文档d和词w是我们得到的样本(样本随机,参数虽未知但固定,所以pLSA属于频率派思想。区别于参考文献8介绍的LDA中:样本固定,参数未知但不固定,是个随机变量,服从一定的分布,所以LDA属于贝叶斯派思想),可观测得到,所以对于任意一篇文档,其是已知的。

从而可以根据大量已知的文档-词项信息,训练出文档-主题和主题-词项,如下公式所示:

故得到文档中每个词的生成概率为:

由于可事先计算求出,未知,所以就是我们要估计的参数(值),通俗点说,就是要最大化这个θ。

用什么方法进行估计呢,常用的参数估计方法有极大似然估计MLE、最大后验证估计MAP、贝叶斯估计等等。因为该待估计的参数中含有隐变量z,所以我们可以考虑EM算法。

4.3 EM算法估计pLSA的两未知参数

首先尝试从矩阵的角度来描述待估计的两个未知变量****

  • 假定用表示词表在主题上的一个多项分布,则可以表示成一个向量,每个元素**表示词项出现在主题**中的概率,即

  • 表示所有主题在文档上的一个多项分布,则可以表示成一个向量,每个元素**表示主题出现在文档中的概率**,即

这样,巧妙的把转换成了两个矩阵。换言之,最终我们要求解的参数是这两个矩阵:

由于词和词之间是相互独立的,所以整篇文档N个词的分布为:

再由于文档和文档之间也是相互独立的,所以整个语料库中词的分布为(整个语料库M篇文档,每篇文档N个词):

其中,表示词项在文档中的词频,表示文档di中词的总数,显然有
从而得到整个语料库的词分布的对数似然函数(下述公式中有个小错误,正确的应该是:N为M,M为N):

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数软件测试工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

因此收集整理了一份《2024年软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。*
[外链图片转存中…(img-6j9dojdG-1713025732986)]
[外链图片转存中…(img-ubFyfL4V-1713025732987)]
[外链图片转存中…(img-J8wYzHzq-1713025732987)]
[外链图片转存中…(img-VZ8RZVY9-1713025732988)]
[外链图片转存中…(img-N3ZSGrIi-1713025732988)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-YoXu3ipx-1713025732989)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值