长江水质定级与预测:模糊综合评价和GM(1,1)模型的工程实战
2026/9/18 6:04:04 网站建设 项目流程

简介:这份《长江水质的评价和预测》数学建模文档,系统展示了针对长江水质评价与预测问题的完整建模思路。文档基于国标地表水环境质量标准,围绕五个子问题构建模糊综合评价模型、污染源判别模型与灰色系统预测模型,对长江近两年水质进行定量评价,识别高锰酸盐和氨氮主要污染源地区,并对未来十年水质河长比例与所需污水处理量做出预测。资源共1个doc文档,压缩包约595KB,内容包含问题重述、模型假设、符号说明、模型求解与结果表格,结构完整。适合数学建模竞赛备赛者、环境类专业学生及水质数据分析人员参考,从数据预处理到模型构建与结果解读均有清晰推导,可作为完整赛题方案学习模糊综合评价与灰色预测的实际应用。已有348人学习下载。

1. 模糊综合评价:长江水质定级的第一步不是查表

长江水质的评价和预测,本质上是一条「定级-溯源-预测-配额」的数据链路:先用模糊综合评价把 17 个观测站点的水质类别定出来,再用一维稳态水质模型反推高锰酸盐和氨氮的主要排放源,然后用 GM(1,1) 灰色系统预测未来 10 年各级水质河长比例,最后把比例换算成每年必须处理的污水总量。这套思路适合正在做环境数据分析、有小样本时序预测需求,或者想复现数学建模完整流程的工程师——它解决的不只是「水质属于几类」的分类问题,而是从监测数据到治理决策的完整推算过程。我拆这份资源时最大的感触是:水质定级这类边界模糊的问题,硬规则往往不如概率分布可靠,而模糊综合评价恰好是处理这种不确定性的成熟工具。

2. 模糊综合评价的隶属函数设计与权重标定

2.1 为什么排除 PH 值再做模糊评价

国标 GB3838-2002 给出了 4 个主要项目标准限值,乍看可以直接按浓度查表定级。但仔细看限值表会发现一个反直觉的事实:PH 值在Ⅰ类到劣Ⅴ类的标准限值全部是 6~9,没有任何区分度。而原始数据里 17 个站点 28 个月的 PH 监测值全部落在 6~9 区间内,也就是说无论水质好坏,这一项都不会把水质等级向下拉。

所以数据预处理阶段就直接把 PH 从评价因子集里拿掉,只保留溶解氧(DO)、高锰酸盐指数(CODMn)和氨氮(NH3-N)三个指标。这里的经验是:做多指标综合评价时,先看每个指标的等级区分度——如果某个指标在所有等级上的限值几乎一致,它只会稀释权重,不会贡献判别信息,应当剔除。这比无脑套四指标模型更贴近实际决策场景。

另外要注意 DO 和其他两个指标的优化方向相反:DO 是越大越好(以最大值为最优),CODMn 和 NH3-N 是越小越好(以最小值为最优)。这个方向差异在后续权重计算和隶属函数设计里要分别处理,不能用一个公式通吃。

2.2 权重归一化与正逆向指标处理

权重的设计逻辑是「超标越多,权重越大」。对以最小值为最优的指标(CODMn、NH3-N),用实测值与该指标各级标准最大值之比作为权重基础;对以最大值为最优的指标(DO),则反过来用最大值与实测值之比。公式化表达为:

  • 正向指标(越大越好):w_i = Smax_i / S_i
  • 逆向指标(越小越好):w_i = S_i / Smax_i

其中 S_i 是第 i 个指标的实测均值,Smax_i 是该指标各级标准中的最大标准值。算完三个权重后做归一化,让权重之和等于 1。注意 DO 的公式里实测值在分母,所以 DO 浓度越低权重越大,符合「溶解氧低说明污染重」的直觉。

以四川攀枝花站为例:DO 实测均值 9.15,CODMn 为 2.43,NH3-N 为 0.18。代入公式再归一化后,权重向量大体会落在 W = [0.21, 0.43, 0.36] 附近(具体数值随 Smax 取值略有浮动)。氨氮浓度虽低,但因为标准限值区间很窄,归一化后权重并不小。

2.3 用 Python 实现梯形隶属函数

