File size: 6,355 Bytes
a6a2244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3d2bdb5
 
 
 
 
 
 
a6a2244
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# app.py
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
import plotly.express as px
import plotly.graph_objects as go
import seaborn as sns
import matplotlib.pyplot as plt

class IrisPredictor:
    def __init__(self):
        self.iris = load_iris()
        self.df = pd.DataFrame(data=np.c_[self.iris['data'], self.iris['target']], 
                             columns=self.iris['feature_names'] + ['target'])
        self.models = {
            'Logistic Regression': LogisticRegression(),
            'Decision Tree': DecisionTreeClassifier(),
            'Random Forest': RandomForestClassifier()
        }
        self.X = self.df.drop('target', axis=1)
        self.y = self.df['target']
        self.scaler = StandardScaler()
        
    def preprocess_data(self):
        # Split the data
        X_train, X_test, y_train, y_test = train_test_split(
            self.X, self.y, test_size=0.2, random_state=42
        )
        
        # Scale the features
        X_train_scaled = self.scaler.fit_transform(X_train)
        X_test_scaled = self.scaler.transform(X_test)
        
        return X_train_scaled, X_test_scaled, y_train, y_test
    
    def train_model(self, model_name):
        X_train_scaled, X_test_scaled, y_train, y_test = self.preprocess_data()
        
        # Train model
        model = self.models[model_name]
        model.fit(X_train_scaled, y_train)
        
        # Make predictions
        y_pred = model.predict(X_test_scaled)
        
        # Calculate metrics
        accuracy = accuracy_score(y_test, y_pred)
        conf_matrix = confusion_matrix(y_test, y_pred)
        class_report = classification_report(y_test, y_pred)
        
        return {
            'model': model,
            'accuracy': accuracy,
            'confusion_matrix': conf_matrix,
            'classification_report': class_report,
            'X_test': X_test_scaled,
            'y_test': y_test,
            'y_pred': y_pred
        }
    
    def plot_confusion_matrix(self, conf_matrix):
        fig = px.imshow(conf_matrix,
                       labels=dict(x="Predicted", y="Actual"),
                       x=['Setosa', 'Versicolor', 'Virginica'],
                       y=['Setosa', 'Versicolor', 'Virginica'],
                       title="Confusion Matrix")
        return fig
    
    def plot_feature_importance(self, model_name, model):
        if model_name == 'Logistic Regression':
            importance = abs(model.coef_[0])
        else:
            importance = model.feature_importances_
            
        fig = px.bar(x=self.X.columns, y=importance,
                    title=f"Feature Importance - {model_name}",
                    labels={'x': 'Features', 'y': 'Importance'})
        return fig
    
    def predict_single_sample(self, model, features):
        # Scale features
        scaled_features = self.scaler.transform([features])
        # Make prediction
        prediction = model.predict(scaled_features)
        probabilities = model.predict_proba(scaled_features)
        return prediction[0], probabilities[0]

def main():
    st.title("🌸 Iris Flower Prediction App")
    st.write("""
    This app predicts the Iris flower type based on its features.
    Choose a model and see how it performs!
    """)
    
    # Initialize predictor
    predictor = IrisPredictor()
    
    # Model selection
    st.sidebar.header("Model Selection")
    model_name = st.sidebar.selectbox(
        "Choose a model",
        list(predictor.models.keys())
    )
    
    # Train model and show results
    if st.sidebar.button("Train Model"):
        with st.spinner("Training model..."):
            results = predictor.train_model(model_name)
            
            # Display metrics
            st.header("Model Performance")
            st.metric("Accuracy", f"{results['accuracy']:.2%}")
            
            # Display confusion matrix
            st.subheader("Confusion Matrix")
            conf_matrix_fig = predictor.plot_confusion_matrix(results['confusion_matrix'])
            st.plotly_chart(conf_matrix_fig)
            
            # Display feature importance
            st.subheader("Feature Importance")
            importance_fig = predictor.plot_feature_importance(model_name, results['model'])
            st.plotly_chart(importance_fig)
            
            # Display classification report
            st.subheader("Classification Report")
            st.text(results['classification_report'])
            
            # Store the trained model in session state
            st.session_state['trained_model'] = results['model']
    
    # Make predictions
    st.header("Make Predictions")
    col1, col2 = st.columns(2)
    
    with col1:
        sepal_length = st.slider("Sepal Length", 4.0, 8.0, 5.4)
        sepal_width = st.slider("Sepal Width", 2.0, 4.5, 3.4)
    
    with col2:
        petal_length = st.slider("Petal Length", 1.0, 7.0, 4.7)
        petal_width = st.slider("Petal Width", 0.1, 2.5, 1.4)
    
    if st.button("Predict"):
        if 'trained_model' in st.session_state:
            features = [sepal_length, sepal_width, petal_length, petal_width]
            prediction, probabilities = predictor.predict_single_sample(
                st.session_state['trained_model'], features
            )
            
            # Display prediction
            iris_types = ['Setosa', 'Versicolor', 'Virginica']
            st.success(f"Predicted Iris Type: {iris_types[int(prediction)]}")
            
            # Display probability distribution
            st.subheader("Prediction Probabilities")
            prob_fig = px.bar(x=iris_types, y=probabilities,
                            title="Prediction Probability Distribution",
                            labels={'x': 'Iris Type', 'y': 'Probability'})
            st.plotly_chart(prob_fig)
        else:
            st.warning("Please train a model first!")

if __name__ == "__main__":
    main()