基于机器学习的生态组合塘强化城市污水处理厂脱氮优化
一项利用机器学习优化城市污水处理厂脱氮的研究。针对生态组合塘(ECPs)工艺在进水水质波动下难以动态调整的问题,研究采集三年运行数据,采用 XGBoost 模型预测出水总氮浓度。通过 SHAP 分析和部分依赖图(PDP)识别关键参数,结合 NSGA-II 和 TOPSIS 算法进行多目标优化。最终开发了图形用户界面(GUI),实现了出水总氮、能耗及外加碳源用量的同步降低,年碳减排量显著,为污水处理厂的节能与达标排放提供了有效方案。

一项利用机器学习优化城市污水处理厂脱氮的研究。针对生态组合塘(ECPs)工艺在进水水质波动下难以动态调整的问题,研究采集三年运行数据,采用 XGBoost 模型预测出水总氮浓度。通过 SHAP 分析和部分依赖图(PDP)识别关键参数,结合 NSGA-II 和 TOPSIS 算法进行多目标优化。最终开发了图形用户界面(GUI),实现了出水总氮、能耗及外加碳源用量的同步降低,年碳减排量显著,为污水处理厂的节能与达标排放提供了有效方案。

题目: Machine learning-based optimization of enhanced nitrogen removal in a full-scale urban wastewater treatment plant with ecological combination ponds。
期刊: Water Research https://doi.org/10.1016/j.watres.2025.123976
【背景与痛点】在中国小城镇采用生态组合塘(ECPs)工艺的城镇污水处理厂,正面临进水水质波动下难以动态调整运行参数的困境。为满足严格的总氮(TN)排放标准,常出现曝气过量、外加碳源投加过度的问题。
【研究目的与方法】为解决这些难题,亟需为采用生态组合塘的污水处理厂建立适宜的总氮强化去除模型。本研究采集了某采用生态组合塘工艺的全尺度城镇污水处理厂三年的运行数据,通过可解释性机器学习方法对出水总氮浓度进行预测与优化。
其中,XGBoost 模型在训练集和测试集的决定系数(R²)分别达到 0.997 和 0.911,均方根误差(RMSE)分别为 0.196 和 1.283。借助 SHAP 分析与部分依赖图,本研究确定了优化的运行参数:在提升总氮去除效果的同时,实现了能耗与化学需氧量(COD)碳源投加量的平衡削减。研究还开发了图形用户界面,以支持工艺运行参数的持续预测与协同优化,最终达成了出水总氮、能耗及外加碳源用量的同步降低——其中出水总氮浓度下降 17.50%,年 COD 碳源投加量减少 33.29%。值得注意的是,采用生态组合塘工艺的污水处理厂展现出显著的碳减排潜力:仅通过强化总氮去除、降低能耗与碳源投加量,即可实现年碳减排量 788.40 吨二氧化碳。
该大型城市污水处理厂位于中国浙江,采用生态组合塘(ECPs)工艺,设计处理能力为 60,000 m³/d。整个生态组合塘系统分为 13 个区域,各区平均水深为 8.8 m,具体构造包括:第一好氧区(1–5 区)、缺氧区(6–8 区)、第二好氧区(9–12 区)以及沉淀区(13 区)。运行过程中,在第一缺氧区(6 区)和第二缺氧区(7 区)添加了一种聚合物外加碳源,并将混合液从沉淀区回流至第一缺氧区(6 区)。

