Spaces:
Sleeping
Sleeping
File size: 4,862 Bytes
895617f | 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 | """
PHASE 3: ML Model Training
Goal: Predict environmental impact category (Low / Medium / High Impact)
Algorithm: RandomForestClassifier
HF Spaces compatible β uses BASE_DIR for all file paths.
"""
import os
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report, accuracy_score
import joblib
import warnings
warnings.filterwarnings("ignore")
# ββ HF-safe absolute paths ββββββββββββββββββββββββββββββββββββββββββββββββββ
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
MODEL_PATH = os.path.join(BASE_DIR, "models", "eco_classifier.pkl")
ENCODER_PATH = os.path.join(BASE_DIR, "models", "category_encoder.pkl")
LABEL_ENCODER_PATH= os.path.join(BASE_DIR, "models", "label_encoder.pkl")
DATA_PATH = os.path.join(BASE_DIR, "dataset", "products.csv")
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def preprocess_data(df: pd.DataFrame):
df = df.copy()
cat_encoder = LabelEncoder()
df["category_encoded"] = cat_encoder.fit_transform(df["category"])
feature_cols = [
"category_encoded",
"deforestation_risk",
"pollution_level",
"biodiversity_impact",
]
X = df[feature_cols].values
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(df["eco_label"])
return X, y, cat_encoder, label_encoder, feature_cols
def train_model(data_path: str = DATA_PATH):
os.makedirs(os.path.join(BASE_DIR, "models"), exist_ok=True)
print("π Loading dataset...")
df = pd.read_csv(data_path)
print(f" Dataset shape: {df.shape}")
print(f" Label distribution:\n{df['eco_label'].value_counts()}\n")
print("βοΈ Preprocessing data...")
X, y, cat_encoder, label_encoder, feature_cols = preprocess_data(df)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
print(f" Train: {len(X_train)} | Test: {len(X_test)}\n")
print("π² Training RandomForest model...")
model = RandomForestClassifier(
n_estimators=200,
max_depth=10,
min_samples_split=2,
random_state=42,
class_weight="balanced",
)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
report = classification_report(
y_test, y_pred,
target_names=label_encoder.classes_,
output_dict=True,
)
report_str = classification_report(y_test, y_pred, target_names=label_encoder.classes_)
print(f"β
Accuracy: {accuracy:.2%}\n{report_str}")
joblib.dump(model, MODEL_PATH)
joblib.dump(cat_encoder, ENCODER_PATH)
joblib.dump(label_encoder, LABEL_ENCODER_PATH)
print(f"πΎ Saved β {MODEL_PATH}")
return {
"accuracy": accuracy,
"report": report,
"feature_importances": dict(zip(feature_cols, model.feature_importances_)),
"classes": list(label_encoder.classes_),
}
def load_model():
if not os.path.exists(MODEL_PATH):
print("Model not found β training now...")
train_model()
model = joblib.load(MODEL_PATH)
cat_encoder = joblib.load(ENCODER_PATH)
label_encoder = joblib.load(LABEL_ENCODER_PATH)
return model, cat_encoder, label_encoder
def predict_impact(
category: str,
deforestation_risk: float,
pollution_level: float,
biodiversity_impact: float,
) -> dict:
model, cat_encoder, label_encoder = load_model()
known_cats = list(cat_encoder.classes_)
if category not in known_cats:
category = known_cats[0]
cat_encoded = cat_encoder.transform([category])[0]
X = np.array([[cat_encoded, deforestation_risk, pollution_level, biodiversity_impact]])
pred_idx = model.predict(X)[0]
proba = model.predict_proba(X)[0]
predicted_label = label_encoder.inverse_transform([pred_idx])[0]
confidence_dict = {
cls: round(float(p), 3)
for cls, p in zip(label_encoder.classes_, proba)
}
return {
"predicted_impact": predicted_label,
"confidence": round(float(proba[pred_idx]), 3),
"all_probabilities": confidence_dict,
"known_categories": known_cats,
}
if __name__ == "__main__":
print("=== EcoVision ML Model Training ===\n")
results = train_model()
print(f"\nFinal Accuracy: {results['accuracy']:.2%}")
|