隶属函数是模糊综合评价的核心。水质等级之间不是硬边界,比如Ⅲ类和Ⅳ类之间没有一条「断崖」,而是渐变过渡。这里采用梯形隶属函数,把每个指标在每个等级上的隶属度算出来,组成模糊关系矩阵 R。

import numpy as np # 国标限值:DO / CODMn / NH3-N,单位 mg/L # 行索引 0..5 对应 I, II, III, IV, V, 劣V 类 limits = { 'DO': [7.5, 6, 5, 3, 2, 0], 'CODMn': [2, 4, 6, 10, 15, np.inf], 'NH3-N': [0.15, 0.5, 1.0, 1.5, 2.0, np.inf] } def assign_level(value, name): """对单个指标值做等级分配(用于后续隶属度计算的初判)""" lv = limits[name] if np.isinf(lv[-1]) and value >= lv[-2]: return len(lv) - 1 for i in range(len(lv) - 1): if value <= lv[i]: return i return len(lv) - 1 def trapezoid_membership(value, low, high): """梯形隶属度:落在 [low, high] 内为 1,两侧线性过渡到 0""" if value <= low: return max(0.0, 1 - (low - value) / max(low, 1e-6)) if value >= high: return max(0.0, 1 - (value - high) / max(high, 1e-6)) return 1.0

这段代码的要点:assign_level 先做初判确定该指标最优落在哪个等级区间,trapezoid_membership 负责在区间边界做线性过渡。参数 low 和 high 对应国标里相邻等级的标准限值,比如 CODMn 在Ⅱ类对应区间是 2~4,实测 3.2 时对Ⅱ类的隶属度就是 1.0,同时它对Ⅲ类(4~6)的隶属度按线性衰减,从而保留「接近边界」的模糊信息。np.inf 用在劣Ⅴ类上限,避免数值溢出。

有了隶属函数后,对 17 个站点、3 个指标分别计算 6 个等级的隶属度,组成 3×6 的模糊关系矩阵 R,再与归一化权重向量 W 做模糊合成,得到多指标模糊概率综合评价矩阵 M = W ∘ R。合成算子常见取加权平均型:

def fuzzy_compose(weights, R): """加权平均型模糊合成:M[j] = sum(W[i] * R[i][j])""" return np.dot(weights, R)

逻辑说明:weights 是长度为 3 的一维数组,R 是 3×6 的二维数组,np.dot 对每个等级 j 做加权求和,输出长度为 6 的 M 向量。M[j] 表示该站点水质归属于第 j 类的综合模糊概率。定级时取最大隶属度原则——M 中最大值对应的索引就是水质类别;同时计算综合质量系数 M 与等级向量 [1,2,3,4,5,6] 的内积,这个系数越高说明水质越差,用于跨站点横向排名。

2.4 17 个站点的模糊概率与综合质量系数

按上述流程跑完全部站点,抽取几个有代表性的结果:

站点Ⅰ类Ⅱ类Ⅲ类Ⅳ类Ⅴ类劣Ⅴ类评价等级综合质量系数排名
四川攀枝花0.9100.8800.0000.0000.0000.0002.6688
湖北丹江口胡家岭1.0000.0000.0000.0000.0000.0001.00017
四川乐山岷江大桥0.0000.2901.0000.0000.0000.0003.5802
江西南昌滁槎0.3700.7200.3900.0000.1100.1704.5301
江苏南京林山1.0000.1400.0000.0000.0000.0001.28016

注意两个细节:一是丹江口和南京林山虽然都定级为Ⅰ类,但综合质量系数不同,说明系数提供了等级之外的排序信息,适合做细粒度污染排名;二是江西南昌滁槎对不同等级都有非零概率,最大隶属度原则把它判为Ⅳ类,但它的Ⅱ类概率其实有 0.72,这种「跨界」信号在传统查表法里会被直接丢弃。这也是模糊综合评价相对硬分类的核心优势——保留不确定性,而不是强行二值化。

从结果统计看,17 个站点中 23.53% 为Ⅰ类、70.59% 为Ⅱ类、5.88% 为Ⅲ类,没有站点落入Ⅳ类以下。整体水质偏好,但支流站点(乐山岷江大桥、南昌滁槎)明显比干流差,这个结论直接为后续污染溯源提供了方向。

3. 污染源判别模型:一维稳态水质方程与排放量反推

3.1 浓度沿程衰减与质量流量换算

