diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 26c78f2c..e2ca4169 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -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.")