本研究收集了一座采用生态组合塘(ECPs)工艺的大型城市污水处理厂的日常运行数据,数据集包含自 2021 年 1 月 1 日至 2023 年 12 月 31 日期间共 1095 组时间序列数据。该厂系统监测了包括废水温度、进水 pH 值及出水化学需氧量(COD)浓度在内的 16 项关键运行参数,并通过严格的特征选择方案,确定了 13 个作为后续预测模型驱动因素的重要参数,具体包括:进水流量(Flowrateinf)、进水氨氮(NH₄⁺-N_inf)、进水总氮(TN_inf)、5 号区溶解氧(DO_5)、5 号区总氮(TN_5)、6 号区化学需氧量(COD_6)、6 号区总氮(TN_6)、7 号区溶解氧(DO_7)、7 号区化学需氧量(COD_7)、7 号区总氮(TN_7)、外加碳源(ECS)、能耗(EC)以及出水总氮(TN_eff)。
此外,研究采用 KNN 算法对采集的数据集进行了缺失值处理与离群值清洗,剔除了占总数据集不足 1% 的包含离群值的记录。
| 参数分类 | 参数名称 (中) | 英文缩写 | 备注 / 功能说明 |
|---|---|---|---|
| 进水特征 | 进水流量 | Flowrate_inf | 反映污水处理厂的实时水力负荷 |
| 进水氨氮 | NH₄⁺-N_inf | 硝化过程的主要底物来源 | |
| 进水总氮 | TN_inf | 脱氮处理的总负荷基础 | |
| 过程监控 | 5 区溶解氧 | DO_5 | 第一好氧区末端的充氧状态 |
| (中间分区) | 5 区总氮 | TN_5 | 第一好氧区后的氮素残留情况 |
| 6 区化学需氧量 | COD_6 | 第一缺氧区的碳源水平 | |
| 6 区总氮 | TN_6 | 第一缺氧区的脱氮初步效果 | |
| 7 区溶解氧 | DO_7 | 第二缺氧区的环境状态 (需维持低 DO) | |
| 7 区化学需氧量 | COD_7 | 第二缺氧区用于反硝化的有效碳源 | |
| 7 区总氮 | TN_7 | 深度脱氮后的氮素水平 | |
| 操作/控制 | 外部碳源投加量 | ECS | 人为干预以增强反硝化的关键手段 |
| 能耗 | EC | 反映曝气和回流等操作的运行成本 | |
| 预测目标 | 出水总氮 | TN_eff | 核心预测变量,衡量排放是否达标 |
在模型开发阶段,预处理后的数据集按 8:2 的比例划分为训练集(80%)和测试集(20%)。为提升模型的泛化能力,研究首先通过 Pearson 相关性分析剔除预测增益低且存在共线性的特征;同时,引入 SHAP(SHapley Additive exPlanations)值系统评估包括出水总氮在内的 16 个初始特征的重要性,剔除冗余项。基于对特征显著性、相关性及模型复杂度的综合平衡,最终构建了包含出水总氮在内的 13 个关键特征的精简数据集。
模型开发在 Anaconda 平台的 JupyterLab 环境中基于 Python 3.8 完成,并采用提前停止(Early Stopping)策略防止过拟合。通过网格搜索(Grid Search)进行超参数优化,并结合 5 折交叉验证评估模型性能以降低结果方差。评价指标选用决定系数和均方根误差。研究对比了多元线性回归(MLR)、支持向量机(SVM)、轻量级梯度提升机(LightGBM)、随机森林(RF)、极端梯度提升(XGBoost)和类别特征提升(CatBoost)六种机器学习算法。
结果显示,MLR 的预测能力有限(测试集 R² = 0.459),而其余五种非线性模型的性能表现优异,测试集 R² 均在 0.775 至 0.829 之间。其中,XGBoost 模型表现最为突出,训练集准确率接近完美(R² = 0.999,RMSE = 0.073),但在测试集上的泛化能力略弱(R² = 0.829)。
随后,研究通过 SHAP 分析对特征贡献度进行了量化。结果发现,进水 pH 值和进水氨氮(NH₄⁺-N)的特征重要性最低,将其判定为冗余特征并予以剔除;而出水 COD 浓度和废水温度也被剔除以降低模型复杂度。
经过特征修剪后,对各模型进行了重新训练。优化后的 XGBoost 模型性能显著提升,训练集和测试集的 R² 分别达到 0.997 和 0.911,RMSE 分别为 0.196 和 1.283。结果表明,由 SHAP 特征重要性评估引导的降维策略极大地改善了模型表现。

