7.1.主成分分析对人脸图像降维

1)题目:

在这个练习中,你将运用主成分分析(PCA)来实现降维。首先,你将用一个二维的样本集来实验,从而对PCA如何运行的有一个直观的感受,然后再在一个更大的由5000个人脸图像组成的数据集上实现PCA。
数据集链接: https://pan.baidu.com/s/1cEgQIvehUcLxZ0WVhxcPuQ 提取码: xejn

2)知识点概括:

  • 降维(dimensionality reduction):
    压缩数据(减少内存和硬盘的需求/加速算法)
    可视化数据

  • 主成分分析(principal components analysis,简称PCA)
    先将数据进行均值归一化(mean normalization),然后找到一个低维平面,将数据投影到上面,使得投影误差(projection error)最小(即找到一组基向量,然后将数据投影到这个向量空间里,使得投影误差最小)

  • 具体步骤(将n维数据降到k维):
    1、数据预处理(均值归一化 / 特征缩放feature scaling)
    2、计算协方差矩阵Σ(n×n)=1m∑i=1n(x(i))(x(i))T=1mXTX\Sigma_{(n\times n)}={1\over m}\sum_{i=1}^n(x^{(i)})(x^{(i)})^T={1\over m}X^TXΣ(n×n)​=m1​∑i=1n​(x(i))(x(i))T=m1​XTX以及它的特征向量
    可以用SVD奇异值分解(Singular Value Decomposition)或eig求特征向量
    3、取U矩阵(特征向量矩阵)中前k个向量得到一个n乘k维的矩阵UreduceU_{reduce}Ureduce​,转置后乘以数据x就可得到降维后的数据z=XUreducez=XU_{reduce}z=XUreduce​

  • k(主成分的数量)的选择
    投影误差的平方和:1m∑i=1m∥x(i)−xapprox(i)∥2{1\over m}\sum_{i=1}^m\|x^{(i)}-x_{approx}^{(i)}\|^2m1​∑i=1m​∥x(i)−xapprox(i)​∥2,PCA的目标就是最小化x和其在低维表面上的映射点之间的距离的平方。
    数据的总方差:1m∑i=1m∥x(i)∥2{1\over m}\sum_{i=1}^m\|x^{(i)}\|^2m1​∑i=1m​∥x(i)∥2,训练样本长度的平均值
    一般来说,就是选择k使得下式小于0.01,即1m∑i=1m∥x(i)−xapprox(i)∥21m∑i=1m∥x(i)∥2≤0.01{{1\over m}\sum_{i=1}^m\|x^{(i)}-x_{approx}^{(i)}\|^2\over {1\over m}\sum_{i=1}^m\|x^{(i)}\|^2}\le0.01m1​∑i=1m​∥x(i)∥2m1​∑i=1m​∥x(i)−xapprox(i)​∥2​≤0.01,用PCA的语言说就是,保留了99%的差异性。当采取SVD分解时,上式可以等价于1−∑i=1kSii∑i=1nSii≤0.011-{\sum_{i=1}^kS_{ii}\over \sum_{i=1}^nS_{ii}}\le0.011−∑i=1n​Sii​∑i=1k​Sii​​≤0.01,其中SiiS_{ii}Sii​为S矩阵中的主对角元素(S为一个对角阵)。然后尝试k从1到n,选择第一个满足上式的k即可。
    ∑i=1kSii∑i=1nSii{\sum_{i=1}^kS_{ii}\over \sum_{i=1}^nS_{ii}}∑i=1n​Sii​∑i=1k​Sii​​也是一个平方投影误差的测量指标,即使是手动选择k时,也可以阐述百分之多少的差异性被保留了下来。

  • 原始数据的重构(reconstruction)
    利用z=XUreducez=XU_{reduce}z=XUreduce​得到原始数据的一个近似值

  • 在监督学习中可以用PCA来降低高维数据的维数,得到较低维的训练数据,再使用降维后的数据进行学习,使得算法更快的实现,例如在神经网络中。

  • 警告:
    PCA去防止过拟合是一个特别不好的应用,可能会丢失一些有价值的信息!
    此外除非在强有力的证据下说明原始数据直接建模不好(内存太大或者运行太慢),才使用PCA进行降维处理之后再进行建模,一般强烈建议直接用原始数据进行建模!

