这是完整代码:import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler
import joblib
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import warnings
from datetime import datetime
import os
warnings.filterwarnings('ignore')
class WaterPlantModel:
"""单个水厂的模型和数据"""
def __init__(self, plant_name):
self.plant_name = plant_name
self.model_dosage_1 = None
self.model_dosage_2 = None
self.model_water_quality = None
self.scaler_dosage = None
self.scaler_water_quality = None
self.data = None
self.feedback_data = []
def load_data(self, filepath):
"""加载数据"""
self.data = pd.read_csv(filepath)
print(f"{self.plant_name}水厂数据加载成功,共{len(self.data)}条记录")
def preprocess_data(self):
"""数据预处理"""
if self.data is None:
raise ValueError("请先加载数据")
# 创建滞后特征(4小时后的出水浊度)
self.data['future_turbidity'] = self.data['出水浊度'].shift(-1)
self.data = self.data.dropna()
# 分离特征和目标变量
# 需矾量模型的特征
features_dosage = [
'原水浊度', '原水ph', '1#沉淀池流量', '2#沉淀池流量',
'矾原液密度', '矾液浓度'
]
# 水质模型的特征
features_water_quality = features_dosage + ['1#需矾量', '2#需矾量']
# 目标变量
target_dosage_1 = '1#需矾量'
target_dosage_2 = '2#需矾量'
target_water_quality = 'future_turbidity'
return features_dosage, features_water_quality, target_dosage_1, target_dosage_2, target_water_quality
def train_models(self):
"""训练模型"""
if self.data is None:
raise ValueError("请先加载数据")
features_dosage, features_water_quality, target_dosage_1, target_dosage_2, target_water_quality = self.preprocess_data()
# 训练需矾量模型1
X_dosage_1 = self.data[features_dosage]
y_dosage_1 = self.data[target_dosage_1]
X_train, X_test, y_train, y_test = train_test_split(
X_dosage_1, y_dosage_1, test_size=0.2, random_state=42
)
self.scaler_dosage = StandardScaler()
X_train_scaled = self.scaler_dosage.fit_transform(X_train)
X_test_scaled = self.scaler_dosage.transform(X_test)
self.model_dosage_1 = RandomForestRegressor(n_estimators=100, random_state=42)
self.model_dosage_1.fit(X_train_scaled, y_train)
y_pred = self.model_dosage_1.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"{self.plant_name}水厂1#需矾量模型 - MSE: {mse:.4f}, R²: {r2:.4f}")
# 训练需矾量模型2
y_dosage_2 = self.data[target_dosage_2]
X_train, X_test, y_train, y_test = train_test_split(
X_dosage_1, y_dosage_2, test_size=0.2, random_state=42
)
X_train_scaled = self.scaler_dosage.transform(X_train)
X_test_scaled = self.scaler_dosage.transform(X_test)
self.model_dosage_2 = RandomForestRegressor(n_estimators=100, random_state=42)
self.model_dosage_2.fit(X_train_scaled, y_train)
y_pred = self.model_dosage_2.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"{self.plant_name}水厂2#需矾量模型 - MSE: {mse:.4f}, R²: {r2:.4f}")
# 训练水质模型
X_water_quality = self.data[features_water_quality]
y_water_quality = self.data[target_water_quality]
X_train, X_test, y_train, y_test = train_test_split(
X_water_quality, y_water_quality, test_size=0.2, random_state=42
)
self.scaler_water_quality = StandardScaler()
X_train_scaled = self.scaler_water_quality.fit_transform(X_train)
X_test_scaled = self.scaler_water_quality.transform(X_test)
self.model_water_quality = RandomForestRegressor(n_estimators=100, random_state=42)
self.model_water_quality.fit(X_train_scaled, y_train)
y_pred = self.model_water_quality.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"{self.plant_name}水厂水质模型 - MSE: {mse:.4f}, R²: {r2:.4f}")
def save_models(self, path_prefix=None):
"""保存模型"""
if path_prefix is None:
path_prefix = self.plant_name
joblib.dump(self.model_dosage_1, f"{path_prefix}_dosage_1.pkl")
joblib.dump(self.model_dosage_2, f"{path_prefix}_dosage_2.pkl")
joblib.dump(self.model_water_quality, f"{path_prefix}_water_quality.pkl")
joblib.dump(self.scaler_dosage, f"{path_prefix}_scaler_dosage.pkl")
joblib.dump(self.scaler_water_quality, f"{path_prefix}_scaler_water_quality.pkl")
print(f"{self.plant_name}水厂模型保存成功")
def load_models(self, path_prefix=None):
"""加载模型"""
if path_prefix is None:
path_prefix = self.plant_name
self.model_dosage_1 = joblib.load(f"{path_prefix}_dosage_1.pkl")
self.model_dosage_2 = joblib.load(f"{path_prefix}_dosage_2.pkl")
self.model_water_quality = joblib.load(f"{path_prefix}_water_quality.pkl")
self.scaler_dosage = joblib.load(f"{path_prefix}_scaler_dosage.pkl")
self.scaler_water_quality = joblib.load(f"{path_prefix}_scaler_water_quality.pkl")
print(f"{self.plant_name}水厂模型加载成功")
def predict_dosage_1(self, input_data):
"""预测1#需矾量"""
input_scaled = self.scaler_dosage.transform([input_data])
return self.model_dosage_1.predict(input_scaled)[0]
def predict_dosage_2(self, input_data):
"""预测2#需矾量"""
input_scaled = self.scaler_dosage.transform([input_data])
return self.model_dosage_2.predict(input_scaled)[0]
def predict_water_quality(self, input_data):
"""预测出水浊度"""
input_scaled = self.scaler_water_quality.transform([input_data])
return self.model_water_quality.predict(input_scaled)[0]
def add_feedback(self, input_data, actual_turbidity, predicted_turbidity):
"""添加反馈数据"""
similarity = 1 - (abs(actual_turbidity - predicted_turbidity) / max(actual_turbidity, predicted_turbidity))
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.feedback_data.append({
'timestamp': timestamp,
'input': input_data,
'actual_turbidity': actual_turbidity,
'predicted_turbidity': predicted_turbidity,
'similarity': similarity
})
return similarity
def export_feedback_data(self, filename=None):
"""导出反馈数据为CSV文件,格式与原始数据表一致"""
if not self.feedback_data:
messagebox.showwarning("警告", "没有反馈数据可导出")
return False
if filename is None:
filename = filedialog.asksaveasfilename(
defaultextension=".csv",
filetypes=[("CSV files", "*.csv"), ("All files", "*.*")],
title=f"保存{self.plant_name}水厂反馈数据"
)
if not filename:
return False
# 创建与原始数据表结构一致的DataFrame
feedback_list = []
for fd in self.feedback_data:
# 将反馈数据转换为与原始数据表相同的格式
feedback_row = {
'时间': fd['timestamp'],
'原水浊度': fd['input'][0],
'原水ph': fd['input'][1],
'1#沉淀池流量': fd['input'][2],
'2#沉淀池流量': fd['input'][3],
'矾原液密度': fd['input'][4],
'矾液浓度': fd['input'][5],
'1#需矾量': fd['input'][6],
'2#需矾量': fd['input'][7],
'出水浊度': fd['actual_turbidity'],
# 以下字段在反馈数据中没有,设置为空或默认值
'1#矾液流量': None,
'2#矾液流量': None,
'1#沉后ph': None,
'1#沉后浊度': None,
'2#沉后ph': None,
'2#沉后浊度': None,
'滤后ph': None,
'滤后浊度': None,
'出水ph': None
}
feedback_list.append(feedback_row)
# 创建DataFrame并确保列的顺序与原始数据一致
original_columns = [
'时间', '原水浊度', '原水ph', '1#沉淀池流量', '1#矾液流量',
'2#沉淀池流量', '2#矾液流量', '矾原液密度', '矾液浓度',
'1#需矾量', '2#需矾量', '1#沉后ph', '1#沉后浊度',
'2#沉后ph', '2#沉后浊度', '滤后ph', '滤后浊度', '出水ph', '出水浊度'
]
feedback_df = pd.DataFrame(feedback_list)
# 确保所有原始列都存在,如果不存在则添加空列
for col in original_columns:
if col not in feedback_df.columns:
feedback_df[col] = None
# 按原始顺序重新排列列
feedback_df = feedback_df[original_columns]
# 保存到CSV文件
feedback_df.to_csv(filename, index=False, encoding='utf-8-sig')
print(f"{self.plant_name}水厂反馈数据已导出到: {filename}")
return True
def retrain_with_feedback(self):
"""使用反馈数据重新训练模型"""
if not self.feedback_data:
print("没有反馈数据可用于重新训练")
return
# 将反馈数据转换为DataFrame
feedback_df = pd.DataFrame([{
'原水浊度': fd['input'][0],
'原水ph': fd['input'][1],
'1#沉淀池流量': fd['input'][2],
'2#沉淀池流量': fd['input'][3],
'矾原液密度': fd['input'][4],
'矾液浓度': fd['input'][5],
'1#需矾量': fd['input'][6],
'2#需矾量': fd['input'][7],
'future_turbidity': fd['actual_turbidity']
} for fd in self.feedback_data])
# 合并原始数据和反馈数据
combined_data = pd.concat([self.data, feedback_df], ignore_index=True)
# 重新训练水质模型
features_water_quality = [
'原水浊度', '原水ph', '1#沉淀池流量', '2#沉淀池流量',
'矾原液密度', '矾液浓度', '1#需矾量', '2#需矾量'
]
target_water_quality = 'future_turbidity'
X = combined_data[features_water_quality]
y = combined_data[target_water_quality]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
self.scaler_water_quality = StandardScaler()
X_train_scaled = self.scaler_water_quality.fit_transform(X_train)
X_test_scaled = self.scaler_water_quality.transform(X_test)
self.model_water_quality = RandomForestRegressor(n_estimators=100, random_state=42)
self.model_water_quality.fit(X_train_scaled, y_train)
y_pred = self.model_water_quality.predict(X_test_scaled)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"{self.plant_name}水厂重新训练后的水质模型 - MSE: {mse:.4f}, R²: {r2:.4f}")
# 清空反馈数据
self.feedback_data = []
print(f"{self.plant_name}水厂模型已使用反馈数据重新训练")
class AlumDosagePredictionSystem:
"""多水厂预测系统"""
def __init__(self):
self.plants = {
"JB": WaterPlantModel("JB"),
"GH": WaterPlantModel("GH"),
"LG": WaterPlantModel("LG"),
"THY": WaterPlantModel("THY")
}
self.current_plant = "JB" # 默认水厂
def get_current_model(self):
"""获取当前水厂模型"""
return self.plants[self.current_plant]
def switch_plant(self, plant_name):
"""切换当前水厂"""
if plant_name in self.plants:
self.current_plant = plant_name
print(f"已切换到{plant_name}水厂")
return True
return False
class AlumPredictionApp:
def __init__(self, root, prediction_system):
self.root = root
self.root.title("自来水厂矾液投加预测系统")
self.root.geometry("1200x800")
self.prediction_system = prediction_system
# 创建顶部控制框架
self.control_frame = ttk.Frame(root)
self.control_frame.pack(fill='x', padx=10, pady=5)
# 水厂选择下拉菜单
ttk.Label(self.control_frame, text="选择水厂:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.plant_var = tk.StringVar(value="JB")
self.plant_combo = ttk.Combobox(self.control_frame, textvariable=self.plant_var,
values=list(self.prediction_system.plants.keys()),
state="readonly", width=10)
self.plant_combo.grid(row=0, column=1, padx=5, pady=5)
self.plant_combo.bind('<<ComboboxSelected>>', self.on_plant_changed)
# 模型操作按钮
ttk.Button(self.control_frame, text="加载模型", command=self.load_models).grid(row=0, column=2, padx=5, pady=5)
ttk.Button(self.control_frame, text="训练模型", command=self.train_models).grid(row=0, column=3, padx=5, pady=5)
ttk.Button(self.control_frame, text="保存模型", command=self.save_models).grid(row=0, column=4, padx=5, pady=5)
# 创建公共参数框架
self.common_frame = ttk.LabelFrame(root, text="公共参数")
self.common_frame.pack(fill='x', padx=10, pady=5)
# 公共参数输入框
ttk.Label(self.common_frame, text="原水浊度:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.common_turbidity = ttk.Entry(self.common_frame, width=10)
self.common_turbidity.grid(row=0, column=1, padx=5, pady=5)
ttk.Label(self.common_frame, text="原水pH:").grid(row=0, column=2, padx=5, pady=5, sticky='e')
self.common_ph = ttk.Entry(self.common_frame, width=10)
self.common_ph.grid(row=0, column=3, padx=5, pady=5)
ttk.Label(self.common_frame, text="矾原液密度:").grid(row=0, column=4, padx=5, pady=5, sticky='e')
self.common_density = ttk.Entry(self.common_frame, width=10)
self.common_density.grid(row=0, column=5, padx=5, pady=5)
ttk.Label(self.common_frame, text="矾液浓度:").grid(row=0, column=6, padx=5, pady=5, sticky='e')
self.common_concentration = ttk.Entry(self.common_frame, width=10)
self.common_concentration.grid(row=0, column=7, padx=5, pady=5)
# 创建选项卡
self.notebook = ttk.Notebook(root)
self.notebook.pack(fill='both', expand=True, padx=10, pady=10)
# 创建各个选项卡
self.create_dosage_1_tab()
self.create_dosage_2_tab()
self.create_water_quality_tab()
self.create_combined_tab()
self.create_feedback_tab()
self.create_curve_tab()
# 更新水厂标签
self.update_plant_label()
def on_plant_changed(self, event):
"""水厂选择改变事件"""
plant_name = self.plant_var.get()
if self.prediction_system.switch_plant(plant_name):
self.update_plant_label()
def update_plant_label(self):
"""更新界面中的水厂标签"""
plant_name = self.prediction_system.current_plant
for tab_id in self.notebook.tabs():
tab = self.nametowidget(tab_id)
if hasattr(tab, 'winfo_children'):
for child in tab.winfo_children():
if isinstance(child, ttk.LabelFrame):
child.config(text=f"{child.cget('text').split('(')[0].strip()}({plant_name}水厂)")
def load_models(self):
"""加载当前水厂模型"""
try:
plant_model = self.prediction_system.get_current_model()
plant_model.load_models()
messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂模型加载成功")
except Exception as e:
messagebox.showerror("错误", f"加载模型失败: {str(e)}")
def train_models(self):
"""训练当前水厂模型"""
try:
plant_name = self.prediction_system.current_plant
data_file = f"{plant_name}_water_quality_data.csv"
if not os.path.exists(data_file):
messagebox.showerror("错误", f"找不到数据文件: {data_file}")
return
plant_model = self.prediction_system.get_current_model()
plant_model.load_data(data_file)
plant_model.train_models()
messagebox.showinfo("成功", f"{plant_name}水厂模型训练成功")
except Exception as e:
messagebox.showerror("错误", f"训练模型失败: {str(e)}")
def save_models(self):
"""保存当前水厂模型"""
try:
plant_model = self.prediction_system.get_current_model()
plant_model.save_models()
messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂模型保存成功")
except Exception as e:
messagebox.showerror("错误", f"保存模型失败: {str(e)}")
def create_dosage_1_tab(self):
"""创建1#需矾量预测选项卡"""
tab = ttk.Frame(self.notebook)
self.notebook.add(tab, text="1#需矾量预测")
frame = ttk.LabelFrame(tab, text="1#需矾量预测(JB水厂)")
frame.pack(fill='both', expand=True, padx=10, pady=10)
# 创建输入框
ttk.Label(frame, text="1#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.flow_1 = ttk.Entry(frame, width=15)
self.flow_1.grid(row=0, column=1, padx=5, pady=5)
# 预测按钮
ttk.Button(frame, text="预测1#需矾量", command=self.predict_dosage_1).grid(row=1, column=0, columnspan=2, pady=10)
# 结果显示
ttk.Label(frame, text="预测1#需矾量:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
self.result_dosage_1 = ttk.Label(frame, text="", width=15)
self.result_dosage_1.grid(row=2, column=1, padx=5, pady=5, sticky='w')
def create_dosage_2_tab(self):
"""创建2#需矾量预测选项卡"""
tab = ttk.Frame(self.notebook)
self.notebook.add(tab, text="2#需矾量预测")
frame = ttk.LabelFrame(tab, text="2#需矾量预测(JB水厂)")
frame.pack(fill='both', expand=True, padx=10, pady=10)
# 创建输入框
ttk.Label(frame, text="2#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.flow_2 = ttk.Entry(frame, width=15)
self.flow_2.grid(row=0, column=1, padx=5, pady=5)
# 预测按钮
ttk.Button(frame, text="预测2#需矾量", command=self.predict_dosage_2).grid(row=1, column=0, columnspan=2, pady=10)
# 结果显示
ttk.Label(frame, text="预测2#需矾量:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
self.result_dosage_2 = ttk.Label(frame, text="", width=15)
self.result_dosage_2.grid(row=2, column=1, padx=5, pady=5, sticky='w')
def create_water_quality_tab(self):
"""创建水质预测选项卡"""
tab = ttk.Frame(self.notebook)
self.notebook.add(tab, text="水质预测")
frame = ttk.LabelFrame(tab, text="水质预测(JB水厂)")
frame.pack(fill='both', expand=True, padx=10, pady=10)
# 创建输入框
ttk.Label(frame, text="1#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.flow1_wq = ttk.Entry(frame, width=15)
self.flow1_wq.grid(row=0, column=1, padx=5, pady=5)
ttk.Label(frame, text="2#沉淀池流量:").grid(row=1, column=0, padx=5, pady=5, sticky='e')
self.flow2_wq = ttk.Entry(frame, width=15)
self.flow2_wq.grid(row=1, column=1, padx=5, pady=5)
ttk.Label(frame, text="1#需矾量:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
self.dosage1_wq = ttk.Entry(frame, width=15)
self.dosage1_wq.grid(row=2, column=1, padx=5, pady=5)
ttk.Label(frame, text="2#需矾量:").grid(row=3, column=0, padx=5, pady=5, sticky='e')
self.dosage2_wq = ttk.Entry(frame, width=15)
self.dosage2_wq.grid(row=3, column=1, padx=5, pady=5)
# 预测按钮
ttk.Button(frame, text="预测出水浊度", command=self.predict_water_quality).grid(row=4, column=0, columnspan=2, pady=10)
# 结果显示
ttk.Label(frame, text="预测出水浊度:").grid(row=5, column=0, padx=5, pady=5, sticky='e')
self.result_water_quality = ttk.Label(frame, text="", width=15)
self.result_water_quality.grid(row=5, column=1, padx=5, pady=5, sticky='w')
def create_combined_tab(self):
"""创建组合预测选项卡"""
tab = ttk.Frame(self.notebook)
self.notebook.add(tab, text="组合预测")
frame = ttk.LabelFrame(tab, text="组合预测(JB水厂)")
frame.pack(fill='both', expand=True, padx=10, pady=10)
# 创建输入框
ttk.Label(frame, text="1#沉淀池流量:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.flow1_combined = ttk.Entry(frame, width=15)
self.flow1_combined.grid(row=0, column=1, padx=5, pady=5)
ttk.Label(frame, text="2#沉淀池流量:").grid(row=1, column=0, padx=5, pady=5, sticky='e')
self.flow2_combined = ttk.Entry(frame, width=15)
self.flow2_combined.grid(row=1, column=1, padx=5, pady=5)
# 预测按钮
ttk.Button(frame, text="预测1#需矾量", command=self.predict_dosage_1_combined).grid(row=2, column=0, pady=10)
ttk.Button(frame, text="预测2#需矾量", command=self.predict_dosage_2_combined).grid(row=2, column=1, pady=10)
ttk.Button(frame, text="预测出水浊度", command=self.predict_water_quality_combined).grid(row=3, column=0, columnspan=2, pady=10)
# 结果显示
ttk.Label(frame, text="预测1#需矾量:").grid(row=4, column=0, padx=5, pady=5, sticky='e')
self.result_dosage_1_combined = ttk.Label(frame, text="", width=15)
self.result_dosage_1_combined.grid(row=4, column=1, padx=5, pady=5, sticky='w')
ttk.Label(frame, text="预测2#需矾量:").grid(row=5, column=0, padx=5, pady=5, sticky='e')
self.result_dosage_2_combined = ttk.Label(frame, text="", width=15)
self.result_dosage_2_combined.grid(row=5, column=1, padx=5, pady=5, sticky='w')
ttk.Label(frame, text="预测出水浊度:").grid(row=6, column=0, padx=5, pady=5, sticky='e')
self.result_water_quality_combined = ttk.Label(frame, text="", width=15)
self.result_water_quality_combined.grid(row=6, column=1, padx=5, pady=5, sticky='w')
def create_feedback_tab(self):
"""创建反馈选项卡"""
tab = ttk.Frame(self.notebook)
self.notebook.add(tab, text="反馈系统")
frame = ttk.LabelFrame(tab, text="反馈系统(JB水厂)")
frame.pack(fill='both', expand=True, padx=10, pady=10)
# 实际浊度输入
ttk.Label(frame, text="实际出水浊度:").grid(row=0, column=0, padx=5, pady=5, sticky='e')
self.actual_turbidity = ttk.Entry(frame, width=15)
self.actual_turbidity.grid(row=0, column=1, padx=5, pady=5)
# 预测浊度显示
ttk.Label(frame, text="预测出水浊度:").grid(row=1, column=0, padx=5, pady=5, sticky='e')
self.predicted_turbidity_fb = ttk.Label(frame, text="", width=15)
self.predicted_turbidity_fb.grid(row=1, column=1, padx=5, pady=5, sticky='w')
# 相似度显示
ttk.Label(frame, text="预测相似度:").grid(row=2, column=0, padx=5, pady=5, sticky='e')
self.similarity = ttk.Label(frame, text="", width=15)
self.similarity.grid(row=2, column=1, padx=5, pady=5, sticky='w')
# 按钮
ttk.Button(frame, text="提交反馈", command=self.submit_feedback).grid(row=3, column=0, padx=5, pady=10)
ttk.Button(frame, text="重新训练模型", command=self.retrain_model).grid(row=3, column=1, padx=5, pady=10)
# 添加导出按钮
ttk.Button(frame, text="导出反馈数据", command=self.export_feedback).grid(row=4, column=0, columnspan=2, pady=10)
def create_curve_tab(self):
"""创建曲线选项卡"""
tab = ttk.Frame(self.notebook)
self.notebook.add(tab, text="关系曲线")
frame = ttk.LabelFrame(tab, text="关系曲线(JB水厂)")
frame.pack(fill='both', expand=True, padx=10, pady=10)
# 创建画布
self.fig, self.ax = plt.subplots(figsize=(8, 6))
self.canvas = FigureCanvasTkAgg(self.fig, frame)
self.canvas.get_tk_widget().pack(fill='both', expand=True)
# 更新曲线按钮
ttk.Button(frame, text="更新曲线", command=self.update_curve).pack(pady=10)
def get_common_params(self):
"""获取公共参数"""
try:
return [
float(self.common_turbidity.get()),
float(self.common_ph.get()),
float(self.common_density.get()),
float(self.common_concentration.get())
]
except:
messagebox.showerror("错误", "请先输入公共参数")
return None
def predict_dosage_1(self):
"""预测1#需矾量"""
common_params = self.get_common_params()
if common_params is None:
return
try:
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow_1.get()),
0, # 2#沉淀池流量设为0,因为只预测1#
common_params[2], # 矾原液密度
common_params[3] # 矾液浓度
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_dosage_1(input_data)
self.result_dosage_1.config(text=f"{prediction:.4f}")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def predict_dosage_2(self):
"""预测2#需矾量"""
common_params = self.get_common_params()
if common_params is None:
return
try:
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
0, # 1#沉淀池流量设为0,因为只预测2#
float(self.flow_2.get()),
common_params[2], # 矾原液密度
common_params[3] # 矾液浓度
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_dosage_2(input_data)
self.result_dosage_2.config(text=f"{prediction:.4f}")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def predict_water_quality(self):
"""预测出水浊度"""
common_params = self.get_common_params()
if common_params is None:
return
try:
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow1_wq.get()),
float(self.flow2_wq.get()),
common_params[2], # 矾原液密度
common_params[3], # 矾液浓度
float(self.dosage1_wq.get()),
float(self.dosage2_wq.get())
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_water_quality(input_data)
self.result_water_quality.config(text=f"{prediction:.4f}")
self.predicted_turbidity_fb.config(text=f"{prediction:.4f}")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def predict_dosage_1_combined(self):
"""组合预测1#需矾量"""
common_params = self.get_common_params()
if common_params is None:
return
try:
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow1_combined.get()),
0, # 2#沉淀池流量设为0,因为只预测1#
common_params[2], # 矾原液密度
common_params[3] # 矾液浓度
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_dosage_1(input_data)
self.result_dosage_1_combined.config(text=f"{prediction:.4f}")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def predict_dosage_2_combined(self):
"""组合预测2#需矾量"""
common_params = self.get_common_params()
if common_params is None:
return
try:
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
0, # 1#沉淀池流量设为0,因为只预测2#
float(self.flow2_combined.get()),
common_params[2], # 矾原液密度
common_params[3] # 矾液浓度
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_dosage_2(input_data)
self.result_dosage_2_combined.config(text=f"{prediction:.4f}")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def predict_water_quality_combined(self):
"""组合预测出水浊度"""
common_params = self.get_common_params()
if common_params is None:
return
try:
# 如果需矾量没有预测,使用默认值0
dosage1 = float(self.result_dosage_1_combined.cget("text")) if self.result_dosage_1_combined.cget("text") else 0
dosage2 = float(self.result_dosage_2_combined.cget("text")) if self.result_dosage_2_combined.cget("text") else 0
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow1_combined.get()),
float(self.flow2_combined.get()),
common_params[2], # 矾原液密度
common_params[3], # 矾液浓度
dosage1,
dosage2
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_water_quality(input_data)
self.result_water_quality_combined.config(text=f"{prediction:.4f}")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def submit_feedback(self):
"""提交反馈"""
try:
actual_turb = float(self.actual_turbidity.get())
predicted_turb = float(self.predicted_turbidity_fb.cget("text"))
if predicted_turb == 0:
messagebox.showerror("错误", "请先进行水质预测")
return
common_params = self.get_common_params()
if common_params is None:
return
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow1_wq.get()),
float(self.flow2_wq.get()),
common_params[2], # 矾原液密度
common_params[3], # 矾液浓度
float(self.dosage1_wq.get()),
float(self.dosage2_wq.get())
]
plant_model = self.prediction_system.get_current_model()
similarity = plant_model.add_feedback(input_data, actual_turb, predicted_turb)
self.similarity.config(text=f"{similarity:.4f}")
messagebox.showinfo("成功", "反馈已提交")
except Exception as e:
messagebox.showerror("错误", f"输入数据有误: {str(e)}")
def retrain_model(self):
"""重新训练模型"""
plant_model = self.prediction_system.get_current_model()
plant_model.retrain_with_feedback()
messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂模型已使用反馈数据重新训练")
def export_feedback(self):
"""导出反馈数据"""
plant_model = self.prediction_system.get_current_model()
success = plant_model.export_feedback_data()
if success:
messagebox.showinfo("成功", f"{self.prediction_system.current_plant}水厂反馈数据已成功导出")
def update_curve(self):
"""更新关系曲线"""
try:
common_params = self.get_common_params()
if common_params is None:
return
# 获取当前输入值作为基准
base_dosage_1 = float(self.dosage1_wq.get()) if self.dosage1_wq.get() else 0
base_dosage_2 = float(self.dosage2_wq.get()) if self.dosage2_wq.get() else 0
# 生成一系列需矾量值
dosage_range = np.linspace(0.5 * base_dosage_1, 1.5 * base_dosage_1, 20)
# 预测对应的出水浊度
turbidity_predictions = []
for dosage in dosage_range:
input_data = [
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow1_wq.get()),
float(self.flow2_wq.get()),
common_params[2], # 矾原液密度
common_params[3], # 矾液浓度
dosage,
base_dosage_2
]
plant_model = self.prediction_system.get_current_model()
prediction = plant_model.predict_water_quality(input_data)
turbidity_predictions.append(prediction)
# 绘制曲线
self.ax.clear()
self.ax.plot(dosage_range, turbidity_predictions, 'b-')
self.ax.set_xlabel('1#需矾量')
self.ax.set_ylabel('预估出水浊度')
self.ax.set_title(f'{self.prediction_system.current_plant}水厂需矾量与出水浊度关系曲线')
self.ax.grid(True)
# 标记当前点
if base_dosage_1 > 0:
current_prediction = plant_model.predict_water_quality([
common_params[0], # 原水浊度
common_params[1], # 原水pH
float(self.flow1_wq.get()),
float(self.flow2_wq.get()),
common_params[2], # 矾原液密度
common_params[3], # 矾液浓度
base_dosage_1,
base_dosage_2
])
self.ax.plot(base_dosage_1, current_prediction, 'ro', markersize=8)
self.ax.annotate('当前点',
xy=(base_dosage_1, current_prediction),
xytext=(base_dosage_1*1.1, current_prediction*1.1),
arrowprops=dict(facecolor='black', shrink=0.05))
self.canvas.draw()
except Exception as e:
messagebox.showerror("错误", f"无法生成曲线: {str(e)}")
# 主程序
if __name__ == "__main__":
# 创建预测系统
system = AlumDosagePredictionSystem()
# 创建GUI界面
root = tk.Tk()
app = AlumPredictionApp(root, system)
root.mainloop()
最新发布