凸优化—SVD—PCA原理详情

一、凸优化

      ~~~~~      两个正数的算术平均数大于等于几何平均数:
a + b 2 ⩾ a b \frac{a+b}{2} \geqslant \sqrt{ab} 2a+bab
      ~~~~~      给定可逆对称阵Q,对于任意的向量x,y,有:
x T Q x + y T Q − 1 y ⩾ 2 x T y x^TQx+y^TQ^{-1}y \geqslant 2x^Ty xTQx+yTQ1y2xTy
这里写图片描述

1.1 仿射集:(直线)

        ~~~~~~~        通过集合C中任意两个不同点的直线仍然在集合C内,则称集合C为仿射集。
∀ θ ∈ R ,    ∀ x 1 , x 2 ∈ C    则 x = θ x 1 + ( 1 − θ ) x 2 ∈ C \forall \theta \in R ,~~ \forall x_1 ,x_2 \in C ~~则 x = \theta x_1+(1-\theta)x_2 \in C θR,  x1,x2C  x=θx1+(1θ)x2C

1.2 凸集:(线段)

        ~~~~~~~        如果通过集合C中任意两个不同点之间的线段(上的任何点)仍在集合C中,那么称集合C是凸的。
θ x 1 + ( 1 − θ ) x 2 ∈ C ; 其 中 x 1 , x 2 ∈ C , 0 ⩽ θ ⩽ 1 θx_1+(1-θ)x_2 ∈ C;其中 x1,x2∈ C,0\leqslant θ\leqslant 1 θx1+(1θ)x2C;x1,x2C0θ1

1.3 锥定义(射线)

        ~~~~~~~        给定 C ∈ R n , 满 足 x ∈ C ⇒ t x ∈ C 对 于 任 意 t ≥ 0 C∈R_n,满足x∈C⇒tx∈C 对于任 意t≥0 CRnxCtxCt0称之为锥。

凸锥(convex cone):
        ~~~~~~~         x 1 , x 2 ∈ C ⇒ t 1 x 1 + t 2 x 2 ∈ C , 对 于 任 意 t 1 , t 2 ≥ 0 x_1,x_2∈C ⇒ t_1x_1+t_2x_2∈C,对于任意t_1,t_2≥0 x1,x2Ct1x1+t2x2C,t1,t20都成立,那么称集合C 为凸锥。显然凸锥是锥的一种。

这里写图片描述

1.4 凸优化

若函数f的定义域domf 为凸集,且满足: ∀ x , y ∈ d o m f , θ ∈ [ 0 , 1 ] \forall x,y \in domf , \theta \in [0,1] x,ydomf,θ[0,1]
f ( θ x + ( 1 − θ ) y ) ⩽ θ f ( x ) + ( 1 − θ ) f ( y ) f(\theta x + (1-\theta)y) \leqslant \theta f(x) + (1-\theta)f(y) f(θx+(1θ)y)θf(x)+(1θ)f(y)
这里写图片描述
拉格朗日乘子法就是求函数 f ( x 1 , x 2 , . . . ) f(x1,x2,...) f(x1,x2,...) 在约束条件 h ( x 1 , x 2 , . . . ) = 0 h(x1,x2,...)=0 h(x1,x2,...)=0下的极值的方法:
F ( x , λ ) = f ( x ) + ∑ k = 1 l λ k h k ( x ) F(x,\lambda) = f(x)+\sum_{k=1}^{l}λ_kh_k(x) F(x,λ)=f(x)+k=1lλkhk(x)
这里写图片描述

1.5 示例

求椭球的内接最大体积 :
x 2 a 2 + x 2 b 2 + x 2 c 2 = 1     求 f ( x , y , z ) = 8 x y z 最 大 值 \frac{x^2}{a^2}+ \frac{x^2}{b^2} + \frac{x^2}{c^2} = 1~~~求 f(x,y,z) = 8xyz 最大值 a2x2+b2x2+c2x2=1   f(x,y,z)=8xyz
由拉格朗日函数F(x):(λk是各个约束的待定系数)
F ( x , λ ) = f ( x ) + ∑ k = 1 l λ k h k ( x ) F(x,\lambda) = f(x)+\sum_{k=1}^{l}λ_kh_k(x) F(x,λ)=f(x)+k=1lλkhk(x)
这里写图片描述

