123 发表于 2020-3-11 16:57:06

prony算法问题

以下为prony算法matlab程序。
拟合实际曲线时用的算法如下图。
但是这不是相当于拿原先的数据复制粘贴吗?

%打开指定文件,并对信号进行Prony分析计算
function =x_svdprony(x_in, dt, fL, showfigure)
    format long;
    load input3.txt;
    x_in=input3;%xlsread('shiyishi.xls');
    x = x_in;
    cpu=cputime;
         N=size(x,1);
      %取N/2的整数部分为初始的P
      P=floor(N/2);

      %去直流环节
      x_Sum = 0;
      for i=1:N
            x_Sum = x_Sum + x(i);
      end
      x_av = x_Sum / N;
    if x_av > 10E-10
            for i=1:N
                x(i) = x(i) - x_av;
            end
    end
      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

      %滤波环节
      %fL=1;
    fL=2;
      if fL>1
            for i=fL+1:N
                x(i-fL)=0;
                for j=1:fL
                  x(i-fL) = x(i-fL)+(1/fL)*x(i-j+1);
                end
            end
      end
      N=N-fL;
      tt=0:1:N-1;
      
      %P要求为偶数
      if mod(P, 2) ~= 0
         P = P - 1;
      end
      
      P1=P;
      if mod(P, 2) == 0
         % Generate R,生成样本矩阵
         for i=1:P1
                  for j=1:P1+1
                      ss=0;
                      for k=P1:N-1
                        %前向预测误差
%                         ss=ss+x(k+2-j,1)*x(k+1-i,1);
                        %后向预测误差
                        ss=ss+x(k+1-P1+i)*x(k+1-P1-1+j);
                        %同时考虑双向误差
%                         ss=ss+x(k+2-j,1)*x(k+1-i,1)+x(k+1-P1+i)*x(k+1-P1-1+j);            
                      end   
                      R(i,j)=ss;
                  end
         end