3)大致步骤:

  • 导入数据以及数据可视化。

  • 主成分分析。首先进行数据标准化,注意这里的sigma如果取无偏的标准差,则自由度为n-1;然后计算协方差矩阵,再进行SVD奇异值分解得到特征向量和特征值;然后对比两个不同的特征向量(即第1列和第2列)哪个的投影误差更小,画出以数据均值为中心的特征向量,可以看出取U矩阵中前1列得到矩阵(这里为[-0.70710678, -0.70710678]),转置后乘以数据x就可得到降维后的数据z=XUreducez=XU_{reduce}z=XUreduce​。

  • 将数据投影到主成分上,可以得到z的第一个值为1.48127391。然后再重建数据得到数据的近似值,因为U是特征向量矩阵,它由标准正交基组成,因此U.T@U为单位矩阵,所以这里要重建数据只需xrec=zUreduce′x_{rec}=zU_{reduce}'xrec​=zUreduce′​,可以得到重建后的第一行数据为[-1.04741883, -1.04741883]。然后再可视化投影,画出标准化的数据以及投影之后又重建的数据,把对应点用虚线连接起来。然后看看降维后的数据保留了原始数据多少的差异性,这里只有不到87%

  • 导入人脸数据以及数据可视化。x是一个(5000, 1024)的数据,每列对应一个人脸图像,需要reshape成32*32的再画出。选出前100个人脸图像进行可视化。

  • 在人脸数据上实施主成分分析。先将人脸数据标准化,再计算特征向量,然后可视化前36个特征向量,注意这里每个特征向量都是1024维的。

  • 人脸数据降维以及可视化。和前面一样对数据进行降维,这里设置k=100,再进行重建数据,画出重建后的前100个人脸图,和降维前的对比。这里93.19%的差异性保持了。

  • 最后是对上次作业的一个提升,先重复上次作业中对图片进行的处理,即先运行k-means算法,得到聚类中心和索引,然后再随机选取1000个样本像素画出三维图。之后再用PCA进行降维,画出降维后的二维图。99.34%的差异性保持了。

4)关于Python:

  • plt.plot([1,2], [1,2])可以画出点[1,1]到点[2,2]的连线。
  • np.random.randint( )函数可以随机选择整数,没有np.的话是一个闭区间中选取,这里是一个开区间。
  • plt.cm.get_cmap(‘Accent’) plt.cm是matplotlib库中内置的色彩映射函数,Accent是get_cmap函数可选的一个颜色参数。
  • import mpl_toolkits.mplot3d as Axes3D模块可以用来绘制三维图。

5)代码与结果:

