特征值分解实验:人脸识别与PageRank网页排序

奋斗吧
奋斗吧
擅长邻域:未填写

标签: 特征值分解实验:人脸识别与PageRank网页排序 JavaScript博客 51CTO博客

2023-07-04 18:24:30 264浏览

特征值分解实验:人脸识别与PageRank网页排序,特征值分解实验特征值与特征向量特征值分解实对称矩阵工程应用:主成分分析(PrincipalComponentAnalysis)数学推导示例




特征值分解实验

  • 特征值与特征向量
  • 特征值分解
  • 实对称矩阵
  • 工程应用:主成分分析
  • 数学推导:主成分分析算法
  • 举个荔枝
  • 工程应用:人脸识别
  • 数学推导:任何求大规模矩阵的特征值?
  • 马尔可夫过程
  • 工程应用:PageRank网页排序
  • 终止点和陷阱问题



 


特征值与特征向量

特征值分解实验:人脸识别与PageRank网页排序_工程应用

矩阵乘法对应一个线性变换,把输入的任意一个向量,变成另一个方向或长度都改变的新向量,在这个变换的过程中,原来的向量主要发生了旋转、伸缩的变换。

特别情况,存在某些向量使得变换矩阵作用于 TA 们时,只对长度做了伸缩的变换,却不对输入向量产生旋转的变换(不改变原来向量的方向),这些向量就称为这个矩阵的特征向量,伸缩的比例就叫特征值

特征值分解实验:人脸识别与PageRank网页排序_工程应用_02

如上图所示,输出向量只是输入向量的 特征值分解实验:人脸识别与PageRank网页排序_特征向量_03

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_04 在数学上,称为 矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_05
  • 输出向量 特征值分解实验:人脸识别与PageRank网页排序_特征向量_06 在数学上,称为 矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_05 的特征值特征值分解实验:人脸识别与PageRank网页排序_特征向量_04对应的【特征向量】。

本科的线性代数主要研究的是方阵(行数等于列数),【特征值】、【特征向量】也是只有方阵才有的。

举个例子。

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_09

 

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_10

可以把 特征值分解实验:人脸识别与PageRank网页排序_工程应用_11

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_12

特征值分解实验:人脸识别与PageRank网页排序_工程应用_11 就是 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 的特征值, 特征值分解实验:人脸识别与PageRank网页排序_特征向量_15 是 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14

矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 不变,如果把 特征值分解实验:人脸识别与PageRank网页排序_特征向量_18 改成 特征值分解实验:人脸识别与PageRank网页排序_特征向量_19 代进入算,发现都是 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_11

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_22
  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_23
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_24

只是通过一个 特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_11,就找到了好多特征向量,这是为什么呢?

特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_11

所以说,矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14

要求某一个特征值的某一个特征向量,只要找到这个特征值对应的一个特征向量即可。