二、SVD分解

奇异值分解能够简约数据,去除噪声和冗余数据。其实也是一种降维方法,将数据映射到低维空间。
奇异值分解(singular value decomposition,SVD)是线性代数中一种重要的矩阵分解,在信号处理、统计学等领域有重要应用。

假设 M M M是一个 m × n m \times n m×n 阶矩阵,其中的元素全部属于域 K K K,也就是实数域或复数域。如此则存在一个分解使得 M = U Σ V ∗ M=UΣV^ ∗ M=UΣV

在这里插入图片描述
其中 U U U m × m m \times m m×m 阶矩阵; Σ \Sigma Σ m × n m \times n m×n 阶非负实数对角矩阵;而 V ∗ V^∗ V 为矩阵 V V V 的共轭转置矩阵,是 n × n n \times n n×n 阶矩阵。这样的分解就称为矩阵 M M M奇异值分解。

2.1 奇异值分解

M = [ 2 4 1 3 0 0 0 0 ] M = \begin{bmatrix} 2 & 4\\ 1 & 3\\ 0 & 0\\ 0 & 0 \end{bmatrix} M=21004300

  1. 分别理解计算 M M T MM^T MMT M T M M^TM MTM 的特征向量及其特征值

  2. M M T MM^T MMT 的特征向量组成 U U U
    M T M M^TM MTM 的特征向量组成 V V V

  3. M M T MM^T MMT M T M M^TM MTM的非零特征值求平方根,对应上述的特征向量的位置,填入 ∑ \sum 的非零对角元素(即 M 的奇异值)。
    W = M M T = [ 2 4 1 3 0 0 0 0 ] [ 2 1 0 0 4 3 0 0 ] = [ 20 14 0 0 14 10 0 0 0 0 0 0 0 0 0 0 ] W = MM^T = \begin{bmatrix} 2 & 4\\ 1 & 3\\ 0 & 0\\ 0 & 0 \end{bmatrix}\begin{bmatrix} 2 &1 &0 &0 \\ 4 &3 &0 &0 \end{bmatrix} = \begin{bmatrix} 20 &14 &0 &0 \\ 14 &10 &0 &0 \\ 0 &0 &0 &0 \\ 0 &0 &0 &0 \end{bmatrix} W=MMT=21004300[24130000]=20140014100000000000
    W W W特征值 与特征向量。由定义 W x → = λ x → W\overrightarrow{x} = \lambda \overrightarrow{x} Wx =λx ;因此 ( W − λ I ) x → = 0 → (W-λI) \overrightarrow{x} = \overrightarrow{0} (WλI)x =0
    ( [ 20 14 0 0 14 10 0 0 0 0 0 0 0 0 0 0 ] − λ [ 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ] ) x → = 0 → (\begin{bmatrix} 20 &14 &0 &0 \\ 14 &10 &0 &0 \\ 0 &0 &0 &0 \\ 0 &0 &0 &0 \end{bmatrix}-λ\begin{bmatrix} 1 &0 &0 &0 \\ 0 &1 &0 &0 \\ 0 &0 &1 &0 \\ 0 &0 &0 &1 \end{bmatrix}) \overrightarrow{x} =\overrightarrow{0} (20140014100000000000λ1000010000100001)x =0
    即:
    [ 20 − λ 14 0 0 14 10 − λ 0 0 0 0 − λ 0 0 0 0 − λ ] = ∣ 20 − λ 14 14 10 − λ ∣ ∣ − λ 0 0 − λ ∣ = 0 \begin{bmatrix} 20-λ &14 &0 &0 \\ 14 &10-λ &0 &0 \\ 0 &0 &-λ &0 \\ 0 &0 &0 &-λ \end{bmatrix} =\begin{vmatrix} 20-λ & 14\\ 14 & 10-λ \end{vmatrix}\begin{vmatrix} -λ & 0\\ 0 & -λ \end{vmatrix} = 0 20λ14001410λ0000λ0000λ=20λ141410λλ00λ=0
    求行列式det得: ( ( 20 − λ ) ( 10 − λ ) − 196 ) λ 2 = 0 。 ((20-λ)(10-λ)-196)λ^2 = 0 。 ((20λ)(10λ)196)λ2=0

    特征值λ: λ 1 = λ 2 = 0 , λ 3 = 15 + 221 ≈ 29.866 , λ 4 = 15 − 221 ≈ 0.134 λ_1 = λ_2 = 0,λ_3 =15+\sqrt{221}\approx 29.866,λ_4 = 15-\sqrt{221}\approx 0.134 λ1=λ2=0,λ3=15+221 29.866λ4=15221 0.134
    将特征值带入原方程 M ,可解的特征向量。


