python做系统辨识_python实现一般最小二乘系统辨识方法

问题:

对于一个未知参数的系统,往往需要用到系统辨识的方法,例如对于一个单输入单输出系统:

Z(k)+a1*Z(k-1)+a2*Z(k-2)=b1*U(k-1)+b2*U(k-2)+V(k)

其中:V(k)=c1*v(k)+c2*v(k-1)+c3*v(k-3)

输入信号采用四阶幅值为1的M序列,高斯噪声v(k)均值为0,方差为0.1。

假设真值为a1=1.6,a2=0.7,b1=1.0,b2=0.4,c1=1.0,c2=1.6,c3=0.7。需要对以上参数进行辨识。

方法:

一般最小二乘法是系统辨识中最简单的辨识方法之一,其MATLAB实现方法十分简单,我发现网上一大把,所以我决定“翻译”一个python版的一般最小二乘辨识方法供读者参考。

本文用到的库:

importnumpy as npimportmatplotlib.pyplot as pltfrom operator importxorfrom numpy.linalg import inv

M序列的产生:

在python中,M序列的产生方法与matlab类似,先产生随机数,然后采用四阶移位寄存器滤波变换,得到我们想要的M序列。

#M序列产生

L=16

#设置M序列周期#定义初始值

y=np.zeros(L)

u=np.zeros(L)

y1=1y2=1y3=1y4=0for i inrange(0,L):

x1=xor(y3,y4)

x2=y1

x3=y2

x4=y3

y[i]=y4if y[i]>0.5:

u[i]=-1

else:

u[i]=1y1=x1

y2=x2

y3=x3

y4=x4

plt.figure(num=2)

x=np.linspace(0,15,16)

plt.bar(x,u,width=0.1)

plt.title('输入信号M序列')

高斯分布噪声:

这里采用的是random库中的函数,可以看到,我们设置的均值为0,方差为0.1。

#产生一组16个N(0,1)的高斯分布的随机噪声

mu=0

sigma=0.1

samplenum=16

n=np.random.normal(mu,sigma,samplenum)

plt.figure(num=1)

plt.plot(n)

plt.title("高斯分布随机噪声")

最小二乘辨识程序:

#最小二乘辨识过程

z=np.zeros(16)for k in range(2,15):

z[k]=-1.6*z[k-1]-0.7*z[k-2]+1.0*u[k-1]+0.4*u[k-2]+1.0*n[k]+1.6*n[k-1]+0.7*n[k-2]

plt.figure(num=3)

plt.bar(x,z,width=0.1)

plt.title('输出观测值')

H=np.array([[-z[1],-z[0],u[1],u[0]],[-z[2],-z[1],u[2],u[1]],[-z[3],-z[2],u[3],u[2]],[-z[4],-z[3],u[4],u[3]],[-z[5],-z[4],u[5],u[4]],[-z[6],-z[5],u[6],u[5]],[-z[7],-z[6],u[7],u[6]],[-z[8],-z[7],u[8],u[7]],[-z[9],-z[8],u[9],u[8]],[-z[10],-z[9],u[10],u[9]],[-z[11],-z[10],u[11],u[10]],[-z[12],-z[11],u[12],u[11]],[-z[13],-z[12],u[13],u[12]],[-z[14],-z[13],u[14],u[13]]])

Z=np.array([z[2],z[3],z[4],z[5],z[6],z[7],z[8],z[9],z[10],z[11],z[12],z[13],z[14],z[15]])

In_1=np.transpose(H)

In_2=np.dot(In_1,H)

In_3=inv(In_2)

In_4=np.dot(In_3,In_1)

c=np.dot(In_4,Z)

分离参数:

#分离参数并显示

a1=c[0]

a2=c[1]

b1=c[2]

b2=c[3]print("a1的值是:",a1)print("a2的值是:",a2)print("b1的值是:",b1)print("b2的值是:",b2)

注意:

由于在python中plt的库是不支持中文的,所以要加上这些代码,保证输出的图片标题的中文显示正常。

#显示中文字体

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签

plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

结果:

在网上找了半天python画针状图的资料,发现没有。。所以强行用瘦了的柱状图表示针状图了。

总结:

可以看出Python写的系统辨识误差还是有一些的,不过也是受到一般最小二乘参数辨识方法的限制,如果采用递推最小二乘,增广最小二乘等方法可能会进一步提高准确性。笔者尝试过递推最小二乘,但是与MATLAB相比,其代码量大大增加,因此在系统辨识方法上,不建议都用Python来写,MATLAB是个不错的选择。当然,喜欢写python的话,这都不是问题。

代码全文:

1 #-*- coding: utf-8 -*-

2 """

3 Created on Wed Sep 20 16:11:27 20174 @author: Hangingter5 """

6 #一般最小二乘辨识

7

8 #导入相应科学计算的包

9 importnumpy as np10 importmatplotlib.pyplot as plt11 from operator importxor12 from numpy.linalg importinv13

14 #显示中文字体

15 plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签

16 plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

17 #产生一组16个N(0,1)的高斯分布的随机噪声

18 mu=019 sigma=0.1

20 samplenum=16

21 n=np.random.normal(mu,sigma,samplenum)22 plt.figure(num=1)23 plt.plot(n)24 plt.title("高斯分布随机噪声")25 #M序列产生

26 L=16

27 #设置M序列周期

28 #定义初始值

29 y=np.zeros(L)30 u=np.zeros(L)31 y1=1

32 y2=1

33 y3=1

34 y4=035 for i inrange(0,L):36 x1=xor(y3,y4)37 x2=y138 x3=y239 x4=y340 y[i]=y441 if y[i]>0.5:42 u[i]=-1

43 else:44 u[i]=1

45 y1=x146 y2=x247 y3=x348 y4=x449 plt.figure(num=2)50 x=np.linspace(0,15,16)51 plt.bar(x,u,width=0.1)52 plt.title('输入信号M序列')53 #最小二乘辨识过程

54 z=np.zeros(16)55

56 for k in range(2,15):57 z[k]=-1.6*z[k-1]-0.7*z[k-2]+1.0*u[k-1]+0.4*u[k-2]+1.0*n[k]+1.6*n[k-1]+0.7*n[k-2]58

59 plt.figure(num=3)60 plt.bar(x,z,width=0.1)61 plt.title('输出观测值')62

63 H=np.array([[-z[1],-z[0],u[1],u[0]],[-z[2],-z[1],u[2],u[1]],[-z[3],-z[2],u[3],u[2]],[-z[4],-z[3],u[4],u[3]],[-z[5],-z[4],u[5],u[4]],[-z[6],-z[5],u[6],u[5]],[-z[7],-z[6],u[7],u[6]],[-z[8],-z[7],u[8],u[7]],[-z[9],-z[8],u[9],u[8]],[-z[10],-z[9],u[10],u[9]],[-z[11],-z[10],u[11],u[10]],[-z[12],-z[11],u[12],u[11]],[-z[13],-z[12],u[13],u[12]],[-z[14],-z[13],u[14],u[13]]])64 Z=np.array([z[2],z[3],z[4],z[5],z[6],z[7],z[8],z[9],z[10],z[11],z[12],z[13],z[14],z[15]])65

66 In_1=np.transpose(H)67 In_2=np.dot(In_1,H)68 In_3=inv(In_2)69 In_4=np.dot(In_3,In_1)70 c=np.dot(In_4,Z)71

72 #分离参数并显示

73 a1=c[0]74 a2=c[1]75 b1=c[2]76 b2=c[3]77 print("a1的值是:",a1)78 print("a2的值是:",a2)79 print("b1的值是:",b1)80 print("b2的值是:",b2)

参考:

MATLAB版的系统辨识一般最小二乘方法:

http://blog.csdn.net/sinat_20265495/article/details/51426537

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值