研究采用 SHAP 和 PDP(部分依赖图)方法分析特征重要性,阐明 XGBoost 模型的预测机制,并识别影响出水总氮浓度的关键参数。结果显示,TN_7、EC(能耗)、DO_5、TN_6、进水流量以及 DO_7 是决定出水总氮浓度的最重要特征。
为了进一步探究特征对模型输出的具体影响,研究利用 PDP 考察了单特征及多特征交互作用对出水总氮的影响。出水总氮受硝化和反硝化过程的共同调节。DO_5 部分依赖图显示,维持较高的 DO_5 浓度有利于提高总氮去除效率;然而,由于该工艺中 5 号区的曝气兼具搅拌功能,导致其 DO_5 浓度时常超过 10 mg/L,这凸显了利用机器学习优化 DO_5 以降低能耗的必要性。
DO_7 与出水总氮浓度呈正相关。这是因为 7 号区为缺氧区,较高的溶解氧会干扰反硝化效率。同时,COD_6 和 COD_7 的 PDP 结果表明,适量的 COD 投加能增强脱氮性能,但过量投加则会增加废水负荷与化学品消耗,反而对反硝化产生不利影响。
在多特征交互分析方面,较低的 DO_7 与较高的 DO_5 结合可实现更高的脱氮效率。综上所述,强化脱氮效率的最优运行区间为:DO_5 控制在 5.8–8.8 mg/L,DO_7 在 0.3–2.8 mg/L,COD_6 在 28.0–35.5 mg/L,COD_7 在 0–26.4 mg/L,且 ECS 投加量控制在 1.9–2.3 m³/d。
污水处理厂的生态组合塘(ECPs)旨在通过好氧硝化和缺氧反硝化实现脱氮。如图 3 所示,TN_7、EC(能耗)和 DO_5 是影响脱氮效率的三大核心参数。由于 5 号区作为最后的好氧区且溶解氧(DO)未受控制,导致后续的 6 号区(第一缺氧区)DO 浓度升高,即便添加外加碳源也难以发生反硝化作用。相比之下,7 号区(第二缺氧区)通过控制 DO 浓度并添加外加碳源,促进了显著的反硝化过程,因此 TN_7 成为影响出水总氮浓度最关键的参数。
此外,5 号区和 7 号区不受控的 DO 浓度导致了过度曝气,从而增加了电力消耗;同时,在进水水质波动的情况下,外加碳源的不规范投加也造成了化学品的过量使用,这两者共同推高了整体能耗,使 EC 成为影响脱氮效率的第二大关键参数。
机器学习模型的研究结果强调了优化工艺参数以同步降低出水总氮(TN_eff)浓度、能耗(EC)和 COD 投药量的重要性。为了便于实际工程应用,本研究开发了一个集成 TN_eff、EC 和 COD 投药量模型的图形用户界面(GUI)。
该 GUI 基于 PDP 分析推导出的最优控制参数区间,并集成了简化版的 NSGA-II(带策略非支配排序遗传算法)和 TOPSIS(逼近理想解排序法)算法。通过该优化控制策略,用户可以灵活调整关键运行参数;在输入进水水质数据及核心工艺参数后,GUI 能够自动预测并优化出水总氮、能耗和外加碳源(ECS)的使用。
建议根据 PDP 识别出的区间进行工艺优化。例如,通过优化关键参数,出水总氮浓度从 14.29 mg/L 降至 11.59 mg/L,污水处理厂能耗每天减少了 128.66 kWh,COD 投加浓度降低了 34.29 mg/L,对应外加碳源投加量从 3.72 m³/d 降至 2.25 m³/d。全年来看,出水总氮浓度平均下降了 17.50%,而 COD 投药量减少了 33.29%。
#!/usr/bin/env python # coding: utf-8
# 导入机器学习、数据处理及可视化所需的库
from sklearn.model_selection import KFold, GridSearchCV, train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from sklearn.preprocessing import StandardScaler
import pickle
from xgboost import XGBRegressor
import shap
# --- 1. 数据加载与初步切分 ---
# 从 CSV 文件读取脱氮工艺数据集
file_path = r'data.csv'
df = pd.read_csv(file_path, encoding='GBK')
# 提取特征变量 (X) 和目标变量 (y,即出水 TN 浓度)
X = df.drop(columns='Effluent TN')
y = df['Effluent TN']
# 将数据划分为训练集 (80%) 和测试集 (20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42)
# --- 2. 特征标准化 ---
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
with open('scaler.pkl', 'wb') as f:
pickle.dump(scaler, f)
# --- 3. 超参数优化 (Grid Search) ---
param_grid = {
'n_estimators': [100, 300, 500, 1000],
'max_depth': [3, , , , ],
: [, , , ],
: [, , ],
: [, , ],
: [, , ],
: [, , ],
: [, , ]
}
base_model = XGBRegressor(objective=, random_state=)
grid_search = GridSearchCV(
estimator=base_model,
param_grid=param_grid,
scoring=,
cv=,
verbose=,
n_jobs=-
)
grid_search.fit(X_train_scaled, y_train)
best_params = grid_search.best_params_
()
(best_params)
xgboost_model = XGBRegressor(**best_params, objective=, random_state=)
kf = KFold(n_splits=, shuffle=, random_state=)
train_r2_scores, train_rmse_scores = [], []
test_r2_scores, test_rmse_scores = [], []
all_y_train_pred, all_y_test_pred = [], []
all_y_train_true, all_y_test_true = [], []
train_index, test_index kf.split(X_train_scaled):
X_train_fold, X_test_fold = X_train_scaled[train_index], X_train_scaled[test_index]
y_train_fold, y_test_fold = y_train.iloc[train_index], y_train.iloc[test_index]
X_train_part, X_val_part, y_train_part, y_val_part = train_test_split(
X_train_fold, y_train_fold, test_size=, random_state=)
xgboost_model.fit(X_train_part, y_train_part, eval_set=[(X_val_part, y_val_part)], early_stopping_rounds=, verbose=)
best_iteration = xgboost_model.best_iteration
xgboost_model.n_estimators = best_iteration
xgboost_model.fit(X_train_fold, y_train_fold)
y_train_pred = xgboost_model.predict(X_train_fold)
y_test_pred = xgboost_model.predict(X_test_fold)
all_y_train_pred.extend(y_train_pred)
all_y_test_pred.extend(y_test_pred)
all_y_train_true.extend(y_train_fold.values)
all_y_test_true.extend(y_test_fold.values)
train_r2_scores.append(r2_score(y_train_fold, y_train_pred))
train_rmse_scores.append(np.sqrt(mean_squared_error(y_train_fold, y_train_pred)))
test_r2_scores.append(r2_score(y_test_fold, y_test_pred))
test_rmse_scores.append(np.sqrt(mean_squared_error(y_test_fold, y_test_pred)))
()
()
plt.figure(figsize=(, ), dpi=)
plt.scatter(all_y_train_true, all_y_train_pred, edgecolors=, c=, marker=, s=, alpha=, label=)
plt.scatter(all_y_test_true, all_y_test_pred, edgecolors=, c=, marker=, s=, alpha=, label=)
X_plot = np.array(all_y_test_true).reshape(-, )
y_plot_pred = np.array(all_y_test_pred)
sorted_idx = np.argsort(X_plot.flatten())
X_sorted = X_plot[sorted_idx]
y_sorted = y_plot_pred[sorted_idx]
linear_model = sm.OLS(y_sorted, sm.add_constant(X_sorted)).fit()
y_pred_line = linear_model.predict(sm.add_constant(X_sorted))
predictions_summary = linear_model.get_prediction(sm.add_constant(X_sorted)).summary_frame(alpha=)
plt.plot(X_sorted, y_pred_line, color=, linewidth=, label=)
plt.fill_between(X_sorted.flatten(), predictions_summary[], predictions_summary[], color=, alpha=, label=)
plt.plot([, ], [, ], c=, linestyle=, label=)
plt.legend(); plt.show()
explainer = shap.Explainer(xgboost_model, X_train_scaled)
shap_values = explainer(X_train_scaled)
shap.summary_plot(shap_values, X_train_scaled, feature_names=X_train.columns)
#!/usr/bin/env python # coding: utf-8
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from xgboost import XGBRegressor
import numpy as np
import matplotlib.pyplot as plt
import shap
file_path = r'D:\vscode-water\TNeff-GUI-master\Modelset\Data.csv'
df = pd.read_csv(file_path, encoding='GBK')
X = df.drop(columns='Effluent TN')
y = df['Effluent TN']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
xgboost_model = XGBRegressor(
objective='reg:squarederror',
n_estimators=1000,
max_depth=6,
learning_rate=0.01,
subsample=0.8,
colsample_bytree=0.8,
random_state=42
)
xgboost_model.fit(X_train, y_train)
feature_importances = xgboost_model.feature_importances_
sorted_idx = np.argsort(feature_importances)[::-1]
plt.figure(figsize=(12, 8))
plt.bar(range(len(feature_importances)), feature_importances[sorted_idx], color='deepskyblue', alpha=0.3)
plt.xticks(range(len(feature_importances)), [X.columns[i] for i in sorted_idx], rotation=90, fontsize=18)
plt.title('Feature Importance', fontsize=20)
plt.xlabel(, fontsize=)
plt.ylabel(, fontsize=)
plt.show()
explainer = shap.TreeExplainer(xgboost_model)
shap_values = explainer.shap_values(X_train)
shap.summary_plot(shap_values, X_train, feature_names=X.columns)
#!/usr/bin/env python # coding: utf-8
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from xgboost import XGBRegressor
from sklearn.model_selection import train_test_split
from sklearn.inspection import partial_dependence
from scipy.interpolate import splev, splrep
file_path = r'D:\vscode-water\TNeff-GUI-master\Modelset\Data.csv'
df = pd.read_csv(file_path, encoding='GBK')
X = df.drop(columns='Effluent TN')
y = df['Effluent TN']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
xgboost_model = XGBRegressor(
objective='reg:squarederror',
n_estimators=1000,
max_depth=6,
learning_rate=0.01,
subsample=0.8,
colsample_bytree=0.8,
random_state=42
)
xgboost_model.fit(X_train, y_train)
features_to_plot = [
'External Carbon Source', 'COD of Zone 6', 'COD of Zone 7',
'DO of Zone 7', 'DO of Zone 5', 'Influent NH4+-N',
'Influent TN', 'Influent Flowrate', 'TN of Zone 5',
'TN of Zone 6', 'TN of Zone 7', 'Energy Consumption'
]
sns.set_theme(style="ticks", palette=, font_scale=)
():
pdp = partial_dependence(xgboost_model, X_train, [feature], kind=, grid_resolution=)
plot_x = pd.Series(pdp.grid_values[]).rename()
plot_y = pd.Series(pdp.average[]).rename()
plot_i = pdp.individual[]
tck = splrep(plot_x, plot_y, s=)
xnew = np.linspace(plot_x.(), plot_x.(), )
ynew = splev(xnew, tck, der=)
fig, ax = plt.subplots(figsize=(, ))
a plot_i:
a_series = pd.Series(a)
df_i = pd.concat([plot_x, a_series.rename()], axis=)
sns.lineplot(data=df_i, x=, y=, color=, linewidth=, linestyle=, alpha=, ax=ax)
ax.plot(xnew, ynew, color=, linewidth=, label=)
std_error = np.std(plot_y) / np.sqrt((plot_y))
lower_bound = plot_y - * std_error
upper_bound = plot_y + * std_error
ax.fill_between(plot_x, lower_bound, upper_bound, color=, alpha=, label=)
sns.rugplot(data=X_train.sample(), x=feature, height=, color=, alpha=, ax=ax)
ax.set_ylabel()
ax.set_xlabel(feature)
x_min = plot_x.() - *(plot_x.() - plot_x.())
x_max = plot_x.() + *(plot_x.() - plot_x.())
ax.set_xlim(x_min, x_max)
ax.legend()
plt.savefig(, dpi=, bbox_inches=)
plt.show()
feature features_to_plot:
plot_pdp(feature)
#!/usr/bin/env python # coding: utf-8
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from xgboost import XGBRegressor
from sklearn.model_selection import train_test_split
from sklearn.inspection import PartialDependenceDisplay
file_path = r'D:\vscode-water\TNeff-GUI-master\Modelset\Data.csv'
df = pd.read_csv(file_path, encoding='GBK')
X = df.drop(columns='Effluent TN')
y = df['Effluent TN']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
xgboost_model = XGBRegressor(
objective='reg:squarederror',
n_estimators=1000,
max_depth=6,
learning_rate=0.01,
subsample=0.8,
colsample_bytree=0.8,
random_state=42
)
xgboost_model.fit(X_train, y_train)
target_feature = 'External Carbon Source'
related_features = ['COD of Zone 6', 'COD of Zone 7']
for feature in related_features:
if feature == target_feature: continue
feature_idx = X.columns.get_loc(feature)
target_idx = X.columns.get_loc(target_feature)
plt.figure(figsize=(8, 6))
PartialDependenceDisplay.from_estimator(
xgboost_model, X_train, [(target_idx, feature_idx)],
feature_names=X.columns, kind='average'
)
plt.title(f'2D Partial Dependence: {target_feature}_feature vs ')
plt.show()
import numpy as np
def topsis(data, weights):
if len(data) == 0: return np.array([])
if data.ndim == 1: data = data.reshape(1, -1)
norm_data = (data - data.min(axis=0)) / (data.max(axis=0) - data.min(axis=0) + 1e-10)
weighted_data = norm_data * weights
ideal_best = np.min(weighted_data, axis=0)
ideal_worst = np.max(weighted_data, axis=0)
dist_best = np.sqrt(np.sum((weighted_data - ideal_best) ** 2, axis=1))
dist_worst = np.sqrt(np.sum((weighted_data - ideal_worst) ** 2, axis=1))
scores = dist_worst / (dist_best + dist_worst + 1e-10)
return scores
data = np.array([
[12.5, 300, 50],
[10.0, 450, 80],
[8.5, 600, 120],
[11.0, 350, 60]
])
weights = np.array([0.5, 0.3, 0.2])
scores = topsis(data, weights)
print("各策略的 TOPSIS 综合得分 (得分越高越优):")
for i, score (scores):
()
best_index = np.argmax(scores)
()
import numpy as np
import random
from deap import base, creator, tools, algorithms
import xgboost as xgb
import pandas as pd
from sklearn.preprocessing import StandardScaler
default_data = {
'Influent NH4+-N': 29.6,
'Influent TN': 35.9,
'Influent Flowrate': 38808.4,
'DO of Zone 5': 7.1,
'TN of Zone 5': 22.2,
'COD of Zone 6': 55.0,
'TN of Zone 6': 13.8,
'DO of Zone 7': 4.06,
'COD of Zone 7': 31.9,
'TN of Zone 7': 11.7,
'External Carbon Source': 3.3
}
variable_ranges = [
(5.8, 7.5),
(28.0, 35.5),
(0.3, 2.8),
(1.0, 26.4),
(1.9, 2.3)
]
df = pd.DataFrame([default_data])
scaler = StandardScaler()
scaler.fit(df)
model_tn = xgb.Booster()
model_power = xgb.Booster()
prediction_cache = {}
def predict_outputs(data):
if data.ndim == 1: key = tuple(data); data = data.reshape(, -)
: model_power.predict(xgb.DMatrix(data)), model_tn.predict(xgb.DMatrix(data))
key prediction_cache:
np.array([prediction_cache[key][]]), np.array([prediction_cache[key][]])
dmatrix = xgb.DMatrix(data)
pred_energy = model_power.predict(dmatrix)
pred_tn = model_tn.predict(dmatrix)
prediction_cache[key] = (pred_energy[], pred_tn[])
pred_energy, pred_tn
():
full_input = np.concatenate([fixed_water_params, individual])
energy, tn = predict_outputs(np.array(full_input))
delta_energy = energy[] - true_energy
delta_tn = tn[] - true_tn
delta_energy, delta_tn
():
(creator, ):
creator.create(, base.Fitness, weights=(-, -))
(creator, ):
creator.create(, , fitness=creator.FitnessMin)
toolbox = base.Toolbox()
toolbox.register(, : [random.uniform(r[], r[]) r variable_ranges])
toolbox.register(, tools.initIterate, creator.Individual, toolbox.attr_float)
toolbox.register(, tools.initRepeat, , toolbox.individual)
toolbox.register(, tools.cxSimulatedBinaryBounded, low=[r[] r variable_ranges], up=[r[] r variable_ranges], eta=)
():
individual = tools.mutPolynomialBounded(individual, low=[r[] r variable_ranges], up=[r[] r variable_ranges], eta=, indpb=)[]
i ((individual)):
low, up = variable_ranges[i]
individual[i] = (low, (up, individual[i]))
(individual[i], ) np.isnan(individual[i]) np.isinf(individual[i]):
individual[i] = (low + up) /
individual
toolbox.register(, custom_mutate)
toolbox.register(, tools.selNSGA2)
full_input = np.concatenate([fixed_water_params, initial_operating_params])
true_energy, true_tn = predict_outputs(full_input)
():
evaluate(ind, fixed_water_params, true_energy[], true_tn[])
toolbox.register(, fitness_func)
pop = toolbox.population(n=)
pop[][:] = initial_operating_params.copy()
ind pop: ind.fitness.values = toolbox.evaluate(ind)
hof = tools.ParetoFront()
hof.update(pop)
best_fitness = ([ind.fitness.values[] ind pop])
stall_count =
gen ():
offspring = algorithms.varOr(pop, toolbox, lambda_=, cxpb=, mutpb=)
ind offspring:
ind.fitness.valid: ind.fitness.values = toolbox.evaluate(ind)
pop = toolbox.select(pop + offspring, k=)
hof.update(pop)
current_best = ([ind.fitness.values[] ind pop])
current_best < best_fitness * :
best_fitness = current_best
stall_count =
:
stall_count +=
stall_count >= :
n_samples = (, (hof))
pareto_samples = [hof[i] i np.linspace(, (hof) - , n_samples, dtype=)]
pareto_samples, true_energy[], true_tn[]
#!/usr/bin/env python # coding: utf-8
import tkinter as tk
from tkinter import ttk
import xgboost as xgb
import pandas as pd
from sklearn.preprocessing import StandardScaler
default_data = {
'Influent NH4+-N': 29.6,
'Influent TN': 35.9,
'Influent Flowrate': 38808.4,
'DO of Zone 5': 7.1,
'TN of Zone 5': 22.2,
'COD of Zone 6': 55.0,
'TN of Zone 6': 13.8,
'DO of Zone 7': 4.06,
'COD of Zone 7': 31.9,
'TN of Zone 7': 11.7,
'External Carbon Source': 3.3
}
df = pd.DataFrame([default_data])
scaler = StandardScaler()
scaler.fit(df)
model_tn = xgb.Booster()
model_tn.load_model('model_effluent_TN.json')
model_power = xgb.Booster()
model_power.load_model('model_energy_consumption.json')
run_count = 0
first_external_carbon_source = None
original_tn = tk.StringVar()
original_power = tk.StringVar()
optimized_tn = tk.StringVar()
optimized_power = tk.StringVar()
energy_savings_var = tk.StringVar()
carbon_savings_var = tk.StringVar()
output_text = tk.StringVar()
units = {
"Influent NH4+-N": "5.4 - 60.7 mg/L",
"Influent TN": "9.8 - 108.0 mg/L",
"TN of Zone 5": "4.8 - 44.6 mg/L",
: ,
: ,
: ,
: ,
: ,
: ,
: ,
:
}
root = tk.Tk()
root.title()
root.geometry()
root.configure(bg=)
main_frame = tk.Frame(root, bg=, padx=, pady=)
main_frame.pack(expand=)
title_label = tk.Label(main_frame, text=, font=(, , ), bg=)
title_label.grid(row=, column=, columnspan=, pady=)
left_labels = [
(, ),
(, ),
(, ),
(, ),
(, )
]
right_labels = [
(, ),
(, ),
(, ),
(, ),
(, ),
(, )
]
feature_entry_map = {}
tk.Label(main_frame, text=, font=(, , ), bg=).grid(row=, column=, columnspan=, pady=)
i, (label, feature) (left_labels, start=):
tk.Label(main_frame, text=label, font=(, ), bg=).grid(row=i, column=, padx=, pady=, sticky=)
entry = tk.Entry(main_frame, font=(, ), width=)
entry.grid(row=i, column=, padx=, pady=, sticky=)
feature_entry_map[feature] = entry
unit_text = units.get(feature, )
tk.Label(main_frame, text=, font=(, ), bg=).grid(row=i, column=, padx=, pady=, sticky=)
tk.Label(main_frame, text=, font=(, , ), bg=).grid(row=, column=, columnspan=, pady=)
i, (label, feature) (right_labels, start=):
tk.Label(main_frame, text=label, font=(, ), bg=).grid(row=i, column=, padx=, pady=, sticky=)
entry = tk.Entry(main_frame, font=(, ), width=)
entry.grid(row=i, column=, padx=, pady=, sticky=)
feature_entry_map[feature] = entry
unit_text = units.get(feature, )
tk.Label(main_frame, text=, font=(, ), bg=).grid(row=i, column=, padx=, pady=, sticky=)
():
run_count, first_external_carbon_source
run_count =
first_external_carbon_source =
entry feature_entry_map.values():
entry.delete(, tk.END)
original_tn.()
original_power.()
optimized_tn.()
optimized_power.()
energy_savings_var.()
carbon_savings_var.()
output_text.()
():
run_count, first_external_carbon_source
run_count >= :
output_text.()
inputs = []
feature, entry feature_entry_map.items():
value = entry.get().strip()
value:
inputs.append(default_data[feature])
:
:
validated = (value)
inputs.append(validated)
ValueError:
output_text.()
:
inputs_df = pd.DataFrame([inputs], columns=default_data.keys())
inputs_scaled = scaler.transform(inputs_df)
dmatrix = xgb.DMatrix(inputs_scaled)
effluent_tn_pred = model_tn.predict(dmatrix)[]
power_consumption_pred = model_power.predict(dmatrix)[]
run_count == :
original_tn.()
original_power.()
first_external_carbon_source = inputs_df[].iloc[]
run_count == :
optimized_tn.()
optimized_power.()
original_power_value = (original_power.get()) original_power.get()
energy_savings = original_power_value - power_consumption_pred
energy_savings_var.()
second_external_carbon_source = inputs_df[].iloc[]
carbon_savings = first_external_carbon_source - second_external_carbon_source
carbon_savings_var.()
run_count +=
Exception e:
output_text.()
predict_button = tk.Button(main_frame, text=, font=(, ), command=predict, bg=, fg=, width=)
predict_button.grid(row=, column=, columnspan=, pady=)
reset_button = tk.Button(main_frame, text=, font=(, ), command=clear_inputs, bg=, fg=, width=)
reset_button.grid(row=, column=, columnspan=, pady=)
output_frame = tk.Frame(main_frame, bg=)
output_frame.grid(row=, column=, columnspan=, padx=, pady=)
tk.Label(output_frame, text=, font=(, ), bg=).grid(row=, column=, sticky=)
tk.Entry(output_frame, textvariable=original_tn, font=(, ), state=).grid(row=, column=)
tk.Label(output_frame, text=, font=(, ), bg=).grid(row=, column=, sticky=)
tk.Entry(output_frame, textvariable=optimized_tn, font=(, ), state=).grid(row=, column=)
tk.Label(output_frame, text=, font=(, ), bg=).grid(row=, column=, sticky=)
tk.Entry(output_frame, textvariable=original_power, font=(, )).grid(row=, column=)
tk.Label(output_frame, text=, font=(, ), bg=).grid(row=, column=, sticky=)
tk.Entry(output_frame, textvariable=optimized_power, font=(, ), state=).grid(row=, column=)
tk.Label(output_frame, text=, font=(, ), bg=).grid(row=, column=, sticky=)
tk.Entry(output_frame, textvariable=energy_savings_var, font=(, ), state=).grid(row=, column=)
tk.Label(output_frame, text=, font=(, ), bg=).grid(row=, column=, sticky=)
tk.Entry(output_frame, textvariable=carbon_savings_var, font=(, ), state=).grid(row=, column=)
output_label = tk.Label(output_frame, textvariable=output_text, font=(, ), bg=, fg=)
output_label.grid(row=, column=, columnspan=)
root.mainloop()

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online