λ 1 = λ 2 = 0 λ_1 = λ_2 = 0 λ1=λ2=0

[ 20 14 0 0 14 10 0 0 0 0 0 0 0 0 0 0 ] ⇒ ( 20 x 1 + 14 y 1 = 0 14 x 1 + 10 y 1 = 0 ) \begin{bmatrix} 20 & 14 &0 &0 \\ 14& 10& 0 &0 \\ 0 & 0 & 0 &0 \\ 0 &0 & 0 & 0 \end{bmatrix}\Rightarrow\begin{pmatrix} 20x_1+14y_1=0\\ 14x_1+10y_1=0 \end{pmatrix} 20140014100000000000(20x1+14y1=014x1+10y1=0)

λ 3 λ_3 λ3 = 29.866
∣ − 9.866 14 0 0 14 − 19.866 0 0 0 0 − 29.866 0 0 0 0 − 29.866 ∣ ⇒ ( − 9.866 x 2 + 14 y 2 = 0 14 x 2 − 19.866 y 2 = 0 − 29.866 z 2 = 0 − 29.866 i 2 = 0 ) \begin{vmatrix} -9.866& 14& 0&0 \\ 14 &-19.866 &0 &0 \\ 0 & 0 & -29.866&0 \\ 0 &0 &0 &-29.866 \end{vmatrix} \Rightarrow \begin{pmatrix} -9.866x_2+14y_2=0\\ 14x_2-19.866y_2=0\\ -29.866z_2 = 0\\ -29.866i_2 = 0 \end{pmatrix} 9.86614001419.866000029.866000029.8669.866x2+14y2=014x219.866y2=029.866z2=029.866i2=0

λ 4 λ_4 λ4 = 0.134
∣ 19.866 14 0 0 14 9.866 0 0 0 0 − 0.134 0 0 0 0 − 0.134 ∣ ⇒ ( 19.866 x + 14 y = 0 14 x + 9.866 y = 0 − 0.134 z = 0 − 0.134 i = 0 ) \begin{vmatrix} 19.866& 14& 0&0 \\ 14 &9.866 &0 &0 \\ 0 & 0 & -0.134&0 \\ 0 &0 &0 &-0.134 \end{vmatrix} \Rightarrow \begin{pmatrix} 19.866x+14y=0\\ 14x+9.866y=0\\ -0.134z = 0\\ -0.134i = 0 \end{pmatrix} 19.8661400149.86600000.13400000.13419.866x+14y=014x+9.866y=00.134z=00.134i=0
这里写图片描述

2.2 SVD概念及理解

在实数内,我们实质上是将一个复杂的变换 M : R m → R n M: \mathbb{R}^m \rightarrow \mathbb{R}^n M:RmRn分解成了三个变换:
旋转/镜像 U : R m → R m U:\mathbb{R}^m\rightarrow \mathbb{R}^m URmRm
缩放 ∑ : R m → R n \sum:\mathbb{R}^m\rightarrow \mathbb{R}^n :RmRn
旋转/镜像 V : R n → R n V:\mathbb{R}^n\rightarrow \mathbb{R}^n V:RnRn

我们假设 m = n m=n m=n以及 U U U V V V 都是旋转矩阵,则这个过程可以表示为:

  1. V V V首先将(可能是退化的)单位球旋转(旋转标准正交基),
  2. 而后经由 Σ Σ Σ将单位圆缩放拉伸成椭圆(超空间中的超椭球),
  3. 再经由 U U U 将超椭球在空间中旋转。
    这个超椭球的各个半轴的长度, 就是矩阵 M M M 的奇异值,也就是矩阵 Σ Σ Σ 对角线上的元素。
