为什么要数据降维
大数据时代面临的最大问题是"维度灾难",度量上的不平衡和高维空间的学习复杂度都让机器学习算法在高维数据上很多时候行不通。而且,如果数据超过三维,它们也很难被可视化。不能被可视化的数据是很难理解的。
如果我们的数据比较高维,不适合直接进行监督或聚类学习,则我们可以先用一些其他的无监督或有监督的技巧把数据进行降维。这一系列的方法也常常被叫做度量学习。
通过有监督或者无监督的方法,学习在原始的坐标距之上的距离评估方法,就是度量学习。度量学习可以为KNN和聚类服务,有时这些方法也可以被直接用在数据预处理上,而且一般表现都不错。我们首先介绍的是PCA,主成分分析;
PCA
PCA使用一个线性变换投影来得到新的坐标空间,也就是把原向量空间里的数据x乘上一个W矩阵,变换到另一个向量空间。PCA的目的就是确定W应该是怎样的W;考虑我们希望的是让被处理后的数据被分的尽可能开,也就是让投影后的数据点的方差最大化,问题就简化为了最大化协方差矩阵的迹。如果投影后的新向量是
W T x W^Tx WTx
那么协方差矩阵就是
W T ( x − x ^ ) ( x − x ^ ) T W W^T(x-\hat{x})(x-\hat{x})^TW WT(x−x^)(x−x^)TW
因为W^T是投影矩阵,新的坐标基应该满足两两正交条件,还需要有约束条件
W T W = I W^TW = I WTW=I
PCA有意思就有意思在下面的步骤,我们知道如果是约束优化问题,可以用拉格朗日乘子法来解。给上面的约束条件使用拉格朗日乘子法添上一个 λ \lambda λ,就变成
W T ( x − x ^ ) ( x − x ^ ) T W = λ ( W T W − I ) W^T(x-\hat{x})(x-\hat{x})^TW=\lambda (W^TW - I) WT(x−x^)(x−x^)TW=λ(WTW−I)
再计算偏导等于零,原式变为
( x − x ^ ) ( x − x ^ ) T W = λ W (x-\hat{x})(x-\hat{x})^TW=\lambda W (x−x^)(x−x^)TW=λW
这是特征值分解的形式!特征值分解找到的特征值和特征向量对有多个,也就是满足约束条件的解有多个。对W的一个向量w,我们希望最大化的目标函数是
w T ( x − x ^ ) . ( x − x ^ ) T . w = w T w λ = λ w^T(x-\hat{x}).(x-\hat{x})^T.w=w^Tw\lambda=\lambda wT(x−x^).(x−x^)T.w=wTwλ=λ
就等于 λ \lambda λ,最大的 λ \lambda λ对应最好的约束优化问题的解;好了,现在拿到数据,我们把数据做个标准化,让 x ^ \hat x x^=0,然后令S = X T X X^TX XTX,对S做特征值分解,在得到的 λ \lambda λ中选k个最大的对应的特征向量,就得到W矩阵,做W点乘X就能把数据降维到k维。算法就结束啦。下面的代码也可以看到,只需要几行就可以实现。
def PCA(X,dim):
#中心化
xmean = np.mean(X,axis=0)
X=deepcopy(X-xmean)
#协方差矩阵
Covs = X.T.dot(X)
lamda,V=np.linalg.eigh(Covs)
#取前dim个最大的特征值对应的特征向量
index=np.argsort(-lamda)[:dim]
V_selected=V[:,index]
return V_selected
我们可以试试在Iris上的效果
X,y = datasets.load_iris(return_X_y=True)
W = PCA(X,2)
X_ = X.dot(W)
plt.scatter(X_[:,0], X_[:,1],edgecolors='black',c=y)
LDA
PCA并不总能把事情做的很好,因为PCA盲目地把数据映射到了最能"平铺"的空间。如果我们想完成二分类任务,我们的数据集像油条的两根那样平行地排布在一起,而且又被拉长,则PCA只会把油条平放在桌子上,而我们希望油条被竖直地立在桌子上,这样才能更好地区分两个类别。
为此需要引入有标签的线性降维学习方法LDA,其实思想是和PCA完全一致,但现在我们希望最小化类内方差,最大化类间方差。事实上这部分内容在讲线性模型时已经讲过了,我们这里复习一下。
首先定义类间距离和类内距离,类间距就是两个类中心的距离,类内距就是所有数据点到类中心的距离均值
J 0 = ( ( μ 1 − μ 0 ) W ) T ( ( μ 1 − μ 0 ) W ) = W T ( μ 1 − μ 0 ) T ( μ 1 − μ 0 ) W J_0=((\mu_1-\mu_0)W)^T((\mu_1-\mu_0)W)=W^T(\mu_1-\mu_0)^T(\mu_1-\mu_0)W J0=((μ1−μ0)W)T((μ1−μ0)W)=WT(μ1−μ0)T(μ1−μ0)W
J 1 = ( ( X − μ ) W ) T ( ( X − μ ) W ) = W T ( X − μ ) T ( X − μ ) W J_1=((X-\mu)W)^T((X-\mu)W)=W^T(X-\mu)^T(X-\mu)W J1=((X−μ)W)T((X−μ)W)=WT(X−μ)T(X−μ)W
我们设 S 1 = ( X − μ ) T ( X − μ ) , S 0 = ( μ 1 − μ 0 ) T ( μ 1 − μ 0 ) S_1=(X-\mu)^T(X-\mu),S_0 = (\mu_1-\mu_0)^T(\mu_1-\mu_0) S1=(X−μ)T(X−μ),S0=(μ1−μ0)T(μ1−μ0)
有了这两个量就可以自己定义损失函数了,一种能保证数据规模不会影响loss的方法是设J1=1,最大化J0。即 J = W T S 0 W s . t . W T S 1 W = 1 J=W^TS_0W \quad s.t.\quad W^TS_1W=1 J=WTS0Ws.t.WTS1W=1
这个问题直接用拉格朗日乘子法就能求解,写出拉格朗日函数
L ( W , λ ) = W T S 0 W − λ ( W T S 1 W − 1 ) L(W,\lambda)=W^TS_0W-\lambda (W^TS_1W-1) L(W,λ)=WTS0W−λ(WTS1W−1)
计算偏导并让它等于0,就得到极值的必要条件
∂ L ∂ W = 2 W T S 0 W − 2 λ W T S 1 = 0 \frac{\partial{L}} {\partial{W}}=2W^TS_0W-2\lambda W^TS_1=0 ∂W∂L=2WTS0W−2λWTS1=0
S 0 W = λ S 1 W S_0W=\lambda S_1W S0W=λS1W
S 1 − 1 S 0 W = λ W S_1^{-1}S_0W=\lambda W S1−1S0W=λW
即W是最优解时上式一定成立,从上式我们能逐步推导出
S 0 W = λ S 1 W S_0 W = \lambda S_1 W S0W=λS1W
W T S 0 W = λ W T S 1 W = λ = J W^TS_0W = \lambda W^TS_1W = \lambda = J WTS0W