大家好,欢迎来到IT知识分享网。
本文主要介绍了以下几个方面的内容:简单介绍了经典的主成分分析方法,包括其数学推导,算法步骤,和几个实际算例;简单介绍了其它的数据降维方法,譬如局部线性嵌入以及它的简单算例;更近一步,我们介绍了函数型主成分分析方法(FPCA),包括其基本思想、数学推导、算法描述等,最为重要的是,我们将该方法和本领域进行结合,有了一些新的思考。
文章目录
前言
“维数灾难”带来的直接结果就是很多低维空间行之有效的算法在高维空间中变得不可计算,为此,我们需要进行降维。在另一个方面,数据偏平化的情况下,降维有助于我们抓住数据的主要结构,过滤可能的误差带来的影响,使模型更加真实。另外,在某些情况下,降维可用于可视化。数据降维的方法有很多,比如说基于”最小化投影误差”(最大化类内方法)的主成分分析方法(PCA),以及基于保持拓扑结构不变(高维空间中是邻居,到了地位空间中还是邻居)的局部线性嵌入(LLE)等方法。
在多元统计分析中,主成分分析(Principal Components Analysis,PCA)是一种统计分析、简化数据集的方法。它利用正交变换来对一系列可能相关的变量的观测值进行线性变换,从而投影为一系列线性不相关变量的值,这些不相关变量称为主成分(Principal Components)。具体地,主成分可以看做一个线性方程,其包含一系列线性系数来指示投影方向。PCA对原始数据的正则化或预处理敏感(相对缩放)。PCA本质上寻求的是数据点在低秩空间中的一个表示。
高维数据,意味着数据需要多于两个或三个维度来表示,一般很难被解释。一种简化的方法是假设数据嵌在高维空间的一个非线性流形上。如果这个流形维数足够低,那么数据可以在低维空间中被可视化。局部线性嵌入(Locally Linear Embedding,LLE)关注于降维时保持样本局部的线性特征,由于LLE在降维时保持了样本的局部特征,它广泛的用于图像图像识别,高维数据可视化等领域。
有了降维和主成分分析,我们做PDE的就会思考,既然可以对 R n \mathbb{R}^n Rn空间中的数据做降维,那么函数作为一组基函数的线性组合,如果将基函数看作一些坐标系中的一个个坐标轴,是否也可以对函数空间中的”数据”做降维呢?答案是肯定的。函数型(数据)主成分分析(Functional Principal Components analysis)可以视为是传统的主成分分析的一种推广。类比于PCA,它希望能将高维函数空间中的函数放到低维空间中去表示,而使得被表示的数据集损失最小。更通俗地说,就是希望用更少的基函数来表示某个已知基函数的函数空间的一堆函数,新空间的基函数用旧空间的基函数来线性表出。那么,我们就需要定义函数之间的距离,函数空间的內积等等。
主成分分析(PCA)
数据降维简介
PCA算法的原理解释
所谓的主成分分析,不过是在高维的空间中寻找一个低维的正交坐标系,比如说在三维空间中寻找一个二维的直角坐标系。那么这个二维的直角坐标系就会构成一个平面,将三维空间中的各个点在这个二维平面上做投影,就得到了各个点在二维空间中的一个表示,由此数据点就从三维降成了二维。
这个过程的关键在于,我们如何选取这个低维的坐标系,即坐标系原点在哪?各个轴朝哪个方向?一个原则就是使得各个点到到这个平面的距离平方和达到最小。由此,通过简单地数学推导,就能得到原点的表达公式和坐标系的各个基向量的表达公式。
PCA算法的数学推导
我们假设输入为p维的N个对象, X X X表示如下图所示的一个矩阵:
通过PCA降维,将其降为d维的N个对象,假设为 Y Y Y,同前,每列表示一个对象,每行表示一个特征:
我们要将所有点投影到新的坐标系中去,无非是寻找新坐标系的坐标原点和各个坐标轴。
我们假设 W W W的每一列为新的坐标系中单位正交的坐标轴表示, x 0 x_0 x0为新坐标系的原点(相对于原坐标系)。
那么,我们要做的就是找到一个合适的 W W W和 x 0 x_0 x0,使其极小化所有点到新的坐标平面的距离平方和。
容易知道,每一个点到新坐标系的距离平方为(其中 X ‾ = ( x 0 , W ) \underline X = (x_0,W) X=(x0,W)表示的是位置参数):
Ds X ( x , X ‾ ) = ( x − x 0 − ∑ i = 1 d w i T ( x − x 0 ) w i ) T ( x − x 0 − ∑ i = 1 d w i T ( x − x 0 ) w i ) \operatorname{Ds}_{X}(x, \underline{X})=\left(x-x_{0}-\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}\right)^{T}\left(x-x_{0}-\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}\right) DsX(x,X)=(x−x0−i=1∑dwiT(x−x0)wi)T(x−x0−i=1∑dwiT(x−x0)wi)
对其进行化简,可得:
D s X ( x , X ‾ ) = ( x − x 0 − ∑ i = 1 d w i T ( x − x 0 ) w i ) T ( x − x 0 − ∑ i = 1 d w i T ( x − x 0 ) w i ) = ( x − x 0 ) T ( x − x 0 ) − ( ∑ i = 1 d w i T ( x − x 0 ) w i ) T ( x − x 0 ) − ( x − x 0 ) T ∑ i = 1 d w i T ( x − x 0 ) w i + ( ∑ i = 1 d w i T ( x − x 0 ) w i ) T ∑ i = 1 d w i T ( x − x 0 ) w i \begin{array}{l}{D s_{X}(x, \underline{X})=\left(x-x_{0}-\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}\right)^{T}\left(x-x_{0}-\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}\right)} \\ {=\left(x-x_{0}\right)^{T}\left(x-x_{0}\right)-\left(\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}\right)^{T}\left(x-x_{0}\right)} \\ {-\left(x-x_{0}\right)^{T} \sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}+\left(\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}\right)^{T} \sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right) w_{i}}\end{array} DsX(x,X)=(x−x0−∑i=1dwiT(x−x0)wi)T(x−x0−∑i=1dwiT(x−x0)wi)=(x−x0)T(x−x0)−(∑i=1dwiT(x−x0)wi)T(x−x0)−(x−x0)T∑i=1dwiT(x−x0)wi+(∑i=1dwiT(x−x0)wi)T∑i=1dwiT(x−x0)wi
进而有,
Ds X ( x , X ‾ ) = ( x − x 0 ) T ( x − x 0 ) − ∑ i = 1 d w i T ( x − x 0 ) ( x − x 0 ) T w i \operatorname{Ds}_{X}(x, \underline{X})=\left(x-x_{0}\right)^{T}\left(x-x_{0}\right)-\sum_{i=1}^{d} w_{i}^{T}\left(x-x_{0}\right)\left(x-x_{0}\right)^{T} w_{i} DsX(x,X)=(x−x0)T(x−x0)−i=1∑dwiT(x−x0)(x−x0)Twi
让所有点到投影点距离平方和最小,即求解约束优化问题:
min X ‾ ∑ k D s X ( x k , X ‾ ) = ∑ k ( x k − x 0 ) T ( x k − x 0 ) − ∑ i = 1 d w i T ∑ k ( x k − x 0 ) ( x k − x 0 ) T w i w i T w j = δ i j δ i j = 1 , i = j δ i j = 0 , i ≠ j \begin{array}{l}{\min _{\underline{X}} \sum_{k} D s_{X}\left(x_{k}, \underline{X}\right)=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)} \\ {-\sum_{i=1}^{d} w_{i}^{T} \sum_{k}\left(x_{k}-x_{0}\right)\left(x_{k}-x_{0}\right)^{T} w_{i}} \\ {w_{i}^{T} w_{j}=\delta_{i j} \quad \delta_{i j}=1, \quad i=j} \\ {\delta_{i j}=0, \quad i \neq j}\end{array} minX∑kDsX(xk,X)=∑k(xk−x0)T(xk−x0)−∑i=1dwiT∑k(xk−x0)(xk−x0)TwiwiTwj=δijδij=1,i=jδij=0,i=j
我们借助拉格朗日乘子法来求解此约束优化问题:
L = ∑ k ( x k − x 0 ) T ( x k − x 0 ) − ∑ i = 1 d w i T ∑ k ( x k − x 0 ) ( x k − x 0 ) T w i − ∑ i = 1 d λ i ( w i T w i − 1 ) L=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)-\sum_{i=1}^{d} w_{i}^{T} \sum_{k}\left(x_{k}-x_{0}\right)\left(x_{k}-x_{0}\right)^{T} w_{i}-\sum_{i=1}^{d} \lambda_{i}\left(w_{i}^{T} w_{i}-1\right) L=k∑(xk−x0)T(xk−x0)−i=1∑dwiTk∑(xk−x0)(xk−x0)Twi−i=1∑dλi(wiTwi−1)
∂ L ∂ x 0 = − 2 ( I p − ∑ i = 1 d w i w i T ) ∑ k ( x k − x 0 ) ∂ L ∂ w i = 2 ∑ k ( x k − x 0 ) ( x k − x 0 ) T w i − 2 λ i w i \begin{array}{l}{\frac{\partial L}{\partial x_{0}}=-2\left(I_{p}-\sum_{i=1}^{d} w_{i} w_{i}^{T}\right) \sum_{k}\left(x_{k}-x_{0}\right)} \\ {\frac{\partial L}{\partial w_{i}}=2 \sum_{k}\left(x_{k}-x_{0}\right)\left(x_{k}-x_{0}\right)^{T} w_{i}-2 \lambda_{i} w_{i}}\end{array} ∂x0∂L=−2(Ip−∑i=1dwiwiT)∑k(xk−x0)∂wi∂L=2∑k(xk−x0)(xk−x0)Twi−2λiwi
由两个偏导为0,可以得到:
x 0 = ∑ k x k N ∑ k ( x k − x 0 ) ( x k − x 0 ) T w i = λ i w i \begin{array}{l}{x_{0}=\sum_{k} \frac{x_{k}}{N}} \\ {\sum_{k}\left(x_{k}-x_{0}\right)\left(x_{k}-x_{0}\right)^{T} w_{i}=\lambda_{i} w_{i}}\end{array} x0=∑kNxk∑k(xk−x0)(xk−x0)Twi=λiwi
因为半正定矩阵的特征值非负,所以,原最小化损失函数可进行转化:
min X ‾ ∑ k D s X ( x k , X ‾ ) = ∑ k ( x k − x 0 ) T ( x k − x 0 ) − ∑ i = 1 d w i T ∑ k ( x k − x 0 ) ( x k − x 0 ) T w i = ∑ k ( x k − x 0 ) T ( x k − x 0 ) − ∑ i = 1 d λ i w i T w i = ∑ k ( x k − x 0 ) T ( x k − x 0 ) − ∑ i = 1 d λ i \begin{array}{l}{\min _{\underline{X}} \sum_{k} D s_{X}\left(x_{k}, \underline{X}\right)} \\ {=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)-\sum_{i=1}^{d} w_{i}^{T} \sum_{k}\left(x_{k}-x_{0}\right)\left(x_{k}-x_{0}\right)^{T} w_{i}} \\ {=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)-\sum_{i=1}^{d} \lambda_{i} w_{i}^{T} w_{i}} \\ {=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)-\sum_{i=1}^{d} \lambda_{i}}\end{array} minX∑kDsX(xk,X)=∑k(xk−x0)T(xk−x0)−∑i=1dwiT∑k(xk−x0)(xk−x0)Twi=∑k(xk−x0)T(xk−x0)−∑i=1dλiwiTwi=∑k(xk−x0)T(xk−x0)−∑i=1dλi
我们利用矩阵的性质,要想最小化距离平方和,有:
min X ‾ ∑ k Ds X ( x k , X ‾ ) = ∑ k ( x k − x 0 ) T ( x k − x 0 ) − ∑ i = 1 d λ i \min _{\underline{X}} \sum_{k} \operatorname{Ds}_{X}\left(x_{k}, \underline{X}\right)=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)-\sum_{i=1}^{d} \lambda_{i} Xmink∑DsX(xk,X)=k∑(xk−x0)T(xk−x0)−i=1∑dλi
令 Σ X = ∑ k ( x k − x 0 ) ( x k − x 0 ) T \Sigma_{X}=\sum_{k}\left(x_{k}-x_{0}\right)\left(x_{k}-x_{0}\right)^{T} ΣX=∑k(xk−x0)(xk−x0)T为 p × p p\times p p×p的矩阵。有性质:
tr ( Σ X ) = ∑ k ( x k − x 0 ) T ( x k − x 0 ) = ∑ i = 1 p λ i \operatorname{tr}\left(\Sigma_{X}\right)=\sum_{k}\left(x_{k}-x_{0}\right)^{T}\left(x_{k}-x_{0}\right)=\sum_{i=1}^{p} \lambda_{i} tr(ΣX)=k∑(xk−x0)T(xk−x0)=i=1∑pλi
则有,
min X ‾ ∑ k Ds X ( x k , X ‾ ) = ∑ i = 1 p λ i − ∑ i = 1 d λ i = ∑ i = d + 1 p λ i \min _{\underline{X}} \sum_{k} \operatorname{Ds}_{X}\left(x_{k}, \underline{X}\right)=\sum_{i=1}^{p} \lambda_{i}-\sum_{i=1}^{d} \lambda_{i}=\sum_{i=d+1}^{p} \lambda_{i} Xmink∑DsX(xk,X)=i=1∑pλi−i=1∑dλi=i=d+1∑pλi
由此我们可以看到,要得到极小值,我们只要计算 X X T XX^T XXT矩阵的前d个最大特征值,是投影后样本具有最小损失的特点。那么此时的 W W W就是 X X T XX^T XXT矩阵前d个最大特征值对应的特征向量。
不难知道,对于 X X T XX^T XXT的特征分解: X X T = U Λ U T XX^T = U\Lambda U^T XXT=UΛUT
这里的U就是前天提到的奇异值分解的U。同理,虽然我们这里没有用到 V V V,但其实奇异值分解的 V V V正式 X T X X^TX XTX的特征值分解的特征矩阵。
为了比较 X X T XX^T XXT特征分解和 X X X进行奇异值分解的消耗,写了一段小程序,并使用matlab探查功能进行比较如下:
这个比较事实上没有太大的意义。所用的代码如附录。
PCA算法简单描述
假设 X X X是一个m*n矩阵,表示n个对象的m个特征表示数据,即每一列表示一个对象,每一行表示一个特征。我们希望将特征降为d维,d远小于m。输出结果为 Y Y Y,一个d*n的矩阵。
- 记 X = [ x 1 , x 2 . . . x n ] X=[x_1,x_2…x_n] X=[x1,x2...xn],计算每个对象点的平均值 x 0 = 1 n ∑ i = 1 n x i x_0 = \frac{1}{n}\sum\limits _{i=1}^nx_i x0=n1i=1∑nxi。
- 对 X − x 0 : = [ x 1 − x 0 , x 2 − x 0 . . . x n − x 0 ] X-x_0 : = [x_1-x_0,x_2-x_0…x_n-x_0] X−x0:=[x1−x0,x2−x0...xn−x0]做奇异值分解: X − x 0 = U Λ V T X-x_0 = U\Lambda V^T X−x0=UΛVT。
- 则 x 0 x_0 x0即为新坐标系的原点, U U U的前d列即为去中心化后的新的坐标系,不妨记为 W W W。那么,所有点在新坐标系下的表示为: Y = W T ∗ ( X − x 0 ) Y=W^T*(X-x_0) Y=WT∗(X−x0)。同样地,要将新的投影点 y y y还原到原坐标系中,可以写为: x 0 + W ∗ y x_0+W*y x0+W∗y。
下面以基于矩阵的视角写出PCA算法的算法流程,输入为矩阵p*N矩阵X,输出为d*N矩阵Y。矩阵的每一列都表示一个对象,每一行都表示对象的一个特征表示。
PCA算例一
假设小明和小红有身高和体重两个特征(实际操作数据要进行预处理,这里不做),如下表:
那么此时 X = [ 178 165 ; 70 65 ] X = [178 ~165; 70 ~65] X=[178 165;70 65],现在试图通过PCA降维,将身高和体重合并为一个特征。走一遍上面的过程,可得:
X − x 0 = U Λ V T X-x_0 = U\Lambda V^T X−x0=UΛVT
其中,
那么,有
那就是说,最后数据可降维为:
这个问题MATLAB计算的小程序在附录。
PCA算例二
其他数据降维方法
其他的数据降维方法还有很多,比如说线性判别分析,拉普拉斯特征映射等等,我这里就简单介绍一下局部线性嵌入。
当数据具备某些非线性结构,如流形结构时,我们希望降维后的数据仍然保持这些结构。那么就提出了LLE降维算法。LLE(Locally linear embedding):在数据降维后仍然保留原始高维数据的拓扑结构,这种拓扑结构表现为数据点的局部邻接关系。
选取了409×698的图像数据集进行了测试,选取降维后维数为2,选取最近邻个数 k = 12 k=12 k=12,实验后的部分结果如下:
我们使用别人制作的降维工具箱”drtoolbox”重新进行计算并和我的程序结果进行比较。工具箱的使用代码见附录。
函数型数据主成分分析
Idea的萌生
前一段时间我在做一个流体力学上的东西(虽然现在已经不做这个方向了),其中比较关键的步骤就是需要用一个带时间变量的多项式公式,来刻画一个物理过程。这个多项式的各个项前面的系数是未知的,由物理规律来决定。我们希望从一些物理实验数据中来通过一些机器学习的手段来学到多项式各个项前面的系数。
这个问题本质的困难在于,我们不知道那些函数项(基函数)是我们需要的。事实上,只要知道了多项式包含哪些项,是可以通过一些物理原理求得前面的系数的。一个基本的想法就是选足够多的基函数,使得函数空间足够大而包含真值。但是,函数空间太大会带来使用物理原理求系数时的计算困难增大。所以,我们希望能找一个原来大的函数空间的一个子空间,使得用这个子空间,就能够基本刻画原来的物理过程。再用物理原理来求得以子空间基函数为各个项的多项式系数。
仔细一想,这不正是函数空间的PCA吗?如果把每一个函数看做一个数据点,把各个基函数看做是组成坐标系的坐标轴,那么”函数点”在高维函数空间中的表示,就可以通过类似于主成分分析的技巧,变成在低维函数空间中的表示。只要有了能表示刻画整个物理过程的各个数据点的低维空间,那么刻画物理过程的多项式的项(即低维空间的基函数)也就明确了,剩下的事情也就自然而然了。
FPCA简介和理论推导
函数型主成分分析(FPCA,Functional Principal Components Analysis)是传统的PCA的一种推广。考虑我们已经从数据中得到拟合曲线 x i ( s ) , s ∈ T , i = 1 , ⋯ , n x_{i}(s), s \in \mathcal{T}, i=1, \cdots, n xi(s),s∈T,i=1,⋯,n,所谓的第一主成分,就是我们希望能找到一个模为1的函数 β ( s ) \beta(s) β(s),使得 { x i } \{x_i\} {
xi}在 β \beta β上的投影( L 2 L_2 L2內积) { ξ i } \{\xi _i\} {
ξi}的方差达到最大,方差最大其实也就体现 { x i } \{x_i\} {
xi}整体到 β \beta β的距离达到最小。 β \beta β一般就叫做权重函数(可以理解为”坐标轴”单位长度量)。
我们管各个函数到 β \beta β上的投影叫做观测曲线的主成分得分:
ξ i = ∫ T β ( s ) x i ( s ) d s , i = 1 , ⋯ , n \xi_{i}=\int_{\mathcal{T}} \beta(s) x_{i}(s) d s, \quad i=1, \cdots, n ξi=∫Tβ(s)xi(s)ds,i=1,⋯,n故而,求解第一个主成分就变成了求解一个优化问题:
max 1 n ∑ i = 1 n ξ i 2 = max 1 n ∑ i = 1 n ( ∫ T β ( s ) x i ( s ) d s ) 2 s.t. ∥ β ∥ 2 = ∫ T β ( s ) β ( s ) d s = 1 \begin{aligned} \max \frac{1}{n} \sum_{i=1}^{n} \xi_{i}^{2} &=\max \frac{1}{n} \sum_{i=1}^{n}\left(\int_{\mathcal{T}} \beta(s) x_{i}(s) d s\right)^{2} \\ \text { s.t. } &\|\beta\|^{2}=\int_{T} \beta(s) \beta(s) d s=1 \end{aligned} maxn1i=1∑nξi2 s.t. =maxn1i=1∑n(∫Tβ(s)xi(s)ds)2∥β∥2=∫Tβ(s)β(s)ds=1求解这个优化问题,我们就得到了第一主成分 β 1 ( s ) \beta^1(s) β1(s)。
第 k k k主成分无非就是在满足和前面 k − 1 k-1 k−1个主成分权重函数垂直的基础上,求解上述优化问题而已,即求解
max 1 n ∑ i = 1 n ξ i 2 = max 1 n ∑ i = 1 n ( ∫ T β ( s ) x i ( s ) d s ) 2 s.t. ∥ β ∥ 2 = ∫ T β ( s ) β ( s ) d s = 1 ∫ T β ( s ) β l ( s ) d s = 0 , l = 1 , ⋯ , k − 1 \begin{array}{l}{\max \frac{1}{n} \sum_{i=1}^{n} \xi_{i}^{2}=\max \frac{1}{n} \sum_{i=1}^{n}\left(\int_{\mathcal{T}} \beta(s) x_{i}(s) d s\right)^{2}} \\ {\text { s.t. }\|\beta\|^{2}=\int_{T} \beta(s) \beta(s) d s=1} \\ {\int_{T} \beta(s) \beta^{l}(s) d s=0, l=1, \cdots, k-1}\end{array} maxn1∑i=1nξi2=maxn1∑i=1n(∫Tβ(s)xi(s)ds)2 s.t. ∥β∥2=∫Tβ(s)β(s)ds=1∫Tβ(s)βl(s)ds=0,l=1,⋯,k−1
这个优化问题的解可以表述如下。记协方差函数:
v ( s , t ) = 1 n − 1 ∑ i = 1 n ( x i ( s ) − x ‾ ( s ) ) ( x i ( t ) − x ‾ ( t ) ) v(s, t)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{i}(s)-\overline{x}(s)\right)\left(x_{i}(t)-\overline{x}(t)\right) v(s,t)=n−11i=1∑n(xi(s)−x(s))(xi(t)−x(t))
那么权重函数满足特征方程:
∫ T v ( s , t ) β ( t ) d t = λ β ( s ) \int_{\mathcal{T}} v(s, t) \beta(t) d t=\lambda \beta(s) ∫Tv(s,t)β(t)dt=λβ(s)
定义积分变换: V β ( s ) = ∫ T v ( s , t ) β ( t ) d t V \beta(s)=\int_{\mathcal{T}} v(s, t) \beta(t) d t Vβ(s)=∫Tv(s,t)β(t)dt
这里的 V V V称为协方差算子,它将函数 β \beta β变成一个函数。那么,我们有:
V β ( s ) = λ β ( s ) V \beta(s)=\lambda \beta(s) Vβ(s)=λβ(s)
我们也类比PCA,使用特征值的累积贡献率来衡量主成分所占比例:
F V E = ∑ i = 1 K λ i / ∑ i = 1 n − 1 λ i \mathrm{FVE}=\sum_{i=1}^{K} \lambda_{i} / \sum_{i=1}^{n-1} \lambda_{i} FVE=i=1∑Kλi/i=1∑n−1λi这里之所以对 λ \lambda λ只累计到 n n n是因为协方差算子 V V V的秩为样本数量减一个,则非零特征根的个数最多为 n − 1 n-1 n−1个。
由上述已知,我们求解主成分最后归结为求解一个特征值问题。
求解这个问题,目前比较流行的有三种方法:
- 对函数进行SVD离散化
- 对函数进行基函数展开
- 运用一般性的数值积分方法
FPCA和PCA的区别和联系
如上所述,可以看出,如果所选的基函数是正交的,本质上和PCA的以拟合系数为坐标点的函数空间PCA推广是实际上是一样的。若基函数不是正交的,无非就是在此基础上对要求特征值的矩阵得多乘一个 W = ∫ Φ Φ ′ W=\int \Phi \Phi^{\prime} W=∫ΦΦ′,再求特征向量,以及进行 W W W意义下对特征向量进行单位化而已(不单位化也没事,只不过权重函数 β \beta β不再是模长为1的而已, W W W意义下的单位话也就意味着让新的基函数模长为1)。这个也非常容易理解,因为在从函数的元(primal)表示左乘一个质量矩阵就到了到它的对偶(dual)表示,而在基函数不正交的情况下,我们应该在对偶空间中再进行它的主成分分析降维,即各个函数的向量表示应该为这个函数和各个基函数的內积。同理,在对偶框架下得到的新的基函数的向量表示也是在对偶空间下的,应该左乘一个质量矩阵才能回到元空间中去。
基于FPCA的模型约化
Onsager原理简介
简单例子:斜板液滴滑动
问题描述
原理的应用
我们希望能通过上面提到的Onsager原理来确定这里的系数 a i a_i ai。
固定时刻的液滴体积:
Ω = ∫ a 1 a 2 d x ∫ − Y Y d y h ( x , y , t ) \Omega=\int_{a_{1}}^{a_{2}} d x \int_{-Y}^{Y} d y h(x, y, t) Ω=∫a1a2dx∫−YYdyh(x,y,t)
因为体积是守恒量,所以问题的自由度个数就变成了5。 势能函数定义为:
A ( a ) = ∫ a 1 a 2 d x ∫ − Y Y d y [ 1 2 γ θ e 2 + 1 2 γ [ ( ∂ x h ) 2 + ( ∂ y h ) 2 ] + 1 2 ρ g h 2 sin α − ρ g x h cos α ] \begin{aligned} A(a)=& \int_{a_{1}}^{a_{2}} d x \int_{-Y}^{Y} d y\left[\frac{1}{2} \gamma \theta_{e}^{2}+\frac{1}{2} \gamma\left[\left(\partial_{x} h\right)^{2}+\left(\partial_{y} h\right)^{2}\right]\right.\\ &+\frac{1}{2} \rho g h^{2} \sin \alpha-\rho g x h \cos \alpha ] \end{aligned} A(a)=∫a1a2dx∫−YYdy[21γθe2+21γ[(∂xh)2+(∂yh)2]+21ρgh2sinα−ρgxhcosα]
这里的 γ \gamma γ表示液滴的表面张力, ρ \rho ρ表示密度, θ e \theta_e θe是平衡态下的接触角大小, g g g是重力加速度, α \alpha α是前面提到的斜面角。我也不知道势能函数为什么能写成这样,需要一些物理的分析。
可以把 h h h的表达式代入到这个势能函数的表达式中。我们还需要知道能量耗散函数 Φ \Phi Φ。由滑润近似,能量耗散函数可以写成关于速度的变量:
Φ [ v x , v y ] = 1 2 ∫ a 1 a 2 d x ∫ − Y Y d y 3 η h ( v x 2 + v y 2 ) \Phi\left[v_{x}, v_{y}\right]=\frac{1}{2} \int_{a_{1}}^{a_{2}} d x \int_{-Y}^{Y} d y \frac{3 \eta}{h}\left(v_{x}^{2}+v_{y}^{2}\right) Φ[vx,vy]=21∫a1a2dx∫−YYdyh3η(vx2+vy2)
这里的 v x , v y v_x,v_y vx,vy表示两个方向上的速度, η \eta η表示流体的粘性。但是我们想要的耗散函数是关于 a ˙ \dot a a˙
的,所以要想办法替换掉速度。 由体积守恒,我们有:
h ˙ = − ∂ x ( v x h ) − ∂ y ( v y h ) \dot{h}=-\partial_{x}\left(v_{x} h\right)-\partial_{y}\left(v_{y} h\right) h˙=−∂x(vxh)−∂y(vyh)
将 h h h的表达式代入上式,可得:
( 1 − y 2 Y 2 ) ( H ˙ + ∂ x ( v x H ) + H ∂ y v y ) + 2 H y Y 3 ( y Y ˙ + y v x ∂ x Y − Y v y ) = 0 \begin{array}{c}{\left(1-\frac{y^{2}}{Y^{2}}\right)\left(\dot{H}+\partial_{x}\left(v_{x} H\right)+H \partial_{y} v_{y}\right)} \\ {+\frac{2 H y}{Y^{3}}\left(y \dot{Y}+y v_{x} \partial_{x} Y-Y v_{y}\right)=0}\end{array} (1−Y2y2)(H˙+∂x(vxH)+H∂yvy)+Y32Hy(yY˙+yvx∂xY−Yvy)=0
这个约束满足的一个充分条件是:
H ˙ + ∂ x ( v x H ) + H ∂ y v y = 0 y Y ˙ + y v x ∂ x Y − Y v y = 0 \begin{array}{l}{\dot{H}+\partial_{x}\left(v_{x} H\right)+H \partial_{y} v_{y}=0} \\ {y \dot{Y}+y v_{x} \partial_{x} Y-Y v_{y}=0}\end{array} H˙+∂x(vxH)+H∂yvy=0yY˙+yvx∂xY−Yvy=0
一个如下所示的速度场能够满足这样的条件:
v x ( x , y , t ) = V ( x , t ) , v y ( x , y , t ) = W ( x , t ) y v_{x}(x, y, t)=V(x, t), \quad v_{y}(x, y, t)=W(x, t) y vx(x,y,t)=V(x,t),vy(x,y,t)=W(x,t)y
其中, V , W V,W V,W的表达为:
V ( x , t ) = − 1 H Y ∫ a 1 x ( H ˙ Y + H Y ˙ ) d x W = 1 Y ( Y ˙ + V ∂ x Y ) \begin{aligned} V(x, t) &=-\frac{1}{H Y} \int_{a_{1}}^{x}(\dot{H} Y+H \dot{Y}) d x \\ W &=\frac{1}{Y}\left(\dot{Y}+V \partial_{x} Y\right) \end{aligned} V(x,t)W=−HY1∫a1x(H˙Y+HY˙)dx=Y1(Y˙+V∂xY)
那么,我们得到的能量耗散函数其实是:
Φ [ a ˙ , a ] = 1 2 ∫ a 1 a 2 d x ∫ − Y Y d y 3 η h ( V 2 + y 2 W 2 ) \Phi\left[\dot a, a\right]=\frac{1}{2} \int_{a_{1}}^{a_{2}} d x \int_{-Y}^{Y} d y \frac{3 \eta}{h}\left(V^{2}+{y}^{2}W^2\right) Φ[a˙,a]=21∫a1a2dx∫−YYdyh3η(V2+y2W2)
我们把 a a a看成常量,由于 H ˙ , Y ˙ \dot H,\dot Y H˙,Y˙是 a ˙ \dot a a˙的线性组合,意味着 V , W V,W V,W也是,那么 Φ \Phi Φ就是 a ˙ \dot a a˙的二次函数,不妨记为:
Φ ( a ˙ ) = 1 2 ∑ i , j ζ i j a ˙ i a ˙ j \Phi(\dot{a})=\frac{1}{2} \sum_{i, j} \zeta_{i j} \dot{a}_{i} \dot{a}_{j} Φ(a˙)=21i,j∑ζija˙ia˙j
这里的 ξ i j \xi_{ij} ξij是 a a a的函数。
这下有了势能函数和能量耗散函数,我们可以得到关于 a i a_i ai的发展方程为:
∑ j = 1 6 ζ i j a ˙ j + ∂ A ∂ a i = 0 \sum_{j=1}^{6} \zeta_{i j} \dot{a}_{j}+\frac{\partial A}{\partial a_{i}}=0 j=1∑6ζija˙j+∂ai∂A=0
求解之,可得 a a a。
算法步骤
总结一下上述的计算过程,就是:
- 能量耗散函数:
Φ [ a ˙ , a ] = 1 2 ∫ a 1 a 2 d x ∫ − Y Y d y 3 η h ( V 2 + y 2 W 2 ) \Phi\left[\dot a, a\right]=\frac{1}{2} \int_{a_{1}}^{a_{2}} d x \int_{-Y}^{Y} d y \frac{3 \eta}{h}\left(V^{2}+{y}^{2}W^2\right) Φ[a˙,a]=21∫a1a2dx∫−YYdyh3η(V2+y2W2)
其中,
V ( x , t ) = − 1 H Y ∫ a 1 x ( H ˙ Y + H Y ˙ ) d x W = 1 Y ( Y ˙ + V ∂ x Y ) \begin{aligned} V(x, t) &=-\frac{1}{H Y} \int_{a_{1}}^{x}(\dot{H} Y+H \dot{Y}) d x \\ W &=\frac{1}{Y}\left(\dot{Y}+V \partial_{x} Y\right) \end{aligned} V(x,t)W=−HY1∫a1x(H˙Y+HY˙)dx=Y1(Y˙+V∂xY)
h ( x , y , t ) = H ( x , t ) [ 1 − ( y Y ( x , t ) ) 2 ] h(x, y, t)=H(x, t)\left[1-\left(\frac{y}{Y(x, t)}\right)^{2}\right] h(x,y,t)=H(x,t)[1−(Y(x,t)y)2]
H ( x , t ) = ( x − a 1 ( t ) ) ( a 2 ( t ) − x ) ( a 3 ( t ) + a 4 ( t ) x ) Y ( x , t ) = ( x − a 1 ( t ) ) 1 2 ( a 2 ( t ) − x ) 1 2 ( a 5 ( t ) + a 6 ( t ) x ) \begin{array}{c}{H(x, t)=\left(x-a_{1}(t)\right)\left(a_{2}(t)-x\right)\left(a_{3}(t)+a_{4}(t) x\right)} \\ {Y(x, t)=\left(x-a_{1}(t)\right)^{\frac{1}{2}}\left(a_{2}(t)-x\right)^{\frac{1}{2}}\left(a_{5}(t)+a_{6}(t) x\right)}\end{array} H(x,t)=(x−a1(t))(a2(t)−x)(a3(t)+a4(t)x)Y(x,t)=(x−a1(t))21(a2(t)−x)21(a5(t)+a6(t)x) - 由此,我们计算出 Φ ( a ˙ ) \Phi(\dot a) Φ(a˙)表达式,并提取前面的线性组合的系数:
Φ ( a ˙ ) = 1 2 ∑ i , j ζ i j a ˙ i a ˙ j \Phi(\dot{a})=\frac{1}{2} \sum_{i, j} \zeta_{i j} \dot{a}_{i} \dot{a}_{j} Φ(a˙)=21i,j∑ζija˙ia˙j - 势能函数:
A ( a ) = ∫ a 1 a 2 d x ∫ − Y Y d y [ 1 2 γ θ e 2 + 1 2 γ [ ( ∂ x h ) 2 + ( ∂ y h ) 2 ] + 1 2 ρ g h 2 sin α − ρ g x h cos α ] \begin{aligned} A(a)=& \int_{a_{1}}^{a_{2}} d x \int_{-Y}^{Y} d y\left[\frac{1}{2} \gamma \theta_{e}^{2}+\frac{1}{2} \gamma\left[\left(\partial_{x} h\right)^{2}+\left(\partial_{y} h\right)^{2}\right]\right.\\ &+\frac{1}{2} \rho g h^{2} \sin \alpha-\rho g x h \cos \alpha ] \end{aligned} A(a)=∫a1a2dx∫−YYdy[21γθe2+21γ[(∂xh)2+(∂yh)2]+21ρgh2sinα−ρgxhcosα] - 求解ODE方程组(数值解),得出 a a a。
∑ j = 1 6 ζ i j a ˙ j + ∂ A ∂ a i = 0 \sum_{j=1}^{6} \zeta_{i j} \dot{a}_{j}+\frac{\partial A}{\partial a_{i}}=0 j=1∑6ζija˙j+∂ai∂A=0
数值实验
FPCA在液滴下滑问题的应用
这只是我的一个想法,目前有很多问题都没有明确。由于时间关系,我这里也不会展开细述这一部分内容。基本的做法可以分成以下几个步骤:
- 收集数据:除了网络上搜到的三个物理实验视频和论文中的一些截图之外,我没有找到更多的数据,数据严重不足。和文章作者联系,也未要到数据。
- 图像处理:对收集到的视频,按帧提取图像,对每个图像进行去噪,二值化,归一化,提取边缘的坐标位置。
- FPCA降维:对于提取到的数据,选用适当的基函数,做小二乘意义下的拟合,得到拟合系数。这一组组拟合系数,就是我们做FPCA降维的数据。做FPCA,得到子函数空间。
- Onsager原理确定系数:在子函数空间中,使用Onsager基本原理,得到液滴下滑物理过程的表达式系数。
数据不够怎么办?有两个基本的想法。一个是利用同一组参数(如斜板角度)下不同时刻的数据(一个视频),来降维生成这组参数下的随时间变化的物理过程表达过程。另一个是查找更多的数据,哪怕利用上别人文章中的图片,堆砌所有的数据,寻求刻画这个物理过程的”真”表达,找到物理上的”真”规律。
参考文献
[5] 胡宇. 函数型数据分析方法研究及其应用[D]. 东北师范大学, 2011.
[6] 陈宜治. 函数型数据分析若干方法及应用[D]. 浙江工商大学, 2011.
[7] 沈关友. 基于函数型数据主成分分析的银行股票数据预测[D].
[5] 胡宇. 函数型数据分析方法研究及其应用[D]. 东北师范大学, 2011.
[6] 陈宜治. 函数型数据分析若干方法及应用[D]. 浙江工商大学, 2011.
[7] 沈关友. 基于函数型数据主成分分析的银行股票数据预测[D].
附录
{a} clc clear p = 10000; N = 10; d = 10; AR = randn(p,N); x0 = mean(AR,2); % 计算样本均值 AR_shift = AR - repmat(x0,1,N); % 中心平移每个训练样本 Sigma = AR_shift*AR_shift'; [W,D] = eigs(Sigma,d); % 前d个特征向量作为wi Lambda = diag(D); % 提取特征值 %% [U,S,V] = svd(AR_shift); {b} \begin{lstlisting}%[language=MATLAB,frame=shadowbox] clc clear X = [178 165; 70 65]; x0 = sum(X,2)/2; X_x0 = X - [x0 x0]; [U,S,V] = svd(X_x0); W = U(:,1); Y = W'*(X_x0); rebuild_X = [x0 x0]+W*Y; {c} \begin{lstlisting}%[language=MATLAB,frame=shadowbox] %% %编写程序,实现PCA算法 %对图像进行降维实验,并显示降维重建后的图像 %运行已有程序,和自己的对比 %实验报告(伪代码(或流程图)、源代码、实验结果及分析) %% %编写程序,实现PCA和LEE算法 %对图像进行降维实验,并显示降维重建后的图像 %运行已有程序,和自己的对比 %实验报告(伪代码(或流程图)、源代码、实验结果及分析) clc clear addpath(genpath(pwd));%将子孙文件添加到工作目录 load AR %导入数据 d = 20; %% AR = double(AR);%双进度化 [p ,N] = size(AR);%特征维度和对象数目 % for i = 1:N % image = AR(:,i); % image = reshape(image,50,40); % imshow(mat2gray(image));%对原矩阵归一化 % end x0 = mean(AR,2);%计算样本均值 AR_shift = AR - repmat(x0,1,N);%中心平移每个训练样本 %计算协方差矩阵的(n-1)倍,不用内置函数cov,提高代码的重用率和运行速度 Sigma = AR_shift*AR_shift'; %Sigma = cov(AR')*(N-1); [W,D] = eigs(Sigma,d);%前d个特征向量作为wi Lambda = diag(D);%提取特征值 %% close all; k = 1; Y = W'*AR_shift(:,k);%第k个图像的输出表示 X_rebuid = W*Y + x0;%第k个图像的重建还原 image = AR(:,k); image = reshape(image,50,40); imshow(mat2gray(image));%对原矩阵归一化 figure; image_re = X_rebuid; image_re = reshape(image_re,50,40); imshow(mat2gray(image_re));%对原矩阵归一化 {d} \begin{lstlisting}[language=Matlab,frame=shadowbox] %% %编写程序,实现PCA和LLE算法 %对图像进行降维实验,并显示降维重建后的图像 %运行已有程序,和自己的对比 %实验报告(伪代码(或流程图)、源代码、实验结果及分析) %% %编写程序,实现PCA和LEE算法 %对图像进行降维实验,并显示降维重建后的图像 %运行已有程序,和自己的对比 %实验报告(伪代码(或流程图)、源代码、实验结果及分析) clc clear addpath(genpath(pwd));%将子孙文件添加到工作目录 load AR %导入数据 d = 20; %% AR = double(AR);%双进度化 [p ,N] = size(AR);%特征维度和对象数目 % for i = 1:N % image = AR(:,i); % image = reshape(image,50,40); % imshow(mat2gray(image));%对原矩阵归一化 % end x0 = mean(AR,2);%计算样本均值 AR_shift = AR - repmat(x0,1,N);%中心平移每个训练样本 %计算协方差矩阵的(n-1)倍,不用内置函数cov,提高代码的重用率和运行速度 Sigma = AR_shift*AR_shift'; %Sigma = cov(AR')*(N-1); [W,D] = eigs(Sigma,d);%前d个特征向量作为wi Lambda = diag(D);%提取特征值 %% close all; k = 1; Y = W'*AR_shift(:,k);%第k个图像的输出表示 X_rebuid = W*Y + x0;%第k个图像的重建还原 image = AR(:,k); image = reshape(image,50,40); imshow(mat2gray(image));%对原矩阵归一化 figure; image_re = X_rebuid; image_re = reshape(image_re,50,40); imshow(mat2gray(image_re));%对原矩阵归一化 {e} \begin{lstlisting}[language=Matlab,frame=shadowbox] %% %编写程序,实现PCA和LEE算法 %对图像进行降维实验,并显示降维重建后的图像 %运行已有程序,和自己的对比 %实验报告(伪代码(或流程图)、源代码、实验结果及分析) %% 预处理和数据输入 clc clear addpath(genpath(pwd));%将子孙文件添加到工作目录 load face_images; %导入数据 data = images; %data = data(:,1:50); %% 初始化参数 d = 2; len = 64; wid = 64; k = 12; %% [p ,N] = size(data);%特征维度和对象数目 [IDX,~] = knnsearch(data',data','K',k+1); IDX = IDX(:,2:end); W = zeros(N); for i = 1:N xk = data(:,i); index = IDX(i,:); Qk_temp = repmat(xk,1,k) - data(:,index); Qk = Qk_temp'*Qk_temp; wk_temp = Qk\ones(k,1); wk = wk_temp/sum(wk_temp); W(i,index) = wk; end W = W'; I = eye(N); M = (I-W)*(I-W)'; [P,L] = eigs(M,d+1,0); P = P(:,2:end); Y = (P*sqrt(N))'; {f} \begin{lstlisting}[language=Matlab,frame=shadowbox] %% 使用工具箱进行进行降维来和我的实验结果进行比较 clc clear close all method = 'LLE';%可选LLE或者PCA addpath(genpath(pwd)); % 产生测试数据 %[X, labels] = generate_data('helix', 2000); if strcmp(method,'PCA') load AR %导入数据 [p,N] = size(AR); X = double(AR);%导入数据 else load face_images %导入数据 [p,N] = size(images); X = double(images);%导入数据 end % 估计本质维数 %no_dims = round(intrinsic_dim(X, 'MLE')); %disp(['MLE estimate of intrinsic dimensionality: ' num2str(no_dims)]); d = 2; k = 12; % PCA降维或LLE降维 [mappedX, mapping] = compute_mapping(X', method,d); Y = mappedX'; if strcmp(method,'PCA') x0 = (mapping.mean)'; W = (mapping.M); AR_shift = X - repmat(x0,1,N); %% close all; k = 1; y = Y(:,k); X_rebuid = W*y + x0;%第k个图像的重建还原 image = AR(:,k); image = reshape(image,50,40); imshow(mat2gray(image));%对原矩阵归一化 figure; image_re = X_rebuid; image_re = reshape(image_re,50,40); imshow(mat2gray(image_re));%对原矩阵归一化 end {g} \begin{lstlisting}[language=Matlab,frame=shadowbox] % LLE ALGORITHM (using K nearest neighbors) % [Y] = lle(X,K,dmax) % X :data as D x N matrix (D = dimensionality, N = #points) % K :number of neighbors % dmax :max embedding dimensionality % Y :embedding as dmax x N matrix %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %function [Y] = lle(X,K,d) addpath(genpath(pwd));%将子孙文件添加到工作目录 load face_images; %导入数据 data = images; X = data; K = 12; d = 2; %% [D,N] = size(X); fprintf(1,'LLE running on %d points in %d dimensions\n',N,D); %% Step1: compute pairwise distances & find neighbour fprintf(1,'-->Finding %d nearest neighbours.\n',K); X2 = sum(X.^2,1); distance = repmat(X2,N,1)+repmat(X2',1,N)-2*X'*X; [sorted,index] = sort(distance); neighborhood = index(2:(1+K),:); % Step2: solve for recinstruction weights fprintf(1,'-->Solving for reconstruction weights.\n'); if(K>D) fprintf(1,' [note: K>D; regularization will be used]\n'); tol=1e-3; % regularlizer in case constrained fits are ill conditioned else tol=0; end W = zeros(K,N); for ii=1:N z = X(:,neighborhood(:,ii))-repmat(X(:,ii),1,K); % shift ith pt to origin C = z'*z; % local covariance C = C + eye(K,K)*tol*trace(C); % regularlization (K>D) W(:,ii) = C\ones(K,1); % solve Cw=1 W(:,ii) = W(:,ii)/sum(W(:,ii)); % enforce sum(w)=1 end; % Step 3: compute embedding from eigenvects of cost matrix M=(I-W)'(I-W) fprintf(1,'-->Computing embedding.\n'); % M=eye(N,N); % use a sparse matrix with storage for 4KN nonzero elements M = sparse(1:N,1:N,ones(1,N),N,N,4*K*N); for ii=1:N w = W(:,ii); jj = neighborhood(:,ii); M(ii,jj) = M(ii,jj) - w'; M(jj,ii) = M(jj,ii) - w; M(jj,jj) = M(jj,jj) + w*w'; end; % calculation of embedding options.disp = 0; options.isreal = 1; options.issym = 1; [Y,eigenvals] = eigs(M,d+1,0,options); Y = Y(:,2:d+1)'*sqrt(N); % bottom evect is [1,1,1,1...] with eval 0 fprintf(1,'Done.\n'); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % other possible regularizers for K>D % C = C + tol*diag(diag(C)); % regularlization % C = C + eye(K,K)*tol*trace(C)*K; % regularlization {h} \begin{lstlisting}[language=Matlab,frame=shadowbox] clc clear close all format short digits(5) %% 设定维数 p = 8; d = 2; %% 读入数据,保存 D = dir('../data/*.csv'); D = struct2cell(D);%结构体不好调用,转成元胞数组来使用 csvs_name = D(1,:); N = 0;%这个表示数据的个数 %csvs_name = csvs_name(5:6); for csv_name = csvs_name %cpicName = 'a001.bmp' N = N+1; csvName = csv_name{1}; Data{N} = load(['../data/' csvName]); end %clear csv_name csvN csvName csvs_name D %% 定义原空间基,生成模型函数,由模型函数通过拟合得到点的坐标表示 %p = 15;%原空间维数 %%根据p自动生成模型函数 eval_poly = 'a(1)'; for i = 2:p eval_poly = [eval_poly '+a(' num2str(i) ').*x.^' num2str(i-1)]; end eval_poly = ['modelfun = @(a,x) x.^(0.5).*(1-x).^(0.5).*(' eval_poly ');']; eval(eval_poly); %modelfun = @(a,x) x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*sin(x)+a(3).*cos(x)+a(4).*1./x+a(5).*x+a(6).*x.^2); % modelfun = @(a,x)(x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*x+a(3).*x.^2+... % a(4).*x.^3))%+a(5).*x.^4+a(6)*x.^5))+... % a(7)*x.^6+a(8).*x.^7+a(9).*x.^8+a(10).*x.^9)); % modelfun = @(a,x)((a(1)+a(2).*x.^2+a(3).*x.^2+... % a(4).*x.^3+a(5).*x.^4+a(6)*x.^5+... % a(7)*x.^6+a(8).*x.^7+a(9).*x.^8+a(10).*x.^9)); %%做一波拟合,求出系数,进行拟合,拟合结果为A %%A中存的是数据点的坐标表示 for k = 1:N data = Data{k}; data(:,2) = abs(data(:,2));%取绝对值 x = data(:,1); y = data(:,2); %y = y./(x.*(1-x));%%%%%%%%如果将x(1-x)项挪到左边,拟合会出问题 a0 = ones(1,p); a = nlinfit(x,y,modelfun,a0); A(:,k) = a'; end %clearvars -except A modelfun x y %% 开始奇异值分解降维,得到新空间的原点和坐标轴,坐标表示 %%由奇异值分解做主成分分析,A的每一列为原空间下的系数,U的每一列为主成分 [p,N] = size(A); %d = 5;%新空间维数 x0 = mean(A,2);%计算样本均值 A_shift = A - repmat(x0,1,N);%中心平移每个训练样本,A_shift为原数据点的平移表示 %%%%对于A_shift的补充处理 syms x; base_vec_T = x.^(0.5).*(1-x).^(0.5).*x.^[0:p-1]; base_vec = conj((base_vec_T))'; W = int(base_vec*base_vec_T,[0,1]); L_prime = chol(W); L_prime_A_shift = L_prime*A_shift; %%%% [U,S,V] = svd(L_prime_A_shift); B = L_prime\U; if size(S,2) == 1 S_diag = S(1); else S_diag = diag(S); end R = cumsum(S_diag)./sum(S_diag); Coord_new = B(:,1:d); %% 新空间的坐标轴和原点的函数表示 %%生成新的空间中的基函数,找到d个新空间基函数及原点坐标 %%Coord_new x0中存的是新坐标系,fi存的是新的函数空间的原点和坐标轴 for k = 1:d;%取出第k个基函数 syms x; c = B(:,k); exp = modelfun(c,x); exp = simplify(exp);%第k个基函数的表达式 f{k} = exp; digits(2); latex(vpa(exp,2));%写成latex表达式黏贴到解释器中 end f0 = modelfun(x0,x); f0 = simplify(f0); latex(vpa(f0,2)); % for i = 1:d % f_fun{i} = matlabFunction(f{i}); % end % f0_fun = matlabFunction(f0); %% 求原坐标系中的投影后在原空间中的位置 %A_new_coord = Coord_new'*A_shift;%A_new_coord表示原数据点在新空间中的表示 syms x; for k = 1:N a = A_shift(:,k); pk_f = modelfun(a,x); for j = 1:d A_new_coord(j,k) = int(pk_f.*f{j},0,1); end end %%函数运算 for k = 1:N A_shadow_f = f0; for i = 1:d A_shadow_f = A_shadow_f+f{i}*A_new_coord(i,k); end A_shadow_f = simplify(A_shadow_f); A_shadow_fs{k} = A_shadow_f; A_shadow_fs_fun{k} = matlabFunction(A_shadow_f); end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%坐标运算,可以注释掉 % A_shadow_coord = Coord_new*A_new_coord+repmat(x0,1,N);%A_shadow_coord表示投影坐标点在原坐标系下的表示 % syms x; % for k = 1:N % a = A_shadow_coord(:,k); % A_shadow_coord_f = modelfun(a,x); % A_shadow_coord_fs{k} = simplify(A_shadow_coord_f); % end % % %%不考虑舍入误差的情况下,可以证明坐标运算和函数运算的得到的函数表达式是一样的,验证代码如下 % k=5; % diff = A_shadow_coord_fs{k}-A_shadow_fs{k} % diff = simplify(diff) % digits(2); % latex(vpa(diff,2)) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 画图和求误差 Errors = []; NN = 1000; h = 1/NN; xx = linspace(0,1,NN+1); close all; for k = 1:N %%原数据点 data = Data{k}; data(:,2) = abs(data(:,2));%取绝对值 x = data(:,1); y = data(:,2); %%拟合曲线 a = A(:,k); data_fit_f = @(x) modelfun(a,x); %%投影函数 A_shadow_f_fun = A_shadow_fs_fun{k}; %%原点函数 f0_fun = matlabFunction(f0); %%开始画图 figure(k); scatter(x,y,'.','MarkerEdgeColor','b',... 'MarkerFaceColor','c',... 'LineWidth',0.5); hold on; y_fit = data_fit_f(xx); y_shadow = A_shadow_f_fun(xx); y_f0 = f0_fun(xx); plot(xx,y_fit,'g'); plot(xx,y_shadow,'black'); plot(xx,y_f0,'r'); legend('数据','拟合','投影','原点'); %%求拟合曲线和投影函数之间的L2误差 %Errors(end+1) = norm((y_fit-y_shadow),2); Errors(end+1) = sum(abs(y_fit-y_shadow)*h); end Errors_mean = mean(Errors) %% test % close all; % plot(xx,xx); % hold on; % plot(xx,xx.^9) {i} \begin{lstlisting}[language=Matlab,frame=shadowbox] %图片提取数据与清洗 function I_fresh = denoise( I ) % 去除噪声,填充空洞 [L,num] = bwlabel(~I,8); stats = regionprops(L); stats_cell = struct2cell(stats); [~,maxind] = max([stats_cell{1,:}]); Imp = ismember(L, maxind); I_fresh = imfill(Imp,'holes'); I_fresh = ~I_fresh; end function [ coord,L ] = edge_extract( I ) % 提取边缘 [B,L] = bwboundaries(I,'noholes'); %imshow(I) % figure; % imshow(L) coord = B{1}; L = bwperim(I); end function [Ia,Ib] = image_process( pic_name,plotflag) % 图像分割,二值化处理 %pic_name = '1\65.png'; A = imread(pic_name);%读取到一张图片 [low_num,col_num,~] = size(A); Aa = imcrop(A,[1,1,270-1,low_num-1]);%分割点定在了270 Ab = imcrop(A,[270,1,col_num-270,low_num-1]); %thresh = graythresh(A);%自动确定二值化阈值 %L = bwperim(A);imshow(L) Ia = im2bw(Aa,58/255); %对图像二值化处理 Ib = im2bw(Ab,58/255); %对图像二值化处理 if plotflag == 1 %if 0 figure(100); subplot(2,2,1);imshow(Aa); subplot(2,2,2);imshow(Ab); subplot(2,2,3);imshow(Ia); subplot(2,2,4);imshow(Ib); end end function [ B ] = myrotate( A,O,angle ) %定义我的旋转函数,表示A当中的点,绕O点,逆时针旋转angle角度后的点 x0 = O(1);y0 = O(2); x1s = A(:,1); y1s = A(:,2); x1new = (x1s - x0)*cos(angle) - (y1s - y0)*sin(angle) + x0 ; y1new = (x1s - x0)*sin(angle) + (y1s - y0)*cos(angle) + y0 ; B = [x1new y1new]; % myrotate([1 1],[2 1],-pi/4) end function [ Coordinates_normalized ] = normalize( Coordinates ) %此函数对于输入的二维坐标,按照x轴向映射的【0,1】区间 % 对输入的坐标点归一化 x = Coordinates(:,1); %y = Coordinates(:,2); xmax = max(x); %xmin = min(x);%这个应该是等于0的 Coordinates_normalized = Coordinates./xmax; end function pic_extract(video_name,freq) %视频中提取图像函数,video_name表示视频名称,freq表示每几帧提取一次 %video_name = '1'; VideoAd = VideoReader([video_name '.mp4']);%输入视频位置 numFrames = VideoAd.NumberOfFrames;% 帧的总数 videoF = VideoAd.FrameRate;%视频采集速率,每秒走几帧 videoD = VideoAd.Duration; %时间 %numname=3;%图片名称长度 %nz = strcat('%0',num2str(numname),'d'); T = 1*freq;%提取帧数间隔,这里设定每1秒提取一一帧 %T=1;%提取帧数间隔,这里设定每1秒提取一一帧 if ~exist(video_name,'dir')==1 mkdir(video_name);%生成文件夹存放图片 end i=1; for k = 1 :T: numFrames%? ? ? numframe = read(VideoAd,k);%读取第几帧 %num=sprintf(nz,i);%i为保存图片的序号 dir_path = strcat(video_name,'\',num2str(i)); if ~exist(dir_path,'dir')==1 mkdir(dir_path);%生成文件夹存放图片 end imwrite(numframe,strcat(video_name,'\',num2str(i),'\',num2str(i),'.png'),'png'); %写入图片 i=i+1; end end \begin{lstlisting}[language=Matlab,frame=shadowbox] %% 处理左图的程序 clc clear addpath('../');%添加上层目录,方便调用函数 D = dir('./*.bmp'); D = struct2cell(D);%结构体不好调用,转成元胞数组来使用 pics_name = D(1,:); for pic_name = pics_name %cpicName = 'a001.bmp' picName = pic_name{1}; picN = strsplit(picName,'.'); picN = picN{1}; A = imread(picName); imshow(A); I = im2bw(A,100/255); %对图像二值化处理 I = denoise(I); imshow(I); [ coord,L ] = edge_extract( ~I ); imshow(L); x = coord(:,2); y = coord(:,1); inds = find(y == max(y)); ind_max = max(inds); ind_min = min(inds); X0 = [max(y) (x(ind_min)+x(ind_max))/2 ];%使用矩阵坐标,即ij坐标 point_num = size(coord,1); Coordinates = (repmat(X0,point_num,1) - coord); Coord = normalize( Coordinates );%一个归一化处理 imwrite(L,[picN 'E.png']); %写入图片 csvwrite([picN '.csv'],Coord); figure; pic_std = plot(Coord(1:end,1),Coord(1:end,2),'r.'); saveas(pic_std,[picN 'STD.jpg']); %写入图片 end \begin{lstlisting}[language=Matlab,frame=shadowbox] %% 处理右图的程序 clc clear addpath('../');%添加上层目录,方便调用函数 D = dir('./*.bmp'); D = struct2cell(D);%结构体不好调用,转成元胞数组来使用 pics_name = D(1,:); for pic_name = pics_name %picName = 'b001.bmp' picName = pic_name{1}; picN = strsplit(picName,'.'); picN = picN{1}; A = imread(picName); imshow(A); I = im2bw(A,60/255); %对图像二值化处理 I = denoise(I); imshow(I); [ coord,L ] = edge_extract( ~I );%绕一圈儿,回到原点 imshow(L); x = coord(:,2); y = coord(:,1); inds = find(y == max(y)); ind_max = max(inds); ind_min = min(inds); X0 = [max(y) (x(ind_min)+x(ind_max))/2 ];%使用矩阵坐标,即ij坐标 %找到上顶点的索引,做旋转矫正 inds_up = find(y == min(y)); ind_up_max = max(inds_up); ind_up_min = min(inds_up); Y0 = [min(y) (x(ind_up_min)+x(ind_up_max))/2 ]; ang = -atan((X0(2)-Y0(2))/(X0(1)-Y0(1))); if abs(ang) > 0.01%角度太小就不用转了吧 coord = myrotate( coord,X0,ang); end %可视化矫正结果,调试用,只能调试到这一步时用,再往下X0不动的 % if min(min(coord))<1 % coord = coord-min(min(coord))+1; % end % [low_num,col_num] = size(I); % L_test = sparse(round(coord(:,1)),round(coord(:,2)),1,low_num+100,col_num+100); % L_test = full(L_test); % imshow(L_test) % figure(99); % scatter(coord(:,1),coord(:,2)) x = coord(:,2); y = coord(:,1); % inds = find(y == max(y)); % ind_max = max(inds); % ind_min = min(inds); % X0 = [max(y) (x(ind_min)+x(ind_max))/2 ];%使用新选的X0 inds_half = ((x<(X0(2)-1))&(y<=(X0(1)))); coord_half = coord(inds_half,:); point_num = size(coord_half,1); coord = coord_half; Coordinates = (repmat(X0,point_num,1) - coord); % test 可视化结果 %edge_rebuid = sparse(round(Coordinates(:,1))+10,round(Coordinates(:,2))+10,1,500,200); %min(round(Coordinates(:,2))+1) % imshow(full(edge_rebuid)); % figure; % scatter(points_coord(:,1),points_coord(:,2)) Coord = normalize( Coordinates );%一个归一化处理 imwrite(L,[picN 'E.png']); %写入图片 csvwrite([picN '.csv'],Coord); figure; pic_std = plot(Coord(1:end,1),Coord(1:end,2),'r.'); saveas(pic_std,[picN 'STD.jpg']); %写入图片 % pause(2); % scatter(Coord(:,1),Coord(:,2)); end \begin{lstlisting}[language=Matlab,frame=shadowbox] %% 主成分分析 function [ coef ] = find_symbol_coef( exp,item ) %输入一个表达式,即一个项,提取项前面的系数 % author:lusong %exp = Phi 很鲁棒 charexp=char(exp); item=char(item); indexItem=strfind(charexp,item); %获取存在item项的指标 indexPseudo=union(strfind(charexp,['(',item]),strfind(charexp,[item,'^'])); %获取伪指标 indexItem=setdiff(indexItem,indexPseudo); %获取真正的item指标 %循环计算各个item位置的系数 itemLen=length(item); expLen=length(charexp); coef=sym(0); for i=1:length(indexItem) index=indexItem(i); %计算当前item项的位置 cache=sym(1); %存储当前项的系数 if index~=1 && charexp(index-1)=='*' indexFront=index-2; %初始化系数项的前指标 while indexFront~=1 && charexp(indexFront-1)~=' ' indexFront=indexFront-1; end cache=cache*sym(charexp(indexFront:index-2)); end if index+itemLen~=expLen && charexp(index+1)=='*' indexBack=index+2; %初始化系数项的后指标 while indexFront+itemLen~=expLen && charexp(indexBack+1)~=' ' indexBack=indexBack+1; end cache=cache*sym(charexp(index+2:indexBack)); end coef=coef+cache; end end clc; clear; close all; syms x y t; eta = 104;gamma = 20.9;rho = 964; theta_e = degtorad(53);alpha = degtorad(15);g = 9.8; num = 6; a = sym('a',[num,1]); adot = sym('adot',[num,1]); %% Phi的计算 H = (x-a(1)).*(a(2)-x).*(a(3)+a(4)*x); Y = (x-a(1))^0.*(a(2)-x).^0*(a(5)+a(6)*x); h = H.*(1-(y./Y)^0.5); HY = H.*Y; HY_dot = conj(gradient(HY,a)')*adot; HY_dot = simplify(HY_dot); latex(HY_dot) V = -1/(HY).*int(HY_dot,x,a(1),x);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%这个积分算不出来,因为0.5次方的存在。 Y_dot = conj(gradient(Y,a)')*adot; W = 1./Y*(Y_dot+V.*diff(Y,x)); %Phi_intvar = 3*eta*(V.^2+(y*W).^2)./h; Phi_intvar = W.^2; %Phi_intvar = simplify(Phi_intvar); %latex(Phi_intvar) %Phi_intvar_resy = int(Phi_intvar,y,-Y,Y); %Phi = 0.5*(int(Phi_intvar_resy,x,a(1),a(2))); Phi_intvar_resx= int(Phi_intvar,x,a(1),a(2));%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%这个积分算不出来,被积函数算不出来 Phi = 0.5*(int(Phi_intvar_resx,y,-Y,Y)); %% 提取Phi关于adot的系数 A = a*conj(a'); Phi = sum(sum(A.*(adot*conj(adot')))); adot_multi_matrix = adot*conj(adot'); for i=1:num for j=1:num item = adot_multi_matrix(i,j); xi(i,j) = find_symbol_coef(Phi,item); end end xi = 2.*xi; % item = adot(2)*adot(1); % find_symbol_coef(Phi,item) %% 势能函数 int_var = 0.5.*gamma.*theta_e.^2+0.5.*gamma.*(diff(h,x).^2+diff(h,y).^2); remainder_term = 0.5.*rho.*g.*h^2.*sin(alpha)-rho.*g.*x.*h.*cos(alpha); A_temp = int(int_var,y,-Y,Y); A = int(A_temp,x,a(1),a(2))+remainder_term;%%%%%%%%%%积分也不好积 %% 求解DOEs xi_inv = inv(xi); odefun = @(t,a) xi\gradient(A);%%%改 a0 = ones(1,num); [T,a_cal] = ode45(odefun,[1,1],a0); %% 计算出来的结果以及画图 H_cal = subs(H,[a1 a2 a3 a4],[a_cal(1) a_cal(2) a_cal(3) a_cal(4)]); Y_cal = subs(Y,[a1 a2 a5 a6],[a_cal(1) a_cal(2) a_cal(5) a_cal(6)]); H_cal_fun = matlabFunction(H_cal,x); xx = a(1):0.01:a(2); plot(xx,H_cal_fun(xx)); clc clear close all format short digits(5) %% 设定维数 p = 2; d = 2; %% 读入数据,保存 D = dir('../data/*.csv');%%%%%%%%%%%%%%%%%%%%%%%% D = struct2cell(D);%结构体不好调用,转成元胞数组来使用 csvs_name = D(1,:); N = 0;%这个表示数据的个数 %csvs_name = csvs_name(5:6); for csv_name = csvs_name %cpicName = 'a001.bmp' N = N+1; csvName = csv_name{1}; Data{N} = load(['../data/' csvName]);%%%%%%%%%%%%%%%%%%%%% end %clear csv_name csvN csvName csvs_name D %% 定义原空间基,生成模型函数,由模型函数通过拟合得到点的坐标表示 %p = 15;%原空间维数 %%根据p自动生成模型函数 eval_poly = 'a(1)'; for i = 2:p eval_poly = [eval_poly '+a(' num2str(i) ').*x.^' num2str(i-1)]; end eval_poly = ['modelfun = @(a,x) x.^(0.5).*(1-x).^(0.5).*(' eval_poly ');']; eval(eval_poly); %modelfun = @(a,x) x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*sin(x)+a(3).*cos(x)+a(4).*1./x+a(5).*x+a(6).*x.^2); % modelfun = @(a,x)(x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*x+a(3).*x.^2+... % a(4).*x.^3))%+a(5).*x.^4+a(6)*x.^5))+... % a(7)*x.^6+a(8).*x.^7+a(9).*x.^8+a(10).*x.^9)); % modelfun = @(a,x)((a(1)+a(2).*x.^2+a(3).*x.^2+... % a(4).*x.^3+a(5).*x.^4+a(6)*x.^5+... % a(7)*x.^6+a(8).*x.^7+a(9).*x.^8+a(10).*x.^9)); %%做一波拟合,求出系数,进行拟合,拟合结果为A %%A中存的是数据点的坐标表示 for k = 1:N data = Data{k}; data(:,2) = abs(data(:,2));%取绝对值 x = data(:,1); y = data(:,2); %y = y./(x.*(1-x));%%%%%%%%如果将x(1-x)项挪到左边,拟合会出问题 a0 = ones(1,p); a = nlinfit(x,y,modelfun,a0); A(:,k) = a'; end %clearvars -except A modelfun x y %% 开始奇异值分解降维,得到新空间的原点和坐标轴,坐标表示 %%由奇异值分解做主成分分析,A的每一列为原空间下的系数,U的每一列为主成分 [p,N] = size(A); %d = 5;%新空间维数 x0 = mean(A,2);%计算样本均值 A_shift = A - repmat(x0,1,N);%中心平移每个训练样本,A_shift为原数据点的平移表示 %%%%对于A_shift的补充处理 syms x; base_vec_T = x.^(0.5).*(1-x).^(0.5).*x.^[0:p-1]; base_vec = conj((base_vec_T))'; W = int(base_vec*base_vec_T,[0,1]); L_prime = chol(W); L_prime_A_shift = L_prime*A_shift; %%%% [U,S,V] = svd(L_prime_A_shift); B = L_prime\U; if size(S,2) == 1 S_diag = S(1); else S_diag = diag(S); end R = cumsum(S_diag)./sum(S_diag); Coord_new = B(:,1:d); %% 新空间的坐标轴和原点的函数表示 %%生成新的空间中的基函数,找到d个新空间基函数及原点坐标 %%Coord_new x0中存的是新坐标系,fi存的是新的函数空间的原点和坐标轴 for k = 1:d;%取出第k个基函数 syms x; c = B(:,k); exp = modelfun(c,x); exp = simplify(exp);%第k个基函数的表达式 f{k} = exp; digits(2); latex(vpa(exp,2));%写成latex表达式黏贴到解释器中 end f0 = modelfun(x0,x); f0 = simplify(f0); latex(vpa(f0,2)); % for i = 1:d % f_fun{i} = matlabFunction(f{i}); % end % f0_fun = matlabFunction(f0); %% 求原坐标系中的投影后在原空间中的位置 %A_new_coord = Coord_new'*A_shift;%A_new_coord表示原数据点在新空间中的表示 syms x; for k = 1:N a = A_shift(:,k); pk_f = modelfun(a,x); for j = 1:d A_new_coord(j,k) = int(pk_f.*f{j},0,1); end end %%函数运算 for k = 1:N A_shadow_f = f0; for i = 1:d A_shadow_f = A_shadow_f+f{i}*A_new_coord(i,k); end A_shadow_f = simplify(A_shadow_f); A_shadow_fs{k} = A_shadow_f; A_shadow_fs_fun{k} = matlabFunction(A_shadow_f); end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%坐标运算,可以注释掉 % A_shadow_coord = Coord_new*A_new_coord+repmat(x0,1,N);%A_shadow_coord表示投影坐标点在原坐标系下的表示 % syms x; % for k = 1:N % a = A_shadow_coord(:,k); % A_shadow_coord_f = modelfun(a,x); % A_shadow_coord_fs{k} = simplify(A_shadow_coord_f); % end % % %%不考虑舍入误差的情况下,可以证明坐标运算和函数运算的得到的函数表达式是一样的,验证代码如下 % k=5; % diff = A_shadow_coord_fs{k}-A_shadow_fs{k} % diff = simplify(diff) % digits(2); % latex(vpa(diff,2)) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 画图和求误差 Errors = []; NN = 1000; h = 1/NN; xx = linspace(0,1,NN+1); close all; for k = 1:N %%原数据点 data = Data{k}; data(:,2) = abs(data(:,2));%取绝对值 x = data(:,1); y = data(:,2); %%拟合曲线 a = A(:,k); data_fit_f = @(x) modelfun(a,x); %%投影函数 A_shadow_f_fun = A_shadow_fs_fun{k}; %%原点函数 f0_fun = matlabFunction(f0); %%开始画图 figure(k); scatter(x,y,'.','MarkerEdgeColor','b',... 'MarkerFaceColor','c',... 'LineWidth',0.5); hold on; y_fit = data_fit_f(xx); y_shadow = A_shadow_f_fun(xx); y_f0 = f0_fun(xx); plot(xx,y_fit,'g'); plot(xx,y_shadow,'black'); plot(xx,y_f0,'r'); legend('数据','拟合','投影','原点'); %%求拟合曲线和投影函数之间的L2误差 %Errors(end+1) = norm((y_fit-y_shadow),2); Errors(end+1) = sum(abs(y_fit-y_shadow)*h); end Errors_mean = mean(Errors) %% test % close all; % plot(xx,xx); % hold on; % plot(xx,xx.^9) clc clear close all format short digits(5) %% 设定维数 p = 2; d = 1; %% 读入数据,保存 D = dir('../data2/*.csv');%%%%%%%%%%%%%%%%%%%%%%%% D = struct2cell(D);%结构体不好调用,转成元胞数组来使用 csvs_name = D(1,:); N = 0;%这个表示数据的个数 %csvs_name = csvs_name(5:6); for csv_name = csvs_name %cpicName = 'a001.bmp' N = N+1; csvName = csv_name{1}; Data{N} = load(['../data2/' csvName]);%%%%%%%%%%%%%%%%%%%%% end %clear csv_name csvN csvName csvs_name D %% 定义原空间基,生成模型函数,由模型函数通过拟合得到点的坐标表示 %p = 15;%原空间维数 %%根据p自动生成模型函数 eval_poly = 'a(1)'; for i = 2:p eval_poly = [eval_poly '+a(' num2str(i) ').*x.^' num2str(i-1)]; end eval_poly = ['modelfun = @(a,x) x.^(1).*(1-x).^(1).*(' eval_poly ');']; eval(eval_poly); %modelfun = @(a,x) x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*sin(x)+a(3).*cos(x)+a(4).*1./x+a(5).*x+a(6).*x.^2); % modelfun = @(a,x)(x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*x+a(3).*x.^2+... % a(4).*x.^3))%+a(5).*x.^4+a(6)*x.^5))+... % a(7)*x.^6+a(8).*x.^7+a(9).*x.^8+a(10).*x.^9)); % modelfun = @(a,x)((a(1)+a(2).*x.^2+a(3).*x.^2+... % a(4).*x.^3+a(5).*x.^4+a(6)*x.^5+... % a(7)*x.^6+a(8).*x.^7+a(9).*x.^8+a(10).*x.^9)); %%做一波拟合,求出系数,进行拟合,拟合结果为A %%A中存的是数据点的坐标表示 for k = 1:N data = Data{k}; data(:,2) = abs(data(:,2));%取绝对值 x = data(:,1); y = data(:,2); %y = y./(x.*(1-x));%%%%%%%%如果将x(1-x)项挪到左边,拟合会出问题 a0 = ones(1,p); a = nlinfit(x,y,modelfun,a0); A(:,k) = a'; end %clearvars -except A modelfun x y %% 开始奇异值分解降维,得到新空间的原点和坐标轴,坐标表示 %%由奇异值分解做主成分分析,A的每一列为原空间下的系数,U的每一列为主成分 [p,N] = size(A); %d = 5;%新空间维数 x0 = mean(A,2);%计算样本均值 A_shift = A - repmat(x0,1,N);%中心平移每个训练样本,A_shift为原数据点的平移表示 %%%%对于A_shift的补充处理 syms x; base_vec_T = x.^(1).*(1-x).^(1).*x.^[0:p-1]; base_vec = conj((base_vec_T))'; W = int(base_vec*base_vec_T,[0,1]); L_prime = chol(W); L_prime_A_shift = L_prime*A_shift; %%%% [U,S,V] = svd(L_prime_A_shift); B = L_prime\U; if size(S,2) == 1 S_diag = S(1); else S_diag = diag(S); end R = cumsum(S_diag)./sum(S_diag); Coord_new = B(:,1:d); %% 新空间的坐标轴和原点的函数表示 %%生成新的空间中的基函数,找到d个新空间基函数及原点坐标 %%Coord_new x0中存的是新坐标系,fi存的是新的函数空间的原点和坐标轴 for k = 1:d;%取出第k个基函数 syms x; c = B(:,k); exp = modelfun(c,x); exp = simplify(exp);%第k个基函数的表达式 f{k} = exp; digits(2); latex(vpa(exp,2));%写成latex表达式黏贴到解释器中 end f0 = modelfun(x0,x); f0 = simplify(f0); latex(vpa(f0,2)); % for i = 1:d % f_fun{i} = matlabFunction(f{i}); % end % f0_fun = matlabFunction(f0); %% 求原坐标系中的投影后在原空间中的位置 %A_new_coord = Coord_new'*A_shift;%A_new_coord表示原数据点在新空间中的表示 syms x; for k = 1:N a = A_shift(:,k); pk_f = modelfun(a,x); for j = 1:d A_new_coord(j,k) = int(pk_f.*f{j},0,1); end end %%函数运算 for k = 1:N A_shadow_f = f0; for i = 1:d A_shadow_f = A_shadow_f+f{i}*A_new_coord(i,k); end A_shadow_f = simplify(A_shadow_f); A_shadow_fs{k} = A_shadow_f; A_shadow_fs_fun{k} = matlabFunction(A_shadow_f); end % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%坐标运算,可以注释掉 % A_shadow_coord = Coord_new*A_new_coord+repmat(x0,1,N);%A_shadow_coord表示投影坐标点在原坐标系下的表示 % syms x; % for k = 1:N % a = A_shadow_coord(:,k); % A_shadow_coord_f = modelfun(a,x); % A_shadow_coord_fs{k} = simplify(A_shadow_coord_f); % end % % %%不考虑舍入误差的情况下,可以证明坐标运算和函数运算的得到的函数表达式是一样的,验证代码如下 % k=5; % diff = A_shadow_coord_fs{k}-A_shadow_fs{k} % diff = simplify(diff) % digits(2); % latex(vpa(diff,2)) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% 画图和求误差 Errors = []; NN = 1000; h = 1/NN; xx = linspace(0,1,NN+1); close all; for k = 1:N %%原数据点 data = Data{k}; data(:,2) = abs(data(:,2));%取绝对值 x = data(:,1); y = data(:,2); %%拟合曲线 a = A(:,k); data_fit_f = @(x) modelfun(a,x); %%投影函数 A_shadow_f_fun = A_shadow_fs_fun{k}; %%原点函数 f0_fun = matlabFunction(f0); %%开始画图 figure(k); scatter(x,y,'.','MarkerEdgeColor','b',... 'MarkerFaceColor','c',... 'LineWidth',0.5); hold on; y_fit = data_fit_f(xx); y_shadow = A_shadow_f_fun(xx); y_f0 = f0_fun(xx); plot(xx,y_fit,'g'); plot(xx,y_shadow,'black'); plot(xx,y_f0,'r'); legend('数据','拟合','投影','原点'); %%求拟合曲线和投影函数之间的L2误差 %Errors(end+1) = norm((y_fit-y_shadow),2); Errors(end+1) = sum(abs(y_fit-y_shadow)*h); end Errors_mean = mean(Errors) %% test % close all; % plot(xx,xx); % hold on; % plot(xx,xx.^9) \begin{lstlisting}[language=Matlab,frame=shadowbox] %% 最小二乘 clc clear D = dir('data/*.csv'); D = struct2cell(D); names = D(1,:); data = []; for name = names name = name{1}; data = [data;load(['data/' name])]; end x = data(:,1); y = data(:,2); %modelfun = @(a,x)(x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*x+a(6)*x*4+a(3).*x.^2+a(4).*x.^3+a(5).*x.^5))%+a(6)*x.*4)); modelfun = @(a,x)(x.^(0.5).*(1-x).^(0.5).*(a(1)+a(2).*x.*100+a(3).*x.^2+a(4).*x.^3+a(5).*x.^4+a(6)*x.^5)); a0 = ones(1,6)*100; modelfun(a0,0) modelfun(a0,1) a = nlinfit(x,y,modelfun,a0) a(abs(a)<2) = 0 plot(x,modelfun(a,x))
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/136327.html