降维问题在很久以前就接触了,那时候也会用协方差矩阵实现PCA来实现降维,可以应用在图像压缩和数据维度缩减,减少噪声数据等。但是最近在用sklearn的pca工具实现降维时候发现这儿的pca降得到的维度只能小于等于样本数和维度的最小值(
首先,心中有疑惑,才有寻求答案的动力,才有探寻真理的动力。
疑惑一:为什么实现pca需要用协方差矩阵?
疑惑二:用svd实现降维和用协方差实现有什么关联?
首先介绍实现pca有两种方案,第一个是特征值分解,第二个是奇异值分解
其中特征值分解是通过协方差矩阵来实现的
pca的实现思路也有两种解释:
1、第一种是最大可分性:使得投影点在超平面上的投影尽可能分开
2、第二种是最近重构性:使得样本点到超平面的距离都足够近
这儿假设数据是
1、对数据标准归一化(去均值,各维度统一方差,将各维度在统一尺度上计算)
2、计算协方差矩阵
3、计算C的特征向量矩阵和特征值,将特征值对应的特征向量按照特征值由大到小排列得到特征向量矩阵,取前k列特征向量组成投影矩阵
4、计算降维后的数据
5、这样就将n维的矩阵降到k维
以上的实现方法是基于特征值分解的,那么为什么pca还可以用svd来实现呢?
SVD(奇异值分解)是对矩阵分解的一种方法,
其中X是m*n的矩阵,U是m*m的矩阵,它是由
这儿可以将协方差矩阵C进行奇异值分解来降维,也可以直接对X来奇异值分解降维。
1、对X进行svd,得到的V(
解释:
首先说明 特征分解
那么
这儿发现
还可以从另一个角度看,V本来就是
2、对
看完上面用协方差矩阵和
参考文献:
Andrew NG 的CS229
http://justdark.github.io/%E5%8D%9A%E5%AE%A2/2016/11/12/pca_svd_recall/
http://blog.csdn.net/wangjian1204/article/details/50642732
http://blog.csdn.net/babywong/article/details/50085239
2017.11.24更新———————————————–
今天通过python实现了下使用协方差矩阵对cifar中49张图片降维。
import matplotlib.pyplot as plt
import numpy as np
def unpickle(file):
import pickle
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
return dict
def show(imgs):
matrix=np.zeros(shape=(7*32,7*32,3),dtype=np.uint8)
print(matrix.shape)
print(imgs[0].shape)
index=-1
for i in range(7):
for j in range(7):
index+=1
matrix[i*32:(i+1)*32,j*32:(j+1)*32,:]=imgs[index]
plt.imshow(matrix)
plt.show()
def pca(imgs_raw):
'''
:param imgs: 49*3072
:return:
'''
imgs_raw=imgs_raw.astype(np.float32)
imgs=imgs_raw-np.mean(imgs_raw,axis=0)
cov=np.dot(imgs.T,imgs)/(imgs.shape[0]*imgs.shape[1])
U,S,V=np.linalg.svd(cov)
# 去相关
# imgs=np.dot(imgs,U)
# 降维
imgs_pca=np.dot(imgs,U[:,:30])
imgs_pca_r=np.dot(imgs_pca,U[:,:30].T)
imgs_pca_r+=np.mean(imgs_raw,0)
imgs_pca_r = imgs_pca_r.reshape((len(imgs), 3, 32, 32)).transpose(0, 2, 3, 1)
show(imgs_pca_r)
# imgs = imgs.reshape((len(imgs), 3, 32, 32)).transpose(0, 2, 3, 1)
if __name__ == '__main__':
data_labels=unpickle('H:\\Machine Learning\\'
'deep-learning-master\\deep-learning-master\\image-classification\\cifar-10-batches-py\\data_batch_1')
imgs=data_labels[b'data'][:49]
pca(imgs)
# show(imgs)
第一张是原图:
第二张是降维到50维度的样子:
第三张是降维到30维度的样子: