fertilizer / app.py
Bhargavitippareddy's picture
Update app.py
08f21f2 verified
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Input, Dense
import matplotlib.pyplot as plt
# Load dataset
@st.cache_data
def load_data():
return pd.read_csv("f2.csv")
df = load_data()
st.title("Fertilizer Prediction with ANN - Interactive Demo")
# Define target and features
target = 'Fertilizer'
cat_features = ['Soil_Type', 'Crop_Type']
num_features = ['Temparature', 'Humidity', 'Moisture', 'Nitrogen', 'Potassium', 'Phosphorous']
X = df.drop(columns=[target])
y = df[target]
# Preprocessing pipeline
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), num_features),
('cat', OneHotEncoder(handle_unknown='ignore'), cat_features)
]
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=27)
X_train = preprocessor.fit_transform(X_train)
X_test = preprocessor.transform(X_test)
le = LabelEncoder()
y_train = le.fit_transform(y_train)
y_test = le.transform(y_test)
# Sidebar params
st.sidebar.header("Model Parameters")
epochs = st.sidebar.slider("Epochs", 5, 100, 30)
batch_size = st.sidebar.selectbox("Batch Size", [8, 16, 32, 64], index=1)
# Build ANN model
model = Sequential()
model.add(Input(shape=(X_train.shape[1],)))
model.add(Dense(16, activation='relu'))
model.add(Dense(32, activation='relu'))
model.add(Dense(len(np.unique(y_train)), activation='softmax'))
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
if st.button("Train Model"):
history = model.fit(X_train, y_train, validation_split=0.2, epochs=epochs, batch_size=batch_size, verbose=0)
st.success("Model training complete.")
st.subheader("Model Summary")
# Capture model summary into a list
model_summary = []
model.summary(print_fn=lambda x: model_summary.append(x))
st.write("Model Summary")
st.code("\n".join(model_summary))
# Extract table rows from the summary
table_data = []
start_parsing = False
for line in model_summary:
if 'Layer' in line and 'Output' in line and 'Param' in line:
start_parsing = True
continue
if start_parsing and all(char == '=' for char in line.strip()):
continue
if start_parsing and ('Total params' in line or 'Trainable params' in line or 'Non-trainable params' in line):
break
if start_parsing:
# Try splitting by '|' first
parts = [p.strip() for p in line.split('|')]
parts = [p for p in parts if p]
if len(parts) == 3:
table_data.append(parts)
continue # Move to the next line if successful
# If '|' split fails, try splitting by multiple spaces
parts = [p.strip() for p in line.split(' ') if p.strip()]
if len(parts) >= 3:
table_data.append(parts[:3])
# Display as a table if data is available
if table_data:
# Ensure the correct number of columns
if table_data and len(table_data[0]) == 3:
model_df = pd.DataFrame(table_data, columns=["Layer (type)", "Output Shape", "Param #"])
st.table(model_df)
else:
st.warning("Could not create table: Inconsistent number of columns found.")
st.write("Extracted Data (for debugging):")
st.write(table_data)
else:
st.warning("")
# Plot training metrics
st.subheader("Training and Validation Metrics")
fig, ax = plt.subplots(2, 1, figsize=(8, 6))
ax[0].plot(history.history['loss'], label='Loss')
ax[0].plot(history.history['val_loss'], label='Val Loss')
ax[0].legend()
ax[0].set_title("Loss vs Validation Loss")
ax[1].plot(history.history['accuracy'], label='Accuracy')
ax[1].plot(history.history['val_accuracy'], label='Val Accuracy')
ax[1].legend()
ax[1].set_title("Accuracy vs Validation Accuracy")
st.pyplot(fig)
# Show min val loss and best val accuracy
st.write(f"**Minimum Validation Loss:** {min(history.history['val_loss']):.4f}")
st.write(f"**Best Validation Accuracy:** {max(history.history['val_accuracy']):.4f}")
# Save model and label encoder in session state for predictions
st.session_state['model'] = model
st.session_state['preprocessor'] = preprocessor
st.session_state['label_encoder'] = le
# Only show prediction UI if model is trained and saved
if 'model' in st.session_state:
st.subheader("🌾 Predict Fertilizer Type Based on Input Features")
input_soil = st.selectbox("Select Soil Type", df["Soil_Type"].unique())
input_crop = st.selectbox("Select Crop Type", df["Crop_Type"].unique())
input_temp = st.slider("Temperature (°C)", float(df["Temparature"].min()), float(df["Temparature"].max()), float(df["Temparature"].mean()))
input_humidity = st.slider("Humidity (%)", float(df["Humidity"].min()), float(df["Humidity"].max()), float(df["Humidity"].mean()))
input_moisture = st.slider("Moisture (%)", float(df["Moisture"].min()), float(df["Moisture"].max()), float(df["Moisture"].mean()))
input_nitrogen = st.slider("Nitrogen Level", float(df["Nitrogen"].min()), float(df["Nitrogen"].max()), float(df["Nitrogen"].mean()))
input_potassium = st.slider("Potassium Level", float(df["Potassium"].min()), float(df["Potassium"].max()), float(df["Potassium"].mean()))
input_phosphorous = st.slider("Phosphorous Level", float(df["Phosphorous"].min()), float(df["Phosphorous"].max()), float(df["Phosphorous"].mean()))
# Prepare input data
input_dict = {
"Soil_Type": input_soil,
"Crop_Type": input_crop,
"Temparature": input_temp,
"Humidity": input_humidity,
"Moisture": input_moisture,
"Nitrogen": input_nitrogen,
"Potassium": input_potassium,
"Phosphorous": input_phosphorous,
}
input_df = pd.DataFrame([input_dict])
X_input = st.session_state['preprocessor'].transform(input_df)
# Predict
probs = st.session_state['model'].predict(X_input)[0]
pred_class_idx = np.argmax(probs)
pred_label = st.session_state['label_encoder'].inverse_transform([pred_class_idx])[0]
st.success(f"🌟 Predicted Fertilizer: **{pred_label}**")
# Plot confidence
fig, ax = plt.subplots()
fertilizer_classes = st.session_state['label_encoder'].classes_
ax.bar(fertilizer_classes, probs)
ax.set_ylabel("Prediction Probability")
ax.set_title("Fertilizer Prediction Confidence")
plt.xticks(rotation=45)
st.pyplot(fig)