SVD 分解至少有两方面作用:
分析了解 原矩阵的主要特征和携带的信息(取若干最大的奇异值),这引出了主成分分析(PCA)
丢弃忽略原矩阵的次要特征和携带的次要信息(丢弃若干较小的奇异值),这引出了信息有损压缩、矩阵低秩近似等话题。

三、PCA—主成分分析

关于PCA粗略认识请查看:特征工程——数据降维
降维就是一种对高维度特征数据预处理方法。降维是将高维度的数据保留下最重要的一些特征,去除噪声和不重要的特征,从而实现提升数据处理速度的目的
在实际的生产和应用中,降维在一定的信息损失范围内,可以为我们节省大量的时间和成本。降维也成为应用非常广泛的数据预处理方法

降维具有如下一些优点:

  1. 使得数据集更易使用。
  2. 降低算法的计算开销。
  3. 去除噪声。
  4. 使得结果容易理解。

降维的算法有很多,比如奇异值分解(SVD)、主成分分析(PCA)、因子分析(FA)、独立成分分析(ICA)。

3.1 PCA的概念

PCA(Principal Component Analysis),即主成分分析方法,是一种使用最广泛的数据降维算法。
PCA的主要思想是将n维特征映射到k维上,这k维是全新的正交特征也被称为主成分,是在原有n维特征的基础上重新构造出来的k维特征。PCA的工作就是从原始的空间中顺序地找一组相互正交的坐标轴,新的坐标轴的选择与数据本身是密切相关的。其中,第一个新坐标轴选择是原始数据中方差最大的方向,第二个新坐标轴选取是与第一个坐标轴正交的平面中使得方差最大的,第三个轴是与第1,2个轴正交的平面中方差最大的。依次类推,可以得到n个这样的坐标轴。通过这种方式获得的新的坐标轴,我们发现,大部分方差都包含在前面k个坐标轴中,后面的坐标轴所含的方差几乎为0。于是,我们可以忽略余下的坐标轴,只保留前面k个含有绝大部分方差的坐标轴。事实上,这相当于只保留包含绝大部分方差的维度特征,而忽略包含方差几乎为0的特征维度,实现对数据特征的降维处理。

简而言之:通过计算数据矩阵的协方差矩阵,然后得到协方差矩阵的特征值特征向量,选择特征值最大(即方差最大)的k个特征所对应的特征向量组成的矩阵。这样就可以将数据矩阵转换到新的空间当中,实现数据特征的降维。

获取协方差矩阵的特征值特征向量有两种方法:
基于 特征值分解协方差矩阵实现PCA算法
基于 SVD分解协方差矩阵实现PCA算法。
3.2 协方差和散度矩阵

样本均值: x ˉ = 1 n ∑ i = 1 N x i \bm{\bar{x}= \frac{1}{n}\sum_{i=1}^{N}x_i} xˉ=n1i=1Nxi
样本方差: S 2 = 1 n − 1 ∑ i = 1 N ( x i − x ˉ ) 2 \bm{S^2 = \frac{1}{n-1}\sum_{i=1}^{N}(x_i- \bar{x})^2} S2=n11i=1N(xixˉ)2
样本 X X X 和样本 Y Y Y的协方差:
C o v ( X , Y ) = E [ ( X − E ( X ) ) ( Y − E ( Y ) ) ] = 1 n − 1 ∑ i = 1 N ( x i − x ˉ ) ( y i − y ˉ ) \begin{aligned} Cov(X,Y)&=E\left [ (X-E(X))(Y-E(Y)) \right ] \\ &= \frac{1}{n-1}\sum_{i=1}^{N}(x_i- \bar{x})(y_i- \bar{y}) \end{aligned} Cov(X,Y)=E[(XE(X))(YE(Y))]=n11i=1N(xixˉ)(yiyˉ)

  1. 协方差要求样本必须至少满足二维特征;方差只是协方差的特殊情况。
  2. 方差和协方差的除数是n-1,这是为了得到方差和协方差的无偏估计。
  3. 协方差为正时,说明X和Y是正相关关系;
  4. 协方差为负时,说明X和Y是负相关关系;
  5. 协方差为0时,说明X和Y无相关关系。Cov(X,X)就是X的方差。当样本是n维数据时,它们的协方差实际上是协方差矩阵(对称方阵)。

