matlab建模遇见的一些问题和解决方法

来源:互联网 发布:the weeknd earned it 编辑:程序博客网 时间:2024/06/07 22:37

工具:MATLAB
警告:Equation is badly conditioned. Remove repeated data points or try centering and scaling.
出现这一警告的一般是因为数据在横坐标方向上跨度太大,在这种跨度很大的多项式拟合里,为了提高拟合精度,通常希望让横坐标变得更加集中,因为在一个相对狭窄的小区间上去拟合,要比在一个相对很宽的区间上拟合更容易,且能提高拟合精度。MATLAB推荐的做法是: centering and scaling transformation,即以横坐标的均值为中心、以横坐标的标准差来做归一化因子,将数据变得相对集中。
比如将这段代码:

x=1990:1:2008;y=[34.1972 38.0773 42.3786 47.1423 52.4127 58.2367 64.6644 71.7483 79.5432 88.1057 97.4938 107.7658 118.9796 131.1914 144.4542 158.8166 174.3208 191.0005 208.8791];n=2;p=polyfit(x,y,n);

变成:

x=1990:1:2008;y=[34.1972 38.0773 42.3786 47.1423 52.4127 58.2367 64.6644 71.7483 79.5432 88.1057 97.4938 107.7658 118.9796 131.1914 144.4542 158.8166 174.3208 191.0005 208.8791];n=3;mu = [mean(x); std(x)];x1 = (x - mu(1))/mu(2);   % 手动实现 centering and scalingp1 = polyfit(x1,y,n);plot(x,y,'bo',x,polyval(p1,x1),'r-')legend('data','fitted',2)

警告:
Warning: Duplicate x-y data points detected: using average of the z values.
意思就是,你的(x,y) 坐标值出现了重复的点,计算时会取z的平均值来计算。

一个个检查有没有重复可不是什么好办法。好在看见网上有人出了一个很聪明的方法:先建立一个新的矩阵A,使得A=x+sqrt(-1)*y. 这样就使得xy坐标变成了一个复数。接着借助unique()函数,这个函数可以判断出一个矩阵中所有不重复的值。举个例子,如果A=[1 1 2 3 4 5 5 6], unique(A)=[1 2 3 4 5 6],因为A中出现了1到6. 这样利用unique(x+sqrt(-1)*y)就可以判断出数组中有没有重复的了。
可是我的数据经过这样的处理,发现并没有重复的xy值。这是怎么回事?
查询matlab的help文件,上面有这么一句话:
“this means that there are two or more data points where the input values (x, y) are the same or very close together.”
这就是说,如果两个值差得很近,也许也会被当做一样来处理?关键是,这个小,究竟是多小?
griddata()的源代码是怎么说。这一段如下:


% Sort x and y so duplicate points can be averaged before passing to delaunay need x,y and z to be column vectorssz = numel(x);x = reshape(x,sz,1);y = reshape(y,sz,1);z = reshape(z,sz,1);sxyz = sortrows([x y z],[2 1]);x = sxyz(:,1);y = sxyz(:,2);z = sxyz(:,3);myepsx = eps(0.5 * (max(x) - min(x)))^(1/3);myepsy = eps(0.5 * (max(y) - min(y)))^(1/3);ind = [0; ((abs(diff(y)) < myepsy) & (abs(diff(x)) < myepsx)); 0];if sum(ind) > 0 warning('MATLAB:griddata:DuplicateDataPoints',['Duplicate x-y data points detected: using average of the z values.']);______

部分如下:
sxyz = sortrows([x y z],[2 1]);
将需要插值的(x,y,z)放到一个大的矩阵中,x,y,z分别一列。然后以y为主导,对y从小到大排列,对应的x和z的值也跟着移动。
myepsx = eps(0.5 * (max(x) - min(x)))^(1/3);
myepsy = eps(0.5 * (max(y) - min(y)))^(1/3);
这两行代码,是分别计算x和y的表示的精度值,也可以理解为在你的具体应用中,x和y的值的最小精度是多少。这里计算的方法是计算二分之一x的阈值的开三次方的精度值,应该也可以有别的方法。
ind = [0; ((abs(diff(y)) < myepsy) & (abs(diff(x)) < myepsx)); 0];
diff(y)的意思是[y2-y1,y3-y2,……,yn-y(n-1)]形成的一个新的矩阵,如果这个新的矩阵的每一个元素的值小于之前计算的y的最小精度,那么就认为这个值是0,或者说认为这两个值相等。如果小于的条件是成立的,就返回1(True);反之则返回0(False)。后面的那个是一样的,就是x的值的对比。
那么我们想想,两个对应的列,如果y的差值还小于精度值(就是认为两个值相等,结果返回1),如果这时候同时X的差值还小于精度值(就是x的两个值也相等,结果返回1),那个1&1=1,结果就返回1.
if sum(ind) > 0
只要结果中有一个1,就说明有一对(x,y)是相等的(或者非常接近),那个总和就必定大于1,就会返回这个警告。
比如说,经过整理以后的结果如下
X=[1 3.001 5 8 0 2 3 3.002 7]
Y=[1 1.001 2 3 5 6 7 7.001 8]
假设精度是0.5(我没有计算,随手举的),那么就意味着在你的计算中最高精度是0.5,低于0.5都可能是没有意义的误差。虽然从这上面看X,Y没有相同的配对,可是如果用上面的计算:
diff(X)=[2.001 1.999 3 -8 2 1 0.002 3.998]
diff(Y)=[0.001 0.999 1 2 1 1 0.001 0.999]
首先看Y,虽然没有0,但是有两个0.001,比0.5小,就可以认为是一样的值,返回两个真值。再检查这两个真值的X的值,其中有一个2.001,大于0.5,说明不同;另外一个,X差值是0.002,小于0.5,说明精度已经低于最小的计算值了,应该认为是相等的。我们回到原来的数据,[3 7]和[3.002 7.001],如果EPS(精度)是大于0.002的,说明后面的尾数很有可能只是超过精度的计算误差,是没有意义的,这个时候做插值,就会返回之前的那个错误,说你有重复的xy值。
不过,总的来说,这个报错并不影响你的结果;他都说了会取z的平均值计算。如果你真的觉得平均值不准想要取特定的值,可以用unique函数找到特定的行列(或者用griddata里面的这个判断也行),然后更改你的z值达到你的目的。

最后,讨论下mathtype公式如何粘贴到matlab中,其基本思想是由latex或者tex转换到matlab里。
首先MathType公式编辑器里面的公式。而在MATLAB的命令窗口和Editor中虽然不能将公式显示的想MathType中那么漂亮。不过,可以在axes坐标轴里面将公式显示的和MathType公式编辑器里面的一样漂亮。
如果想要将MathType中的公式,拿到Matlab里面显示,首先需要将MathType中的公式转换为Tex格式的命令。这点,可以通过设置MathType来实现。
打开MathType,“Preferences”-》“Translator”,然后如下面的设置:
然后再MathType里面输入一个公式,然后拷贝到一个记事本里,如下:
打开MATLAB,运行下面的命令:
>>showLatex(f_s^t\left( \alpha \right) = \sum\limits_{k = 1}^n {{s^3}} ‘)$
结果是

showLatex(‘

fts(α)=k=1ns3
’)

注意,showLatex函数的输入参数是MathType生成的Tex命令。
感谢:http://blog.sina.com.cn/s/blog_5da928d70101g7py.html
如何在MATLAB中显示MathType公式编辑器里的公式

2 0
原创粉丝点击