Interactive Iris Flower Classifier

Client-Side ML Active

Adjust Flower Measurements

Input
Sepal Length 5.8 cm
4.0 cm 8.0 cm
Sepal Width 3.0 cm
2.0 cm 4.5 cm
Petal Length 4.3 cm
1.0 cm 7.0 cm
Petal Width 1.3 cm
0.1 cm 2.5 cm

Real-Time SVG Representation

Live View
Predicted Species

Iris Versicolor

Setosa 0%
Versicolor 100%
Virginica 0%

Model Training Hyperparameters

Sandbox
Train/Test Split Ratio 80/20
50/50 90/10

Learning Rate (Alpha) 0.1
0.01 1.0
Max Iterations 500
50 2000
Number of Neighbors (K) 3
1 15
Max Tree Depth 3
1 10

Model Evaluation Metrics

Metrics
Accuracy

100.0%

On test split (80/20)
Total Features

4

Sepal/Petal Dimensions

Classification Report (Test Data)

Class Precision Recall F1-Score
Setosa (0) 1.00 1.00 1.00
Versicolor (1) 1.00 1.00 1.00
Virginica (2) 1.00 1.00 1.00

Confusion Matrix

Pred 0
Pred 1
Pred 2
Act 0
10
0
0
Act 1
0
9
0
Act 2
0
0
11

Setosa: 0

Versicolor: 1

Virginica: 2

A clean diagonal means perfect classification with zero misclassifications.

Iris Dataset Cluster Plot

Visualization
Setosa
Versicolor
Virginica
Your Custom Input

Project Insights & FAQ

Documentation

Backend Python (Scikit-Learn) vs Frontend JS Algorithms

Code Compare
# Training code in Python (iris_classification.ipynb)
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
import pandas as pd

# Load dataset
iris_df = pd.read_csv('Iris.csv')

# Drop duplicates & encode labels
iris_df.drop_duplicates(inplace=True)
le = LabelEncoder()
iris_df['Species_encoded'] = le.fit_transform(iris_df['Species'])

# Split Features & Target
X = iris_df.drop(['Id', 'Species', 'Species_encoded'], axis=1, errors='ignore')
y = iris_df['Species_encoded']

# Split train/test sets (80% / 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Fit Logistic Regression model
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)

# Output evaluation metrics
y_pred = model.predict(X_test)
print("Accuracy:", model.score(X_test, y_test))
// K-Nearest Neighbors Classifier written in Vanilla JavaScript
class KNNClassifier {
    constructor(k = 3, metric = 'euclidean') {
        this.k = k;
        this.metric = metric;
    }

    fit(X, y) {
        this.X_train = X;
        this.y_train = y;
    }

    distance(pt1, pt2) {
        if (this.metric === 'manhattan') {
            return pt1.reduce((sum, val, idx) => sum + Math.abs(val - pt2[idx]), 0);
        }
        // Default: Euclidean
        const sumSq = pt1.reduce((sum, val, idx) => sum + Math.pow(val - pt2[idx], 2), 0);
        return Math.sqrt(sumSq);
    }

    predictSingle(xQuery) {
        // Calculate distances from query point to all training points
        const dists = this.X_train.map((xTrain, idx) => ({
            dist: this.distance(xQuery, xTrain),
            label: this.y_train[idx]
        }));

        // Sort by ascending distance and get top K
        dists.sort((a, b) => a.dist - b.dist);
        const kNearest = dists.slice(0, this.k);

        // Count votes per class
        const votes = [0, 0, 0];
        kNearest.forEach(n => votes[n.label]++);
        
        // Calculate probabilities
        const sum = votes.reduce((a, b) => a + b, 0);
        const probs = votes.map(v => v / sum);

        return {
            predictedClass: votes.indexOf(Math.max(...votes)),
            probabilities: probs
        };
    }
}
# Backend Serving API (app.py) using FastAPI
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import joblib
import numpy as np

app = FastAPI(title="Iris Classifier API", description="Serves Scikit-Learn models")

# Enable CORS for local deployment
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Load trained Model
try:
    model = joblib.load("iris_logistic_model.pkl")
except:
    model = None

class FlowerFeatures(BaseModel):
    sepal_length: float
    sepal_width: float
    petal_length: float
    petal_width: float

@app.post("/predict")
def predict(features: FlowerFeatures):
    if model is None:
        return {"error": "Model pickle file not found. Place 'iris_logistic_model.pkl' in the directory."}
        
    input_data = np.array([[
        features.sepal_length,
        features.sepal_width,
        features.petal_length,
        features.petal_width
    ]])
    
    prediction = int(model.predict(input_data)[0])
    probs = model.predict_proba(input_data)[0].tolist()
    
    species_map = {0: "Setosa", 1: "Versicolor", 2: "Virginica"}
    
    return {
        "species_id": prediction,
        "species_name": species_map[prediction],
        "probabilities": probs
    }