File size: 6,804 Bytes
8872a72
 
 
 
 
 
 
 
817de2f
8872a72
 
 
 
e66bc63
8872a72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
08f21f2
8872a72
 
 
 
d7d00cb
 
8872a72
 
 
d7d00cb
 
 
 
8872a72
 
 
d7d00cb
8872a72
 
d7d00cb
8872a72
 
 
d7d00cb
 
 
 
8872a72
 
d7d00cb
 
 
 
 
 
8872a72
d7d00cb
8872a72
d7d00cb
 
 
 
 
 
 
 
8872a72
d7d00cb
8872a72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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)