模糊综合评价能回答「哪里水质差」,但不能回答「污染物是谁排的」。要定位污染源,需要利用长江干流 7 个观测站点的距离、水流量和水流速数据,建立污染物沿程衰减关系。这里采用一维稳态河流水质模型:污染物浓度随距离按指数规律衰减,即

c_x = c_0 · e^(-K · x / v)

其中 c_0 是上游起点浓度,K 是降解系数(单位 1/天),x 是站点间距离(km),v 是江水流速(km/天)。原始资源里提到 K 通常介于 0.1~0.5,取 0.2 作为默认值。这里的物理含义是:污染物在流动过程中通过物理降解、化学降解和生物降解自然消减,从上游流到下游时浓度已经变小,所以下游站点测到的污染物不全是本地排的,有相当一部分是上游残留。

质量流量换算也很关键。站点浓度单位是 mg/L,要换算成每秒通过断面的污染物质量(g/s),需要乘上断面流量:

M_k = c_k · Q_k

其中 Q_k 是第 k 个站点的水流量(m³/s),换算时注意单位统一:1 mg/L = 1 g/m³,所以 M_k = c_k (mg/L) × Q_k (m³/s) 的结果单位就是 g/s。这一步不做,后面所有排放量比较都是空中楼阁。

3.2 由站点总量分离本地排放量

核心假设是:第 k 个站点的污染物总量 M_k 等于「上游流入本站的残留量」加「本站自身排放量」。而上游流入本站的残留量,可以用第 k-1 个站点的质量流量,按一维稳态模型衰减折算到本站位置:

M_k^up = M_{k-1} · e^(-K · Δx_k / v_k)

于是本站自身排污量:

m_k = M_k - M_k^up

需要注意边界条件:起始站点(四川攀枝花)没有上游,所以它的自身排放量就等于 M_1 本身。这就是假设 2「干流上起始站点所含的污染物只是其本身排放的污染物」的含义。

用 Python 实现如下:

import numpy as np # 7 个干流站点基本数据(示意结构;实际以附件3为准) stations = ['攀枝花', '朱沱', '宜昌南津关', '岳阳城陵矶', '九江河西水厂', '安庆皖河口', '南京林山'] distances = [0, 422, 712, 358, 132, 164, 300] # km,相邻站间距 flow_speed = 1.2 # m/s,干流平均流速(简化取值) K = 0.2 # 1/day,降解系数 Q = [4200, 6800, 7200, 9100, 9800, 10500, 12000] # m^3/s,示意流量 CODMn_conc = [2.1, 2.3, 2.8, 3.1, 2.9, 3.4, 3.6] # mg/L def compute_local_discharge(conc, distances, K, v, Q): v_km_day = v * 86.4 # m/s -> km/day M = np.array(conc) * np.array(Q) # g/s,断面质量流量 local = np.zeros_like(M) local[0] = M[0] for i in range(1, len(M)): delta_x = distances[i] residual = M[i-1] * np.exp(-K * delta_x / v_km_day) local[i] = M[i] - residual return local discharge = compute_local_discharge(CODMn_conc, distances, K, flow_speed, Q)

逻辑说明:v_km_day 把流速从 m/s 换算成 km/天,因为 K 的单位是 1/天,x 的单位是 km,必须保证量纲一致。np.exp 计算的是上游污染物衰减到本站的剩余比例,local[i] 就是本站实际排入长江的污染物质量流量。如果 local 出现负值,通常是浓度测量误差或 K 取值偏大导致衰减过多,这时要把负值按 0 处理,并检查该站点的数据可信度。

3.3 排放量结果与污染源判定

按上述流程计算高锰酸盐和氨氮在 7 个站点上的自身排放量:

站点高锰酸盐排放量 (g/s)氨氮排放量 (g/s)
四川攀枝花66974464
重庆朱沱2915827337
湖北宜昌南津关45284268
湖南岳阳城陵矶5435180845
江西九江河西水厂3593459950
安徽安庆皖河口5628173298
江苏南京三江营155769899

判定规则是:高锰酸盐排放量超过 40 kg/s、氨氮排放量超过 3 kg/s 的站点列为对应污染物的主要污染源。按此规则,高锰酸盐的主要污染源依次是安徽安庆、湖南岳阳、江西九江、江苏南京、湖北宜昌;氨氮的主要污染源依次是湖南岳阳、安徽安庆、江西九江、重庆朱沱、湖北宜昌。这里有个单位转换的坑要提醒:模型计算结果是 g/s,判定阈值是 kg/s,两者差 1000 倍,很多初做这个项目的人会在这里对不上数。

