Spaces:
Sleeping
Sleeping
| import pandas as pd | |
| import numpy as np | |
| import gradio as gr | |
| from tensorflow.keras.models import Sequential | |
| from tensorflow.keras.layers import LSTM, Dense | |
| from sklearn.preprocessing import MinMaxScaler | |
| # ================================ | |
| # Sequence creator | |
| # ================================ | |
| def create_sequences(data, seq_len=12): | |
| X, y = [], [] | |
| for i in range(len(data) - seq_len): | |
| X.append(data[i:i+seq_len]) | |
| y.append(data[i+seq_len]) | |
| return np.array(X), np.array(y) | |
| # ================================ | |
| # Train Model | |
| # ================================ | |
| def train_model(file): | |
| try: | |
| df = pd.read_csv(file.name) | |
| df.columns = df.columns.str.strip() | |
| required_cols = [ | |
| "Date", "pH", "Turbidity", "DO", | |
| "TDS", "Conductivity", "Ammonia-N" | |
| ] | |
| for col in required_cols: | |
| if col not in df.columns: | |
| return None, None, f"❌ Missing column: {col}" | |
| df["Date"] = pd.to_datetime(df["Date"]) | |
| df = df.groupby("Date").mean().sort_index() | |
| df = df.ffill() | |
| # Create WQI | |
| df["WQI"] = df[[ | |
| "pH", "Turbidity", "DO", | |
| "TDS", "Conductivity", "Ammonia-N" | |
| ]].mean(axis=1) | |
| data = df[[ | |
| "pH", "Turbidity", "DO", | |
| "TDS", "Conductivity", "Ammonia-N", "WQI" | |
| ]] | |
| scaler = MinMaxScaler() | |
| scaled_data = scaler.fit_transform(data) | |
| seq_len = 12 | |
| X, y = create_sequences(scaled_data, seq_len) | |
| model = Sequential([ | |
| LSTM(64, return_sequences=True, input_shape=(seq_len, X.shape[2])), | |
| LSTM(32), | |
| Dense(X.shape[2]) | |
| ]) | |
| model.compile(optimizer='adam', loss='mse') | |
| model.fit(X, y, epochs=20, batch_size=8, verbose=0) | |
| return model, scaler, "✅ Model trained successfully!" | |
| except Exception as e: | |
| return None, None, str(e) | |
| # ================================ | |
| # Predict Function | |
| # ================================ | |
| def predict(model, scaler, file, steps): | |
| try: | |
| if model is None or scaler is None: | |
| return "❌ Train the model first!" | |
| steps = int(steps) | |
| df = pd.read_csv(file.name) | |
| df.columns = df.columns.str.strip() | |
| df["Date"] = pd.to_datetime(df["Date"]) | |
| df = df.groupby("Date").mean().sort_index() | |
| df = df.ffill() | |
| df["WQI"] = df[[ | |
| "pH", "Turbidity", "DO", | |
| "TDS", "Conductivity", "Ammonia-N" | |
| ]].mean(axis=1) | |
| data = df[[ | |
| "pH", "Turbidity", "DO", | |
| "TDS", "Conductivity", "Ammonia-N", "WQI" | |
| ]] | |
| scaled_data = scaler.transform(data) | |
| seq_len = 12 | |
| last_seq = scaled_data[-seq_len:] | |
| preds = [] | |
| current_seq = last_seq.copy() | |
| for _ in range(steps): | |
| pred = model.predict(current_seq.reshape(1, seq_len, current_seq.shape[1]), verbose=0)[0] | |
| preds.append(pred) | |
| current_seq = np.vstack([current_seq[1:], pred]) | |
| preds = scaler.inverse_transform(preds) | |
| result_df = pd.DataFrame(preds, columns=data.columns) | |
| return result_df[["WQI"]].round(2) | |
| except Exception as e: | |
| return str(e) | |
| # ================================ | |
| # Gradio UI | |
| # ================================ | |
| with gr.Blocks() as app: | |
| gr.Markdown("## 💧 LSTM Water Quality Forecast") | |
| file_input = gr.File(label="Upload CSV") | |
| steps_input = gr.Number(label="Forecast Steps") | |
| train_btn = gr.Button("Train Model") | |
| predict_btn = gr.Button("Predict") | |
| output = gr.Dataframe() | |
| status = gr.Textbox(label="Status") | |
| # State (stores model + scaler) | |
| model_state = gr.State() | |
| scaler_state = gr.State() | |
| train_btn.click( | |
| fn=train_model, | |
| inputs=file_input, | |
| outputs=[model_state, scaler_state, status] | |
| ) | |
| predict_btn.click( | |
| fn=predict, | |
| inputs=[model_state, scaler_state, file_input, steps_input], | |
| outputs=output | |
| ) | |
| app.launch(ssr_mode=False) | |