LSH系列3:p-stable LSH&E2LSH——原理介绍

p-stable LSH

背景

LSH 方法是处理海量高维数据 Approximate Nearest Neighbor(ANN)查询的有效的方法。

c-ANN 查询的定义为:给定一个查询点 q q q,且 o ∗ o^{*} o 是精确的 NN 查询的结果,该查询返回一个点 o o o ∣ ∣ o , q ∣ ∣ p ≤ ∣ ∣ o ∗ , q ∣ ∣ p ||o,q||_p \leq ||o^{*},q||_p o,qpo,qp

在处理欧氏空间中 ANN 问题时,原始的 LSH(Original LSH) 方法将原始空间中的点嵌入到 Hamming 空间中,即将欧氏空间中点的表示形式转换成 Hamming 空间中点的表示形式,原始空间中的距离度量转换成 Hamming 空间中的距离度量,即 Hamming距离(其定义为两个等长序列各位进行异或运算,结果为 1 的个数)。

对应该汉明距离的 Origin LSH 的为位采样运算(bit sampling)。但是一般距离都是用欧式距离进行度量的,将欧式距离映射到 Hamming 空间再比较其的 Hamming 距离比较麻烦,于是研究者提出了基于 p-stable distribution 的位置敏感哈希算法,不需要将原始空间嵌入到 Hamming 空间中而是可以直接处理欧式距离,并解决 (R,c)-近邻问题。

p-stable LSH应用在d维 lp-norm 下的欧几里得空间中, p ∈ ( 0 , 2 ] p∈(0,2] p(0,2]

p-stable distribution

p-stable LSH 之所以会叫这个名字,是因为该算法应用到 p-stable distribution(p-稳定分布)的概念。下面给出的就是p-稳定分布的概念:

对于一个实数集 R 上的分布 D,如果存在 p > = 0 p>=0 p>=0 ,对任何 n 个实数 v 1 , … , v n v_1,…,v_n v1,,vn和 n 个满足 D 分布的变量 X 1 , … , X n X_1,…,X_n X1,,Xn,随机变量 ∑ i v i X i \sum_iv_iX_i iviXi ( ∑ i ∣ v i ∣ p ) 1 / p X (\sum_i|v_i|^p)^{1/p}X (ivip)1/pX 有相同的分布,其中 X X X 是服从D分布的一个随机变量,则称 D 为一个p稳定分布。

对任何 p ∈ ( 0 , 2 ] p∈(0,2] p(0,2] 存在稳定分布:

p = 1 p=1 p=1 是柯西分布,概率密度函数为 c ( x ) = 1 π ( 1 + x 2 ) c(x)=\frac{1}{π(1+x^2)} c(x)=π(1+x2)1

p = 2 p=2 p=2 是高斯分布,概率密度函数为 g ( x ) = 1 ( 2 π ) 1 2 e − x 2 2 g(x)=\frac{1}{(2π)^{\frac{1}{2}}}e^{-\frac{x^2}{2}} g(x)=(2π)211e2x2


利用 p-stable distribution 可以有效的近似高维特征向量,并在保证度量距离的同时,对高维特征向量进行降维,这里先说是如何降维的,其关键思想是:

  • 产生一个 d 维的随机向量 a a a a = ( X 1 , . . . , X d ) a=(X_1,...,X_d) a=(X1,...,Xd),随机向量 a a a 中的每一维随机的、独立的从 p-stable distribution中产生(每一个随机变量都满足 p-stable 分布)。
  • 对于一个 d 维的特征向量 v v v,因为 a ⋅ v = ∑ i v i X i a \cdot v =\sum_iv_iX_i av=iviXi,如 p-stable distribution 的定义,随机变量 a ⋅ v a \cdot v av 具有和 ( ∑ i ∣ v i ∣ p ) 1 / p X (\sum_i|v_i|^p)^{1/p}X (ivip)1/pX 一样的分布,即和 ∣ ∣ v ∣ ∣ p X ||v||_pX vpX 是同分布的。可以用 a ⋅ v a \cdot v av 表示向量 v v v 来估算 ∣ ∣ v ∣ ∣ p ||v||_p vp ,其中 ∣ ∣ v ∣ ∣ p ||v||_p vp 表示向量 v v v 在欧几里得空间 p-norm 下的长度(原始空间中的长度)。
  • 上面 a ⋅ v a \cdot v av 的结果是一个实数,就相当于将一个向量映射到了一个实数上,也就是一维上。我们可以用 k 个这样的随机向量 { a i : a i = ( X 1 , . . . , X d ) , 1 ≤ i ≤ k } \{a_i:a_i=(X_1,...,X_d), 1\leq i \leq k\} {ai:ai=(X1,...,Xd),1ik},每一个随机向量都可以将这个向量映射到一维上,那么这 k 个随机向量映射得到的 k 个实数组成的向量,就可以看成是 k 维投影空间(降维了)中该向量的坐标。

