本文大部分是对于数学建模清风老师的课程学习总结归纳而来,我的理解可能有错误,大家发现错误可以在评论区批评指正,课程地址:《数学建模清风》
灰色关联度分析(Grey Relation Analysis,GRA),是一种多因素统计分析的方法。简单来讲,就是在一个灰色系统中,我们想要了解其中某个我们所关注的某个项目受其他的因素影响的相对强弱,再直白一点,就是说:我们假设以及知道某一个指标可能是与其他的某几个因素相关的,那么我们想知道这个指标与其他哪个因素相对来说更有关系,而哪个因素相对关系弱一点,依次类推,把这些因素排个序,得到一个分析结果,我们就可以知道我们关注的这个指标,与因素中的哪些更相关。
一般的抽象系统,如社会系统、经济系统、农业系统、生态系统、教育系统等都包含有许多种因素,多种因素共同作用的结果决定了该系统的发展态势。人们常常希望知道在众多的因素中,哪些是主要因素,哪些是次要因素;哪些因素对系统发展影响大,哪些因素对系统发展影响小;哪些因素对系统发展起推动作用需强化发展,哪些因素对系统发展起阻碍作用需加以抑制;这些都是系统分析中人们普遍关心的问题。例如,粮食生产系统,人们希望提高粮食总产量,而影响粮食总产量的因素是多方面的,有播种面积以及水利、化肥、土壤、种子、劳力、气候、耕作技术和政策环境等。为了实现少投人多产出,并取得良好的经济效益、社会效益和生态效益,就必须进行系统分析。
灰色关联分析步骤实现大致分为以下几个步骤:
下表为某地区国内生产总值的统计数据(以百万元计),问该地区从 2000 年到 2005 年之间,哪一种产业对 GDP 总量影响最大。
年份 | 国内总产值 | 第一产业 | 第二产业 | 第三产业 |
---|---|---|---|---|
2000 | 1988 | 386 | 839 | 763 |
2001 | 2061 | 408 | 846 | 808 |
2002 | 2335 | 422 | 960 | 953 |
2003 | 2750 | 482 | 1258 | 1010 |
2004 | 3356 | 511 | 1577 | 1268 |
2005 | 3806 | 561 | 1893 | 1352 |
这里的正向化处理和之前提到的处理方法相同,就是将极小型、中间型以及区间型指标统一转化为极大型指标。具体方法参考:《零基础数学建模》——TOPSIS+熵权法
最终得到正向化处理的矩阵为X:
X = [ x 11 x 12 ⋯ x 1 m x 21 x 22 ⋯ x 2 m ⋮ ⋮ ⋱ ⋮ x n 1 x n 2 ⋯ x n m ] X=\left[ \begin{matrix} x_{11} & x_{12} & \cdots & x_{1m}\\ x_{21} & x_{22} & \cdots & x_{2m}\\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \cdots & x_{nm}\\ \end{matrix} \right] X=⎣⎢⎢⎢⎡x11x21⋮xn1x12x22⋮xn2⋯⋯⋱⋯x1mx2m⋮xnm⎦⎥⎥⎥⎤
因为指标变量 国内产值、第一产业、第二产业、第三产业 都是为正向化指标,因此无需正向化。
预处理的两个目的:1. 去除量纲的影响2. 缩小变量范围简化计算
对母序列和子序列中的每个指标进行预处理,先求出每个指标的均值,再用该指标中的每个元素都除以其均值。
设标准化矩阵为 Z Z Z, Z Z Z中元素记为z_{ij}:
z i j = x i j x ˉ i j z_{ij}=\frac{x_{ij}}{\bar x_{ij}} zij=xˉijxij
得到标准化矩阵 Z Z Z:
Z = [ z 11 z 12 ⋯ z 1 m z 21 z 22 ⋯ z 2 m ⋮ ⋮ ⋱ ⋮ z n 1 z n 2 ⋯ z n m ] Z=\left[ \begin{matrix} z_{11} & z_{12} & \cdots & z_{1m}\\ z_{21} & z_{22} & \cdots & z_{2m}\\ \vdots & \vdots & \ddots & \vdots \\ z_{n1} & z_{n2} & \cdots & z_{nm}\\ \end{matrix} \right] Z=⎣⎢⎢⎢⎡z11z21⋮zn1z12z22⋮zn2⋯⋯⋱⋯z1mz2m⋮znm⎦⎥⎥⎥⎤
在例题中,得到的最终标准化矩阵为:
年份 | 国内总产值 | 第一产业 | 第二产业 | 第三产业 |
---|---|---|---|---|
2000 | 0.7320 | 0.8361 | 0.6828 | 0.7439 |
2001 | 0.7588 | 0.8838 | 0.6885 | 0.7878 |
2002 | 0.8597 | 0.9141 | 0.7812 | 0.9292 |
2003 | 1.0125 | 1.0440 | 1.0237 | 0.9847 |
2004 | 1.2356 | 1.1069 | 1.2833 | 1.2363 |
2005 | 1.4013 | 1.2152 | 1.5405 | 1.3182 |
定义灰色系数,即各指标的关联系数为:
y ( x 0 ( k ) , x i ( k ) ) ) = a + ρ b ∣ x 0 ( k ) − x i ( k ) ∣ + ρ b ( i = 1 , 2 , ⋯ , m , k = 1 , 2 , ⋯ , n ) y(x_0(k),x_i(k)))=\frac{a+\rho b}{|x_0(k)-x_i(k)|+\rho b}(i=1,2,\cdots,m,k=1,2,\cdots,n) y(x0(k),xi(k)))=∣x0(k)−xi(k)∣+ρba+ρb(i=1,2,⋯,m,k=1,2,⋯,n)
其中 a a a为两极最小差, b b b为两极最大差, ρ \rho ρ为分辨系数(在本方法中一般取值为 0.5 0.5 0.5)
a = m i n i m i n k ∣ x 0 ( k ) − x i ( k ) ∣ a=min_imin_k|x_0(k)-x_i(k)| a=minimink∣x0(k)−xi(k)∣
b = m i n i m i n k ∣ x 0 ( k ) − x i ( k ) ∣ b=min_imin_k|x_0(k)-x_i(k)| b=minimink∣x0(k)−xi(k)∣
那么根据以上步骤会先得到差值矩阵:
∣ x 0 − x 1 ∣ |x_0-x_1| ∣x0−x1∣ | ∣ x 0 − x 2 ∣ |x_0-x_2| ∣x0−x2∣ | ∣ x 0 − x 3 ∣ |x_0-x_3| ∣x0−x3∣ |
---|---|---|
0.1041 | 0.0492 | 0.0119 |
0.1249 | 0.0704 | 0.0289 |
0.0544 | 0.0785 | 0.0694 |
0.0315 | 0.0112 | 0.0278 |
0.1288 | 0.0477 | 0.0006 |
0.1862 | 0.1392 | 0.0832 |
根据以上矩阵得出两极最小差 a = 0.006 , a=0.006, a=0.006,两极最大差 b = 0.1862 b=0.1862 b=0.1862。
最后根据关联系数公式,计算得出关联系数矩阵:
y ( x 0 ( k ) , x 1 ( k ) y(x_0(k),x_1(k) y(x0(k),x1(k) | y ( x 0 ( k ) , x 2 ( k ) y(x_0(k),x_2(k) y(x0(k),x2(k) | y ( x 0 ( k ) , x 3 ( k ) y(x_0(k),x_3(k) y(x0(k),x3(k) |
---|---|---|
0.4751 | 0.6586 | 0.8922 |
0.4299 | 0.5733 | 0.7680 |
0.6356 | 0.5462 | 0.5766 |
0.7520 | 0.8985 | 0.7753 |
0.4224 | 0.6657 | 1.0000 |
0.3356 | 0.4035 | 0.5317 |
定义 y ( x 0 , x i ) y(x_0,x_i) y(x0,xi)为灰色关联度,即把关联系数矩阵每列求均值:
y ( x 0 , x i ) = 1 n ∑ k = 1 n y ( x 0 ( k ) , x i ( k ) ) y(x_0,x_i)=\frac{1}{n}\sum^n_{k=1}y(x_0(k),x_i(k)) y(x0,xi)=n1k=1∑ny(x0(k),xi(k))
经过计算最终得出灰色关联度:
y ( x 0 , x 1 ) = 0.5084 , y ( x 0 , x 2 ) = 0.6243 , y ( x 0 , x 3 ) = 0.7573 y(x_0,x_1)=0.5084,y(x_0,x_2)=0.6243,y(x_0,x_3)=0.7573 y(x0,x1)=0.5084,y(x0,x2)=0.6243,y(x0,x3)=0.7573
最终得到例题答案:该地区2000年至2005年间的国内总产值受第三产值影响最大。
灰色关联分析对综合评价问题解题步骤大致分为以下几步:
%% 灰色关联分析用于系统分析
clear;clc
load gdp.mat % 导入数据 一个6*4的矩阵
% 不会导入数据的同学可以看看第二讲topsis模型,我们也可以自己在工作区新建变量,并把Excel的数据粘贴过来
% 注意Matlab的当前文件夹一定要切换到有数据文件的这个文件夹内
Mean = mean(gdp); % 求出每一列的均值以供后续的数据预处理
gdp = gdp ./ repmat(Mean,size(gdp,1),1); %size(gdp,1)=6, repmat(Mean,6,1)可以将矩阵进行复制,复制为和gdp同等大小,然后使用点除(对应元素相除),这些在第一讲层次分析法都讲过
disp('预处理后的矩阵为:'); disp(gdp)
Y = gdp(:,1); % 母序列
X = gdp(:,2:end); % 子序列
absX0_Xi = abs(X - repmat(Y,1,size(X,2))) % 计算|X0-Xi|矩阵(在这里我们把X0定义为了Y)
a = min(min(absX0_Xi)) % 计算两级最小差a
b = max(max(absX0_Xi)) % 计算两级最大差b
rho = 0.5; % 分辨系数取0.5
gamma = (a+rho*b) ./ (absX0_Xi + rho*b) % 计算子序列中各个指标与母序列的关联系数
disp('子序列中各个指标的灰色关联度分别为:')
disp(mean(gamma))
%% 灰色关联分析用于综合评价模型
clear;clc
load data_water_quality.mat
% 我们也可以自己在工作区新建变量,并把Excel的数据粘贴过来
% 注意Matlab的当前文件夹一定要切换到有数据文件的这个文件夹内
%% 判断是否需要正向化
[n,m] = size(X);
disp(['共有' num2str(n) '个评价对象, ' num2str(m) '个评价指标'])
Judge = input(['这' num2str(m) '个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0: ']); %1
if Judge == 1
Position = input('请输入需要正向化处理的指标所在的列,例如第2、3、6三列需要处理,那么你需要输入[2,3,6]: '); %[2,3,4]
disp('请输入需要处理的这些列的指 标类型(1:极小型, 2:中间型, 3:区间型) ')
Type = input('例如:第2列是极小型,第3列是区间型,第6列是中间型,就输入[1,3,2]: '); %[2,1,3]
% 注意,Position和Type是两个同维度的行向量
for i = 1 : size(Position,2) %这里需要对这些列分别处理,因此我们需要知道一共要处理的次数,即循环的次数
X(:,Position(i)) = Positivization(X(:,Position(i)),Type(i),Position(i));
% Positivization是我们自己定义的函数,其作用是进行正向化,其一共接收三个参数
% 第一个参数是要正向化处理的那一列向量 X(:,Position(i)) 回顾上一讲的知识,X(:,n)表示取第n列的全部元素
% 第二个参数是对应的这一列的指标类型(1:极小型, 2:中间型, 3:区间型)
% 第三个参数是告诉函数我们正在处理的是原始矩阵中的哪一列
% 该函数有一个返回值,它返回正向化之后的指标,我们可以将其直接赋值给我们原始要处理的那一列向量
end
disp('正向化后的矩阵 X = ')
disp(X)
end
%% 对正向化后的矩阵进行预处理
Mean = mean(X); % 求出每一列的均值以供后续的数据预处理
Z = X ./ repmat(Mean,size(X,1),1);
disp('预处理后的矩阵为:'); disp(Z)
%% 构造母序列和子序列
Y = max(Z,[],2); % 母序列为虚拟的,用每一行的最大值构成的列向量表示母序列
X = Z; % 子序列就是预处理后的数据矩阵
%% 计算得分
absX0_Xi = abs(X - repmat(Y,1,size(X,2))) % 计算|X0-Xi|矩阵
a = min(min(absX0_Xi)) % 计算两级最小差a
b = max(max(absX0_Xi)) % 计算两级最大差b
rho = 0.5; % 分辨系数取0.5
gamma = (a+rho*b) ./ (absX0_Xi + rho*b) % 计算子序列中各个指标与母序列的关联系数
weight = mean(gamma) / sum(mean(gamma)); % 利用子序列中各个指标的灰色关联度计算权重
score = sum(X .* repmat(weight,size(X,1),1),2); % 未归一化的得分
stand_S = score / sum(score); % 归一化后的得分
[sorted_S,index] = sort(stand_S ,'descend') % 进行排序
% function [输出变量] = 函数名称(输入变量)
% 函数的中间部分都是函数体
% 函数的最后要用end结尾
% 输出变量和输入变量可以有多个,用逗号隔开
% function [a,b,c]=test(d,e,f)
% a=d+e;
% b=e+f;
% c=f+d;
% end
% 自定义的函数要单独放在一个m文件中,不可以直接放在主函数里面(和其他大多数语言不同)
function [posit_x] = Positivization(x,type,i)
% 输入变量有三个:
% x:需要正向化处理的指标对应的原始列向量
% type: 指标的类型(1:极小型, 2:中间型, 3:区间型)
% i: 正在处理的是原始矩阵中的哪一列
% 输出变量posit_x表示:正向化后的列向量
if type == 1 %极小型
disp(['第' num2str(i) '列是极小型,正在正向化'] )
posit_x = Min2Max(x); %调用Min2Max函数来正向化
disp(['第' num2str(i) '列极小型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 2 %中间型
disp(['第' num2str(i) '列是中间型'] )
best = input('请输入最佳的那一个值: ');
posit_x = Mid2Max(x,best);
disp(['第' num2str(i) '列中间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 3 %区间型
disp(['第' num2str(i) '列是区间型'] )
a = input('请输入区间的下界: ');
b = input('请输入区间的上界: ');
posit_x = Inter2Max(x,a,b);
disp(['第' num2str(i) '列区间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
else
disp('没有这种类型的指标,请检查Type向量中是否有除了1、2、3之外的其他值')
end
end
function [posit_x] = Min2Max(x)
posit_x = max(x) - x;
%posit_x = 1 ./ x; %如果x全部都大于0,也可以这样正向化
end
function [posit_x] = Mid2Max(x,best)
M = max(abs(x-best));
posit_x = 1 - abs(x-best) / M;
end
function [posit_x] = Inter2Max(x,a,b)
r_x = size(x,1); % row of x
M = max([a-min(x),max(x)-b]);
posit_x = zeros(r_x,1); %zeros函数用法: zeros(3) zeros(3,1) ones(3)
% 初始化posit_x全为0 初始化的目的是节省处理时间
for i = 1: r_x
if x(i) < a
posit_x(i) = 1-(a-x(i))/M;
elseif x(i) > b
posit_x(i) = 1-(x(i)-b)/M;
else
posit_x(i) = 1;
end
end
end