能源头数据发现:攀枝花作为上游起点,虽然浓度不是最低,但因为流量小,绝对排放量反而是 7 个站点里最少的。这说明污染源判别必须用质量流量而非浓度——浓度高的小支流在总污染负荷里可能远不如浓度中等的大干流。这个思路可以平移到任何「多个监测断面、需要区分本地排放和上游输入」的水环境场景。

4. GM(1,1) 灰色预测:级比检验与小样本时序建模

4.1 为什么小样本选灰色模型而不是 ARIMA

问题三是预测 2005 年到 2014 年各级水质河长比例,但手头只有 1995 到 2004 年一共 10 个年度数据点。对 ARIMA 或 LSTM 这类统计/深度模型,10 个样本根本不够支撑参数估计;而灰色系统理论的核心优势就是「少数据、贫信息」——它不需要大样本,也不要求数据满足正态分布或平稳性假设。

GM(1,1) 的基本思路:把原始数列做一次累加生成(1-AGO),把原来波动较大的数据序列变成单调递增序列,然后用一阶微分方程拟合这条累加序列,再通过后减运算还原出预测值。这听起来有点绕,但本质上是「先累加消噪,再拟合趋势,再差分还原」。

4.2 级比检验与平移变换

在建模之前必须先做级比检验,否则模型可能不适用。设原始数据列为 X⁰ = [x⁰(1), x⁰(2), ..., x⁰(n)],级比为:

λ(k) = x⁰(k-1) / x⁰(k)

如果所有级比都落在可容覆盖区间 (e^(-2/(n+1)), e^(2/(n+1))),则数据序列可以直接用 GM(1,1)。n=10 时,可容覆盖区间约为 (0.833, 1.199)。原始资源里对 1995~2004 年枯水期各级水质河长比例做检验时,原始序列的级比范围是 0.89~1.18,勉强落在区间内但余量很小;部分类别(如Ⅰ类水比例接近 0 的那些年份)会越界,因为比例数据大量集中在低位,相邻年份比值波动剧烈。

处理办法是平移变换:对所有数据加一个常数 C,使得新序列的级比落入可容区间。这里取 C=50。平移后枯水期级比范围变成 0.89~1.18,与可容区间 (0.833, 1.199) 对照,全部落在区间内。注意平移变换不会改变序列的相对趋势,只改变幅度,所以预测后再减回 C 即可得到真实比例。

4.3 最小二乘求解与后减还原

GM(1,1) 的完整 Python 实现如下:

import numpy as np def gm11(x0, n_pred=10): """ x0: 原始数据列,长度 n n_pred: 预测步数 返回:预测值序列(含原始区间内的拟合值) """ x0 = np.asarray(x0, dtype=float) n = len(x0) # 1-AGO 累加生成 x1 = np.cumsum(x0) # 构造 B 矩阵和 Y 向量 B = np.column_stack([-0.5 * (x1[:-1] + x1[1:]), np.ones(n - 1)]) Y = x0[1:] # 最小二乘估计参数 [a, u] theta = np.linalg.inv(B.T @ B) @ B.T @ Y a, u = theta[0], theta[1] # 累加序列的拟合值 x1_fit = np.zeros(n + n_pred) x1_fit[0] = x1[0] for k in range(1, n + n_pred): x1_fit[k] = (x0[0] - u / a) * np.exp(-a * k) + u / a # 后减运算还原 x0_fit = np.zeros(n + n_pred) x0_fit[0] = x0[0] x0_fit[1:] = np.diff(x1_fit) return x0_fit, a, u

参数含义:a 是发展灰数,反映序列的增长或衰减趋势,a 的绝对值越大,趋势越强;u 是内生控制灰数,相当于系统的外部驱动项。B 矩阵的每一行是累加序列相邻两项的均值取负,这是灰色模型对微分方程离散化的标准做法;Y 向量是原始序列从第二项开始的值。np.linalg.inv(B.T @ B) @ B.T @ Y 就是最小二乘闭式解,不需要迭代。

