GM(1,1)灰色预测模型-案例长江水质综合评价赛题第三题-matlab完整代码附送
(1)对长江近两年多的水质情况做出定量的综合评价,并分析各地区水质的污染状况。
(2)研究、分析长江干流近一年多主要污染物高锰酸盐指数和氨氮的污染源主要在哪些地区?
(3)假如不采取更有效的治理措施,依照过去10年的主要统计数据,对长江未来水质污染的发展趋势做出预测分析,比如研究未来10年的情况。
(4)根据你的预测分析,如果未来10年内每年都要求长江干流的Ⅳ类和Ⅴ类水的比例控制在20%以内,且没有劣Ⅴ类水,那么每年需要处理多少污水?
(5)你对解决长江水质污染问题有什么切实可行的建议和意见。
预测模型的种类
定量预测方法:
灰色预测
回归分析法
时间序列分析(移动平均、指数平滑)
马尔科夫(Markov)预测
差分方程模型
微分方程模型
神经网络预测法
灰色系统理论
部分公式与理论参考:洛阳理工-常用的预测方法简介ppt-数理部-任铭
为什么要学灰色预测
灰色预测在工业、农业、商业等经济领域,以及环境、社会和军事等领域中都有广泛的应用. 特别是依据目前已有的数据对未来的发展趋势做出预测分析,同时也可以对行为特征的异常情况发生的时刻进行估计计算等等.
灰色预测理论
灰色系统的基本概念
(1)如果一个系统中具有充足的信息量,其发展变化的规律明显、定量描述方便、结构与参数具体,则称此系统为白色系统.
(2)如果一个系统的内部特性全部是未知的,则称此系统为黑色系统.
(3)介于白色系统和黑色系统之间的称为灰色系统,即系统内部信息和特性是部分已知的,另一部分是未知的,例如:社会系统、农业系
统、经济系统、气象系统、生物系统等.
区别白色系统与灰色系统的重要标志:是系统内各因素之间是否具有确定的关系.
灰色系统理论是研究解决灰色系统分析、建模、预测、决策和控制的理论. 灰色系统模型在数据处理和预测中经常使用.
(1)灰色系统理论建模特点:原始数据必须等时间间距.
(2)灰色模型 (Grey Model) 处理思路:首先对原始数据进行累加,弱化原始时间序列数据的随机因素,然后建立生成数的微分方程
(3)灰色预测是对灰色系统所做的预测. 目前常用的一些预测方法(如回归分析等),需要较大的样本. 若样本较小,常造成较大误差,使预测目标失效. 灰色预测模型所需建模信息少,运算方便,建模精度高,在各种预测领域都有着广泛的应用,是处理小样本预测问题的有效工具.
灰色预测方法
灰色预测是指利用GM模型对系统行为特征的发展变化规律进行估计预测,同时也可以对行为特征的异常情况发生的时刻进行估计计算等等. 这些工作实质上是将“随机过程”当作“灰色过程”,“随机变量”当作“灰变量”,并主要以灰色系统理论中的GM(1,1)模型来进行处理.
GM(1,1)模型是灰色系统理论中的单序列一阶灰色微分方程.
预测模型步骤:
设已知参考数据序列为
做1次累加AGO(Acumulated Generating Operation)生成新序列:
求生成均值(mean)序列**(1)**
于是建立灰微分方程为(2)
相应的GM(1,1)白微分方程为(3)
将方程(2)变形为(4)
将方程组(4)采用矩阵形式表达为:
解方程 (5)得到最小二乘解为
解方程 (3)得到GM(1,1)离散解
还原为原始数列,预测模型为
将(7)式代入(8)式得
GM(1,1)模型与统计模型相比,具有两个显著优点:
(1)灰色模型即使在少量数据情况下建立的模型,精度也会很高.
(2)灰色模型从其机理上讲,越靠近当前时间点精度会越高,因此灰色模型的预测功能优于统计模型.
灰色系统建模实际上是一种以数找数的方法,即从系统的一个或几个离散数列中找出系统的变化关系,试图建立系统的连续变化模型.
灰色预测步骤
数据的检验与处理
建立模型
检验预测值
预测预报
-------------------------------------分割线----------------------------------------
说完了灰色预测的具体步骤那么对于长江水质的问题三就迎刃而解了,首先我要说的是,灰色预测数据的选取是否合理对预测结果准确性与否起到很大的影响!
相信大家都看过很多的论文,对于不同的数据选取方法一定有了自己的理解,不过我们可以重新看一下问题三:
(3)假如不采取更有效的治理措施,依照过去10年的主要统计数据,对长江未来水质污染的发展趋势做出预测分析,比如研究未来10年的情况。
灰色预测注意事项
部分公式与理论参考:洛阳理工-长江水质讲解-200619
- 水质污染发展趋势,水质污染发展趋势与许多因素有关,不同的时期(枯水期、丰水期、水文年)可能以后的发展趋势也有所不同,如果全部统一处理,忽略三个时期的不同发展趋势,最后得到的结果是否合理,是否符合现实,有待考证。
所以,鄙人之见:
不妨将所有时期所有河道(全流域、干流、支流)未来十年全部预测-
其实程序大同小异,只是处理的数据量多少而已,这里数据量的导入是一个大问题,这个待会再说。🤭
所有时期所有河道(全流域、干流、支流)未来十年全部预测-后会得到6X90的矩阵。
2.要注意的便是这个要点,其他的和灰色预测步骤相同,可以先选数据I类水-枯水期-全流域-10年的数据组成一个原始矩阵,进行求解。
之后I类水-枯水期-干流-10年………………以此类推。
需要注意的是,因为10年预测后十年,可想而知,误差会有多大,所以为了减小误差,我们可以以前10年预测第11年,再以前11年预测第12年,以此类推。
3.数据一定要提前进行级比检测,不然预测出来的数据emmmmm,没法看。
没有级比检测的预测数据:
有级比检测的预测数据:
级比检测的C值也不太好找,网上也没有什么实质性的文章,详细请参考我上一篇Blog
https://blog.csdn.net/m0_46742690/article/details/107112396
链接: link.
这里有具体代码,此代码也会在本章后出现,
4.因为灰色预测模型只是将原始数据序列的规律趋势体现出来,但并没有考虑六类水质的河长占总河长的百分比为1,且出现的数据既有负值也有正值,也有数据很大,基于此,我们要对数据根据百分比要求进行归一化,即一个时期一个河道六类水百分比为1.
具体实现程序matlab(以c/python的思想进行编译-简单易懂(主要是matlab学的太差-害))
需要注意的是,因为10年预测后十年,可想而知,误差会有多大,所以为了减小误差,我们可以以前10年预测第11年,再以前11年预测第12年,以此类推,此种方法的代码如下:
%导入原始数据
fore_num = 1;
c = 0;
for y = 1 : 54
flag_1 = 1;
for h = 1:10
flag = 0;
if(flag == 0)
level = y ;
if( flag_1 == 1 )
x0 = xlsread('附件四原始数据_拆分' , level ,' A1 : J1 ' );
end
if( flag_1 == 2 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A2 : K2 ' );
end
if( flag_1 == 3 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A3 : L3 ' );
end
if( flag_1 == 4 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A4 : M4 ' );
end
if( flag_1 == 5 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A5 : N5 ' );
end
if( flag_1 == 6 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A6 : O6 ' );
end
if( flag_1 == 7 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A7 : P7 ' );
end
if( flag_1 == 8 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A8 : Q8 ' );
end
if( flag_1 == 9 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A9 : R9 ' );
end
if( flag_1 == 10 )
x0 = xlsread('预测完成数据_级比_拆分' , level ,' A10 : S10 ' );
end
%x0 = xlsread('预测完成数据_级比_拆分' , level , 'A7 : P7' );
b = x0(1,1);
length_x0 = length(x0);
%Ratio为检验系数,即数列的级比
%x0 = x0 + 40;
Ratio = zeros(1 , length_x0 - 1);
for i = 1 : length_x0 - 1
Ratio(i) = x0(i) / x0(i+1);
end
x1 = ones(1 , length_x0);
%对数据的级比做判断
if ( exp(-2 / (length_x0+1)) < min(Ratio) && max(Ratio) < exp(2 / (length_x0+1)) )
%0.8338—1.1994
%对x0数组进行维数累加求和,得到x1
x1 = cumsum(x0);
%生成均值序列 alpha自取
alpha = 0.5;%input('please enter alpha number: ');
z1 = zeros(1 , length_x0 - 1);
for k = 2 : length_x0
z1(k-1) = alpha * x1(k) + (1-alpha) * x1(k-1);
end
%解方程得到最小二乘法的解为 a_b
y0 = x0( 2 : 1 : length_x0 );%()中没有,说明只有行没有列
B = [-z1 ; ones( 1 , length_x0-1 )];
%gj为a和b的数据
a_b = ( inv(B * B') ) * B * y0';
n = fore_num;%input('预测的数据个数为:');
for k = 1 : length_x0 + n - 1
x1(k+1) = ( (x0(1) - (a_b(2) / a_b(1)) ) * ( exp(-k * a_b(1)) ) ) + a_b(2) / a_b(1);
end
x0(1) = x1(1);
for k = 2 : length_x0 + n
x0(k) = x1(k) - x1(k-1);
end
else
disp('数据不满足检验,将对数据进行处理')
while(1)
x0 = x0 + 0.1;
Ratio = zeros(1 , length_x0 - 1);
for i = 1:length_x0 - 1
Ratio(i) = x0(i) / x0(i+1);
end
if( exp(-2 / (length_x0+1)) < min(Ratio) && max(Ratio) < exp(2 / (length_x0+1)) )
break;
end
end
c = x0(1,1) - b;
fprintf( '数据进行处理完成,c的值为%d\n' , c );
flag = 1;
end
end
if(flag == 1)
length_x0 = length(x0);
%Ratio为检验系数,即数列的级比
%x0 = x0 + 40;
Ratio = zeros(1 , length_x0 - 1);
for i = 1:length_x0 - 1
Ratio(i) = x0(i) / x0(i+1);
end
x1 = ones(1 , length_x0);
%对数据的级比做判断
if ( exp(-2 / (length_x0+1)) < min(Ratio) && max(Ratio) < exp(2 / (length_x0+1)) )
%0.8338—1.1994
%对x0数组进行维数累加求和,得到x1
x1 = cumsum(x0);
%生成均值序列 alpha自取
alpha = 0.5;%input('please enter alpha number: ');
z1 = zeros(1 , length_x0 - 1);
for k = 2 : length_x0
z1(k-1) = alpha * x1(k) + (1-alpha) * x1(k-1);
end
%解方程得到最小二乘法的解为 a_b
y0 = x0( 2 : 1 : length_x0 );%()中没有,说明只有行没有列
B = [-z1 ; ones( 1 , length_x0-1 )];
%gj为a和b的数据
a_b = ( inv(B * B') ) * B * y0';
n = fore_num;%input('预测的数据个数为:');
for k = 1 : length_x0 + n - 1
x1(k+1) = ( (x0(1) - (a_b(2) / a_b(1)) ) * ( exp(-k * a_b(1)) ) ) + a_b(2) / a_b(1);
end
x0(1) = x1(1);
for k = 2 : length_x0 + n
x0(k) = x1(k) - x1(k-1);
end
end
end
x0 = x0 -c ;
%plot(x0,'*')
if( flag_1 == 1 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A2 : K2 ' )
flag_1 = 2 ;
elseif( flag_1 == 2 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A3 : L3 ' )
flag_1 = 3 ;
elseif( flag_1 == 3 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A4 : M4 ' )
flag_1 = 4 ;
elseif( flag_1 == 4 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A5 : N5 ' )
flag_1 = 5 ;
elseif( flag_1 == 5 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A6 : O6 ' )
flag_1 = 6 ;
elseif( flag_1 == 6 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A7 : P7 ' )
flag_1 = 7 ;
elseif( flag_1 == 7 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A8 : Q8 ' )
flag_1 = 8 ;
elseif( flag_1 == 8 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A9 : R9 ' )
flag_1 = 9 ;
elseif( flag_1 == 9 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A10 : S10 ' )
flag_1 = 10 ;
elseif( flag_1 == 10 )
xlswrite( '预测完成数据_级比_拆分' , x0 , level , ' A11 : T11 ' )
flag_1 = 11 ;
end
end
end
归一化处理
x0 = xlsread('预测完成数据_级比_总_n=1预测_附件四' , 1 );
a = x0 ./ 100;
%行归一化
v = sum(a,2);% 行求和
D = diag(v);% 生成以向量v为对角的对角矩阵
norm_a = D^-1*a;% norm_a即为行归一化矩阵
norm_a = norm_a * 100;
xlswrite( '预测完成数据_级比_总_n=1预测_附件四' , norm_a , 2 )
~~主要是不想一个一个数据进行导入,一共6X9X10个单元意味着我要导入 (6X9X10 / 10)次,/(ㄒoㄒ)/,谁能受了-----
这就问题来了,matlab一定有相关函数可以快速实现分批导入,我不会 -_-.
不过数据确实蛮多的,我至少运行了2分多钟,要知道我做单片机嵌入式千把行的代码烧录单片机也就10几秒,难道不恐怖吗???????
运行结果(部分):
emmmmmmmmmmmmmmmmmm
**羞答答的玫瑰静悄悄地开**
**慢慢地绽放她留给我的情怀**
**春天的手呀翻阅她的等待**
**我在暗暗思量该不该将她轻轻地摘**
**羞答答的玫瑰静悄悄地开**
**慢慢地燃烧她不承认的情怀**
**清风的手呀试探她的等待**
**我在暗暗犹豫该不该将她轻轻地摘**
**怎么舍得如此接受你的爱**
**从来喜欢都会被爱成悲哀**
**怎么舍得如此揽你入胸怀**
**当我越是深爱脾气就会越坏**
**羞答答的玫瑰静悄悄地开**
**慢慢地同时凋零同时盛开**
**爱情的手呀抚过她的等待**
**我在暗暗惆怅竟不曾将她轻轻地摘**
还是这种图直观一些。。。。。。。。。。。
能看完到最后????
你也太棒了吧!!!!!!!!!
We will part to see you again.