| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import streamlit as st |
| | | import plotly.express as px |
| | | import plotly.graph_objects as go |
| | | import pandas as pd |
| | | import numpy as np |
| | | import joblib |
| | | import os |
| | | from datetime import datetime |
| | | from sklearn.preprocessing import MinMaxScaler |
| | | |
| | | # 页é¢å½æ°å®ä¹ |
| | | def show_optimized_parameter_adjustment(): |
| | | # 页颿 é¢ |
| | | st.title("ä¼åçæ¤åºæºåæ°è°è建议") |
| | | |
| | | # æ·»å æä½æå¼ |
| | | with st.expander("ð æä½æå¼", expanded=True): |
| | | st.markdown(""" |
| | | 欢è¿ä½¿ç¨ä¼åçæ¤åºæºåæ°è°è建议åè½ï¼æ¬åè½åºäºå¤ç®æ ä¼åç®æ³ï¼æ ¹æ®æ¨è¾å
¥çç±³éæ°æ®åå½ååæ°ï¼ä¸ºæ¨æä¾ç§å¦åççåæ°è°æ´å»ºè®®ã |
| | | |
| | | **æä½æ¥éª¤ï¼** |
| | | 1. éæ©ä¸ä¸ªå·²è®ç»å¥½ç模å |
| | | 2. è¾å
¥ç±³éæ åå¼ãä¸ä¸éåå½åæ¤åºæºåæ° |
| | | 3. è¾å
¥å½åå®é
ç±³éæµéå¼ |
| | | 4. è°æ´ä¼ååæ°ï¼å¯éï¼ |
| | | 5. ç¹å»"计ç®ä¼åè°è建议"æé® |
| | | 6. æ¥çç³»ç»çæçåæ°è°æ´å»ºè®® |
| | | |
| | | **注æäºé¡¹ï¼** |
| | | - 请确ä¿è¾å
¥çåæ°å¼å¨è®¾å¤å
许çèå´å
|
| | | - ä¼åç®æ³ä¼å¹³è¡¡ç±³éåå·®åè°æ´å¹
度 |
| | | - åå²è°èè®°å½å¯å¨é¡µé¢åºé¨æ¥ç |
| | | """) |
| | | |
| | | # åå§åä¼è¯ç¶æ |
| | | if 'optimized_adjustment_history' not in st.session_state: |
| | | st.session_state['optimized_adjustment_history'] = [] |
| | | |
| | | # 1. 模åéæ©åºå |
| | | with st.expander("ð æ¨¡åéæ©", expanded=True): |
| | | # å建模åç®å½ï¼å¦æä¸åå¨ï¼ |
| | | model_dir = "saved_models" |
| | | os.makedirs(model_dir, exist_ok=True) |
| | | |
| | | # è·åææå·²ä¿åçæ¨¡åæä»¶ |
| | | model_files = [f for f in os.listdir(model_dir) if f.endswith('.joblib')] |
| | | model_files.sort(reverse=True) # ææ°çæ¨¡åæå¨åé¢ |
| | | |
| | | if not model_files: |
| | | st.warning("å°æªä¿å任使¨¡åï¼è¯·å
è®ç»æ¨¡åå¹¶ä¿åã") |
| | | return |
| | | |
| | | # 模åéæ©ä¸ææ¡ |
| | | selected_model_file = st.selectbox( |
| | | "鿩已ä¿åçæ¨¡å", |
| | | options=model_files, |
| | | help="éæ©è¦ç¨äºé¢æµç模åæä»¶" |
| | | ) |
| | | |
| | | # å 载并æ¾ç¤ºæ¨¡åä¿¡æ¯ |
| | | if selected_model_file: |
| | | model_path = os.path.join(model_dir, selected_model_file) |
| | | model_info = joblib.load(model_path) |
| | | |
| | | # æ¾ç¤ºæ¨¡ååºæ¬ä¿¡æ¯ |
| | | st.subheader("ð æ¨¡åä¿¡æ¯") |
| | | info_cols = st.columns(2) |
| | | |
| | | with info_cols[0]: |
| | | st.metric("模åç±»å", model_info['model_type']) |
| | | st.metric("å建æ¶é´", model_info['created_at'].strftime('%Y-%m-%d %H:%M:%S')) |
| | | st.metric("使ç¨ç¨³ææ°æ®", "æ¯" if model_info.get('use_steady_data', False) else "å¦") |
| | | |
| | | with info_cols[1]: |
| | | st.metric("R² å¾å", f"{model_info['r2_score']:.4f}") |
| | | st.metric("åæ¹è¯¯å·® (MSE)", f"{model_info['mse']:.6f}") |
| | | st.metric("åæ¹æ ¹è¯¯å·® (RMSE)", f"{model_info['rmse']:.6f}") |
| | | |
| | | # æ¾ç¤ºæ¨¡åç¹å¾ |
| | | st.write("ð æ¨¡å使ç¨çç¹å¾:") |
| | | st.code(", ".join(model_info['features'])) |
| | | |
| | | # å¦ææ¯æ·±åº¦å¦ä¹ 模åï¼æ¾ç¤ºåºåé¿åº¦ |
| | | if 'sequence_length' in model_info: |
| | | st.metric("åºåé¿åº¦", model_info['sequence_length']) |
| | | |
| | | # ä¿å模åä¿¡æ¯å°ä¼è¯ç¶æ |
| | | st.session_state['selected_model'] = model_info |
| | | st.session_state['selected_model_file'] = selected_model_file |
| | | |
| | | # 2. åæ°è¾å
¥åºå |
| | | st.subheader("ð åæ°è¾å
¥") |
| | | |
| | | # 2.1 ç±³éæ åå¼ãä¸ä¸éè¾å
¥ |
| | | with st.expander("âï¸ ç±³éæ åä¸ä¸ä¸é", expanded=True): |
| | | weight_cols = st.columns(3) |
| | | |
| | | with weight_cols[0]: |
| | | standard_weight = st.number_input( |
| | | "æ åç±³é", |
| | | key="standard_weight", |
| | | value=5.20, |
| | | min_value=0.01, |
| | | max_value=10.0, |
| | | step=0.0001, |
| | | format="%.4f", |
| | | help="è¾å
¥ç®æ ç±³éæ åå¼" |
| | | ) |
| | | st.caption("åä½: Kg/m") |
| | | |
| | | with weight_cols[1]: |
| | | upper_limit = st.number_input( |
| | | "ç±³éä¸é", |
| | | key="upper_limit", |
| | | value=5.46, |
| | | min_value=standard_weight, |
| | | max_value=10.0, |
| | | step=0.0001, |
| | | format="%.4f", |
| | | help="è¾å
¥ç±³éå
许çä¸éå¼" |
| | | ) |
| | | st.caption("åä½: Kg/m") |
| | | |
| | | with weight_cols[2]: |
| | | lower_limit = st.number_input( |
| | | "ç±³éä¸é", |
| | | key="lower_limit", |
| | | value=5.02, |
| | | min_value=0.01, |
| | | max_value=standard_weight, |
| | | step=0.0001, |
| | | format="%.4f", |
| | | help="è¾å
¥ç±³éå
许çä¸éå¼" |
| | | ) |
| | | st.caption("åä½: Kg/m") |
| | | |
| | | # 2.2 æ¤åºæºå½ååæ°è¾å
¥ |
| | | with st.expander("ð§ æ¤åºæºå½ååæ°", expanded=True): |
| | | param_cols = st.columns(3) |
| | | |
| | | with param_cols[0]: |
| | | current_screw_speed = st.number_input( |
| | | "èºæè½¬é", |
| | | key="current_screw_speed", |
| | | value=230.0, |
| | | min_value=0.0, |
| | | max_value=500.0, |
| | | step=0.1, |
| | | help="è¾å
¥å½åèºæè½¬é" |
| | | ) |
| | | st.caption("åä½: rpm") |
| | | |
| | | current_head_pressure = st.number_input( |
| | | "æºå¤´åå", |
| | | key="current_head_pressure", |
| | | value=0.26, |
| | | min_value=0.0, |
| | | max_value=500.0, |
| | | format="%.4f", |
| | | step=1.0, |
| | | help="è¾å
¥å½åæºå¤´åå" |
| | | ) |
| | | st.caption("åä½: bar") |
| | | |
| | | current_process_speed = st.number_input( |
| | | "æµç¨ä¸»é", |
| | | key="current_process_speed", |
| | | value=6.6, |
| | | min_value=0.0, |
| | | max_value=300.0, |
| | | step=0.1, |
| | | help="è¾å
¥å½åæµç¨ä¸»é" |
| | | ) |
| | | st.caption("åä½: m/min") |
| | | |
| | | with param_cols[1]: |
| | | current_screw_temperature = st.number_input( |
| | | "èºææ¸©åº¦", |
| | | key="current_screw_temperature", |
| | | value=79.9, |
| | | min_value=0.0, |
| | | max_value=300.0, |
| | | step=1.0, |
| | | help="è¾å
¥å½åèºææ¸©åº¦" |
| | | ) |
| | | st.caption("åä½: °C") |
| | | |
| | | current_rear_barrel_temperature = st.number_input( |
| | | "åæºçæ¸©åº¦", |
| | | key="current_rear_barrel_temperature", |
| | | value=79.9, |
| | | min_value=0.0, |
| | | max_value=300.0, |
| | | step=1.0, |
| | | help="è¾å
¥å½ååæºçæ¸©åº¦" |
| | | ) |
| | | st.caption("åä½: °C") |
| | | |
| | | with param_cols[2]: |
| | | current_front_barrel_temperature = st.number_input( |
| | | "åæºçæ¸©åº¦", |
| | | key="current_front_barrel_temperature", |
| | | value=80.1, |
| | | min_value=0.0, |
| | | max_value=300.0, |
| | | step=1.0, |
| | | help="è¾å
¥å½ååæºçæ¸©åº¦" |
| | | ) |
| | | st.caption("åä½: °C") |
| | | |
| | | current_head_temperature = st.number_input( |
| | | "æºå¤´æ¸©åº¦", |
| | | key="current_head_temperature", |
| | | value=95.1, |
| | | min_value=0.0, |
| | | max_value=300.0, |
| | | step=1.0, |
| | | help="è¾å
¥å½åæºå¤´æ¸©åº¦" |
| | | ) |
| | | st.caption("åä½: °C") |
| | | |
| | | # 2.3 å½åå®é
ç±³éæµéå¼è¾å
¥ |
| | | with st.expander("ð å½åå®é
ç±³é", expanded=True): |
| | | actual_weight = st.number_input( |
| | | "å½åå®é
ç±³é", |
| | | key="actual_weight", |
| | | value=5.115, |
| | | min_value=0.01, |
| | | max_value=10.0, |
| | | step=0.0001, |
| | | format="%.4f", |
| | | help="è¾å
¥å½åå®é
æµéçç±³éå¼" |
| | | ) |
| | | st.caption("åä½: Kg/m") |
| | | |
| | | # 3. ä¼ååæ°è®¾ç½® |
| | | st.subheader("âï¸ ä¼ååæ°è®¾ç½®") |
| | | |
| | | with st.expander("ð¯ å¤ç®æ ä¼ååæ°", expanded=True): |
| | | # ç®æ æé设置 |
| | | st.write("### ç®æ æé") |
| | | st.markdown("è°æ´ä»¥ä¸æéæ¥å¹³è¡¡ç±³éåå·®åè°æ´å¹
度çéè¦æ§ï¼") |
| | | weight_cols = st.columns(2) |
| | | |
| | | with weight_cols[0]: |
| | | weight_deviation = st.slider( |
| | | "ç±³éåå·®æé", |
| | | min_value=0.1, |
| | | max_value=1.0, |
| | | value=0.8, |
| | | step=0.1, |
| | | help="æéè¶é«ï¼è¶ä¼å
èèåå°ç±³éåå·®" |
| | | ) |
| | | |
| | | with weight_cols[1]: |
| | | weight_adjustment = st.slider( |
| | | "è°æ´å¹
度æé", |
| | | min_value=0.1, |
| | | max_value=1.0, |
| | | value=0.2, |
| | | step=0.1, |
| | | help="æéè¶é«ï¼è¶ä¼å
èèåå°è°æ´å¹
度" |
| | | ) |
| | | |
| | | # è°æ´æéï¼ç¡®ä¿æ»å为1 |
| | | total_weight = weight_deviation + weight_adjustment |
| | | weight_deviation = weight_deviation / total_weight |
| | | weight_adjustment = weight_adjustment / total_weight |
| | | |
| | | st.write(f"### è°æ´åæéï¼æ»å为1ï¼") |
| | | st.write(f"- ç±³éåå·®æé: {weight_deviation:.2f}") |
| | | st.write(f"- è°æ´å¹
度æé: {weight_adjustment:.2f}") |
| | | |
| | | # åæ°è°æ´çº¦æ |
| | | st.write("### åæ°è°æ´çº¦æ") |
| | | constraint_cols = st.columns(2) |
| | | |
| | | with constraint_cols[0]: |
| | | max_screw_speed_adjust = st.slider( |
| | | "èºæè½¬éæå¤§è°æ´å¹
度(%)", |
| | | min_value=5.0, |
| | | max_value=20.0, |
| | | value=15.0, |
| | | step=1.0, |
| | | help="忬¡è°æ´çæå¤§ç¾åæ¯" |
| | | ) |
| | | |
| | | with constraint_cols[1]: |
| | | max_process_speed_adjust = st.slider( |
| | | "æµç¨ä¸»éæå¤§è°æ´å¹
度(%)", |
| | | min_value=3.0, |
| | | max_value=15.0, |
| | | value=10.0, |
| | | step=1.0, |
| | | help="忬¡è°æ´çæå¤§ç¾åæ¯" |
| | | ) |
| | | |
| | | # 4. 计ç®ä¼åè°è建议 |
| | | st.subheader("ð 计ç®ä¼åè°è建议") |
| | | |
| | | if st.button("ð 计ç®ä¼åè°è建议", key="calculate_optimized_adjustment"): |
| | | # åæ°éªè¯ |
| | | validation_errors = [] |
| | | |
| | | if standard_weight <= 0: |
| | | validation_errors.append("æ åç±³éå¿
须大äº0") |
| | | |
| | | if upper_limit <= standard_weight: |
| | | validation_errors.append("ç±³éä¸éå¿
é¡»å¤§äºæ åç±³é") |
| | | |
| | | if lower_limit >= standard_weight: |
| | | validation_errors.append("ç±³éä¸éå¿
é¡»å°äºæ åç±³é") |
| | | |
| | | if current_screw_speed <= 0: |
| | | validation_errors.append("èºæè½¬éå¿
须大äº0") |
| | | |
| | | if current_process_speed <= 0: |
| | | validation_errors.append("æµç¨ä¸»éå¿
须大äº0") |
| | | |
| | | if actual_weight <= 0: |
| | | validation_errors.append("å®é
ç±³éå¿
须大äº0") |
| | | |
| | | if validation_errors: |
| | | st.error("åæ°è¾å
¥é误ï¼") |
| | | for error in validation_errors: |
| | | st.error(f"- {error}") |
| | | else: |
| | | with st.spinner("æ£å¨è®¡ç®ä¼åè°è建议..."): |
| | | # è·åéä¸ç模å |
| | | if 'selected_model' not in st.session_state: |
| | | st.error("请å
éæ©ä¸ä¸ªæ¨¡å") |
| | | return |
| | | |
| | | model_info = st.session_state['selected_model'] |
| | | model = model_info['model'] |
| | | |
| | | # æ£æ¥æ¯å¦æç¼©æ¾å¨ |
| | | has_scalers = ('scaler_X' in model_info and model_info['scaler_X'] is not None and |
| | | 'scaler_y' in model_info and model_info['scaler_y'] is not None) |
| | | if has_scalers: |
| | | scaler_X = model_info['scaler_X'] |
| | | scaler_y = model_info['scaler_y'] |
| | | |
| | | features = model_info['features'] |
| | | |
| | | # å¤ç®æ ä¼åç®æ³ - ç²å群ä¼å |
| | | def predict_weight(screw_speed, process_speed): |
| | | """ä½¿ç¨æ¨¡å颿µç±³é""" |
| | | # åå¤è¾å
¥æ°æ® |
| | | input_data = { |
| | | 'èºæè½¬é': screw_speed, |
| | | 'æºå¤´åå': current_head_pressure, |
| | | 'æµç¨ä¸»é': process_speed, |
| | | 'èºææ¸©åº¦': current_screw_temperature, |
| | | 'åæºçæ¸©åº¦': current_rear_barrel_temperature, |
| | | 'åæºçæ¸©åº¦': current_front_barrel_temperature, |
| | | 'æºå¤´æ¸©åº¦': current_head_temperature |
| | | } |
| | | |
| | | # æ ¹æ®æ¨¡åç¹å¾å建è¾å
¥DataFrame |
| | | input_df = pd.DataFrame([input_data])[features] |
| | | |
| | | if model_info['model_type'] in ['LSTM', 'GRU', 'BiLSTM']: |
| | | # 深度å¦ä¹ 模åå¤çé»è¾ |
| | | import torch |
| | | |
| | | # æ£æ¥æ¯å¦æç¼©æ¾å¨ |
| | | if has_scalers: |
| | | scaled_input = scaler_X.transform(input_df) |
| | | else: |
| | | scaled_input = input_df.values |
| | | |
| | | # è·ååºåé¿åº¦ |
| | | sequence_length = model_info.get('sequence_length', 10) |
| | | |
| | | # å建åºåæ°æ® |
| | | input_seq = np.tile(scaled_input, (sequence_length, 1)).reshape(1, sequence_length, -1) |
| | | |
| | | # 转æ¢ä¸ºPyTorchå¼ é |
| | | device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') |
| | | input_tensor = torch.tensor(input_seq, dtype=torch.float32).to(device) |
| | | |
| | | # 颿µ |
| | | model.eval() |
| | | with torch.no_grad(): |
| | | y_pred_scaled_tensor = model(input_tensor) |
| | | y_pred_scaled = y_pred_scaled_tensor.cpu().numpy().ravel()[0] |
| | | |
| | | if has_scalers: |
| | | # å缩æ¾é¢æµç»æ |
| | | predicted_weight = scaler_y.inverse_transform(np.array([[y_pred_scaled]]))[0][0] |
| | | else: |
| | | predicted_weight = y_pred_scaled |
| | | |
| | | elif has_scalers: |
| | | # ç¹å¾ç¼©æ¾ |
| | | scaled_input = scaler_X.transform(input_df) |
| | | |
| | | # 模å颿µ |
| | | scaled_prediction = model.predict(scaled_input)[0] |
| | | |
| | | # å缩æ¾é¢æµç»æ |
| | | predicted_weight = scaler_y.inverse_transform(np.array([[scaled_prediction]]))[0][0] |
| | | |
| | | else: |
| | | # ç´æ¥é¢æµï¼ä¸ä½¿ç¨ç¼©æ¾å¨ |
| | | predicted_weight = model.predict(input_df)[0] |
| | | |
| | | return predicted_weight |
| | | |
| | | def objective_function(params): |
| | | """å¤ç®æ ç®æ 彿°""" |
| | | screw_speed_val, process_speed_val = params |
| | | |
| | | # 颿µç±³é |
| | | predicted_weight_val = predict_weight(screw_speed_val, process_speed_val) |
| | | |
| | | # 计ç®ç®æ 1ï¼ç±³éåå·® |
| | | deviation_val = abs(predicted_weight_val - standard_weight) |
| | | deviation_percent_val = abs((predicted_weight_val - standard_weight) / standard_weight * 100) |
| | | |
| | | # 计ç®ç®æ 2ï¼è°æ´å¹
度 |
| | | screw_speed_adjustment_val = abs(screw_speed_val - current_screw_speed) |
| | | process_speed_adjustment_val = abs(process_speed_val - current_process_speed) |
| | | |
| | | screw_speed_adjustment_percent_val = abs((screw_speed_val - current_screw_speed) / current_screw_speed * 100) |
| | | process_speed_adjustment_percent_val = abs((process_speed_val - current_process_speed) / current_process_speed * 100) |
| | | |
| | | # å æç®æ 彿° |
| | | objective_val = (weight_deviation * deviation_percent_val + |
| | | weight_adjustment * (screw_speed_adjustment_percent_val + process_speed_adjustment_percent_val) / 2) |
| | | |
| | | return objective_val, predicted_weight_val, deviation_percent_val, \ |
| | | screw_speed_adjustment_percent_val, process_speed_adjustment_percent_val |
| | | |
| | | # åæ°çº¦æ |
| | | def is_within_constraints(params): |
| | | """æ£æ¥åæ°æ¯å¦å¨çº¦æèå´å
""" |
| | | screw_speed, process_speed = params |
| | | |
| | | # èºæè½¬é约æ |
| | | if not (30 <= screw_speed <= 500): |
| | | return False |
| | | |
| | | # æµç¨ä¸»é约æ |
| | | if not (0 <= process_speed <= 200): |
| | | return False |
| | | |
| | | # 忬¡è°æ´å¹
度约æ |
| | | screw_speed_adjustment_percent = abs((screw_speed - current_screw_speed) / current_screw_speed * 100) |
| | | if screw_speed_adjustment_percent > max_screw_speed_adjust: |
| | | return False |
| | | |
| | | process_speed_adjustment_percent = abs((process_speed - current_process_speed) / current_process_speed * 100) |
| | | if process_speed_adjustment_percent > max_process_speed_adjust: |
| | | return False |
| | | |
| | | return True |
| | | |
| | | # ç²å群ä¼åç®æ³ |
| | | def particle_swarm_optimization(objective, constraints, bounds, n_particles=30, n_iterations=50): |
| | | """ç²å群ä¼åç®æ³""" |
| | | # åå§åç²å |
| | | particles = [] |
| | | velocities = [] |
| | | best_positions = [] |
| | | best_scores = [] |
| | | |
| | | # è¾¹ç |
| | | (screw_speed_min, screw_speed_max), (process_speed_min, process_speed_max) = bounds |
| | | |
| | | for _ in range(n_particles): |
| | | # éæºåå§åä½ç½® |
| | | while True: |
| | | screw_speed = np.random.uniform(screw_speed_min, screw_speed_max) |
| | | process_speed = np.random.uniform(process_speed_min, process_speed_max) |
| | | pos = [screw_speed, process_speed] |
| | | if constraints(pos): |
| | | break |
| | | |
| | | particles.append(pos) |
| | | velocities.append([0.0, 0.0]) |
| | | best_positions.append(pos.copy()) |
| | | |
| | | # 计ç®åå§å¾å |
| | | score, _, _, _, _ = objective(pos) |
| | | best_scores.append(score) |
| | | |
| | | # å
¨å±æä¼ |
| | | global_best_idx = np.argmin(best_scores) |
| | | global_best_position = best_positions[global_best_idx].copy() |
| | | global_best_score = best_scores[global_best_idx] |
| | | |
| | | # PSOåæ° |
| | | w = 0.5 # æ¯æ§æé |
| | | c1 = 1.5 # 认ç¥ç³»æ° |
| | | c2 = 1.5 # 社ä¼ç³»æ° |
| | | |
| | | # è¿ä»£ä¼å |
| | | for _ in range(n_iterations): |
| | | for i in range(n_particles): |
| | | # æ´æ°é度 |
| | | r1, r2 = np.random.rand(), np.random.rand() |
| | | velocities[i][0] = (w * velocities[i][0] + |
| | | c1 * r1 * (best_positions[i][0] - particles[i][0]) + |
| | | c2 * r2 * (global_best_position[0] - particles[i][0])) |
| | | velocities[i][1] = (w * velocities[i][1] + |
| | | c1 * r1 * (best_positions[i][1] - particles[i][1]) + |
| | | c2 * r2 * (global_best_position[1] - particles[i][1])) |
| | | |
| | | # æ´æ°ä½ç½® |
| | | new_pos = [ |
| | | particles[i][0] + velocities[i][0], |
| | | particles[i][1] + velocities[i][1] |
| | | ] |
| | | |
| | | # æ£æ¥çº¦æ |
| | | if constraints(new_pos): |
| | | particles[i] = new_pos |
| | | |
| | | # æ´æ°ä¸ªä½æä¼ |
| | | current_score, _, _, _, _ = objective(new_pos) |
| | | if current_score < best_scores[i]: |
| | | best_scores[i] = current_score |
| | | best_positions[i] = new_pos.copy() |
| | | |
| | | # æ´æ°å
¨å±æä¼ |
| | | if current_score < global_best_score: |
| | | global_best_score = current_score |
| | | global_best_position = new_pos.copy() |
| | | |
| | | return global_best_position, global_best_score |
| | | |
| | | # è®¾ç½®åæ°è¾¹ç |
| | | screw_speed_bounds = [ |
| | | current_screw_speed * (1 - max_screw_speed_adjust / 100), |
| | | current_screw_speed * (1 + max_screw_speed_adjust / 100) |
| | | ] |
| | | |
| | | process_speed_bounds = [ |
| | | current_process_speed * (1 - max_process_speed_adjust / 100), |
| | | current_process_speed * (1 + max_process_speed_adjust / 100) |
| | | ] |
| | | |
| | | # æ§è¡ä¼å |
| | | best_params, best_score = particle_swarm_optimization( |
| | | objective_function, |
| | | is_within_constraints, |
| | | [(screw_speed_bounds[0], screw_speed_bounds[1]), |
| | | (process_speed_bounds[0], process_speed_bounds[1])] |
| | | ) |
| | | |
| | | # è·åæä¼åæ°ç详ç»ä¿¡æ¯ |
| | | best_screw_speed, best_process_speed = best_params |
| | | best_objective, best_predicted_weight, best_deviation_percent, \ |
| | | best_screw_adjust_percent, best_process_adjust_percent = objective_function(best_params) |
| | | |
| | | # 计ç®å½ååæ°ç颿µç»æ |
| | | current_predicted_weight = predict_weight(current_screw_speed, current_process_speed) |
| | | current_deviation_percent = abs((current_predicted_weight - standard_weight) / standard_weight * 100) |
| | | |
| | | # çæè°æ´å»ºè®®ææ¬ |
| | | def generate_recommendation(): |
| | | """çæè°æ´å»ºè®®ææ¬""" |
| | | screw_speed_change = "æé«" if best_screw_speed > current_screw_speed else "éä½" |
| | | process_speed_change = "æé«" if best_process_speed > current_process_speed else "éä½" |
| | | |
| | | recommendation = f"ç±³éåå·® {current_deviation_percent:.2f}%ï¼å»ºè®®è°æ´ï¼\n" |
| | | recommendation += f"1. å°èºæè½¬éä» {current_screw_speed:.1f} rpm {screw_speed_change} è³ {best_screw_speed:.1f} rpm " |
| | | recommendation += f"( {screw_speed_change} {abs(best_screw_adjust_percent):.2f}% )\n" |
| | | recommendation += f"2. å°æµç¨ä¸»éä» {current_process_speed:.1f} m/min {process_speed_change} è³ {best_process_speed:.1f} m/min " |
| | | recommendation += f"( {process_speed_change} {abs(best_process_adjust_percent):.2f}% )\n" |
| | | recommendation += f"\n颿ææï¼ç±³éåå·®å°éè³ {best_deviation_percent:.2f}%" |
| | | |
| | | return recommendation |
| | | |
| | | recommendation = generate_recommendation() |
| | | |
| | | # æå»ºè°æ´ç»æ |
| | | adjustment_result = { |
| | | 'status': 'æ£å¸¸èå´' if best_predicted_weight >= lower_limit and best_predicted_weight <= upper_limit else \ |
| | | 'è¶
ä¸é' if best_predicted_weight > upper_limit else 'è¶
ä¸é', |
| | | 'real_time_weight': actual_weight, |
| | | 'standard_weight': standard_weight, |
| | | 'upper_limit': upper_limit, |
| | | 'lower_limit': lower_limit, |
| | | 'current_screw_speed': current_screw_speed, |
| | | 'current_process_speed': current_process_speed, |
| | | 'new_screw_speed': best_screw_speed, |
| | | 'new_process_speed': best_process_speed, |
| | | 'predicted_weight': best_predicted_weight, |
| | | 'current_predicted_weight': current_predicted_weight, |
| | | 'deviation_percentage': (actual_weight - standard_weight) / standard_weight * 100, |
| | | 'current_predicted_deviation_percent': current_deviation_percent, |
| | | 'predicted_deviation_percent': best_deviation_percent, |
| | | 'screw_speed_adjustment': best_screw_speed - current_screw_speed, |
| | | 'process_speed_adjustment': best_process_speed - current_process_speed, |
| | | 'screw_speed_adjust_percent': best_screw_adjust_percent, |
| | | 'process_speed_adjust_percent': best_process_adjust_percent, |
| | | 'recommendation': recommendation, |
| | | 'weight_deviation': weight_deviation, |
| | | 'weight_adjustment': weight_adjustment, |
| | | 'best_objective_score': best_score |
| | | } |
| | | |
| | | # ä¿åå°åå²è®°å½ |
| | | history_record = { |
| | | 'timestamp': datetime.now(), |
| | | 'model_file': st.session_state.get('selected_model_file', 'æªç¥æ¨¡å'), |
| | | 'standard_weight': standard_weight, |
| | | 'upper_limit': upper_limit, |
| | | 'lower_limit': lower_limit, |
| | | 'actual_weight': actual_weight, |
| | | 'current_screw_speed': current_screw_speed, |
| | | 'current_process_speed': current_process_speed, |
| | | 'adjustment_result': adjustment_result |
| | | } |
| | | |
| | | # æ·»å å°ä¼è¯ç¶æçåå²è®°å½ |
| | | st.session_state['optimized_adjustment_history'].append(history_record) |
| | | |
| | | # éå¶åå²è®°å½æ°é |
| | | if len(st.session_state['optimized_adjustment_history']) > 100: |
| | | st.session_state['optimized_adjustment_history'] = st.session_state['optimized_adjustment_history'][-100:] |
| | | |
| | | # 5. ç»æå±ç¤º |
| | | st.success("ä¼åè°è建议计ç®å®æï¼") |
| | | |
| | | st.subheader("ð ä¼åè°èå»ºè®®ç»æ") |
| | | |
| | | # 5.1 ç±³éç¶æ |
| | | if adjustment_result['status'] == "æ£å¸¸èå´": |
| | | st.success(f"ç±³éç¶æ: {adjustment_result['status']}") |
| | | else: |
| | | st.warning(f"ç±³éç¶æ: {adjustment_result['status']}") |
| | | |
| | | # 5.2 åå·®ä¿¡æ¯ |
| | | st.markdown("### ð å差信æ¯") |
| | | info_cols = st.columns(3) |
| | | info_cols[0].metric("宿¶ç±³é", f"{adjustment_result['real_time_weight']:.4f} Kg/m") |
| | | info_cols[1].metric("æ åç±³é", f"{adjustment_result['standard_weight']:.4f} Kg/m") |
| | | info_cols[2].metric("åå·®ç¾åæ¯", f"{adjustment_result['deviation_percentage']:.2f}%") |
| | | |
| | | # 5.3 颿µç»æå¯¹æ¯ |
| | | st.markdown("### ð 颿µç»æå¯¹æ¯") |
| | | pred_cols = st.columns(3) |
| | | pred_cols[0].metric("å½å忰颿µç±³é", f"{adjustment_result['current_predicted_weight']:.4f} Kg/m") |
| | | pred_cols[1].metric("ä¼åå颿µç±³é", f"{adjustment_result['predicted_weight']:.4f} Kg/m") |
| | | pred_cols[2].metric("颿µåå·®æ¹å", f"{adjustment_result['current_predicted_deviation_percent'] - adjustment_result['predicted_deviation_percent']:.2f}%") |
| | | |
| | | # 5.4 å
³é®è°æ´å»ºè®® |
| | | st.markdown("### ð å
³é®è°æ´å»ºè®®") |
| | | st.info(adjustment_result['recommendation']) |
| | | |
| | | # 5.5 åæ°è°æ´å¯¹æ¯ |
| | | st.markdown("### ð åæ°è°æ´å¯¹æ¯") |
| | | |
| | | param_compare_df = pd.DataFrame({ |
| | | 'åæ°åç§°': ['èºæè½¬é', 'æµç¨ä¸»é'], |
| | | 'å½åå¼': [adjustment_result['current_screw_speed'], adjustment_result['current_process_speed']], |
| | | 'ä¼å建议å¼': [adjustment_result['new_screw_speed'], adjustment_result['new_process_speed']], |
| | | 'è°æ´å¹
度': [f"{adjustment_result['screw_speed_adjust_percent']:.2f}%", |
| | | f"{adjustment_result['process_speed_adjust_percent']:.2f}%"] |
| | | }) |
| | | |
| | | # é«äº®æ¾ç¤ºè°æ´å¹
度 |
| | | def highlight_adjustment(val): |
| | | if isinstance(val, str) and '%' in val: |
| | | try: |
| | | percent = float(val.strip('%')) |
| | | if percent > 0: |
| | | return 'background-color: #90EE90' # 绿è²è¡¨ç¤ºå¢å |
| | | elif percent < 0: |
| | | return 'background-color: #FFB6C1' # 红è²è¡¨ç¤ºåå° |
| | | except: |
| | | pass |
| | | return '' |
| | | |
| | | styled_df = param_compare_df.style.applymap(highlight_adjustment, subset=['è°æ´å¹
度']) |
| | | st.dataframe(styled_df, use_container_width=True, hide_index=True) |
| | | |
| | | # 5.6 å¯è§åå¯¹æ¯ |
| | | fig = go.Figure() |
| | | fig.add_trace(go.Bar( |
| | | x=param_compare_df['åæ°åç§°'], |
| | | y=param_compare_df['å½åå¼'], |
| | | name='å½åå¼', |
| | | marker_color='blue' |
| | | )) |
| | | fig.add_trace(go.Bar( |
| | | x=param_compare_df['åæ°åç§°'], |
| | | y=param_compare_df['ä¼å建议å¼'], |
| | | name='ä¼å建议å¼', |
| | | marker_color='green' |
| | | )) |
| | | |
| | | fig.update_layout( |
| | | barmode='group', |
| | | title='åæ°è°æ´å¯¹æ¯', |
| | | yaxis_title='æ°å¼', |
| | | height=400 |
| | | ) |
| | | |
| | | st.plotly_chart(fig, use_container_width=True) |
| | | |
| | | # 5.7 ä¼åææå¯è§å |
| | | st.markdown("### ð ä¼åææ") |
| | | |
| | | # ç®æ 彿°å¼å¯¹æ¯ |
| | | fig_objective = go.Figure() |
| | | fig_objective.add_trace(go.Bar( |
| | | x=['å½ååæ°', 'ä¼åååæ°'], |
| | | y=[ |
| | | weight_deviation * current_deviation_percent + weight_adjustment * 0, |
| | | weight_deviation * best_deviation_percent + weight_adjustment * \ |
| | | (abs(best_screw_adjust_percent) + abs(best_process_adjust_percent)) / 2 |
| | | ], |
| | | marker_color=['red', 'green'] |
| | | )) |
| | | fig_objective.update_layout( |
| | | title='å¤ç®æ ä¼å彿°å¼å¯¹æ¯', |
| | | yaxis_title='ç®æ 彿°å¼ï¼è¶å°è¶å¥½ï¼', |
| | | height=300 |
| | | ) |
| | | st.plotly_chart(fig_objective, use_container_width=True) |
| | | |
| | | # 6. åå²è®°å½å±ç¤º |
| | | st.subheader("ð åå²è°èè®°å½") |
| | | |
| | | if 'optimized_adjustment_history' in st.session_state and st.session_state['optimized_adjustment_history']: |
| | | # æ¾ç¤ºåå²è®°å½æ°é |
| | | st.write(f"å
± {len(st.session_state['optimized_adjustment_history'])} æ¡åå²è®°å½") |
| | | |
| | | # å页æ¾ç¤º |
| | | page_size = 10 |
| | | total_pages = (len(st.session_state['optimized_adjustment_history']) + page_size - 1) // page_size |
| | | |
| | | page = st.selectbox( |
| | | "鿩页ç ", |
| | | options=range(1, total_pages + 1), |
| | | key="history_page" |
| | | ) |
| | | |
| | | start_idx = (page - 1) * page_size |
| | | end_idx = start_idx + page_size |
| | | paginated_history = st.session_state['optimized_adjustment_history'][start_idx:end_idx] |
| | | |
| | | # ååæ¾ç¤ºï¼ææ°è®°å½å¨åé¢ |
| | | for record in reversed(paginated_history): |
| | | with st.expander(f"è®°å½æ¶é´: {record['timestamp'].strftime('%Y-%m-%d %H:%M:%S')} | 模å: {record['model_file']}"): |
| | | history_cols = st.columns(3) |
| | | |
| | | with history_cols[0]: |
| | | st.write("**ç±³éåæ°**") |
| | | st.write(f"- æ åç±³é: {record['standard_weight']:.4f} Kg/m") |
| | | st.write(f"- ç±³éä¸é: {record['upper_limit']:.4f} Kg/m") |
| | | st.write(f"- ç±³éä¸é: {record['lower_limit']:.4f} Kg/m") |
| | | st.write(f"- å®é
ç±³é: {record['actual_weight']:.4f} Kg/m") |
| | | |
| | | with history_cols[1]: |
| | | st.write("**éåº¦åæ°**") |
| | | st.write(f"- å½åèºæè½¬é: {record['current_screw_speed']:.1f} rpm") |
| | | st.write(f"- å½åæµç¨ä¸»é: {record['current_process_speed']:.1f} m/min") |
| | | st.write(f"- å»ºè®®èºæè½¬é: {record['adjustment_result']['new_screw_speed']:.1f} rpm") |
| | | st.write(f"- 建议æµç¨ä¸»é: {record['adjustment_result']['new_process_speed']:.1f} m/min") |
| | | |
| | | with history_cols[2]: |
| | | st.write("**颿µç»æ**") |
| | | st.write(f"- å½å颿µç±³é: {record['adjustment_result']['current_predicted_weight']:.4f} Kg/m") |
| | | st.write(f"- ä¼åå颿µç±³é: {record['adjustment_result']['predicted_weight']:.4f} Kg/m") |
| | | st.write(f"- å½å颿µåå·®: {record['adjustment_result']['current_predicted_deviation_percent']:.2f}%") |
| | | st.write(f"- ä¼åå颿µåå·®: {record['adjustment_result']['predicted_deviation_percent']:.2f}%") |
| | | |
| | | st.write("**è°æ´å»ºè®®**") |
| | | st.write(record['adjustment_result']['recommendation']) |
| | | else: |
| | | st.info("ææ åå²è°èè®°å½") |
| | | |
| | | # 7. 帮å©è¯´æ |
| | | with st.expander("â 帮å©è¯´æ"): |
| | | st.markdown(""" |
| | | ### åè½è¯´æ |
| | | æ¬åè½æ¨¡ååºäºå¤ç®æ ä¼åç®æ³ï¼æ ¹æ®å½åç±³éæµéå¼åæ¤åºæºåæ°ï¼ä¸ºç¨æ·æä¾ç§å¦åççåæ°è°æ´å»ºè®®ã |
| | | |
| | | ### ä¼åç®æ³ |
| | | - **ç®æ³ç±»å**: ç²å群ä¼åç®æ³ï¼PSOï¼ |
| | | - **ä¼åç®æ **: |
| | | 1. æå°åç±³éåå·® |
| | | 2. æå°ååæ°è°æ´å¹
度 |
| | | - **çº¦ææ¡ä»¶**: |
| | | - èºæè½¬éåæµç¨ä¸»éä¸ä¸é |
| | | - 忬¡æå¤§è°æ´å¹
度 |
| | | |
| | | ### ç»æè§£è¯» |
| | | - **ç±³éç¶æ**: æ¾ç¤ºä¼åå颿µç±³éæ¯å¦å¨å
许èå´å
|
| | | - **å差信æ¯**: å½åç±³é䏿 åç±³éçåå·® |
| | | - **颿µç»æå¯¹æ¯**: å½ååæ°åä¼åååæ°ç颿µç±³éå¯¹æ¯ |
| | | - **è°æ´å»ºè®®**: 详ç»çåæ°è°æ´å»ºè®® |
| | | - **忰坹æ¯**: ç´è§å±ç¤ºåæ°è°æ´å¹
度 |
| | | - **ä¼åææ**: å¤ç®æ ä¼å彿°å¼å¯¹æ¯ |
| | | |
| | | ### 注æäºé¡¹ |
| | | 1. 请确ä¿è¾å
¥çåæ°å¼åç¡®åæ è®¾å¤å½åç¶æ |
| | | 2. ä¼å建议ä»
ä¾åèï¼å®é
æä½æ¶è¯·ç»åç°åºç»éª |
| | | 3. 建议å¨è°æ´åæ°åå¯åè§å¯ç±³éåå |
| | | 4. å®ææ´æ°æ¨¡å以æé«å»ºè®®çåç¡®æ§ |
| | | """) |
| | | |
| | | # 页é¢å
¥å£ |
| | | if __name__ == "__main__": |
| | | show_optimized_parameter_adjustment() |