《Deep Learning》学习1——基于特征分解的主成分分析

来源:互联网 发布:淘宝店铺资金被冻结 编辑:程序博客网 时间:2024/05/19 19:44

这篇文章是基于《Deep Learning》第二章以及UFLDL Tutorial之主成分分析做的总结和python算法实现。

《Deep Learning》第二章主要讲的是矩阵的一些重要性质,由于《Deep Learning》完全讲理论,且很严肃正统,所以,顺带结合UFLDL和斯坦福cs229对应课程一起学习,同时跑UFLDL提供的练习。

 

一.纯理论

1.      线性相关

当我们解如下方程组时:

如果上述方程组不存在两个一样的方程,那么其解有三种可能:有且仅有一组解,无解,有很多组解。

当n< m ,无解

当n=m,有唯一解,

当n>m, 有无限多个解,但其中某些解和另外一些解呈线性关系,即部分确定后,另外一部分可确定部分线性组合得到无数种可能。

 

方程组可以用矩阵的形式表示:

Ax = b

A是m*n矩阵,,x是n*1,b是m*1.

A和x生成b可表示为:


当n>m时,方程有无限多个解可以生成b,此时,A的列数多于其能生成b的需求,称之为列冗余。当列冗余时,列向量线性相关。

 

例如


当x1确定后,x2和x3有无限中组合。同时


矩阵A的第3列可以又第2列线性组合而成,矩阵A线性相关。因此,当n>m,矩阵A线性相关。

当矩阵中任意一个行或列向量不能表示成其他向量的线性组合而成,那么矩阵线性无关。

当方程组有且仅有一个解时,A矩阵必须是方阵,且必须列向量线性无关。

 

2.      特征分解

特征方程:


其中,λ为特征值,v为特征向量,A为方阵。

等式两边同时右乘,得


标量和向量相乘,两者位置变化对结果无影响:

特征向量的含义是与A相乘后相当于对该向量做了缩放。对向量缩放的尺度就是特征值λ。

一个方阵可能有多个特征向量,每个特征向量对应一个特征值,但一个特征值可能对应多个特征向量。将矩阵A的n个线性无关的特征向量组成特征矩阵V,那么V矩阵线性无关,有逆矩阵。同时将n个列向量对应的特征值组成向量。那么:


把λ变成对角矩阵(只有主对角线的值非零)。

如果以上n列向量是线性无关的实向量,且组成正交矩阵Q(正交的方阵),和实特征值,那么


就是对A的矩阵分解。

 

3.      奇异值分解(SVD)

感觉奇异分解比特征分解应用更广泛,尤其是在个性化推荐中。从特征分解的理论来看,无论是矩阵A还是特征矩阵都是线性无关的方阵,而实际上有很多矩阵是奇异的。

对应于特征分解,奇异值分解:


如果A是m*n的矩阵,那么,U是m*m的矩阵,它的列是A的左奇异向量,D是m*n的对角矩阵,主对角线上的值是A的奇异值,V是n*n的矩阵,其列向量是A的右奇异向量。A被分解成两个方阵和一个对角矩阵。

左奇异矩阵是的特征矩阵,右奇异矩阵是方阵的特征矩阵。

 

4.      主成分分析

主成分分析是个编码的过程,只不过这个编码过程是对原输入的压缩,然后通过逆向解码,尽可能的还原输入。

编码的过程:


解码的过程:


D称为解码矩阵。通过解码矩阵D推导最合理的编码矩阵。推导过程实际上是一个最小二乘法的过程。

最小化目标:


目标为找到使解码和输入误差(误差用两者相减后所得矩阵的二阶范数的平方表征)最小的c。

通过范数带入和最小二乘法,得到:


也就是说当编码矩阵是解码矩阵的逆时,编码和解码的误差最小。这样的话,误差能最小化到什么程度,取决于D的取值,并且,为了使解码过程只有唯一解,作者直接限定D的所有列向量彼此正交,但D不一定是正交矩阵,即),那么最小化目标变成了,


D的行列数取决于想要把原矩阵降到什么维度。

最后经过推导,发现,当D是矩阵最大的前k个特征值对应的特征向量组成。

 

因此,总结一下,主成分分析的主要过程:

(1). 输入矩阵为X,求

(2). 求矩阵的特征分解;

(3). 定义主成分的维度(行列数)k

(4). 找到最大的k特征值,并拿到对应的特征向量,组成特征矩阵D

(5). 计算编码过程

 

二.UFLDL的理论分析

UFLDL主成分分析在http://deeplearning.stanford.edu/wiki/index.php/主成分分析

该文章通过例子,讲了PCA大体的思路是:

(1).将数据预处理,使其均值为0.

(2). 计算协方差,


从公式来看,协方差等同于 /m。

 

(3). 计算协方差的特征分解。

根据推导,的特征向量和A的特征向量相等。

 

(4). 用特征分解得到的特征矩阵乘输入,将输入旋转到标准方向上


(5).设置降维后的维度k,只保留前k维的主要特征成分,其他维全部写0。

 

 

三.Python实现

用UFLDL的例子,写python程序,实现PCA。

 

# coding: utf-8# 读数据,按照二维列向量的形式读,组成(2,n)矩阵import numpy as npdataset = []with open("source/pcadata.txt", 'r') as f1:    col1 = f1.readline()    col2 = f1.readline()    datas_1 = col1.split('  ')    datas_2 = col2.split('  ')    l1 = len(datas_1)    l2 = len(datas_2)    l = min(l1, l2)    data1 = []    data2 = []    for i in range(1, l):        data1.append(float(datas_1[i].strip()))        data2.append(float(datas_2[i].strip()))    dataset.append(data1)    dataset.append(data2)dataset# 转化成数组并将数据的期望化为0.data_array = np.array(dataset)m = np.mean(data_array)data_array =data_array - m#画图查看数据import matplotlib.pyplot as pltfig = plt.figure()  ax = fig.add_subplot(111)  plt.scatter(data_array[0, :], data_array[1, :], s=10, c='red')plt.show()#计算协方差covariation = np.cov(data_array)covariation# 协方差矩阵特征分解from numpy import linalg as LAw, v = LA.eig(covariation)print w, v# 寻找前k个最大特征值对应的特征向量列,并组成矩阵k = 1sort_index = np.argsort(-w)sub_sort_index = sort_index[0:k]sub_sort_indexmax_k_v = []for i in sub_sort_index:    k_v = list(v[:,i])    max_k_v .append(k_v)max_k_v = np.array(max_k_v)max_k_v = np.transpose(max_k_v)max_k_v# 编码压缩,并图显示出来。c = np.dot(np.transpose(max_k_v), data_array)c1 = np.zeros(c.shape, float)ax = fig.add_subplot(111)  plt.scatter(c, c1, s=10, c='red')plt.show()

执行后的结果为



横向的值被放大了一点,不知道是不是求协方差时的精度问题。

阅读全文
0 0
原创粉丝点击