调用时要注意:原始数据如果有零值,累加序列会出现连续相等段,导致 B 矩阵奇异。这时要用平移变换或对零值做小幅常数偏移,避免矩阵求逆报错。另外后减运算用的是 np.diff,它会把累加序列的相邻差作为原始序列的拟合值,这一步丢失了第一个点的还原,所以手动把 x0_fit[0] 赋值为 x0[0]。

4.4 残差与级比偏差双重验证

单有预测值不足以说明模型可靠,还要做两类检验。残差检验计算相对误差 ε(k) = (x⁰(k) - x̂⁰(k)) / x⁰(k),要求多数点 ε(k) < 0.1;级比偏差检验先由原始数据算级比 λ(k),再结合发展系数 a 算理论级比,两者偏差小于 0.1 认为合格。以枯水期Ⅰ类水比例为例,2005 到 2014 年的相对误差全部落在 0.00~0.07 之间,级比偏差绝对值最大 0.15,大部分在 0.1 以内,模型通过验证。

预测得到的水文年各级水质河长比例:

年份Ⅰ类Ⅱ类Ⅲ类Ⅳ类Ⅴ类劣Ⅴ类
20050.027.9117.266.313.217.40
20060.028.7515.155.442.727.42
20070.029.6013.054.572.247.43
20080.030.4410.973.701.757.45
20090.031.308.912.831.277.46
20100.032.156.881.970.797.48
20110.033.014.861.110.317.49
20120.033.872.860.260.007.51
20130.034.730.890.000.007.52
20140.035.600.000.001.877.54

数据背后两个信息:一是Ⅱ类水比例逐年上升,说明总体水质在变好;二是劣Ⅴ类比例从 7.40 缓慢爬升到 7.54,说明重污染河段在顽固扩张。前者解释了为什么干流站点评价结果偏好,后者支撑了「需要严格控制污水排放」的结论。如果只做均值或线性回归,很难同时抓住这两种不同速率的趋势,这是灰色模型在这个场景里真正起作用的地方。

5. 从河长比例到治污配额:污水量测算与模型边界

5.1 六类水压缩成三类,处理量公式化

问题四给的条件是:未来 10 年内,Ⅳ类和Ⅴ类水的比例控制在 20% 以内,且没有劣Ⅴ类水。原始资源把六类水按用途压缩成三类——A 类(可饮用水,含Ⅰ、Ⅱ、Ⅲ类)、B 类(可用水,含Ⅳ、Ⅴ类)、C 类(废水,劣Ⅴ类)。需要处理的污水量由两部分组成:B 类超过 20% 的部分全部处理,C 类全部处理。写成公式:

L = max(0, P_B - 20%) × Q_total + P_C × Q_total

其中 P_B、P_C 是 B、C 类水质占河长的百分比,Q_total 是当年长江总水量。用灰色预测分别得到 2005~2014 年的总流量和各级水质比例,代入即得每年处理量。实测结果是逐年递增:2005 年 298.9 亿吨,2014 年 470.8 亿吨,十年涨了 57%。这个单调上升曲线直接说明:在不加干预的前提下,污水治理压力只增不减。

5.2 预测结果如何落入管理指标

这个测算过程的价值在于把「水质类别」这种定性指标,转化成了「每年必须处理多少亿吨污水」的定量配额。对环保部门来说,决策依据不是某段河属于Ⅳ类,而是「要在 20% 红线内,明年至少新增 xx 亿吨处理能力」。类似的逻辑也能迁移到别的场景——工业园区排放总量控制、污水处理厂扩容规划、流域横向生态补偿金额计算,本质都是「先预测比例,再按比例配额」的结构。

5.3 模型的适用边界

复盘时有三点边界值得注意。第一,GM(1,1) 的外推步数最好不要超过样本量的一半;用 10 年数据外推 10 年已经接近极限,预测区间越往后可信度越低,尤其是 2014 年的预测值只能当趋势参考,不能当精确值用。第二,降解系数 K 取常数 0.2 是工程简化,实际中 K 随水温、季节、流量变化很大;如果要做更精细的溯源,需要分段标定 K 值。第三,模糊综合评价的最大隶属度原则在相邻等级概率接近时会误判,比如江西南昌滁槎同时对Ⅱ类和Ⅳ类都有较高隶属度,这时只看评级会丢失信息,建议配合综合质量系数使用。把这三点记在项目文档里,比直接用模型结论写报告要稳妥得多。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询