import numpy as np
import matplotlib.pyplot as plt
import scipy.io as scio
import matplotlib.image as mpimg #读入图片
import mpl_toolkits.mplot3d as Axes3D #用来画三维图'''============================part1 数据导入及可视化========================='''data = scio.loadmat('ex7data1.mat')
x = data['X']
plt.scatter(x[:,0], x[:,1], marker='o', facecolors='none', edgecolors='b')'''============================part2 PCA===================================='''
'''数据标准化'''
def featureNormalize(x):mu = x.mean(axis=0) #求每列的sigma = x.std(axis=0, ddof=1) #无偏的标准差,自由度为n-1x_norm = (x-mu)/sigmareturn x_norm, mu, sigmax_norm, mu, sigma = featureNormalize(x)'''得到特征向量和特征值'''
def pca(x):m, n = x.shapeSigma = (x.T @ x)/m #协方差矩阵U, S, V = np.linalg.svd(Sigma) #SVD奇异值分解return U, SU, S = pca(x_norm)#画出特征向量
plt.figure(figsize=(6,6))
plt.scatter(x[:,0], x[:,1], marker='o', facecolors='none', edgecolors='b')
plt.plot([mu[0], mu[0]+1.5*S[0]*U[0,0]], [mu[1], mu[1]+1.5*S[0]*U[1,0]], 'k') #两个点的连线
plt.plot([mu[0], mu[0]+1.5*S[1]*U[0,1]], [mu[1], mu[1]+1.5*S[1]*U[1,1]], 'k') #这里的1.5和S表示特征向量的长度
plt.title('Computed eigenvectors of the dataset')'''============================part3 降维========================='''
'''降维,数据投影到特征向量上'''
def projectData(x, U, K):U_reduce = U[:, 0:K]return x @ U_reduce#降维后的数据,(50, 1)
z = projectData(x_norm, U, 1)
z[0] #1.48127391'''重建数据'''
def recoverData(z, U, K):U_reduce = U[:, 0:K]return z @ U_reduce.T #因为U是特征向量矩阵,由标准正交基组成,U.T@U为单位矩阵#重建后的数据
x_rec = recoverData(z, U, 1)
x_rec[0,:] #[-1.04741883, -1.04741883]#可视化投影
plt.figure(figsize=(6,6))
plt.xlim((-4, 3))
plt.ylim((-4, 3))
plt.scatter(x_norm[:,0], x_norm[:,1], marker='o', facecolors='none', edgecolors='b')
plt.scatter(x_rec[:,0], x_rec[:,1], marker='o', facecolors='none', edgecolors='r')
for i in range(len(x_norm)):plt.plot([x_norm[i,0], x_rec[i,0]], [x_norm[i,1], x_rec[i,1]], 'k--')
plt.title('The normalized and projected data after PCA')'''保留了多少差异性'''
def retained_variance(S, K):rv = np.sum(S[:K])/np.sum(S)return print('{:.2f}%'.format(rv*100))#看看降维后保留了多少差异性
retained_variance(S, 1) #86.78%'''============================part4 人脸数据导入及可视化========================='''
data = scio.loadmat('ex7faces.mat')
x = data['X']'''人脸可视化'''
def displayData(x):plt.figure()n = np.round(np.sqrt(x.shape[0])).astype(int)#定义n*n的子画布fig, a = plt.subplots(nrows=n, ncols=n, sharex=True, sharey=True, figsize=(6, 6))#在每个子画布中画出一个图像for row in range(n):for column in range(n):a[row, column].imshow(x[n * row + column].reshape(32,32).T, cmap='gray')plt.xticks([]) #去掉坐标轴plt.yticks([])       #可视化前100个人脸
displayData(x[0:100, :])'''============================part5 在人脸数据上实施PCA========================='''
#数据标准化
x_norm, mu, sigma = featureNormalize(x)
#特征向量
U, S = pca(x_norm)
#可视化前36个特征向量
displayData(U[:, 0:36].T)'''============================part6 人脸数据降维以及可视化========================='''
#将原始数据降至100维
K = 100
z = projectData(x_norm, U, K)
z.shape #(5000, 100)
#重建后的数据
x_rec = recoverData(z, U, K) #(5000, 1024)#画图对比
displayData(x[0:100, :])
displayData(x_rec[0:100, :])#看看降维后保留了多少差异性
retained_variance(S, K) #93.19%'''============================part7 PCA用在数据可视化========================='''
#读取图片
A = mpimg.imread('bird_small.png') #读取图片'''上次作业中k-means的代码'''
def findClosestCentroids(x, centroids):idx = np.zeros(len(x))for i in range(len(x)):c = np.sqrt(np.sum(np.square((x[i,:]-centroids)), axis=1)) #行求和idx[i] = np.argmin(c)+1return idxdef computeCentroids(x, idx, K):mu = np.zeros((K, x.shape[1]))for i in range(1, K+1):mu[i-1] = x[idx==i].mean(axis=0) #列求均值return mudef kMeansInitCentroids(x, K):randidx = np.random.permutation(x) #随机排列centroids = randidx[:K, :] #选前K个return centroids#运行k-means
def runKmeans(x, centroids, max_iters):for i in range(max_iters):idx = findClosestCentroids(x, centroids) #簇分配centroids = computeCentroids(x, idx, len(centroids)) #移动聚类中心return centroids, idx#k-means部分
X = A.reshape(A.shape[0] * A.shape[1], 3)
K = 16 #聚类数量
max_iters = 10 #最大迭代次数
initial_centroids = kMeansInitCentroids(X, K) #初始化聚类中心
centroids, idx = runKmeans(X, initial_centroids, max_iters) #得到聚类中心和索引
sel = np.random.randint(X.shape[0], size=1000) #随机选择1000个样本
cm = plt.cm.get_cmap('Accent') #设置颜色#画三维图
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(111, projection='3d') #“111”表示“1×1网格,第一子图”
ax.scatter(X[sel, 0], X[sel, 1], X[sel, 2], c=idx[sel], cmap=cm, s=6)
plt.title('Pixel dataset plotted in 3D. Color shows centroid memberships')#PCA部分
X_norm, mu, sigma = featureNormalize(X) #标准化
U, S = pca(X_norm) #特征向量
Z = projectData(X_norm, U, 2) #投影降维#画二维图
plt.figure(figsize=(8,6))
plt.scatter(Z[sel, 0], Z[sel, 1], c=idx[sel], cmap=cm, s=7)
plt.title('Pixel dataset plotted in 2D, using PCA for dimensionality reduction')#看看降维后保留了多少差异性
retained_variance(S, 2) #99.34%

样本集可视化

两个特征向量(相互正交的)

可视化投影

前100个人脸可视化

可视化前36个特征向量

重建之后的图像(左)与原始的图像(右)

和之前的对比,可以发现降维后能大致保持人脸的轮廓,但是丢失掉一些面部细节的信息,但是数据从(5000, 1024)降到了(5000, 100),如果用在神经网络等算法中很明显会加快运行的速度。

三维图效果

二维图

