ML_Lab2 / app.py
Shinoaki0145's picture
fix name model and notebook
e8720f8
Raw History Blame Contribute Delete
8.89 kB
from pathlib import Path
import gradio as gr
import joblib
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.metrics import mean_squared_error, r2_score
DATA_PATH = Path(__file__).with_name("Fuel_Consumption_2000-2022.csv")
MODEL_PATH = Path(__file__).with_name("best_model.joblib")
TARGET = "CO2 Emissions(g/km)"
NUMERIC_FEATURES = [
"Engine Size(L)",
"Cylinders",
"Fuel Consumption Comb (L/100 km)",
]
CATEGORICAL_FEATURES = [
"Vehicle Class",
"Fuel Type",
]
MODEL_FEATURES = NUMERIC_FEATURES + CATEGORICAL_FEATURES
def load_dataset() -> pd.DataFrame:
df = pd.read_csv(DATA_PATH)
df["Make"] = df["Make"].apply(lambda v: v.upper())
df["Vehicle Class"] = df["Vehicle Class"].apply(
lambda v: v.upper().replace(": ", " - ")
)
return df[MODEL_FEATURES + [TARGET]].copy()
def load_metrics() -> tuple[pd.DataFrame, dict]:
df = load_dataset()
artifact = joblib.load(MODEL_PATH)
y_pred = artifact["holdout_prediction"]
y_test = artifact["y_test"]
metrics = {
"Test RMSE": round(mean_squared_error(y_test, y_pred) ** 0.5, 3),
"Test R2": round(r2_score(y_test, y_pred), 4),
"Train rows": int(artifact["train_rows"]),
"Test rows": int(artifact["test_rows"]),
}
return df, metrics
ARTIFACT = joblib.load(MODEL_PATH)
MODEL = ARTIFACT["model"]
DATAFRAME, METRICS = load_metrics()
VEHICLE_CLASSES = sorted(DATAFRAME["Vehicle Class"].dropna().unique().tolist())
FUEL_TYPES = sorted(DATAFRAME["Fuel Type"].dropna().unique().tolist())
CYLINDER_VALUES = sorted(int(v) for v in DATAFRAME["Cylinders"].dropna().unique().tolist())
ENGINE_MIN = float(DATAFRAME["Engine Size(L)"].min())
ENGINE_MAX = float(DATAFRAME["Engine Size(L)"].max())
FUEL_MIN = float(DATAFRAME["Fuel Consumption Comb (L/100 km)"].min())
FUEL_MAX = float(DATAFRAME["Fuel Consumption Comb (L/100 km)"].max())
def build_relationship_plot():
plot_df = DATAFRAME[
[
"Fuel Consumption Comb (L/100 km)",
TARGET,
"Fuel Type",
]
].dropna()
fuel_types = sorted(plot_df["Fuel Type"].unique().tolist())
cmap = plt.get_cmap("tab10")
fig, ax = plt.subplots(figsize=(8, 5))
for index, fuel in enumerate(fuel_types):
subset = plot_df[plot_df["Fuel Type"] == fuel]
ax.scatter(
subset["Fuel Consumption Comb (L/100 km)"],
subset[TARGET],
s=28,
alpha=0.55,
color=cmap(index % 10),
label=fuel,
)
trend_x = plot_df["Fuel Consumption Comb (L/100 km)"]
trend_y = plot_df[TARGET]
line_coef = np.polyfit(trend_x, trend_y, 1)
line_x = pd.Series([trend_x.min(), trend_x.max()])
line_y = line_coef[0] * line_x + line_coef[1]
ax.plot(line_x, line_y, color="#222222", linewidth=2, label="Trend line")
ax.set_title("Fuel Consumption vs CO2 Emissions")
ax.set_xlabel("Fuel Consumption Comb (L/100 km)")
ax.set_ylabel("CO2 Emissions (g/km)")
ax.set_facecolor("#fafafa")
ax.grid(alpha=0.2, linestyle="--", linewidth=0.6)
ax.legend(title="Fuel Type", fontsize=8)
fig.tight_layout()
return fig
def build_vehicle_class_plot():
class_df = (
DATAFRAME.groupby("Vehicle Class", as_index=False)[TARGET]
.mean()
.sort_values(TARGET, ascending=False)
.head(10)
)
fig, ax = plt.subplots(figsize=(8, 5))
ax.barh(class_df["Vehicle Class"], class_df[TARGET], color="#2a9d8f")
ax.invert_yaxis()
ax.set_title("Top 10 Vehicle Classes by Average CO2 Emissions")
ax.set_xlabel("Average CO2 Emissions (g/km)")
ax.set_ylabel("Vehicle Class")
ax.set_facecolor("#fafafa")
ax.grid(axis="x", alpha=0.2, linestyle="--", linewidth=0.6)
fig.tight_layout()
return fig
def build_emissions_distribution_plot():
fig, ax = plt.subplots(figsize=(8, 5))
ax.hist(DATAFRAME[TARGET].dropna(), bins=30, color="#f4a261", edgecolor="white")
ax.set_title("Distribution of CO2 Emissions")
ax.set_xlabel("CO2 Emissions (g/km)")
ax.set_ylabel("Frequency")
ax.set_facecolor("#fafafa")
ax.grid(axis="y", alpha=0.2, linestyle="--", linewidth=0.6)
fig.tight_layout()
return fig
def build_engine_size_plot():
plot_df = DATAFRAME[["Engine Size(L)", TARGET]].dropna()
fig, ax = plt.subplots(figsize=(8, 5))
ax.scatter(
plot_df["Engine Size(L)"],
plot_df[TARGET],
alpha=0.6,
color="#457b9d",
s=30,
)
ax.set_title("Engine Size vs CO2 Emissions")
ax.set_xlabel("Engine Size(L)")
ax.set_ylabel("CO2 Emissions(g/km)")
ax.set_facecolor("#fafafa")
ax.grid(alpha=0.2, linestyle="--", linewidth=0.6)
fig.tight_layout()
return fig
def predict_co2_emission(
engine_size: float,
cylinders: int,
fuel_consumption_comb: float,
vehicle_class: str,
fuel_type: str,
) -> tuple[float, str]:
sample = pd.DataFrame(
{
"Engine Size(L)": [engine_size],
"Cylinders": [cylinders],
"Fuel Consumption Comb (L/100 km)": [fuel_consumption_comb],
"Vehicle Class": [vehicle_class],
"Fuel Type": [fuel_type],
}
)
prediction = float(MODEL.predict(sample)[0])
details = (
"Model 3 - Parsimonious Mixed\n"
f"Engine Size(L): {engine_size}\n"
f"Cylinders: {cylinders}\n"
f"Fuel Consumption Comb (L/100 km): {fuel_consumption_comb}\n"
f"Vehicle Class: {vehicle_class}\n"
f"Fuel Type: {fuel_type}\n"
f"Estimated CO2: {prediction:.2f} g/km"
)
return round(prediction, 2), details
DESCRIPTION = f"""
# CO2 Emissions Predictor
This app predicts **CO2 emissions** for a vehicle.
It uses the following inputs:
- Engine Size(L)
- Cylinders
- Fuel Consumption Comb (L/100 km)
- Vehicle Class
- Fuel Type
Model performance on test data:
- Test RMSE: {METRICS["Test RMSE"]}
- Test R2: {METRICS["Test R2"]}
The charts below help show simple patterns in the dataset.
"""
with gr.Blocks(title="CO2 Emissions Predictor") as demo:
gr.Markdown(DESCRIPTION)
with gr.Row():
engine_size = gr.Slider(
minimum=ENGINE_MIN,
maximum=ENGINE_MAX,
value=2.0,
step=0.1,
label="Engine Size(L)",
)
cylinders = gr.Dropdown(
choices=CYLINDER_VALUES,
value=4,
label="Cylinders",
)
with gr.Row():
fuel_consumption = gr.Slider(
minimum=FUEL_MIN,
maximum=FUEL_MAX,
value=7.5,
step=0.1,
label="Fuel Consumption Comb (L/100 km)",
)
vehicle_class = gr.Dropdown(
choices=VEHICLE_CLASSES,
value="COMPACT" if "COMPACT" in VEHICLE_CLASSES else VEHICLE_CLASSES[0],
label="Vehicle Class",
)
fuel_type = gr.Dropdown(
choices=FUEL_TYPES,
value="X" if "X" in FUEL_TYPES else FUEL_TYPES[0],
label="Fuel Type",
)
predict_button = gr.Button("Predict")
prediction = gr.Number(label="Predicted CO2 (g/km)")
summary = gr.Textbox(label="Result Summary", lines=7)
predict_button.click(
fn=predict_co2_emission,
inputs=[
engine_size,
cylinders,
fuel_consumption,
vehicle_class,
fuel_type,
],
outputs=[prediction, summary],
)
gr.Markdown("## Charts")
gr.Markdown(
"- Distribution of CO2 emissions across the dataset.\n"
"- Relationship between fuel consumption and CO2 emissions.\n"
"- Relationship between engine size and CO2 emissions.\n"
"- Vehicle classes with the highest average CO2 emissions."
)
with gr.Row():
gr.Plot(
value=build_emissions_distribution_plot,
label="Distribution of CO2 Emissions",
)
gr.Plot(
value=build_relationship_plot,
label="Fuel Consumption vs CO2 Emissions",
)
with gr.Row():
gr.Plot(
value=build_engine_size_plot,
label="Engine Size vs CO2 Emissions",
)
gr.Plot(
value=build_vehicle_class_plot,
label="Top Vehicle Classes by CO2 Emissions",
)
gr.Examples(
examples=[
[2.0, 4, 7.5, "COMPACT", "X"],
[3.5, 6, 10.8, "SUV - SMALL", "X"],
[5.0, 8, 14.2, "PICKUP TRUCK - STANDARD", "Z"],
],
inputs=[
engine_size,
cylinders,
fuel_consumption,
vehicle_class,
fuel_type,
],
outputs=[prediction, summary],
fn=predict_co2_emission,
cache_examples=False,
)
if __name__ == "__main__":
demo.launch()