%               divide R into R1 and R2, and get A; R1*A=R2;
         for i=1:P
            for j=1:P
               R1(i,j)=R(i,j+1);
            end
         end
         for i=1:P
                   R2(i)=R(i,1);
         end
      
         %添加的代码,使用SVD-TLS算法%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
         %首先进行SVD分解
         =svd(R1);
         %根据奇异值确定实际的阶数M
         M=0;
         %计算全部奇异值的均方和
         Sum_SVD=0;
         for i=1:P
            Sum_SVD = Sum_SVD+s(i,i)^2;
         end
         cur_sum = 0;
         i=1;
         while 1 - sqrt(cur_sum/Sum_SVD) > 0.000001 & i<=P
            cur_sum = cur_sum + s(i,i)^2;
            M = M + 1;
            i = i + 1;
         end
         %输出预测的阶数M
         M;

         %生成Sp矩阵
         Sp=zeros(M+1, M+1);
         for j=1:M
            for i=1:(P-1)-M+1
               Sp = Sp+s(j,j)^2*v(i:i+M,j)*v(i:i+M,j)';
            end
         end
      
         %根据公式生成最佳最小二乘解
       Sp_inv=inv(Sp);
       if isinf(Sp_inv(1,1)) == 1
         Sp_inv = pinv(Sp);
       end

         a_SVD = Sp_inv(1+1:M+1, 1)/Sp_inv(1,1);
         P = M;
         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
         % Get Zi
         cof_SVD(1)=1;
         for i=1:M
            cof_SVD(i+1)=a_SVD(i);
         end
         Z=roots(cof_SVD);
         
       % Get y,y should be very close to x
         for i=1:P
            y(i)=x(i);
         end
      
         for i=P+1:N
            y(i)=0;
         end
         for i=P+1:N
            for j=1:P
               y(i)=y(i)-a_SVD(j)*x(i-j);
            end
         end
            
         % Get B
         for i=1:N
            for j=1:P
               Fy(i,j)=Z(j)^(i-1);
               end
         end
         Fz=Fy';
         FH=Fy'*Fy;
         Fn=inv(FH);
         B = inv(Fy'*Fy)*Fy'*y';
      
         % Calculate Amplitude, Phasor, Frequency and damp
       dt=0.01;
         for i=1:P
            Amp(i)=abs(B(i));
            Pha(i)=atan(imag(B(i))/real(B(i)));
            Fre(i)=atan(imag(Z(i))/real(Z(i)))/(2*pi*dt);
            damp(i)=log(abs(Z(i)))/dt;
         end

       %调试用的代码
       if isnan(Amp(1)) == 1
         error('幅值的求解出现错误!');
       end

         % Get xc,verify if xc is nearly equal to x
         for i=1:P
               if(real(B(i))>=0.0)
                     bth(i)=Pha(i);
               else
                     bth(i)=pi+Pha(i);
               end
         end
       %对Pha重新幅值
       for i=1:P
         if Pha(i) < 0
               Pha(i) = Pha(i) + 2*pi;
         end
       end

         for i=1:N
               xc(i)=0.0;
               for j=1:P
                     xc(i)=xc(i)+Amp(j)*exp(damp(j)*(i-1)*dt)*cos(2*pi*Fre(j)*(i-1)*dt+bth(j));
               end
         end

%       if showfigure == 1
%            %显示特征根的位置
%            figure;
%            plot(damp, 2*pi*Fre, 'r*');
%       end

         xj=xc';
         er=0;
         all = 0;
         for i=1:N         
                  er=er+(x(i)-xc(i))^2;
                  all = all+x(i)^2;
         end
         SNR=-20*log(sqrt(er/all));
         
         % Calculate Prony spectrum
         %频谱的取值范围为0-5Hz
         f=0:0.01:4.99;
         for j=1:size(f,2)
               sptr(j)=0;
               sptr1(j)=0;
               sptr2(j)=0;
               angl(j)=0;
               tmpangle = 0;
               for k=1:P
                  sptr1(j)=sptr1(j)+Amp(k)*cos(bth(k))*(2*damp(k)/(damp(k)^2+(2*pi*(f(j)-Fre(k)))^2));
                  sptr2(j)=sptr2(j)+Amp(k)*sin(bth(k))*(2*damp(k)/(damp(k)^2+(2*pi*(f(j)-Fre(k)))^2));
               end
               sptr(j)=sqrt(sptr1(j)^2+sptr2(j)^2);
               tmpangle = atan2(sptr1(j),sptr2(j));
               angl(j) = tmpangle*360/pi;
         end
       %对幅频响应进行归一化,并且寻找主导频率模式
       %寻找sptr的最大值
       max_sptr=0;
       main_f=0;
       for j=1:size(f,2)
         if sptr(j) > max_sptr
               max_sptr = sptr(j);
               %主导频率出现在最大幅频响应位置
               if f(j) ~= 0;
                   main_f = f(j);
               else
                   max_sptr = 0;
               end
         end
       end
       main_f;
       %找出真正计算的频率值
       f_err = 10;
       f_main = 0;
       for i=1:size(Amp, 2)
         if abs(main_f - Fre(i)) < f_err
               f_main = Fre(i);
               damp_main = damp(i);
               f_err = abs(main_f - Fre(i));
         end
       end
       main_f = f_main;
       main_damp = damp_main;
       %进行归一化
       for j=1:size(f,2)
         sptr(j)=sptr(j)/max_sptr;
         Amp_Response(j) = sptr(j);
       end

         for i=1:size(f,2)
               if angl(i) > 0
                   angl(i)=angl(i)-360;
               end
         end
         showfigure = 1;
       if showfigure == 1
            %在一个图上显示时域拟和曲线和Prony频谱分布
            figure;
            subplot(2,1,1);
            %plot(tt,x(1:N),'b', tt,y, 'r', tt,xc, '*b');

          plot(tt,x(1:N),'r', tt,xc, '*b');
          subplot(2,1,2);
            plot(f,sptr);
            %subplot(2,2,3);
            %plot(f,sptr);
            %subplot(2,2,4);
            %plot(f,angl);
      end

          cpu=cputime-cpu;
      format short;
      end



特斯拉之魂 发表于 2020-3-11 19:06:25

老哥,可以交流下吗,我qq257589181。感激不尽

123 发表于 2020-3-18 11:53:59

有什么问题可以在这里说,我懂得就会讲啦
页: [1]
查看完整版本: prony算法问题