吴恩达|机器学习作业7.1.主成分分析(PCA)相关推荐

  1. 吴恩达机器学习作业7 - K-means和PCA主成分分析(Python实现)

    吴恩达机器学习作业7 - K-means和PCA主成分分析(Python实现) Introduction 在本实验中,将实现K-means聚类算法,并将其应用于图像压缩.在第二部分实验中,将使用主成分 ...

  2. 吴恩达机器学习 EX7 第二部分 主成分分析(PCA)

    2 主成分分析 主成分分析通过协方差矩阵提取数据的主要成分,如90%的成分,通常用户数据压缩和数据可视化(维度降低方便可视化) 2.1 导入模块和数据 该部分通过将二维数据压缩成一维数据演示主成分分析 ...

  3. 第一章-机器学习简介 深度之眼_吴恩达机器学习作业训练营

    目录 专栏简介: 一,机器学习简介 1.1 机器学习定义 1.1 机器学习的重要性 1.2 应用领域 二.监督学习 三.无监督学习 四.总结 专栏简介: 本栏主要内容为吴恩达机器学习公开课的学习笔记, ...

  4. 吴恩达机器学习作业ex2-python实现

    系列文章目录 吴恩达机器学习作业ex1-python实现 吴恩达机器学习作业ex2-python实现 吴恩达机器学习作业ex3-python实现 作业说明及数据集 链接:https://pan.bai ...

  5. k均值算法python实现(吴恩达机器学习作业)

    k均值算法python实现(吴恩达机器学习作业) 题目要求 数据集 读取mat文件 K-means 实现 结果 问题 题目要求 采用K均值算法对样本进行聚类. 编写K均值算法源代码,对ex7data2 ...

  6. 吴恩达机器学习作业Python实现(七):K-means和PCA主成分分析

    吴恩达机器学习系列作业目录 1 K-means Clustering 在这个练习中,您将实现K-means算法并将其用于图像压缩.通过减少图像中出现的颜色的数量,只剩下那些在图像中最常见的颜色. 1. ...

  7. 吴恩达机器学习作业Python实现(八):异常检测和推荐系统

    吴恩达机器学习系列作业目录 1 Anomaly detection 这部分,您将实现一个异常检测算法来检测服务器计算机中的异常行为.他的特征是测量每个服务器的响应速度(mb/s)和延迟(ms).当你的 ...

  8. 吴恩达机器学习作业Python实现(六):SVM支持向量机

    吴恩达机器学习系列作业目录 1 Support Vector Machines 1.1 Example Dataset 1 %matplotlib inline import numpy as np ...

  9. 吴恩达机器学习作业Python实现(五):偏差和方差

    吴恩达机器学习系列作业目录 在本练习中,您将实现正则化的线性回归和多项式回归,并使用它来研究具有不同偏差-方差属性的模型 1 Regularized Linear Regression 正则线性回归 ...

最新文章

  1. 李宏毅机器学习笔记4:Brief Introduction of Deep Learning、Backpropagation(后向传播算法)...
  2. Regex入门(一)
  3. nc65语义模型设计_文本匹配方法系列––多维度语义交互匹配模型
  4. Java知识整理——异常处理
  5. 剖析Caffe源码之ImageDataLayer
  6. 【Linux】scp IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
  7. 单片机:DS1302时钟
  8. Android EditText 不得不说的InputFilter、TextWatcher、ActionMode.Callback、OnEditorActionListener
  9. 前端工程师考核总结_web前端年度工作总结
  10. 3D打印机USB联机打印是如何实现的?(以Cura插件USBPrinting为例)
  11. 史上最详细的接口测试,一篇学会接口
  12. 2022-2027年中国民办高校行业市场全景评估及发展战略规划报告
  13. webpack output.publicPath
  14. UNIAPP/微信小程序-下拉刷新的操作
  15. 老虎机数字抽奖(可控制结果)
  16. window10快速关机小技巧(超级简单)
  17. angular ng zorro框架日期框无法自适应宽度的解决方法
  18. w10重装最简单的一个方法
  19. iPad与电脑端文件互传解决方案(基于nPlayer lite)
  20. 谈古论津丨谦德庄有今天,一要谢郭美美,二要谢郭德纲

热门文章

  1. 环信Demo 导入错误
  2. Mac上安装第三方应用显示包资源破坏解决办法
  3. 解决c#,wpf程序带环境安装包体积太大问题
  4. mysql 慢查询开启
  5. Python基础学习笔记(一)python发展史与优缺点,岗位与薪资
  6. JAVA-java内存分配
  7. Django中的prefetch_related()函数优化
  8. 这两天在学习微信小程序,不可避免的又要用到一些图标,通过问朋友解决了这个事情 想分享给你们一下 希望对你们有用...
  9. 搭建subversion 服务器,并自动部署项目
  10. Linux字符串转换函数汇总