同理,对于3维数据(x,y,z),计算它的协方差就是:
C o v ( X , Y , Z ) = [ C o v ( x , x ) C o v ( x , y ) C o v ( x , z ) C o v ( y , x ) C o v ( y , y ) C o v ( y , x ) C o v ( z , x ) C o v ( z , y ) C o v ( z , z ) ] Cov(X,Y,Z) = \begin{bmatrix} Cov(x,x) & Cov(x,y) &Cov(x,z) \\ Cov(y,x) & Cov(y,y) &Cov(y,x) \\ Cov(z,x) & Cov(z,y) & Cov(z,z) \end{bmatrix} Cov(X,Y,Z)=Cov(x,x)Cov(y,x)Cov(z,x)Cov(x,y)Cov(y,y)Cov(z,y)Cov(x,z)Cov(y,x)Cov(z,z)

散度矩阵定义为:
S = ∑ i = 1 n ( ( x k − m ) ( x k − m ) T )   这 里 m 向 量 : m = 1 n ∑ k = 1 n x l S = \sum_{i=1}^n(\bm{(x_k-m)(x_k-m)^T})  这里m向量:\bm{m = \frac{1}{n}\sum_{k=1}^nx_l} S=i=1n((xkm)(xkm)T) mm=n1k=1nxl
对于数据X的散度矩阵为 X X T XX^T XXT。其实协方差矩阵和散度矩阵关系密切,散度矩阵就是协方差矩阵乘以(总数据量-1)。因此它们的特征值和特征向量是一样的。这里值得注意的是,散度矩阵是SVD奇异值分解的一步,因此PCA和SVD是有很大联系。

3.3 基于特征值分解协方差矩阵实现PCA算法

数据集 X = { x 1 , x 2 , … x n } X=\{x_1,x_2,…x_n\} X={x1,x2,xn},需要降到 k 维。

  1. 去中心化,即每一位特征减去各自的平均值。、
  2. 计算协方差矩阵 1 n X X T \frac{1}{n}XX^T n1XXT, 注:这里除或不除样本数量n或n-1,其实对求出的特征向量没有影响。
  3. 用特征值分解方法求协方差矩阵 1 n X X T \frac{1}{n}XX^T n1XXT 的特征值与特征向量。
  4. 对特征值从大到小排序,选择其中最大的 k k k个。然后将其对应的 k k k个特征向量分别作为行向量组成特征向量矩阵 P P P
  5. 将数据转换到 k k k个特征向量构建的新空间中,即 Y = P X Y=PX Y=PX

关于PCA数学原理:http://blog.codinglabs.org/articles/pca-tutorial.html
为什么用特征值分解矩阵,是因为 1 n X X T \frac{1}{n}XX^T n1XXT 是方阵,能很轻松的求出特征值与特征向量。当然,用奇异值分解也可以,是求特征值与特征向量的另一种方法。

