Feat: Umstellung von Decision Tree auf RandomForest für ML-Technikerschätzung
- Umstellung des ML-Modells: Der Algorithmus zur Schätzung der Servicetechniker-Buckets wurde von einem einzelnen Decision Tree auf einen RandomForestClassifier umgestellt. Ziel ist eine höhere Vorhersagegenauigkeit und bessere Generalisierungsfähigkeit durch die Nutzung eines Ensemble-Modells. - Verbesserte Modellevaluation: Die Ausgabe der Baumregeln (spezifisch für Decision Trees) wurde durch die Analyse und Ausgabe der Feature Importance ersetzt. Dies gibt Aufschluss darüber, welche Features (z.B. Log-Umsatz, Branche, Gruppenzugehörigkeit) den größten Einfluss auf die Vorhersagen des RandomForest-Modells haben. - Code-Anpassungen: Die Methode `train_technician_model` wurde entsprechend überarbeitet, um den RandomForestClassifier zu instanziieren, zu trainieren, zu speichern und zu evaluieren. Der `import` für `RandomForestClassifier` wurde hinzugefügt.
This commit is contained in:
@@ -54,6 +54,7 @@ import unicodedata # Fuer Text-Normalisierung
|
||||
# Bibliotheken fuer Datenanalyse und ML
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from sklearn.ensemble import RandomForestClassifier
|
||||
from sklearn.model_selection import train_test_split, GridSearchCV
|
||||
from sklearn.impute import SimpleImputer
|
||||
from sklearn.tree import DecisionTreeClassifier, export_text
|
||||
@@ -9206,43 +9207,37 @@ class DataProcessor:
|
||||
X_train_imputed = pd.DataFrame(X_train_imputed, columns=feature_columns_ml) # feature_columns_ml verwenden
|
||||
X_test_imputed = pd.DataFrame(X_test_imputed, columns=feature_columns_ml) # feature_columns_ml verwenden
|
||||
|
||||
# Die Zeile "Numerische Features imputiert." war ein allgemeiner Kommentar.
|
||||
# Wichtig ist, dass X_train_imputed und X_test_imputed jetzt bereitstehen.
|
||||
|
||||
# 4. Decision Tree Training
|
||||
dt_classifier = DecisionTreeClassifier(random_state=42, class_weight='balanced')
|
||||
# Optional: Hyperparameter-Tuning ...
|
||||
|
||||
self.logger.info(f"Starte Training des Decision Tree Modells auf {X_train_imputed.shape[0]} Trainingsbeispielen mit {X_train_imputed.shape[1]} Features...")
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# +++ ANPASSUNG HIER: RandomForest statt Decision Tree ++++++++++++++++++
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# 4. Random Forest Training
|
||||
# n_estimators=100 ist ein guter Standardwert.
|
||||
# class_weight='balanced' hilft bei unausgewogenen Klassen.
|
||||
# n_jobs=-1 nutzt alle verfügbaren CPU-Kerne und kann das Training beschleunigen.
|
||||
rf_classifier = RandomForestClassifier(n_estimators=100, random_state=42, class_weight='balanced', n_jobs=-1)
|
||||
|
||||
self.logger.info(f"Starte Training des Random Forest Modells auf {X_train_imputed.shape[0]} Trainingsbeispielen...")
|
||||
start_fit_time = time.time()
|
||||
dt_classifier.fit(X_train_imputed, y_train) # << MODELL WIRD HIER TRAINIERT
|
||||
rf_classifier.fit(X_train_imputed, y_train) # << HIER WIRD DER RF TRAINIERT
|
||||
end_fit_time = time.time()
|
||||
self.logger.info(f"Modelltraining abgeschlossen. Dauer: {end_fit_time - start_fit_time:.2f} Sekunden.")
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# +++ HIER DEN CODE ZUM SPEICHERN DES MODELLS EINFÜGEN/VERSCHIEBEN ++++++
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Speichern Sie das trainierte Modell.
|
||||
self.model = dt_classifier # Zuweisung an self.model NACH dem Training
|
||||
# Modell speichern
|
||||
self.model = rf_classifier # Zuweisung des neuen Modells
|
||||
try:
|
||||
model_dir = os.path.dirname(model_out)
|
||||
if model_dir and not os.path.exists(model_dir):
|
||||
os.makedirs(model_dir, exist_ok=True)
|
||||
with open(model_out, 'wb') as f:
|
||||
pickle.dump(dt_classifier, f) # Das trainierte dt_classifier Objekt speichern
|
||||
self.logger.info(f"Decision Tree Modell erfolgreich gespeichert in '{model_out}'.")
|
||||
pickle.dump(rf_classifier, f) # Das trainierte rf_classifier Objekt speichern
|
||||
self.logger.info(f"Random Forest Modell erfolgreich gespeichert in '{model_out}'.")
|
||||
except Exception as e:
|
||||
self.logger.error(f"FEHLER beim Speichern des Modells in '{model_out}': {e}")
|
||||
self.logger.debug(traceback.format_exc())
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# +++ ENDE MODELLSPEICHERUNG ++++++++++++++++++++++++++++++++++++++++++++
|
||||
# +++ ENDE ANPASSUNG ++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# +++ HIER DEN CODE ZUM SPEICHERN DER FEATURE-LISTE EINFÜGEN/VERSCHIEBEN +
|
||||
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
# Speichern Sie die Liste der Feature-Spalten (fuer die Vorhersage)
|
||||
# feature_columns_ml wurde bereits oben korrekt definiert
|
||||
# Feature-Liste speichern (bleibt unverändert)
|
||||
self._expected_features = feature_columns_ml
|
||||
try:
|
||||
patterns_data = {"feature_columns": self._expected_features, "target_classes": list(dt_classifier.classes_)}
|
||||
@@ -9273,11 +9268,17 @@ class DataProcessor:
|
||||
self.logger.info(f"Konfusionsmatrix auf dem Testset (Zeilen=Wahr, Spalten=Vorhersage):\n{cm}")
|
||||
|
||||
try:
|
||||
tree_rules = export_text(dt_classifier, feature_names=feature_columns_ml, max_depth=7)
|
||||
self.logger.info(f"Erste Regeln des Decision Tree (max Tiefe 7):\n{tree_rules}")
|
||||
except Exception as e_tree_rules: # Spezifischere Exception-Variable
|
||||
self.logger.warning(f"FEHLER beim Exportieren der Baumregeln: {e_tree_rules}")
|
||||
self.logger.debug(traceback.format_exc())
|
||||
self.logger.info("Feature Importance (Top 15):")
|
||||
importances = rf_classifier.feature_importances_
|
||||
feature_importance_df = pd.DataFrame({
|
||||
'Feature': feature_columns_ml,
|
||||
'Importance': importances
|
||||
}).sort_values(by='Importance', ascending=False)
|
||||
|
||||
# Ausgabe der Top 15 Features
|
||||
self.logger.info(f"\n{feature_importance_df.head(15).to_string(index=False)}")
|
||||
except Exception as e_feat_imp:
|
||||
self.logger.warning(f"FEHLER beim Berechnen/Anzeigen der Feature Importance: {e_feat_imp}")
|
||||
|
||||
self.logger.info("Modelltraining und -evaluation abgeschlossen.")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user