| """ |
| Iris Flower Classifier - Aplicaci贸n Gradio |
| ============================================ |
| Interfaz interactiva para clasificar flores Iris usando XGBoost. |
| """ |
|
|
| import gradio as gr |
| import joblib |
| import numpy as np |
| import pandas as pd |
| import json |
| import matplotlib.pyplot as plt |
| import seaborn as sns |
| import os |
|
|
| |
| model = joblib.load("model.joblib") |
| le = joblib.load("label_encoder.joblib") |
|
|
| with open("model_info.json") as f: |
| model_info = json.load(f) |
|
|
| |
| df = pd.read_csv("data/IRIS.csv") |
|
|
| |
| FEATURE_RANGES = { |
| "sepal_length": (4.0, 8.0, 5.8), |
| "sepal_width": (2.0, 4.5, 3.0), |
| "petal_length": (1.0, 7.0, 3.8), |
| "petal_width": (0.1, 2.5, 1.2), |
| } |
|
|
| SPECIES_EMOJI = { |
| "Iris-setosa": "馃尭", |
| "Iris-versicolor": "馃尯", |
| "Iris-virginica": "馃尰", |
| } |
|
|
|
|
| def predict(sepal_length, sepal_width, petal_length, petal_width): |
| """Predecir especie de Iris.""" |
| features = np.array([[sepal_length, sepal_width, petal_length, petal_width]]) |
| proba = model.predict_proba(features)[0] |
| result = { |
| f"{SPECIES_EMOJI.get(cls, '')} {cls}": float(p) |
| for cls, p in zip(le.classes_, proba) |
| } |
| return result |
|
|
|
|
| def create_eda_plot(column, plot_type): |
| """Generar gr谩fico EDA interactivo.""" |
| fig, ax = plt.subplots(figsize=(10, 6)) |
|
|
| if plot_type == "Histograma": |
| for species in df['species'].unique(): |
| subset = df[df['species'] == species] |
| ax.hist(subset[column], alpha=0.6, label=species, bins=15) |
| ax.legend() |
| elif plot_type == "Boxplot": |
| sns.boxplot(x='species', y=column, data=df, ax=ax) |
| elif plot_type == "Violin": |
| sns.violinplot(x='species', y=column, data=df, ax=ax) |
| elif plot_type == "Scatter (vs petal_length)": |
| for species in df['species'].unique(): |
| subset = df[df['species'] == species] |
| ax.scatter(subset[column], subset['petal_length'], alpha=0.7, label=species) |
| ax.set_ylabel("petal_length") |
| ax.legend() |
|
|
| ax.set_title(f"{plot_type} de {column}") |
| ax.set_xlabel(column) |
| plt.tight_layout() |
| return fig |
|
|
|
|
| def show_correlation(): |
| """Mostrar matriz de correlaci贸n.""" |
| fig, ax = plt.subplots(figsize=(8, 6)) |
| numeric_df = df.select_dtypes(include=[np.number]) |
| corr = numeric_df.corr() |
| mask = np.triu(np.ones_like(corr, dtype=bool)) |
| sns.heatmap(corr, mask=mask, annot=True, fmt=".2f", cmap="coolwarm", center=0, ax=ax) |
| ax.set_title("Matriz de Correlaci贸n") |
| plt.tight_layout() |
| return fig |
|
|
|
|
| def show_pairplot(): |
| """Generar pairplot.""" |
| fig = sns.pairplot(df, hue='species', diag_kind='kde', height=2.2) |
| return fig.figure |
|
|
|
|
| |
| |
| |
| numeric_cols = ["sepal_length", "sepal_width", "petal_length", "petal_width"] |
|
|
| with gr.Blocks(theme=gr.themes.Soft(), title="Iris Flower Classifier") as demo: |
| gr.Markdown( |
| """ |
| # 馃尯 Iris Flower Classifier |
| Clasificador de flores Iris usando **XGBoost** entrenado con el |
| [dataset de Kaggle](https://www.kaggle.com/datasets/sims22/irisflowerdatasets). |
| """ |
| ) |
|
|
| with gr.Tab("馃敭 Predicci贸n"): |
| with gr.Row(): |
| with gr.Column(): |
| sl = gr.Slider(*FEATURE_RANGES["sepal_length"], label="Sepal Length (cm)") |
| sw = gr.Slider(*FEATURE_RANGES["sepal_width"], label="Sepal Width (cm)") |
| pl = gr.Slider(*FEATURE_RANGES["petal_length"], label="Petal Length (cm)") |
| pw = gr.Slider(*FEATURE_RANGES["petal_width"], label="Petal Width (cm)") |
| predict_btn = gr.Button("Clasificar", variant="primary") |
| with gr.Column(): |
| output_label = gr.Label(num_top_classes=3, label="Predicci贸n") |
|
|
| predict_btn.click(predict, inputs=[sl, sw, pl, pw], outputs=output_label) |
|
|
| gr.Examples( |
| examples=[ |
| [5.1, 3.5, 1.4, 0.2], |
| [6.2, 2.9, 4.3, 1.3], |
| [7.7, 3.0, 6.1, 2.3], |
| ], |
| inputs=[sl, sw, pl, pw], |
| label="Ejemplos por especie", |
| ) |
|
|
| with gr.Tab("馃搳 EDA Interactivo"): |
| with gr.Row(): |
| col_selector = gr.Dropdown( |
| choices=numeric_cols, value="petal_length", label="Feature" |
| ) |
| plot_type = gr.Dropdown( |
| choices=["Histograma", "Boxplot", "Violin", "Scatter (vs petal_length)"], |
| value="Histograma", |
| label="Tipo de gr谩fico", |
| ) |
| eda_plot = gr.Plot(label="Visualizaci贸n") |
| col_selector.change(create_eda_plot, [col_selector, plot_type], eda_plot) |
| plot_type.change(create_eda_plot, [col_selector, plot_type], eda_plot) |
|
|
| with gr.Row(): |
| corr_btn = gr.Button("Matriz de Correlaci贸n") |
| pair_btn = gr.Button("Pairplot") |
| extra_plot = gr.Plot(label="An谩lisis") |
| corr_btn.click(show_correlation, outputs=extra_plot) |
| pair_btn.click(show_pairplot, outputs=extra_plot) |
|
|
| with gr.Tab("馃搵 Datos"): |
| gr.Markdown("### Dataset Iris (150 muestras)") |
| gr.DataFrame(value=df, label="Dataset completo") |
| gr.Markdown(f"### Estad铆sticas descriptivas") |
| gr.DataFrame(value=df.describe().reset_index(), label="Estad铆sticas") |
|
|
| with gr.Tab("馃搱 M茅tricas del Modelo"): |
| gr.Markdown(f""" |
| ### Rendimiento del modelo XGBoost |
| - **Test Accuracy**: {model_info['metrics']['test_accuracy']:.4f} |
| - **CV Accuracy**: {model_info['metrics']['cv_accuracy_mean']:.4f} 卤 {model_info['metrics']['cv_accuracy_std']:.4f} |
| - **Clases**: {', '.join(model_info['classes'])} |
| """) |
| with gr.Row(): |
| if os.path.exists("outputs/confusion_matrix.png"): |
| gr.Image(value="outputs/confusion_matrix.png", label="Confusion Matrix") |
| if os.path.exists("outputs/feature_importance.png"): |
| gr.Image(value="outputs/feature_importance.png", label="Feature Importance") |
| gr.JSON(value=model_info, label="Metadata del modelo") |
|
|
|
|
| if __name__ == "__main__": |
| demo.launch() |
|
|