举例
我们用PCA方法将这两行数据降到一行: X = [ − 1 − 1 0 2 0 − 2 0 0 1 1 ] X = \begin{bmatrix} -1 &-1 &0&2 &0 \\ -2 & 0 &0 &1&1 \end{bmatrix} X=[1210002101]

  1. 显然:X矩阵的每行已经是零均值,所以不需要去平均值。

  2. 求协方差矩阵: C = 1 5 [ − 1 − 1 0 2 0 − 2 0 0 1 1 ] [ − 1 − 2 − 1 0 0 0 2 1 0 1 ] = [ 6 5 4 5 4 5 6 5 ] C = \frac{1}{5}\begin{bmatrix} -1 &-1 &0&2 &0 \\ -2 & 0 &0 &1&1 \end{bmatrix}\begin{bmatrix} -1 &-2 \\ -1 & 0 \\ 0 & 0 \\ 2 &1 \\ 0 &1 \end{bmatrix} = \begin{bmatrix} \frac{6}{5} & \frac{4}{5} \\ \\ \frac{4}{5} & \frac{6}{5} \end{bmatrix} C=51[1210002101]1102020011=56545456

  3. 求协方差矩阵的特征值与特征向量。

    特征值为: λ 1 = 2 , λ 2 = 2 5 \lambda_1 =2,\lambda_2 = \frac{2}{5} λ1=2λ2=52  特征向量为: c 1 = [ 1 1 ] , c 1 = [ − 1 1 ] c_1=\begin{bmatrix} 1 \\ 1 \end{bmatrix},c_1=\begin{bmatrix} -1 \\ 1 \end{bmatrix} c1=[11]c1=[11]

    其中对应的特征向量分别是一个通解, c 1 c_1 c1 c 2 c_2 c2可以取任意实数。
    那么标准化后的特征向量为: [ 1 2 1 2 ] , [ − 1 2 1 2 ] \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \\ \frac{1}{\sqrt{2}} \end{bmatrix},\begin{bmatrix} -\frac{1}{\sqrt{2}} \\ \\ \frac{1}{\sqrt{2}} \end{bmatrix} 2 12 12 12 1

  4. 矩阵 P P P为: P = [ 1 2 1 2 − 1 2 1 2 ] P = \begin{bmatrix} \frac{1}{\sqrt{2}} &\frac{1}{\sqrt{2}} \\ \\ -\frac{1}{\sqrt{2}}& \frac{1}{\sqrt{2}} \end{bmatrix} P=2 12 12 12 1

  5. 最后我们用P的第一行乘以数据矩阵X,就得到了降维后的表示:
    Y = [ 1 2 1 2 ] [ − 1 − 1 0 2 0 − 2 0 0 1 1 ] = [ − 3 2 − 1 2 0 3 2 − 1 2 ] Y = \begin{bmatrix} \frac{1}{\sqrt{2}} &\frac{1}{\sqrt{2}} \end{bmatrix}\begin{bmatrix} -1 &-1 &0&2 &0 \\ -2 & 0 &0 &1&1 \end{bmatrix} = \begin{bmatrix} -\frac{3}{\sqrt{2}} &-\frac{1}{\sqrt{2}} &0&\frac{3}{\sqrt{2}} &-\frac{1}{\sqrt{2}} \end{bmatrix} Y=[2 12 1][1210002101]=[2 32 102 32 1]
    结果如图所示:
    在这里插入图片描述
    注意:如果我们通过特征值分解协方差矩阵,那么我们只能得到一个方向的PCA降维。这个方向就是对数据矩阵X从行(或列)方向上压缩降维。

3.4 基于SVD分解协方差矩阵实现PCA算法

在PCA降维中,我们需要找到样本协方差矩阵 X X T XX^T XXT 的最大k个特征向量,然后用这最大的k个特征向量组成的矩阵来做低维投影降维。可以看出,在这个过程中需要先求出协方差矩阵 X X T XX^T XXT ,当样本数多、样本特征数也多的时候,这个计算还是很大的。当我们用到SVD分解协方差矩阵的时候,SVD有两个好处:

  1. 有一些SVD的实现算法可以先不求出协方差矩阵 X X T XX^T XXT 也能求出我们的右奇异矩阵V。也就是说,我们的PCA算法可以不用做特征分解而是通过SVD来完成,这个方法在样本量很大的时候很有效。实际上,scikit-learn的PCA算法的背后真正的实现就是用的SVD,而不是特征值分解。

  2. 注意到PCA仅仅使用了我们SVD的左奇异矩阵,没有使用到右奇异值矩阵,那么右奇异值矩阵有什么用呢?

假设我们的样本是m*n的矩阵X,如果我们通过SVD找到了矩阵 X T X X^TX XTX 最大的k个特征向量组成的k*n的矩阵 V T V^T VT,则我们可以做如下处理:
X m ∗ k ′ = X m ∗ k V n ∗ k T X'_{m*k} =X_{m*k} V_{n*k}^T Xmk=XmkVnkT

可以得到一个m*k的矩阵X’,这个矩阵和我们原来m*n的矩阵X相比,列数从n减到了k,可见对列数进行了压缩。也就是说,左奇异矩阵可以用于对行数的压缩;右奇异矩阵可以用于对列(即特征维度)的压缩。这就是我们用SVD分解协方差矩阵实现PCA可以得到两个方向的PCA降维(即行和列两个方向)。

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

SongpingWang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值