From 411f33ac4f51b1f718d1a95506543ac736d8fc30 Mon Sep 17 00:00:00 2001 From: Floke Date: Wed, 18 Jun 2025 13:40:52 +0000 Subject: [PATCH] =?UTF-8?q?=C3=84nderung=20ML=20auf=20neue=20Branche?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- brancheneinstufung.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index a2df56dc8..d7bebbfa7 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 imblearn.over_sampling import SMOTE from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.impute import SimpleImputer @@ -8942,7 +8943,7 @@ class DataProcessor: # und weisen ihnen interne, einfachere Namen zu, die im DataFrame verwendet werden. col_keys_mapping = { "name": "CRM Name", # Zur Identifikation, wird spaeter entfernt - "branche_crm": "CRM Branche", # Fuer One-Hot Encoding + "branche_ki": "Chat Vorschlag Branche", # Fuer One-Hot Encoding "umsatz_crm": "CRM Umsatz", # Fuer Konsolidierung "umsatz_wiki": "Wiki Umsatz", # Fuer Konsolidierung "ma_crm": "CRM Anzahl Mitarbeiter", # Fuer Konsolidierung @@ -9098,8 +9099,8 @@ class DataProcessor: # --- Kategoriale Features vorbereiten (Branche) --- self.logger.info("Verarbeite kategoriales Feature 'branche_crm' fuer One-Hot Encoding...") - branche_col_internal = "branche_crm" - df_filtered.loc[:, 'branche_crm'] = df_filtered['branche_crm'].astype(str).fillna('Unbekannt').str.strip() + branche_col_internal = "branche_ki" + df_filtered.loc[:, 'branche_ki'] = df_filtered['branche_crm'].astype(str).fillna('Unbekannt').str.strip() df_encoded = pd.get_dummies(df_filtered, columns=[branche_col_internal], prefix='Branche', dummy_na=False) # --- Finale Auswahl der Features fuer das Modell --- @@ -9206,6 +9207,22 @@ class DataProcessor: X_test_imputed = imputer.transform(X_test) 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 + + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++ NEU: Klassen-Balancierung mit SMOTE auf den Trainingsdaten ++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + self.logger.info("Führe Klassen-Balancierung mit SMOTE auf den Trainingsdaten durch...") + self.logger.info(f"Klassenverteilung VOR SMOTE:\n{y_train.value_counts()}") + + smote = SMOTE(random_state=42) + # Wichtig: SMOTE wird auf die imputierten Trainingsdaten angewendet + X_train_resampled, y_train_resampled = smote.fit_resample(X_train_imputed, y_train) + + self.logger.info(f"Klassenverteilung NACH SMOTE:\n{y_train_resampled.value_counts()}") + self.logger.info(f"Größe des Trainingssets nach Resampling: {len(X_train_resampled)} Zeilen.") + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++ ENDE SMOTE-BLOCK ++++++++++++++++++++++++++++++++++++++++++++++++++ + # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # +++ ANPASSUNG HIER: RandomForest statt Decision Tree ++++++++++++++++++