比如,特征值分解实验:人脸识别与PageRank网页排序_工程应用_28,其 TA 的特征向量都等于 特征值分解实验:人脸识别与PageRank网页排序_特征值_29(特征值分解实验:人脸识别与PageRank网页排序_特征向量_30

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_31
     
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_32

特征值、特征向量是把矩阵看成一种对向量的变换来看方阵,当我们把方阵理解为是一个变换的时候,这个变换拥有一些特征,这些特征会被特征值、特征向量表征出来。

我们可以用 python 算矩阵的特征值、特征向量。

import numpy as np

A = np.array([[5, 1],
			  [3, 3]])

V_eig = np.linalg.eig(A);
print("eigen value:>  ", V_eig[0]);	    # 特征值
print("eigen vector:> \n", V_eig[1]);   # 特征值

运行结果:

eigen value:>   [6. 2.]
eigen vector:> 
 [[ 0.70710678 -0.31622777]
  [ 0.70710678  0.9486833 ]]

矩阵乘法是一种线性变换,变换矩阵定义了变换的规则,也就是定义了要往哪些方向伸缩或旋转(即特征向量),伸缩或旋转的程度是多少(即特征值)。

求矩阵的特征值和特征向量,相当于找出变换规则中的变化方向。

变换方向找到后,也就能把变换过程描述清楚。

 


特征值分解

那会计算矩阵的特征值、特征向量有什么作用吗?

可对矩阵做分解。

以 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 为例,特征值分解实验:人脸识别与PageRank网页排序_工程应用_34,将 特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 分解成 特征值分解实验:人脸识别与PageRank网页排序_特征向量_36

矩阵分解的步骤:

  1. 求得矩阵的特征值和对应的特征向量;
    特征值分解实验:人脸识别与PageRank网页排序_工程应用_37
    特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_38 对应的特征向量 特征值分解实验:人脸识别与PageRank网页排序_工程应用_39,特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_40 对应的特征向量 特征值分解实验:人脸识别与PageRank网页排序_特征向量_41
  2. 将这些特征向量,横向拼成一个矩阵;
    特征值分解实验:人脸识别与PageRank网页排序_特征向量_42
    相当于俩个列向量拼在一起,左边的列向量是特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_38 对应的特征向量,右边的列向量是特征值 特征值分解实验:人脸识别与PageRank网页排序_工程应用_40
  3. 按照顺序,将特征值拼成一个对角矩阵;
    特征值分解实验:人脸识别与PageRank网页排序_工程应用_45
  4. 求出矩阵 特征值分解实验:人脸识别与PageRank网页排序_工程应用_46
    特征值分解实验:人脸识别与PageRank网页排序_工程应用_47
import numpy as np

P = np.array([[1, 1],
          [1, -3]])

P_inv = np.linalg.inv(P)   # 求逆
print("P_inv:>  \n", P_inv)

运行结果:

P_inv:>  
 [[ 0.75  0.25]
 [ 0.25 -0.25]]
  1. 最后,从左到右乘一起。
    特征值分解实验:人脸识别与PageRank网页排序_工程应用_48
    算来算去,最后发现结果等于变换 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_49!!

当然,这不是巧合。这告诉我们,一个方阵如果按照上面的步骤分解,就可以分解为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_36 个矩阵的乘积(特征值分解实验:人脸识别与PageRank网页排序_特征值_51),因为用到了特征值,所以我们把这种分解方法称为【特征值分解】。

特征值分解特征值分解实验:人脸识别与PageRank网页排序_特征值_52.

调换一下,特征值分解实验:人脸识别与PageRank网页排序_特征值_53

矩阵对角化特征值分解实验:人脸识别与PageRank网页排序_特征向量_54

 


实对称矩阵

矩阵可以通过求特征值、特征向量分解为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_36 个矩阵的乘积,特别的,特征值分解实验:人脸识别与PageRank网页排序_工程应用_14

什么是实对称矩阵?

实对称矩阵:矩阵等于TA的转置 特征值分解实验:人脸识别与PageRank网页排序_特征值_57

比如:

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_58

实对称矩阵的性质

  • 性质特征值分解实验:人脸识别与PageRank网页排序_特征值_59:一定可以做特征值分解:特征值分解实验:人脸识别与PageRank网页排序_特征向量_60
  • 性质特征值分解实验:人脸识别与PageRank网页排序_特征值_61:不同特征值对应的特征向量必然正交(正交:内积为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_62

比如:

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_58 的特征值和特征向量 — 特征值分解实验:人脸识别与PageRank网页排序_特征向量_64

俩组特征值和特征向量满足 性质特征值分解实验:人脸识别与PageRank网页排序_特征值_65,又因为 特征值分解实验:人脸识别与PageRank网页排序_特征值_66(俩组特征值不相等),所以说俩组特征向量的内积为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_67

根据 性质特征值分解实验:人脸识别与PageRank网页排序_特征值_65 将 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 做特征值分解特征值分解实验:人脸识别与PageRank网页排序_特征值_52

特征值分解实验:人脸识别与PageRank网页排序_特征向量_71

发现 特征值分解实验:人脸识别与PageRank网页排序_工程应用_72 逆就是 特征值分解实验:人脸识别与PageRank网页排序_工程应用_72 的转置( 特征值分解实验:人脸识别与PageRank网页排序_特征值_74

如果一个矩阵的逆等于这个矩阵的转置,就是正交矩阵(满足 特征值分解实验:人脸识别与PageRank网页排序_工程应用_75)。

所以,这种情况下 特征值分解实验:人脸识别与PageRank网页排序_特征值_52 也可以写成 特征值分解实验:人脸识别与PageRank网页排序_特征向量_77.

因为 特征值分解实验:人脸识别与PageRank网页排序_工程应用_78 矩阵的转置 比 特征值分解实验:人脸识别与PageRank网页排序_特征向量_79矩阵的逆 好算得多。

再来看一个三阶方阵:

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_80

矩阵等于TA的转置 特征值分解实验:人脸识别与PageRank网页排序_特征值_57,所以这也是一个实对称矩阵。

而后呢,TA 有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_36

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_83

这个矩阵比较怪,因为第 特征值分解实验:人脸识别与PageRank网页排序_特征值_84 个特征值是一样哒,根据 性质特征值分解实验:人脸识别与PageRank网页排序_工程应用_85(不同特征值对应第特征向量正交)来看,那 TA 的特征向量就不一定正交了。

不能正交,就不能用 特征值分解实验:人脸识别与PageRank网页排序_特征向量_77 来分解 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14,所以就不能用矩阵的转置代替求矩阵的逆。

后来,人们提供了一种【施密特正交化】方法,将重复特征值不正交的特征向量变成正交,而后再把这些特征向量【单位化】,就变成了俩俩正交的单位向量,再把他们拼起来就是正交矩阵!

特征值分解实验:人脸识别与PageRank网页排序_特征向量_88


这样就满足了 特征值分解实验:人脸识别与PageRank网页排序_特征向量_77.

 


工程应用:主成分分析

矩阵的特征值分解,在工程上也有很广泛的应用,比如主成分分析算法(Principal Component Analysis)。

主成分分析算法:通过线性变换,将原始数据变换为一组各维度线性无关的表示,可以用来提取数据的主要数据分量,多用于高维数据的降维。

这种降维的算法,在尽可能保留原有信息前提下,将一组 特征值分解实验:人脸识别与PageRank网页排序_特征值_90维 降成 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91维 (特征值分解实验:人脸识别与PageRank网页排序_工程应用_92),可以说就是删除重复、相关性强的数据,所以有许多问题需要考虑:

  • 删除哪个维度,信息损失最小?
  • 通过怎样的变换对原始数据降维,信息损失最小?
  • 信息损失最小,如何度量?

那有这样的算法吗?

有的,这个算法就是 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93 啊,具体的算法步骤说一个 特征值分解实验:人脸识别与PageRank网页排序_工程应用_85 维 降成 特征值分解实验:人脸识别与PageRank网页排序_特征值_65

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_96

几何表示为:

特征值分解实验:人脸识别与PageRank网页排序_特征向量_97

为了后续处理方便,对每个维度去【均值】,让每个维度均值都为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_67

去均值:每一个维度(行)的每一个值,都减去该维度的均值。

比如第一维(第一行)的均值是 特征值分解实验:人脸识别与PageRank网页排序_工程应用_85

  • 去均值前:特征值分解实验:人脸识别与PageRank网页排序_特征值_100
  • 去均值后:特征值分解实验:人脸识别与PageRank网页排序_特征向量_101

整体去均值后:

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_102

去均值后,几何表示为:

特征值分解实验:人脸识别与PageRank网页排序_特征值_103


去均值让数据平移:

特征值分解实验:人脸识别与PageRank网页排序_工程应用_104

发现数据点在这个方向?最分散(方差最大):

特征值分解实验:人脸识别与PageRank网页排序_工程应用_105


如果将原始数据投影到这个方向上,就可以将数据的二维表达降至 特征值分解实验:人脸识别与PageRank网页排序_特征值_65

特征值分解实验:人脸识别与PageRank网页排序_工程应用_85 维 降到 特征值分解实验:人脸识别与PageRank网页排序_特征值_65

  • 找一个方差最大的方向;
  • 原数据点往该方向投影,得到一维表达。
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_109

但计算机又没有眼睛,怎么知道完成这俩个步骤呢?

我们再来看一个 特征值分解实验:人脸识别与PageRank网页排序_特征向量_36 维 降为 特征值分解实验:人脸识别与PageRank网页排序_工程应用_85

特征值分解实验:人脸识别与PageRank网页排序_特征向量_112

假设我们找到了方差最大的方向,在把原始的数据点往这个方向投影。

如果是降到 特征值分解实验:人脸识别与PageRank网页排序_特征值_65 维,这样就已经搞定了 — 但我们是要降到 特征值分解实验:人脸识别与PageRank网页排序_工程应用_85

因为俩个方向正交,意味着俩个方向完全独立、完全无关,最有效的表示信息。

但有无数个方向与第一个方向正交,到底选哪一个呢?

条件就是方差,在正交的方向中选择方差最大的方向。

特征值分解实验:人脸识别与PageRank网页排序_特征值_115


而后投影到这俩个方向所代表的平面。

特征值分解实验:人脸识别与PageRank网页排序_特征向量_116


特征值分解实验:人脸识别与PageRank网页排序_特征向量_36 维 降到 特征值分解实验:人脸识别与PageRank网页排序_工程应用_85

  • 找一个方差最大的方向,作为第一个方向(第一维);
  • 选取与已有方向相互正交(各维度完全独立,没有相关性),且方差最大的方向作为第二个方向(第二维);
  • 原数据点往该方向投影,得到二维表达。

一般化,将一组 特征值分解实验:人脸识别与PageRank网页排序_特征值_90维 降成 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91维 (特征值分解实验:人脸识别与PageRank网页排序_工程应用_92):

  • 找到方差最大的方向,作为第一个方向(第一维);
  • 选取与已有方向相互正交(各维度完全独立,没有相关性),且方差最大的方向作为第二个方向(第二维);
  • 选取与已有方向相互正交(各维度完全独立,没有相关性),且方差最大的方向作为第三个方向(第三维);
  • … …
  • 选取与已有方向相互正交(各维度完全独立,没有相关性),且方差最大的方向作为第 特征值分解实验:人脸识别与PageRank网页排序_特征向量_122 个方向(第 特征值分解实验:人脸识别与PageRank网页排序_特征向量_122

降维的思考过程就是这样,而后就是把这些过程给数学化,数学化的这个算法就是 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

特征值分解实验:人脸识别与PageRank网页排序_特征向量_36 维 降到 特征值分解实验:人脸识别与PageRank网页排序_工程应用_85

  • 在三维空间中,找到一个二维标准正交基,使得原始数据投影到这组新基上时,各维度方差必须尽可能大。

俩个条件:

  • 投影方向是正交基;
  • 正交基约束下,各维度的方差要尽可能大。

 


数学推导:主成分分析算法

主成分分析的数学推导,本文最复杂的地方。

从方差说起。

  • 方差:特征值分解实验:人脸识别与PageRank网页排序_特征值_127

特征值分解实验:人脸识别与PageRank网页排序_工程应用_128:这个维度的每一个值

特征值分解实验:人脸识别与PageRank网页排序_工程应用_129:均值

特征值分解实验:人脸识别与PageRank网页排序_特征向量_130:样本总数

因为在降维前,将每一个维度的数据都去均值(均值变为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_67,数据在原点周围),所以每一个维度的数据方差就可简化为:

  • 去均值方差:特征值分解实验:人脸识别与PageRank网页排序_特征值_132

去均值后,大大的简化了计算量。

另外,数学上用协方差来表示数据维度之间的相关性。

  • 协方差:特征值分解实验:人脸识别与PageRank网页排序_特征向量_133

去均值后,俩个维度之间的协方差就可以简化为:

  • 去均值协方差:特征值分解实验:人脸识别与PageRank网页排序_特征值_134

如果俩个维度之间的协方差为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_67,代表这俩个维度完全无关,正是 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

特征值分解实验:人脸识别与PageRank网页排序_特征向量_137

观察方差、协方差的表达式,方差就是向量自身的内积(相乘再相加),只不过在内积的前面乘了 特征值分解实验:人脸识别与PageRank网页排序_特征向量_138,协方差就是俩个向量的内积,也是前面多乘了一个 特征值分解实验:人脸识别与PageRank网页排序_特征向量_138

假设原始数据矩阵 特征值分解实验:人脸识别与PageRank网页排序_工程应用_140

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_141

每条数据都有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_142 三个维度,总共 特征值分解实验:人脸识别与PageRank网页排序_特征向量_130

我们把 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_140

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_145

再将 特征值分解实验:人脸识别与PageRank网页排序_工程应用_146

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_147

这是一个矩阵乘法,再给这个结果乘以 特征值分解实验:人脸识别与PageRank网页排序_特征向量_138

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_149

得出的矩阵,TA的主对角线元素为各维度方差,其他元素为各维度间协方差,而且这个矩阵是实对称矩阵,这样的矩阵称为【协方差矩阵】。

上述的推导过程:

特征值分解实验:人脸识别与PageRank网页排序_工程应用_150

基于现在掌握的知识,将一组 特征值分解实验:人脸识别与PageRank网页排序_特征值_90维 降成 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91维 (特征值分解实验:人脸识别与PageRank网页排序_工程应用_92)的数学任务,就可以做进一步的数学描述。

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_154 维空间中,找到一个 特征值分解实验:人脸识别与PageRank网页排序_特征向量_122 维标准正交基(特征值分解实验:人脸识别与PageRank网页排序_特征值_156),使得原始数据投影到这组新基上时,数据协方差矩阵主对角线原始尽可能大,其他元素为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_62

降维任务的描述越来越数学化,但还是没有找到合适的、最关键的降维工具。

记得,我们可以把矩阵看成一种变换,但只是换了基底,并没有降维。

  • 原始数据协方差矩阵 特征值分解实验:人脸识别与PageRank网页排序_工程应用_158

因为这个矩阵:

  • 主对角线元素为各维度的方差,不全为零;
  • 其他元素为各维度的协方差,全为零。

我们要求协方差为零,相当于要求经过变换后新的基底是标准正交基。

这样就使得协方差矩阵发生了对角化… …

特征值分解实验:人脸识别与PageRank网页排序_特征向量_159


变换的公式为:特征值分解实验:人脸识别与PageRank网页排序_特征值_160

特征值分解实验:人脸识别与PageRank网页排序_工程应用_161


把经过变换的协方差矩阵称为:特征值分解实验:人脸识别与PageRank网页排序_特征向量_162

我们把变换的公式(特征值分解实验:人脸识别与PageRank网页排序_特征值_160)代进入,

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_164

特征值分解实验:人脸识别与PageRank网页排序_特征向量_165,那这个公式就变成了,

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_166

这说明,要想使得数据的协方差矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_167对角化为特征值分解实验:人脸识别与PageRank网页排序_特征向量_168,就要求出 特征值分解实验:人脸识别与PageRank网页排序_特征向量_167

特征值分解实验:人脸识别与PageRank网页排序_特征向量_167 的特征值,其实就是新基底下各维度的数据方差,如果把这些方差排序好,拼成对角矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_168,又因为 特征值分解实验:人脸识别与PageRank网页排序_工程应用_172,所以就可以把新的特征向量以行向量的形式,纵向拼成一个矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_72

最后,取 特征值分解实验:人脸识别与PageRank网页排序_工程应用_72 的前 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91 个行向量,构成一个新的矩阵 特征值分解实验:人脸识别与PageRank网页排序_工程应用_14,这 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91 个行向量就是我们要找的 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91 个正交的基向量,这 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91 个正交的基向量就构成了一个 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91

特征值分解实验:人脸识别与PageRank网页排序_工程应用_91

特征值分解实验:人脸识别与PageRank网页排序_特征值_182


原始数据矩阵,通过 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91 维的标准的正交的基投影,就在变换时降成 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91

至此,特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

基于上述的讨论,将一组 特征值分解实验:人脸识别与PageRank网页排序_特征值_90维 降成 特征值分解实验:人脸识别与PageRank网页排序_工程应用_91维 (特征值分解实验:人脸识别与PageRank网页排序_工程应用_92)的任务,就可以描述为:

  • 求一个变换矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_189,当 特征值分解实验:人脸识别与PageRank网页排序_工程应用_190 时,有 特征值分解实验:人脸识别与PageRank网页排序_特征值_191,取 特征值分解实验:人脸识别与PageRank网页排序_工程应用_189 的前 特征值分解实验:人脸识别与PageRank网页排序_特征向量_122 行构成矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_05,则 特征值分解实验:人脸识别与PageRank网页排序_工程应用_195

特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

  • 求原始数据协方差矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_197的特征值和特征向量;
  • 将特征值(方差)排好序,从上到下拼成矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_198;
  • 将特征向量从上到下,遵循特征值顺序纵向拼成矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_189
  • 取出 特征值分解实验:人脸识别与PageRank网页排序_工程应用_189 中前 特征值分解实验:人脸识别与PageRank网页排序_特征向量_122 行构成降维矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_05,作用于原始数据,即完成降维。

 


举个荔枝

任务:将二维数据降到一维。

原始数据:特征值分解实验:人脸识别与PageRank网页排序_特征向量_203

  1. 去均值
    特征值分解实验:人脸识别与PageRank网页排序_工程应用_204
  2. 求协方差矩阵
    特征值分解实验:人脸识别与PageRank网页排序_特征值_205
  3. 求特征值和特征向量
    俩组:特征值分解实验:人脸识别与PageRank网页排序_工程应用_206
  4. 将特征向量纵向拼成矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_46
    特征值分解实验:人脸识别与PageRank网页排序_特征向量_208
  5. 取出 特征值分解实验:人脸识别与PageRank网页排序_工程应用_46 的第 特征值分解实验:人脸识别与PageRank网页排序_特征值_210 行构成降维矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_49
    特征值分解实验:人脸识别与PageRank网页排序_特征向量_212
  6. 特征值分解实验:人脸识别与PageRank网页排序_工程应用_49 作用于 特征值分解实验:人脸识别与PageRank网页排序_工程应用_214(投影),得到一维表达
    特征值分解实验:人脸识别与PageRank网页排序_工程应用_215

特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

特征值分解实验:人脸识别与PageRank网页排序_特征向量_93 只能解除数据的线性相关性,对于高阶相关性不起作用,可以改进为【核PCA】,通过核函数将非线性相关转为线性相关,再使用 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

特征值分解实验:人脸识别与PageRank网页排序_特征向量_93 是一种无参技术,即没有主观参数的介入,所以 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

 


import numpy as np
import matplotlib.pyplot as plt

def myPCA(dataMat, K=2):     # K为目标维度
    # 2. 对数据矩阵去均值
    meanVals = np.mean(dataMat, axis=1)   #axis=0,求列的均值,axis=1,求行的均值
    meanRemoved = dataMat - meanVals      #python的广播机制

    # 3. 计算协方差矩阵
    # rowvar:默认为True,此时每一行代表一个维度,每一列代表一条数据;为False时,则反之。
    # bias:默认为False,此时标准化时除以m-1(无偏估计);反之为m(有偏估计)。其中m为数据总数。
    covMat = np.cov(meanRemoved,rowvar=True,bias=True) 
    print("\n-----covMat-----\n",covMat)

    # 4. 计算协方差矩阵的特征值和特征向量
    eigVals, eigVects = np.linalg.eig(np.mat(covMat))
    print("-----eigVals-----\n",eigVals)
    print("-----eigVects-----\n",eigVects)

    # 5. 将特征值由小到大排序,并返回对应的索引
    eigValInd = np.argsort(eigVals)   #argsort函数返回的是数组值从小到大的索引   [ 2.   0.4] -> [ 0.4.   2] -> 
    print("-----eigValInd 1-----\n",eigValInd)

    # 6. 根据eigValInd后K个特征值索引,找出eigVects中对应的特征向量,拼成降维矩阵  
    eigValInd = eigValInd[-1:-(K+1):-1]
    print("-----eigValInd 2-----\n",eigValInd)
    redEigVects=eigVects[:,eigValInd].T   #取出特征向量(即降维矩阵)
    print("-----redEigVects-----\n",redEigVects)

    # 7. 执行降维操作(矩阵乘法)
    lowDMat = np.dot(redEigVects , meanRemoved)  
    
    # 8. 重构数据矩阵
    resturctMat = np.dot(redEigVects.I , lowDMat)  + meanVals
    
    return lowDMat,resturctMat

if __name__ == '__main__':
    dataMat = np.mat([[1,1,2,2,4],
                      [1,3,3,4,4]])

    lowDMat , resturctMat = myPCA(dataMat,K=1)
    print("-----lowDmat-----\n",lowDMat)
    print("-----resturctMat-----\n",resturctMat)
    
    # 绘制数据点
    fig = plt.figure()  
    plt.xlim(-1, 5)
    plt.ylim(-1, 5)
    plt.grid(color='gray')
    plt.axvline(x=0, color='gray')
    plt.axhline(y=0, color='gray')
    ax = fig.add_subplot(111)
    ax.scatter(dataMat[0, :].flatten().A[0], dataMat[1, :].flatten().A[0], marker='*', s=300, c='red')      #描原数据点
    ax.scatter(resturctMat[0, :].flatten().A[0], resturctMat[1, :].flatten().A[0], marker='o', s=50, c='green')  #描重建数据点
    plt.show()

 


工程应用:人脸识别

下图中,有两张照片是同一个人的:

特征值分解实验:人脸识别与PageRank网页排序_特征值_221


对于这个问题,人是很容易分辨出来的,但计算机应该怎么办呢?

其中一种方法就是将之线性化。首先,给出此人更多的照片:

特征值分解实验:人脸识别与PageRank网页排序_特征向量_222


将其中某张照片分为眼、鼻、嘴三个部位,这是人脸最重要的三个部位。通过某种算法,可以用三个实数来分别表示这三个部位,比如下图得到的分别是特征值分解实验:人脸识别与PageRank网页排序_特征向量_223特征值分解实验:人脸识别与PageRank网页排序_工程应用_224特征值分解实验:人脸识别与PageRank网页排序_工程应用_225

特征值分解实验:人脸识别与PageRank网页排序_特征值_226

将所有这些照片分别算出来,用三维坐标来表示得到的结果,比如上图得到的结果就是特征值分解实验:人脸识别与PageRank网页排序_特征向量_227

将这些三维坐标用点标注在直角坐标系中,发现这些点都落在某平面上,或该平面的附近。因此,可认为此人的脸线性化为了该平面。

特征值分解实验:人脸识别与PageRank网页排序_特征向量_228


将人脸线性化为平面后,再给出一张新的照片,按照刚才的方法算出这张照片的三维坐标,发现不在平面上或者平面附近,就可以判断不是此人的照片:

特征值分解实验:人脸识别与PageRank网页排序_特征值_229


将人脸识别这种复杂的问题线性化,就可以用使用线性代数解决TA。

线性代数要学习的内容就是 如何解决线性问题,而如何把 复杂问题线性化 是别的学科的内容,比如《微积分》、《信号与系统》、《概率与统计》等。

基于矩阵对角化理论的 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

数据集:(可下载)

特征值分解实验:人脸识别与PageRank网页排序_特征值_231


数据集里有 特征值分解实验:人脸识别与PageRank网页排序_工程应用_232 个人,每个都有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_233 张照片,分别存储在 特征值分解实验:人脸识别与PageRank网页排序_工程应用_232 个文件夹里,特征值分解实验:人脸识别与PageRank网页排序_特征值_235,每个文件夹下面都有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_233特征值分解实验:人脸识别与PageRank网页排序_工程应用_237 照片,每张照片的尺寸 特征值分解实验:人脸识别与PageRank网页排序_工程应用_238(长 * 宽)。

特征值分解实验:人脸识别与PageRank网页排序_工程应用_239

把数据集,分成:

  • 训练集:50%
  • 测试集:50%
def loadDataSet(m):
    dataSetDir = input('att_faces path:>' )    # 输入训练集文件位置
    train_face = np.zeros((40*m,112*92))       # 训练集矩阵,40个人,取前 m 张照片;每张照片有 112*92 个维度
    train_face_number = np.zeros(40*m)
    test_face = np.zeros((40*(10-m),112*92))   # 测试集矩阵,40个人,取后 m 张照片;每张照片有 112*92 个维度
    test_face_number = np.zeros(40*(10-m))

把训练集送入 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

降维矩阵,可以提取数据的主要信息,去除冗余 — 所以也可以称为【主成分提取器】。

从测试集里,随机抽出一张照片,送入【主成分提取器】将该照片的主要信息提取出来,而后与数据库中所有信息做比对检索,计算欧式距离,找出最相似的一张照片,即完成我们的人脸识别。

上述架构:

特征值分解实验:人脸识别与PageRank网页排序_工程应用_241


特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

def myPCA(dataMat, K=2):    
    # 1. 对数据矩阵去均值
    meanVals = np.mean(dataMat, axis=1)   # axis=0,求列的均值,axis=1,求行的均值
    meanRemoved = dataMat - meanVals  
    
    # 2. 计算协方差矩阵
    covMat = np.cov(meanRemoved, rowvar=True, bias=True)

    # 3. 计算协方差矩阵的特征值和特征向量
    eigVals, eigVects = np.linalg.eig(np.mat(covMat))

    # 4. 将特征值由小到大排序,并返回对应的索引
    eigValInd = np.argsort(eigVals)

    # 5. 根据eigValInd后K个特征值索引,找出eigVects中对应的特征向量,拼成降维矩阵  
    eigValInd = eigValInd[-1:-(K+1):-1]
    Extractor = eigVects[:,eigValInd].T		  # 取出特征向量(降维矩阵)

    # 6. 执行降维(矩阵乘法)
    lowDMat = np.dot(Extractor, meanRemoved)
    
    # 返回 降维后的数据、训练集的均值、降维矩阵(主成分提取器) 
    return lowDMat, meanRemoved, Extractor

特征值分解实验:人脸识别与PageRank网页排序_特征向量_93

import os, cv2  
# cv2 是 opencv-python 模块
import numpy as np
import matplotlib.pyplot as plt
 
def myPCA(dataMat, K=2):   
	# 加进来吧!
    
def img2vector(filename):
    img = cv2.imread(filename,0)              # 读取图片
    rows,cols = img.shape
    imgVector = np.zeros((1,rows*cols)) 
    imgVector = np.reshape(img,(1,rows*cols)) # 图片2D -> 1D
    return imgVector
 
def loadDataSet(m):
    print ("--------- Getting data set ---------")
    dataSetDir = input('att_faces path:>' )    # 输入训练集文件位置
    train_face = np.zeros((40*m,112*92))       # 训练集矩阵,40个人,取前 m 张照片;每张照片有 112*92 个维度
    train_face_number = np.zeros(40*m)
    test_face = np.zeros((40*(10-m),112*92))   # 测试集矩阵,40个人,取后 m 张照片;每张照片有 112*92 个维度
    test_face_number = np.zeros(40*(10-m))
    
    choose = np.array([1,2,3,4,5,6,7,8,9,10])  
    # 创建1->10的数组。(因为图片编号是1.bgm~10.bgm)
    for i in range(40):      # 总共有40个人
        people_num = i+1     # 个体编号
        for j in range(10):  # 每个人都有10张脸部照片
            if j < m:        # 先从10张图片中选m张作为训练集
                filename = dataSetDir+'/s'+str(people_num)+'/'+str(choose[j])+'.pgm'
                # 人脸数据的路径,路径是字符串类型,所以要把数字转换为字符串
                img = img2vector(filename)
                train_face[i*m+j,:] = img
                train_face_number[i*m+j] = people_num    #记录这张图片所属之人
            else:            # 余下10-m张作为测试集
                filename = dataSetDir+'/s'+str(people_num)+'/'+str(choose[j])+'.pgm'
                img = img2vector(filename)
                test_face[i*(10-m)+(j-m),:] = img
                test_face_number[i*(10-m)+(j-m)] = people_num
                
    return np.mat(train_face.T), train_face_number, np.mat(test_face.T), test_face_number
    # 训练集train_face、测试集test_face 做一个转置.T,原来一个图片对应一个行向量,现在每一列都代表一张图片
 
if __name__=='__main__':
    # 1 .从文件夹中加载图片数据
    train_face, train_face_number, test_face, test_face_number = loadDataSet(5)
    print("train_face shape:", train_face.shape)   
    print("train_face_number shape:", train_face_number.shape, "\n", train_face_number)
    print("test_face shape:", test_face.shape)
    print("test_face_number shape:", test_face_number.shape, "\n" , test_face_number)

特征值分解实验:人脸识别与PageRank网页排序_特征向量_36

查看一下这个协方差矩阵:

print("covMat shape:>  ", covMat.shape)

输出:(10304, 10304)

每一个像素点都是一个维度,这么大的协方差矩阵,协方差矩阵 特征值分解实验:人脸识别与PageRank网页排序_特征向量_245

为了求大规模特征值和特征向量,其实有俩组方案:

  • 安装 特征值分解实验:人脸识别与PageRank网页排序_特征向量_246 这种组合库,调包即可,计算一万维大概是 特征值分解实验:人脸识别与PageRank网页排序_特征值_59
  • 通过某个小规模的矩阵来求(采用)。

 


数学推导:任何求大规模矩阵的特征值?

现实生活里,我们拍照都是高清配置,数据样本的维度就很高,计算量也非常的大。

来看一段推导。

假设 特征值分解实验:人脸识别与PageRank网页排序_工程应用_140特征值分解实验:人脸识别与PageRank网页排序_特征值_249 的数据矩阵,则对应的协方差矩阵:特征值分解实验:人脸识别与PageRank网页排序_工程应用_250特征值分解实验:人脸识别与PageRank网页排序_特征向量_251

现在有一个矩阵:特征值分解实验:人脸识别与PageRank网页排序_工程应用_252(和 特征值分解实验:人脸识别与PageRank网页排序_特征向量_245 相反),特征值分解实验:人脸识别与PageRank网页排序_特征值_254特征值分解实验:人脸识别与PageRank网页排序_工程应用_255

接着,由特征值和特征向量的定义可以得到:特征值分解实验:人脸识别与PageRank网页排序_特征值_256特征值分解实验:人脸识别与PageRank网页排序_特征向量_03特征值分解实验:人脸识别与PageRank网页排序_特征值_254 的特征值,特征值分解实验:人脸识别与PageRank网页排序_特征向量_18特征值分解实验:人脸识别与PageRank网页排序_特征值_254 关于 特征值特征值分解实验:人脸识别与PageRank网页排序_特征向量_03

特征值分解实验:人脸识别与PageRank网页排序_特征值_254 换成 特征值分解实验:人脸识别与PageRank网页排序_工程应用_140

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_264

等式左右俩边,都乘以 特征值分解实验:人脸识别与PageRank网页排序_工程应用_140

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_266

等式变形:

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_267

因为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_03

又因为 特征值分解实验:人脸识别与PageRank网页排序_工程应用_269 就是协方差矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_245

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_271

特征值分解实验:人脸识别与PageRank网页排序_工程应用_272

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_273

这个式子说明了,协方差矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_245 和 矩阵特征值分解实验:人脸识别与PageRank网页排序_特征值_254

所以只要求出矩阵特征值分解实验:人脸识别与PageRank网页排序_特征值_254 的特征值就求出了 特征值分解实验:人脸识别与PageRank网页排序_特征向量_245 的特征值,而协方差矩阵 特征值分解实验:人脸识别与PageRank网页排序_特征向量_245 的特征向量,就是矩阵特征值分解实验:人脸识别与PageRank网页排序_特征值_254 的特征向量 乘 特征值分解实验:人脸识别与PageRank网页排序_工程应用_140

这样,求 特征值分解实验:人脸识别与PageRank网页排序_工程应用_255 阶的矩阵特征值分解实验:人脸识别与PageRank网页排序_特征值_254 间接求出了 特征值分解实验:人脸识别与PageRank网页排序_特征向量_251 阶矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_245,但矩阵特征值分解实验:人脸识别与PageRank网页排序_特征值_254的特征值只有 特征值分解实验:人脸识别与PageRank网页排序_工程应用_255 个,而矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_245特征值分解实验:人脸识别与PageRank网页排序_特征向量_251 个,也就是说,通过这种方式只能求出 矩阵特征值分解实验:人脸识别与PageRank网页排序_特征向量_245 的前 特征值分解实验:人脸识别与PageRank网页排序_工程应用_255

但没关系,前 特征值分解实验:人脸识别与PageRank网页排序_工程应用_255 是方差最大的 特征值分解实验:人脸识别与PageRank网页排序_工程应用_255

# 2. 计算协方差矩阵
covMat = np.cov(meanRemoved, rowvar=True, bias=True)

优化后:

# 2. 计算协方差矩阵(1/m 是一个标量所以不必加进来)
T = meanRemoved.T * meanRemoved  # (200, 200)
print("T shape:", T.shape)       # (10304, 10304)

 
特征向量也需要改

# 5. 取出特征向量(降维矩阵)
Extractor = eigVects[:,eigValInd].T

优化后:

# 5. auto为真,自动计算目标维数K
if auto==True:  # 是否自动计算目标维数
	num = 0     # 需要保存的特征值个数
	for i in range(len(eigVals)):
		if (np.linalg.norm(eigVals[:i + 1]) / np.linalg.norm(eigVals)) > 0.999:  # 看看前i个特征值有没有达到总方差的99.9%
			num = i + 1
			break  
	print("The num:", num)
	K = num

 

优化特征值和特征向量后:

import os, cv2
# cv2 是 opencv-python 模块
import numpy as np
import matplotlib.pyplot as plt
 
def myPCA(dataMat, K=2, auto=False):       # K为目标维度
    # 1. 对数据矩阵去均值
    meanVals = np.mean(dataMat, axis=1)   # axis=0,求列的均值,axis=1,求行的均值
    meanRemoved = dataMat - meanVals  
        
    # 2. 计算协方差矩阵,1/m 是一个标量所以不必加进来
    T = meanRemoved.T * meanRemoved  # (200, 200)
    print("T shape:", T.shape)       # (10304, 10304)
    
    # 3. 计算协方差矩阵的特征值和特征向量
    # 计算大规模协方差矩阵的特征值和特征向量,有两种方案:
    # (1). 安装“numpy+mkl”这种组合库(调包)。
    # (2). 通过某个小规模的矩阵来求(采用)。
    eigVals, eigVects = np.linalg.eig(np.mat(T))
    
    # 4. 将特征值由小到大排序,并返回对应的索引
    eigValInd = np.argsort(eigVals)  
    
    # 5. 自动计算目标维数K
    if auto==True:  # 是否自动计算目标维数
        num = 0     # 需要保存的特征值个数
        for i in range(len(eigVals)):
            if (np.linalg.norm(eigVals[:i + 1]) / np.linalg.norm(eigVals)) > 0.999:  # 看看前i个特征值有没有达到总方差的99.9%
                num = i + 1
                break  
        print("The num:", num)
        K = num 
    
    # 6. 根据eigValInd后K个特征值索引,找出eigVects中对应的特征向量,拼成降维矩阵  
    eigValInd = eigValInd[-1:-(K+1):-1]
    Extractor0 = meanRemoved * eigVects[:,eigValInd]   #求出协方差矩阵的前K个特征向量(即降维矩阵)
    
    # 7. 单位化特征向量
    for i in range(K): 
        Extractor0[:,i] = Extractor0[:,i]/np.linalg.norm(Extractor0[:,i])
        
    # 8. 执行降维操作(矩阵乘法)
    Extractor = Extractor0.T
    lowDMat = np.dot(Extractor, meanRemoved)  
     
    # 返回 降维后的数据、训练集的均值、降维矩阵(主成分提取器)  
    return lowDMat, meanVals, Extractor
 
def img2vector(filename):
    img = cv2.imread(filename,0)              # 读取图片
    rows,cols = img.shape
    imgVector = np.zeros((1,rows*cols)) 
    imgVector = np.reshape(img,(1,rows*cols)) # 图片2D -> 1D
    return imgVector
 
def loadDataSet(m):
    print ("--------- Getting data set ---------")
    dataSetDir = input('att_faces path:>' )    # 输入训练集文件位置
    train_face = np.zeros((40*m,112*92))       # 训练集矩阵,40个人,取前 m 张照片;每张照片有 112*92 个维度
    train_face_number = np.zeros(40*m)
    test_face = np.zeros((40*(10-m),112*92))   # 测试集矩阵,40个人,取后 m 张照片;每张照片有 112*92 个维度
    test_face_number = np.zeros(40*(10-m))
    
    choose = np.array([1,2,3,4,5,6,7,8,9,10])  # 创建1->10的数组。(因为图片编号是1.bgm~10.bgm)
    for i in range(40):      # 总共有40个人
        people_num = i+1     # 个体编号
        for j in range(10):  # 每个人都有10张脸部照片
            if j < m:        # 先从10张图片中选m张作为训练集
                filename = dataSetDir+'/s'+str(people_num)+'/'+str(choose[j])+'.pgm'
                img = img2vector(filename)
                train_face[i*m+j,:] = img
                train_face_number[i*m+j] = people_num    # 记录这张图片所属之人
            else:            # 余下10-m张作为测试集
                filename = dataSetDir+'/s'+str(people_num)+'/'+str(choose[j])+'.pgm'
                img = img2vector(filename)
                test_face[i*(10-m)+(j-m),:] = img
                test_face_number[i*(10-m)+(j-m)] = people_num
                
    return np.mat(train_face.T), train_face_number, np.mat(test_face.T), test_face_number
    # 训练集train_face、测试集test_face 做一个转置.T,原来一个图片对应一个行向量,现在每一列都代表一张图片
 
if __name__=='__main__':
    # 1. 从文件夹中加载图片数据
    train_face, train_face_number, test_face, test_face_number = loadDataSet(5)
    print("train_face shape:", train_face.shape)   
    print("train_face_number shape:", train_face_number.shape, "\n", train_face_number)
    print("test_face shape:", test_face.shape)
    print("test_face_number shape:", test_face_number.shape, "\n",  test_face_number)
    
    # 2. 利用PCA进行降维(提取数据的主要信息)-> 利用训练集训练“主成分提取器”
    DataBase, train_meanVals, Extractor= myPCA(train_face, 40, auto=True)
    print("Train OK!!!")
    
    # 3. 将主成分提取器作用于测试集图片
    test_face_new = Extractor * (test_face - train_meanVals)
    
    # 4. 逐一遍历测试集图片,同时检索数据库,计算识别正确的个数
    true_num = 0                      # 正确个数
    num_test = test_face.shape[1]     # 测试集图片数
    for i in range(num_test):   
        testFace = test_face_new[:,i] # 取出一张测试图片             
        EucDist = np.sqrt(np.sum(np.square(DataBase - testFace), axis=0))# 求出该测试图片与数据库中所有图片的欧式距离
        DistIdx = EucDist.argsort()   # 距离由小到大排序,返回索引
        idxMin = DistIdx[:,0]         # 取出最小距离所在索引
        if train_face_number[idxMin] == test_face_number[i]:
            true_num += 1
            
    accu = float(true_num)/num_test
    print ('The classify accuracy is: %.2f%%' %(accu * 100))
    # 显示匹配成功率

输出:

The classify accuracy is: 89.00%

特征值分解实验:人脸识别与PageRank网页排序_工程应用_293 里面的 特征值分解实验:人脸识别与PageRank网页排序_特征向量_93 算法,是奇异值分解(特征值分解实验:人脸识别与PageRank网页排序_工程应用_295)实现的,因为用数据矩阵的奇异值分解代替协方差矩阵的特征值分解,速度更快。

 


马尔可夫过程

您是否也有过这样的感觉:不管付出了多少努力,事情总会回到老样子,就好像冥冥之中有个无法摆脱的宿命一样。

数学模型能告诉您其中的原理,这个数学模型就是马尔可夫过程。

想要一次性地采取一个行动去改变某件事,结果徒劳无功,其实,这就是一个马尔可夫过程,满足马尔可夫过程有四个条件。

  • 第一,系统中存在有限多个状态。
  • 第二,状态之间切换的概率是固定的。
  • 第三,系统要具有遍历性,也就是从任何一个状态出发,都能找到一条路线,切换到任何一个其他的状态。
  • 第四,其中没有循环的情况,不能说几个状态形成闭环,把其他状态排斥在外。

举个例子,某位老师,发现课堂上总有学生无法集中注意力,会溜号。

所谓马尔可夫过程,就是假设学生在 “认真” 和 “溜号” 这两个状态之间的切换概率,是 固定的。

我们设定,今天认真听讲的学生,明天依旧认真的概率是 90%,还有 10% 的概率会溜号。

而今天溜号的学生,明天继续溜号的可能性是 70%,剩下 30% 的可能性会变得认真。

咱们看看这个模型怎么演化。假设总共有 100 个学生,第一天认真和溜号的各占一半。

  • 第二天,根据概率的设定,50 个认真的学生中会有 5 人变成溜号;
  • 而溜号的学生中,会有 15 人变成认真;

所以,第二天是有 60 (50-5+15) 个人认真,剩下 40 个人溜号。

第三天,有 66 个认真的,34 个溜号的……

以此类推,最后有一天,您会发现有 75 个认真,25 个溜号的。

而到了这一步,模型就进入了一个稳定的状态,数字就不变了。

因为下一天会有 7.5 个学生从认真变成溜号,同时恰好有 7.5 个学生从溜号变成认真!

特征值分解实验:人脸识别与PageRank网页排序_工程应用_296


而老师对这个稳定态很不满意,为什么只有 75 个认真的呢 ?

TA 安排了一场无比精彩的公开课,还请了别的老师来帮 TA 监督学生。

这一天,100 个学生都是认真的。

但这样的干预对马尔可夫过程是无效的。

第二天认真的学生就变成了 90 个,第三天就变成了 84 个,……直到某一天,还是 75 个认真和 25 个溜号。

马尔可夫过程最重要的就是第二个过程,状态之间切换的概率是固定的

对应到人的身上,是人的习惯、环境、认知、本性等等影响的,只要是马尔可夫过程,不管 初始值/状态 如何,也不管在这个过程中有什么一次性的干预,ta 终究会演化到一个统计的 平衡态:其中每个状态所占的比例是不变的。

就好像终究会有 75% 的学生认真,25% 的学生溜号。马尔可夫过程,都有一个宿命般的结局。

对于马尔可夫过程,得知道状态之间切换的概率是固定的

 


工程应用:PageRank网页排序

PageRank 是网页排序算法,Page 是网页的意思,Rank 是权重的意思。

已知某个用户,在搜索框中输入一个关键词,假设搜索到 特征值分解实验:人脸识别与PageRank网页排序_特征向量_297

工程师要做的就是设计好,这 特征值分解实验:人脸识别与PageRank网页排序_特征向量_297

  • 目标:将 特征值分解实验:人脸识别与PageRank网页排序_工程应用_299
  • 参考:学术界判断学术论文的重要性,看论文的引用次数。

PageRank 的核心思想:被越多网页指向的网页,优秀的越大,权重就应该更高。

特征值分解实验:人脸识别与PageRank网页排序_特征向量_297

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_05 指向的网页有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_302
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_303 指向的网页有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_304
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_197 指向的网页有 特征值分解实验:人脸识别与PageRank网页排序_特征向量_05
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_307 指向的网页有 特征值分解实验:人脸识别与PageRank网页排序_特征值_308

这种相互指向的关系,形成一幅有向图:

特征值分解实验:人脸识别与PageRank网页排序_特征向量_309

而后,我们用一个二维数组存储网页间跳转的概率。

Page

A

B

C

D

A

B

C

D

特征值分解实验:人脸识别与PageRank网页排序_特征值_325

这是用来存储图的邻接矩阵,比如:

  • 坐标特征值分解实验:人脸识别与PageRank网页排序_特征值_325,因为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_05
  • 坐标特征值分解实验:人脸识别与PageRank网页排序_特征值_328,因为 特征值分解实验:人脸识别与PageRank网页排序_特征向量_05

假设有一个上网者,先随机打开 特征值分解实验:人脸识别与PageRank网页排序_工程应用_330

各个网页的最终概率,就是我们想要的网页权重,概率等同权重。

而上网者的行为,就是马尔可夫过程(状态之间切换的概率是固定的)。

这个过程有俩部分:

  • 初始概率向量 特征值分解实验:人脸识别与PageRank网页排序_特征向量_331
  • 状态转移矩阵 特征值分解实验:人脸识别与PageRank网页排序_特征向量_332

马尔可夫过程:

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_333
  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_334
  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_335
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_336

PageRank发明人拉里·佩奇证明了,这个马尔可夫过程是收敛的,最终的收敛为:

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_337

也就是说,无论 特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 作用于 特征值分解实验:人脸识别与PageRank网页排序_工程应用_339 多少次,特征值分解实验:人脸识别与PageRank网页排序_工程应用_339

而这个稳定下了的 特征值分解实验:人脸识别与PageRank网页排序_工程应用_339,就是我们要的 特征值分解实验:人脸识别与PageRank网页排序_工程应用_330

特征值分解实验:人脸识别与PageRank网页排序_工程应用_339 是 矩阵特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 关于特征值特征值分解实验:人脸识别与PageRank网页排序_特征值_65

演示过程:

  • 特征值分解实验:人脸识别与PageRank网页排序_特征向量_346
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_347
  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_348
  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_349

得出,特征值分解实验:人脸识别与PageRank网页排序_工程应用_14 概率(权重)最高,特征值分解实验:人脸识别与PageRank网页排序_工程应用_351

求这个最终的网页概率分布,有俩种方法:

  • 特征向量
  • 暴力迭代,反复做矩阵乘法,最后就会得到收敛的 特征值分解实验:人脸识别与PageRank网页排序_工程应用_352
import numpy as np
 
def init_transfer_array():
    A = np.array([[0.000000, 0.50, 1.00, 0.00],
                  [0.333333, 0.00, 0.00, 0.50],
                  [0.333333, 0.00, 0.00, 0.50],
                  [0.333333, 0.50, 0.00, 0.00]], dtype=float)
    return A
    
def init_first_pr(d):
    first_pr = np.zeros((d,1),dtype=float)   
    for i in range(d):
        first_pr[i] = float(1) / d
    return first_pr
 
def compute_pagerank0(transfer_array,v0):  
# 用特征向量法,来求解最终的pagerank值Vn
    eigVals, eigVects = np.linalg.eig(transfer_array)
    print("eigVals:\n",eigVals)
    print("eigVects:\n",eigVects)
    
    idx = 0
    for i in range(transfer_array.shape[0]):
        if abs(eigVals[i]-1.0) < 1e-5:  # 若当前特征值近似等于1,则为我们要找的特征值1,返回索引
            idx = i
            break
    print("idx=",idx)        
    return eigVects[:,i]/2
 
def compute_pagerank1(transfer_array,v0):  
# 用“迭代”法,来求解最终的pagerank值Vn
    iter_num = 0  # 记录迭代次数
    pagerank = v0
    while np.sum(abs(pagerank - np.dot(transfer_array,pagerank))) > 1e-6: # 若当前值与上一次的值误差小于某个值,则认为已经收敛,停止迭代
        pagerank = np.dot(transfer_array,pagerank)
        iter_num += 1      
    print("iter_num=",iter_num)
    return pagerank
    
    
if __name__ == '__main__':
    # 1.定义状态转移矩阵A
    transfer_array = init_transfer_array()
    # 2.定义初始概率矩阵V0
    v0 = init_first_pr(transfer_array.shape[0])
    # 3.计算最终的PageRank值
    # 方法一:特征向量
    PageRank0 = compute_pagerank0(transfer_array,v0)
    print("PageRank0:\n", PageRank0) 
    # 方法二:暴力迭代
    PageRank1 = compute_pagerank1(transfer_array,v0)
    print("PageRank1:\n", PageRank1)

 


终止点和陷阱问题

上述网页浏览者的行为是一个马尔科夫过程,但满足收敛性于 特征值分解实验:人脸识别与PageRank网页排序_工程应用_339,需要具备一个条件:

  • 图是强连通的,即从任意网页可以到达其他任意网页。

这就有俩个问题,会让马尔科夫过程的收敛于 特征值分解实验:人脸识别与PageRank网页排序_工程应用_339,而是 特征值分解实验:人脸识别与PageRank网页排序_特征向量_67

  • 【终止点问题】:有一些网页不指向任何网页,上网者就会永恒的停止在 特征值分解实验:人脸识别与PageRank网页排序_工程应用_356
    设置终止点:把 特征值分解实验:人脸识别与PageRank网页排序_工程应用_356特征值分解实验:人脸识别与PageRank网页排序_工程应用_49 的链接丢掉,特征值分解实验:人脸识别与PageRank网页排序_工程应用_356
    按照对应的转移矩阵:
  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_360

P.S. 第三列全为 特征值分解实验:人脸识别与PageRank网页排序_工程应用_361

不断迭代下去,最终所有元素都为 特征值分解实验:人脸识别与PageRank网页排序_工程应用_361

特征值分解实验:人脸识别与PageRank网页排序_特征向量_363

  • 【陷阱问题】:有些网页不指向别的网页,但指向自己,上网者就会陷入困境,再也不能从 特征值分解实验:人脸识别与PageRank网页排序_工程应用_356
    设置陷阱:把 特征值分解实验:人脸识别与PageRank网页排序_工程应用_356特征值分解实验:人脸识别与PageRank网页排序_工程应用_49 的链接丢掉,特征值分解实验:人脸识别与PageRank网页排序_工程应用_356
    按照对应的转移矩阵:
  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_360

不断迭代下去,最终只有 特征值分解实验:人脸识别与PageRank网页排序_特征值_369

特征值分解实验:人脸识别与PageRank网页排序_特征向量_370

那怎么解决终止点问题和陷阱问题呢?

其实这个过程忽略了一个问题 — 网页浏览者浏览的随意性

浏览者会随机地选择网页,而当遇到一个结束网页或者一个陷阱网页(比如两个示例中的 特征值分解实验:人脸识别与PageRank网页排序_特征向量_167)时,TA可能会在浏览器的地址中随机输入一个地址,当然这个地址可能又是原来的网页,但这有可能逃离这个陷阱。

根据现实网页浏览者的浏览行为,对算法进行改进。

假设每一步,网页浏览者离开当前网页跳转到各个网页的概率是 特征值分解实验:人脸识别与PageRank网页排序_特征向量_372,查看当前网页的概率为特征值分解实验:人脸识别与PageRank网页排序_特征向量_373,那么TA从浏览器地址栏跳转的概率为特征值分解实验:人脸识别与PageRank网页排序_特征向量_374,于是原来的迭代公式转化为:

  • 特征值分解实验:人脸识别与PageRank网页排序_工程应用_375

现在我们来计算带陷阱的网页图的概率分布:

  • 特征值分解实验:人脸识别与PageRank网页排序_特征值_376

不断迭代下去,得到:

特征值分解实验:人脸识别与PageRank网页排序_特征向量_377


这就是 PageRank网页排序算法,MapReduce上有 java 版的源码。


好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695