这里证明 p=2 情形下,将高维数据映射到投影空间后,是如何保证距离度量的。p=2 采用欧氏距离作为距离度量方式,且记 p-stable distribution 服从标准正态分布, X ~ N ( 0 , 1 ) X~N(0,1) XN(0,1)

  • 对于原始空间中任意两个特征向量 v 1 , v 2 v_1,v_2 v1,v2,其在投影空间中的坐标点分别为 v 1 ′ , v 2 ′ v_1^{'},v_2^{'} v1,v2,记 r = ∣ ∣ v 1 , v 2 ∣ ∣ r=||v_1,v_2|| r=v1,v2 为其在原始空间中的距离, r ′ = ∣ ∣ v 1 ′ , v 2 ′ ∣ ∣ r^{'}=||v_1^{'},v_2^{'}|| r=v1,v2 为其在投影空间中的距离。
    ρ i \rho_i ρi 为投影空间中这两个点第 i 维坐标值的差,那么显然有 r ′ = ( ∑ i = 1 k ρ i 2 ) 1 2 r^{'} = (\sum_{i=1}^{k}\rho_i^{2})^{\frac{1}{2}} r=(i=1kρi2)21
    由 p-stable 分布的定义可知, ρ i = a i ⋅ ( v 1 − v 2 ) \rho_i = a_i \cdot (v_1-v_2) ρi=ai(v1v2),与 r ⋅ X r \cdot X rX 是同分布的,即 ρ ~ N ( 0 , r 2 ) \rho ~N(0,r^2) ρN(0,r2),即 ρ r ~ N ( 0 , 1 ) \frac{\rho}{r} ~ N(0,1) rρN(0,1)
    r ′ 2 r 2 = ∑ ρ i 2 r 2 \frac{r^{'2}}{r^2} = \frac{\sum\rho_i^{2}}{r^2} r2r2=r2ρi2,也就是 k 个相互独立的标准正态分布之和,有:
    r ′ 2 r 2 ~ χ 2 ( k ) \frac{r^{'2}}{r^2} ~ \chi^2(k) r2r2χ2(k)
  • 接下来对 r ′ r^{'} r置信区间进行估计,建立起 r r r r ′ r^{'} r 之间的强依赖关系。给定原始空间中的两个点 o 1 , o 2 o_1,o_2 o1,o2,我们有:
    • T h e   p r o b a b i l i t y   t h a t   r ′   <   r χ 1 − α 2 ( k )   i s   α . The\ probability\ that\ r^{'}\ <\ r\sqrt{\chi_{1-\alpha}^{2}(k)}\ is\ \alpha. The probability that r < rχ1α2(k)  is α.
    • T h e   p r o b a b i l i t y   t h a t   r ′   >   r χ α 2 ( k )   i s   α . The\ probability\ that\ r^{'}\ >\ r\sqrt{\chi_{\alpha}^{2}(k)}\ is\ \alpha. The probability that r > rχα2(k)  is α.
    • 证明如下:对于卡方分布 χ 2 ( k ) \chi^2(k) χ2(k) 来说,给定一个概率 α \alpha α,去寻找使得 χ 2 ( k ) \chi^2(k) χ2(k) 大于某个数的概率为 α \alpha α,这个数就记为卡方分布在参数 k , α k,\alpha k,α 下的上侧分位数记为 χ α 2 ( k ) \chi^2_{\alpha}(k) χα2(k),表示:
      ∫ χ α 2 ( k ) ∞ f ( x ; k ) = α \int_{\chi^2_{\alpha}(k)}^{\infin}f(x;k) = \alpha χα2(k)f(x;k)=α
      我们知道 r ′ 2 r 2 \frac{r^{'2}}{r^2} r2r2 是服从卡方分布的,我们对 r ′ 2 r 2 \frac{r^{'2}}{r^2} r2r2 的置信区间 I = [ u , v ] I=[u,v] I=[u,v] 进行估计,对任何给定的 α \alpha α 要求其落在 I I I 内的概率为 1 − 2 α 1-2\alpha 12α。一个标准做法就是选择使得 P r [ r ′ 2 r 2 < u ] = α Pr[\frac{r^{'2}}{r^2}<u]=\alpha Pr[r2r2<u]=α,即 P r [ r ′ 2 r 2 > u ] = 1 − α Pr[\frac{r^{'2}}{r^2}>u]=1-\alpha Pr[r2r2>u]=1α 以及 P r [ r ′ 2 r 2 > v ] = α Pr[\frac{r^{'2}}{r^2}>v]=\alpha Pr[r2r2>v]=α 成立的 u , v u,v u,v取值,也就是找使得 ∫ u ∞ f ( x ; k ) = 1 − α \int_{u}^{\infin}f(x;k) =1- \alpha uf(x;k)=1α ∫ v ∞ f ( x ; k ) = α \int_{v}^{\infin}f(x;k) = \alpha vf(x;k)=α 成立的 u , v u,v u,v 取值。根据卡方分布上侧分位数的定义,我们有 u = χ 1 − α 2 ( k ) u=\chi_{1-\alpha}^{2}(k) u=χ1α2(k) v = χ α 2 ( k ) v=\chi_{\alpha}^{2}(k) v=χα2(k)。所以:
      P r [ r ′ < r χ 1 − α 2 ( k ) ] = α P r [ r ′ > r χ α 2 ( k ) ] = α Pr[r^{'}<r\sqrt{\chi_{1-\alpha}^{2}(k)}] = \alpha \\ Pr[r^{'}>r\sqrt{\chi_{\alpha}^{2}(k)}] = \alpha Pr[r<rχ1α2(k) ]=αPr[r>rχα2(k) ]=α
      得证。这样就建立起了原始空间中的距离与投影距离的置信区间之间的一种强关系。

p-stable LSH 的哈希函数

在 p-stable LSH 中,点积 a ⋅ v a \cdot v av 不用来估计 ∣ ∣ v ∣ ∣ p ||v||_p vp 的值,而是用来生成哈希函数,且该哈希函数是局部敏感的(即空间中距离较近的点映射后发生冲突的概率高,空间中距离较远的点映射后发生冲突的概率低),使用它对每一个特征向量 v v v 赋予一个哈希值。

对于两个向量 v 1 , v 2 v_1,v_2 v1,v2 , ( a ⋅ v 1 − a ⋅ v 2 ) ,(a \cdot v_1-a \cdot v_2) (av1av2)是映射后的距离,而其值与 ∣ ∣ v 1 − v 2 ∣ ∣ p X ||v_1-v_2||_pX v1v2pX 同分布,因此原始距离 ∣ ∣ v 1 − v 2 ∣ ∣ p ||v_1-v_2||_p v1v2p 较小时,映射后的距离也小,因此使用点积来生成哈希函数可以保持局部敏感性。如果 v 1 v_1 v1 v 2 v_2 v2 距离很近,它们的哈希值将相同,并被哈希到同一个桶中的概率会很大。

大体方法 a ⋅ v a \cdot v av将特征向量 v v v 映射到实数集R,如果将实轴以宽度 w w w 等分,并对每一段进行标号,则 a ⋅ v a \cdot v av 落到哪个区间,就将此区间标号作为哈希值赋给它。

哈希函数定义如下:

h a , b ( v ) : R d → N h_{a,b}(v):R^d→ N ha,b(v):RdN映射一个 d 维特征向量 v v v 到一个整数集。哈希函数中有两个随机变量 a a a b b b,其中 a a a 为一个 d 维向量,随机向量 a a a 中的每一维随机的、独立的从 p-stable distribution 中产生, b b b [ 0 , w ] [0,w] [0,w] 范围内的随机数, w w w 是人为设定的一个参数。对于一个固定的 a , b a,b a,b,p-stable LSH 的哈希函数 h a b ( v ) h_{ab}(v) hab(v) 为:
h a b ( v ) = ⌊ a ⋅ v + b w ⌋ h_{ab}(v) = \lfloor \frac{a \cdot v + b}{w} \rfloor hab(v)=wav+b

这样的哈希函数构成的集合 { h a , b ( v ) : R d → N } \{h_{a,b}(v):R^d→ N\} {ha,b(v):RdN} 为 p-stable LSH 的哈希函数族。

两个向量在 p-stable LSH 的哈希函数映射下发生碰撞的概率分析

从 p-stable LSH 的哈希函数族中随机选取一个哈希函数,现在估计两个向量 v 1 , v 2 v_1,v_2 v1,v2 在该哈希函数下发生冲突(也就是落在一个桶中)的概率。若要向量 v 1 v_1 v1 v 2 v_2 v2 映射后发生冲突,需要满足如下条件: v 1 v_1 v1 v 2 v_2 v2 通过与 a a a 进行点积运算分别映射到一段长度为 w w w 线段后,再通过加 b b b 运算,能使映射后的点在同一条线段上。

首先定义 c = ∣ ∣ v 1 − v 2 ∣ ∣ p c=||v_1-v_2||_p c=v1v2p(原始空间中的距离), f p ( t ) f_p(t) fp(t)为 p-stable 的分布的概率密度函数,那么特征向量 v 1 v_1 v1 v 2 v_2 v2 映射到一个桶上的距离是 ∣ a ⋅ v 1 − a ⋅ v 2 ∣ < w |a·v_1-a·v_2|<w av1av2<w,即 ∣ ( v 1 − v 2 ) ⋅ a ∣ < w |(v_1-v_2)·a|<w (v1v2)a<w,根据p-Stable分布的特性,即 ∣ ∣ v 1 − v 2 ∣ ∣ p X = ∣ c X ∣ < w ||v1-v2||_pX=|cX|<w v1v2pX=cX<w,其中随机变量 X X X 满足 p-stable distribution。

P ( c ) = P r [ h a b ( v 1 ) − h a b ( v 2 ) ] = ∫ 0 w 1 c f p ( t c ) ( 1 − t w ) d t P(c)=Pr[h_{ab}(v_1)-h_{ab}(v_2)] = \int_{0}^{w}\frac{1}{c}f_p(\frac{t}{c})(1-\frac{t}{w})dt P(c)=Pr[hab(v1)hab(v2)]=0wc1fp(ct)(1wt)dt

关于这个概率公式的证明,详见它的最后一部分。

根据该式,可以得出两个特征向量的冲突碰撞概率随着距离 c c c(指的是原始空间中的距离) 的增加而减小,这符合局部敏感哈希函数的要求。

E2LSH

各路博客中 E2LSH 的解释

这里已经尽力把网上给出的 E2LSH 算法整理了一遍了,完全是没有道理的,至于为什么没有道理,在下一节开始会给出。

欧氏局部敏感哈希(E2LSH,Exact Euclidean locality sensitive Hashing)是 p-stable LSH在欧氏空间的一种随机化实现方法,其基本原理是:利用基于p-稳定分布的位置敏感函数对高维数据进行降维映射,使原始空间中距离很近的两个点经映射操作后依然很近。

一组哈希函数的情况

只有一个 g ( v ) g(v) g(v) 的情况,只有一个哈希表。

为拉大距离近的点与距离远的点经映射后碰撞概率之间的差距,E2LSH 常将 k 个 p-stable LSH 哈希函数联合使用。

从 p-stable LSH 哈希函数族 { h a , b ( v ) : R d → N } \{h_{a,b}(v):R^d→ N\} {ha,b(v):RdN} 选择 k 个哈希函数,组成一组哈希函数 g ( v ) = ( h 1 ( v ) , . . . , h k ( v ) ) g(v)=(h_1(v),...,h_k(v)) g(v)=(h1(v),...,hk(v)),对于每个数据点 v ∈ R d v \in R^d vRd,经函数 g ( v ) g(v) g(v) 降维后可以得到一个 k 维向量 a = ( a 1 , a 2 , ⋅ ⋅ ⋅ , a k ) a = (a_1 , a_2 , ··· , a_k ) a=(a1,a2,,ak)这个 k k k 元组就代表一个桶

但将 k 元组 a a a 直接作为该哈希表的桶标号,即占用内存,又不便于查找。为解决此问题,设计者又将其分层,使用数组+链表的方式,其中链表中的每一项都是一个哈希桶,即将原来的哈希表组织成下面的形式。

在这里插入图片描述

对每个形式为 k 元组的桶标号 a a a,使用如下两个哈希函数 H1 和 H2 计算得到两个值:

  • 其中 H1 的值是数组中的位置,数组的大小也就相当于是哈希表的大小。
  • 其中 H2 的值作为 k 元组的代表,链接到对应 H1 数组位置的链表中。

H1 和H2 的具体形式如下:

H 1 ( a ) = [ ( ∑ i = 1 k r i a i )   m o d   C ]   m o d   t a b l e S i z e H 2 ( a ) = ( ∑ i = 1 k r i ′ a i )   m o d   C H_1(a) = [(\sum_{i=1}^{k}r_ia_i)\ mod\ C]\ mod\ tableSize \\ H_2(a) = (\sum_{i=1}^{k}r_i^{'}a_i)\ mod\ C H1(a)=[(i=1kriai) mod C] mod tableSizeH2(a)=(i=1kriai) mod C

其中:

  • r i r_i ri r i ′ r_i^{'} ri 是随机整数;
  • C C C 是一个大素数,在 32 位机器上可以设置为 2 32 − 5 2^{32}-5 2325;

索引构建过程:

  • 对数据集中的所有点 v v v,使用 g ( v ) g(v) g(v) 函数对其进行降维,也就是确定其桶标号。
  • 然后使用新定义的哈希函数 H 1 H_1 H1 H 2 H_2 H2,将其存在对应位置的哈希桶内
  • 也就是根据 H 1 H_1 H1 的值找到在数组中的位置,然后根据 H 2 H_2 H2 的值在链表中寻找对应的哈希桶,在将原始数据点 v v v 存到对应的哈希桶中。

查询过程如下:

  • 对于查询点 q;
  • 使用这 k 个哈希函数构成的函数(即 g ( q ) g(q) g(q))计算桶标号的 k 元组
  • 对 k 元组计算 H1 和 H2 的值;
  • 获取哈希表 H1 位置的链表;
  • 在链表中查找 H2 值对应的哈希桶;
  • 计算 q 与桶中样本的精确的距离,并排序;
  • 找到规定的点。

多组哈希函数的情况

定义 { g l ( v ) : g l ( v ) = ( h 1 ( v ) , . . . , h k ( v ) ) , 1 ≤ l ≤ L } \{g_l(v):g_l(v)=(h_1(v),...,h_k(v)),1 \leq l \leq L\} {gl(v):gl(v)=(h1(v),...,hk(v)),1lL},也就是定义 L L L 个前面那样的 g ( v ) g(v) g(v) 函数,这对应着 L L L 个哈希表。每个 g l ( v ) g_l(v) gl(v) 函数由从哈希函数族 { h a , b ( v ) : R d → N } \{h_{a,b}(v):R^d→ N\} {ha,b(v):RdN} 中随机独立地选取 k 个哈希函数组成, g l ( v ) g_l(v) gl(v) 对向量 v v v 降维后的值,表示其在第 l l l 个哈希表中哈希桶标号。

对于每个 g l ( v ) g_l(v) gl(v)函数,都对应着一个哈希表,每个哈希表都由数组+链表的形式构成。

哈希表

在构建索引时,对数据集中的每个数据点 v v v,计算其 L L L 个哈希函数的值,并将其存在 L L L 个哈希表对应的哈希桶内。

查询时,同样计算查询点 q q q L L L g l ( q ) g_l(q) gl(q) 函数值,找到 q q q 所在的 L L L 个哈希桶,计算 q q q 与这些哈希桶中的全部点(有的说是 3 L 3L 3L 个点)的精确距离,找到规定的点。

实际上呢?需要 (r,c)-BC query 来回答 c-ANN query

实际上,现有的方法都不是都不是直接地去解决 c-ANN 查询问题的,因为就算你筛选出了候选集,但是你不知道精确的 NN 结果,所以你无法验证到底哪个点 o o o 符合 ∣ ∣ q , o ∣ ∣ ≤ c ∗ ∣ ∣ q , o ∗ ∣ ∣ ||q,o||\leq c*||q,o^{*}|| q,ocq,o 条件,所以上面的验证方法都是白扯。

为了解决 c-ANN 查询问题,提出了一个 ( r , c ) − B C   q u e r y ( ( r , c )   b a l l   c o v e r ) (r,c)-BC\ query((r,c)\ ball\ cover) (r,c)BC query(r,c) ball cover 的概念。这里给出它的定义,其中 r r r 是超球体的半径, c c c 是近似比,数据集为 D D D,记 B ( q , r ) B(q,r) B(q,r) 为以 q q q 为中心, r r r 为半径的一个超球体。一个 ( r , c ) − B C (r,c)-BC (r,c)BC 查询返回:

  • 如果 B ( q , r ) B(q,r) B(q,r) 至少包含 D D D 中一个点的话,那么返回距离 q q q 至多为 c r cr cr 的一个点;
  • 如果 B ( q , c r ) B(q,cr) B(q,cr) 不包含 D D D 中的任何点的话,那么什么都不返回。
  • O t h e r w i s e ,   t h e   r e s u l t   i s   u n d e f i n e d Otherwise,\ the\ result\ is\ undefined Otherwise, the result is undefined.

在这里插入图片描述

如上图,考虑 ( r , 2 ) − B C (r,2)-BC (r,2)BC 查询:

  • q 1 q_1 q1 查询时,由于 B ( q 1 , r ) B(q_1,r) B(q1,r) 内有点,所以返回 o 1 o_1 o1 o 2 o_2 o2,因为这两个点都在 B ( q 1 , 2 r ) B(q_1,2r) B(q1,2r)内;
  • q 2 q_2 q2 查询时,由于 B ( q 2 , 2 r ) B(q_2,2r) B(q2,2r) 内没有点,所以什么都不返回。

在这里插入图片描述

c − A N N c-ANN cANN 查询可以通过执行一组 ( r , c ) − B C (r,c)-BC (r,c)BC 查询来解决。基本思想是这样的:如果 B ( q , r ) B(q,r) B(q,r) 不包含任何点,但 B ( q , c r ) B(q,cr) B(q,cr) 包含点,那么 B ( q , c r ) B(q,cr) B(q,cr) 中的任何一点都可以作为 c − A N N c-ANN cANN 查询的结果。就是说精确解 o ∗ o^{*} o 肯定是在这两个超球组成的超环之内的,所以对于这个超环内的任何一点 o o o 肯定有 ∣ ∣ q , o ∣ ∣ ≤ ∣ ∣ q , o ∗ ∣ ∣ ||q,o||\leq ||q,o^{*}|| q,oq,o。如上图, B ( q , r ) B(q,r) B(q,r) 不包含任何点,但是 B ( q , c r ) B(q,cr) B(q,cr) 包含点,所以 q q q 精确的 N N NN NN 查询结果到 q q q 的距离一定在 r r r c r cr cr 之间,所以说 B ( q , c r ) B(q,cr) B(q,cr) 中任何一点都是 q q q c − A N N c-ANN cANN 查询的结果

上一节中的方法进行 ( r , c ) − B C q u e r y (r,c)-BC query (r,c)BCquery 是完全没问题的,但是直接回答 c − A N N c-ANN cANN 查询是完全没有道理的,没有任何理论保证。

其实 LSH 的实际实现方法中,都是通过求解一系列的 ( r , c ) − B C   q u e r y (r,c)-BC\ query (r,c)BC query 来解决 c − A N N c-ANN cANN 问题的,除了E2LSH之外,还有PM_LSHLSB-treeC2LSH等。详细算法都需要涉及到复杂的理论保证推导,感兴趣自行了解。

参考

http://blog.sina.com.cn/s/blog_67914f2901019p3v.html

https://blog.csdn.net/jasonding1354/article/details/38237353

https://wenku.baidu.com/view/c616e7c008a1284ac85043cd.html

https://www.cnblogs.com/jiejnan/archive/2012/03/13/2393660.html

https://www.cnblogs.com/hxsyl/p/4627477.html

https://blog.csdn.net/camu7s/article/details/48948069

  • 11
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值