adgw
/

Joblib
adgw commited on
Commit
aa2da0e
·
verified ·
1 Parent(s): 45d102e
Files changed (3) hide show
  1. dummy.py +13 -27
  2. main_jsonl.py +6 -15
  3. main_parquet.py +7 -19
dummy.py CHANGED
@@ -13,25 +13,16 @@ Użycie:
13
  python interactive_classifier.py
14
  """
15
 
16
- # --- Importy bibliotek ---
17
-
18
- # Biblioteki standardowe
19
- import os
20
  import pickle
21
  import joblib
22
  import pandas as pd
23
  from text_analyzer.analyzer import TextAnalyzer
24
  from text_analyzer import constants
25
 
26
- # --- Stałe globalne ---
27
-
28
  MODELS_DIR = 'models'
29
 
30
  # --- Ładowanie modeli ---
31
 
32
- # Modele i analizator są ładowane globalnie tylko raz przy starcie skryptu.
33
- # Dzięki temu unika się wielokrotnego, kosztownego odczytu plików z dysku
34
- # w pętli interaktywnej, co zapewnia natychmiastową odpowiedź na zapytanie użytkownika.
35
  print("Ładowanie modeli i analizatora...")
36
 
37
  with open('models/scaler.pkl', 'rb') as f:
@@ -48,7 +39,7 @@ def classify_single_text(text_to_classify: str) -> tuple[str | None, float | Non
48
  używając tego samego potoku co w przetwarzaniu wsadowym.
49
 
50
  Potok inferencyjny:
51
- 1. Ekstrakcja cech lingwistycznych za pomocą TextAnalyzer.
52
  2. Uporządkowanie cech zgodnie z `constants.COLUMN_ORDER`.
53
  3. Skalowanie cech za pomocą wczytanego skalera.
54
  4. Predykcja prawdopodobieństw klas za pomocą modelu.
@@ -60,7 +51,7 @@ def classify_single_text(text_to_classify: str) -> tuple[str | None, float | Non
60
  Returns:
61
  tuple[str | None, float | None]: zawiera:
62
  - Przewidywaną kategorię ('LOW', 'MEDIUM', 'HIGH') lub None w przypadku błędu.
63
- - Pewność predykcji (w procentach, 0-100) lub None w przypadku błędu.
64
  """
65
  # Krok walidacji wejścia
66
  if not isinstance(text_to_classify, str) or not text_to_classify.strip():
@@ -69,27 +60,24 @@ def classify_single_text(text_to_classify: str) -> tuple[str | None, float | Non
69
 
70
  try:
71
  # Krok 1: Ekstrakcja cech. Używamy `analyze_batch` z listą jednoelementową,
72
- # aby zapewnić identyczne przetwarzanie jak w skrypcie masowym.
73
- # `next()` pobiera pierwszy (i jedyny) wynik z generatora.
74
  features_dict = next(text_analyzer.analyze_batch([text_to_classify]))
75
 
76
- # Krok 2: Uporządkowanie cech. To kluczowe dla spójności z modelem.
77
  ordered_features = [features_dict.get(fname, 0.0) for fname in constants.COLUMN_ORDER]
78
 
79
- # Krok 3: Przygotowanie danych do predykcji (DataFrame z jedną próbką).
80
  features_df = pd.DataFrame([ordered_features], columns=constants.COLUMN_ORDER)
81
  input_features_scaled = scaler.transform(features_df)
82
 
83
  # Krok 4: Wykonanie predykcji.
84
- # Używamy `predict_proba` aby uzyskać pewność (confidence score).
85
  y_pred_proba = classifier.predict_proba(input_features_scaled)
86
 
87
- # Krok 5: Przetworzenie wyników predykcji.
88
- # `y_pred_proba` ma kształt (1, 3), więc bierzemy pierwszy element `[0]`.
89
- hardcoded_labels = ["LOW", "MEDIUM", "HIGH"]
90
  category_probabilities = {
91
  label: prob
92
- for label, prob in zip(hardcoded_labels, y_pred_proba[0])
93
  }
94
 
95
  most_probable_category = max(category_probabilities, key=category_probabilities.get)
@@ -106,29 +94,27 @@ def classify_single_text(text_to_classify: str) -> tuple[str | None, float | Non
106
  # --- Główny blok wykonawczy ---
107
 
108
  if __name__ == '__main__':
109
- # Wyświetlenie instrukcji dla użytkownika.
110
  print("\n--- Interaktywny Klasyfikator Jakości Tekstu ---")
111
  print("Wpisz tekst i naciśnij Enter, aby uzyskać klasyfikację.")
112
  print("Wpisz 'quit' lub 'exit', aby zakończyć.")
113
 
114
- # Główna pętla interaktywna (REPL: Read-Evaluate-Print Loop).
115
  while True:
116
  try:
117
- # Read: Pobierz dane wejściowe od użytkownika.
118
  user_input = input("\n> ")
119
 
120
- # Sprawdź warunek wyjścia z pętli.
121
  if user_input.lower() in ['quit', 'exit']:
122
  print("Zamykanie programu...")
123
  break
124
 
125
- # Evaluate: Przetwórz dane wejściowe.
126
  category, confidence = classify_single_text(user_input)
127
 
128
- # Print: Wyświetl wynik, jeśli przetwarzanie zakończyło się sukcesem.
129
  if category is not None:
130
  print(f" └── Predykcja: {category} (Pewność: {confidence}%)")
131
 
132
- except KeyboardInterrupt: # Obsługa Ctrl+C
133
  print("\nPrzerwano przez użytkownika. Zamykanie programu...")
134
  break
 
13
  python interactive_classifier.py
14
  """
15
 
 
 
 
 
16
  import pickle
17
  import joblib
18
  import pandas as pd
19
  from text_analyzer.analyzer import TextAnalyzer
20
  from text_analyzer import constants
21
 
 
 
22
  MODELS_DIR = 'models'
23
 
24
  # --- Ładowanie modeli ---
25
 
 
 
 
26
  print("Ładowanie modeli i analizatora...")
27
 
28
  with open('models/scaler.pkl', 'rb') as f:
 
39
  używając tego samego potoku co w przetwarzaniu wsadowym.
40
 
41
  Potok inferencyjny:
42
+ 1. Ekstrakcja cech za pomocą TextAnalyzer.
43
  2. Uporządkowanie cech zgodnie z `constants.COLUMN_ORDER`.
44
  3. Skalowanie cech za pomocą wczytanego skalera.
45
  4. Predykcja prawdopodobieństw klas za pomocą modelu.
 
51
  Returns:
52
  tuple[str | None, float | None]: zawiera:
53
  - Przewidywaną kategorię ('LOW', 'MEDIUM', 'HIGH') lub None w przypadku błędu.
54
+ - Pewność predykcji (w procentach) lub None w przypadku błędu.
55
  """
56
  # Krok walidacji wejścia
57
  if not isinstance(text_to_classify, str) or not text_to_classify.strip():
 
60
 
61
  try:
62
  # Krok 1: Ekstrakcja cech. Używamy `analyze_batch` z listą jednoelementową,
63
+ # `next()` pobiera pierwszy (i jedyny) wynik z generatora
 
64
  features_dict = next(text_analyzer.analyze_batch([text_to_classify]))
65
 
66
+ # Krok 2: Uporządkowanie cech
67
  ordered_features = [features_dict.get(fname, 0.0) for fname in constants.COLUMN_ORDER]
68
 
69
+ # Krok 3: Przygotowanie danych do predykcji (DataFrame z jedną próbką)
70
  features_df = pd.DataFrame([ordered_features], columns=constants.COLUMN_ORDER)
71
  input_features_scaled = scaler.transform(features_df)
72
 
73
  # Krok 4: Wykonanie predykcji.
 
74
  y_pred_proba = classifier.predict_proba(input_features_scaled)
75
 
76
+ # Krok 5: Przetworzenie wyników predykcji
77
+ labels = ["LOW", "MEDIUM", "HIGH"]
 
78
  category_probabilities = {
79
  label: prob
80
+ for label, prob in zip(labels, y_pred_proba[0])
81
  }
82
 
83
  most_probable_category = max(category_probabilities, key=category_probabilities.get)
 
94
  # --- Główny blok wykonawczy ---
95
 
96
  if __name__ == '__main__':
 
97
  print("\n--- Interaktywny Klasyfikator Jakości Tekstu ---")
98
  print("Wpisz tekst i naciśnij Enter, aby uzyskać klasyfikację.")
99
  print("Wpisz 'quit' lub 'exit', aby zakończyć.")
100
 
101
+ # Główna pętla interaktywna
102
  while True:
103
  try:
104
+ # Read: Pobierz dane wejściowe od użytkownika
105
  user_input = input("\n> ")
106
 
 
107
  if user_input.lower() in ['quit', 'exit']:
108
  print("Zamykanie programu...")
109
  break
110
 
111
+ # Przetwórz dane wejściowe.
112
  category, confidence = classify_single_text(user_input)
113
 
114
+ # Wyświetl wynik
115
  if category is not None:
116
  print(f" └── Predykcja: {category} (Pewność: {confidence}%)")
117
 
118
+ except KeyboardInterrupt:
119
  print("\nPrzerwano przez użytkownika. Zamykanie programu...")
120
  break
main_jsonl.py CHANGED
@@ -22,22 +22,16 @@ from tqdm import tqdm
22
  from typing import List
23
 
24
  from text_analyzer.analyzer import TextAnalyzer
25
- from text_analyzer import constants # Potrzebujemy COLUMN_ORDER
26
 
27
  # --- Ładowanie modeli i konfiguracja ---
28
 
29
- # Modele są ładowane na poziomie globalnym. W systemach uniksowych (Linux/macOS)
30
- # dzięki mechanizmowi 'fork', procesy-dzieci dziedziczą te obiekty bez ponownego
31
- # odczytu z dysku. Na Windowsie ('spawn'), każdy proces-dziecko musi zaimportować
32
- # skrypt i załadować modele od nowa.
33
-
34
  with open('models/scaler.pkl', 'rb') as f:
35
  scaler = pickle.load(f)
36
  classifier = joblib.load("models/model.joblib")
37
  text_analyzer = TextAnalyzer()
38
 
39
- # Liczba procesów roboczych do wykorzystania podczas analizy tekstów wewnątrz jednego pliku.
40
- NUM_PROCESSES = 10
41
 
42
  class NumpyJSONEncoder(json.JSONEncoder):
43
  """
@@ -61,9 +55,8 @@ def predict_batch(texts: List[str], analyzer: TextAnalyzer, scaler_model, classi
61
  """
62
  all_features = []
63
 
64
- # Krok 1: Ekstrakcja cech dla wszystkich tekstów za jednym zamachem
65
- # Używamy tqdm, aby śledzić postęp analizy wsadowej
66
- feature_generator = analyzer.analyze_batch(texts, batch_size=NUM_PROCESSES) # Dostosuj batch_size
67
  for features_dict in tqdm(feature_generator, total=len(texts), desc="Analiza cech"):
68
  ordered_features = [features_dict.get(fname, 0.0) for fname in constants.COLUMN_ORDER]
69
  all_features.append(ordered_features)
@@ -80,16 +73,14 @@ def predict_batch(texts: List[str], analyzer: TextAnalyzer, scaler_model, classi
80
 
81
  # Krok 4: Przetworzenie wyników
82
  results = []
83
- hardcoded_labels = ["LOW", "MEDIUM", "HIGH"]
84
  for single_pred_proba in pred_probas:
85
  category_prob = {
86
  label: prob
87
- for label, prob in zip(hardcoded_labels, single_pred_proba)
88
  }
89
  # Sortujemy, aby znaleźć kategorię z najwyższym prawdopodobieństwem
90
  sorted_category_prob = sorted(category_prob.items(), key=lambda item: item[1], reverse=True)
91
-
92
- # Pobieramy nazwę i wartość
93
  most_probable_category, confidence = sorted_category_prob[0]
94
 
95
  results.append((most_probable_category, round(float(confidence) * 100, 2)))
 
22
  from typing import List
23
 
24
  from text_analyzer.analyzer import TextAnalyzer
25
+ from text_analyzer import constants
26
 
27
  # --- Ładowanie modeli i konfiguracja ---
28
 
 
 
 
 
 
29
  with open('models/scaler.pkl', 'rb') as f:
30
  scaler = pickle.load(f)
31
  classifier = joblib.load("models/model.joblib")
32
  text_analyzer = TextAnalyzer()
33
 
34
+ batch_size = 10
 
35
 
36
  class NumpyJSONEncoder(json.JSONEncoder):
37
  """
 
55
  """
56
  all_features = []
57
 
58
+ # Krok 1: Ekstrakcja cech dla wszystkich tekstów
59
+ feature_generator = analyzer.analyze_batch(texts, batch_size=batch_size)
 
60
  for features_dict in tqdm(feature_generator, total=len(texts), desc="Analiza cech"):
61
  ordered_features = [features_dict.get(fname, 0.0) for fname in constants.COLUMN_ORDER]
62
  all_features.append(ordered_features)
 
73
 
74
  # Krok 4: Przetworzenie wyników
75
  results = []
76
+ labels = ["LOW", "MEDIUM", "HIGH"]
77
  for single_pred_proba in pred_probas:
78
  category_prob = {
79
  label: prob
80
+ for label, prob in zip(labels, single_pred_proba)
81
  }
82
  # Sortujemy, aby znaleźć kategorię z najwyższym prawdopodobieństwem
83
  sorted_category_prob = sorted(category_prob.items(), key=lambda item: item[1], reverse=True)
 
 
84
  most_probable_category, confidence = sorted_category_prob[0]
85
 
86
  results.append((most_probable_category, round(float(confidence) * 100, 2)))
main_parquet.py CHANGED
@@ -9,7 +9,6 @@ wyniki do nowego pliku w folderze wyjściowym, zachowując oryginalną struktur
9
  danych i dodając wyniki klasyfikacji.
10
  """
11
 
12
- # --- Importy bibliotek ---
13
  import os
14
  import glob
15
  import time
@@ -22,22 +21,16 @@ from tqdm import tqdm
22
  from typing import List
23
 
24
  from text_analyzer.analyzer import TextAnalyzer
25
- from text_analyzer import constants # Potrzebujemy COLUMN_ORDER
26
 
27
  # --- Ładowanie modeli i konfiguracja ---
28
 
29
- # Modele są ładowane na poziomie globalnym. W systemach uniksowych (Linux/macOS)
30
- # dzięki mechanizmowi 'fork', procesy-dzieci dziedziczą te obiekty bez ponownego
31
- # odczytu z dysku. Na Windowsie ('spawn'), każdy proces-dziecko musi zaimportować
32
- # skrypt i załadować modele od nowa.
33
-
34
  with open('models/scaler.pkl', 'rb') as f:
35
  scaler = pickle.load(f)
36
  classifier = joblib.load("models/model.joblib")
37
  text_analyzer = TextAnalyzer()
38
 
39
- # Liczba procesów roboczych do wykorzystania podczas analizy tekstów wewnątrz jednego pliku.
40
- NUM_PROCESSES = 10
41
 
42
  class NumpyJSONEncoder(json.JSONEncoder):
43
  """
@@ -61,9 +54,8 @@ def predict_batch(texts: List[str], analyzer: TextAnalyzer, scaler_model, classi
61
  """
62
  all_features = []
63
 
64
- # Krok 1: Ekstrakcja cech dla wszystkich tekstów za jednym zamachem
65
- # Używamy tqdm, aby śledzić postęp analizy wsadowej
66
- feature_generator = analyzer.analyze_batch(texts, batch_size=NUM_PROCESSES) # Dostosuj batch_size
67
  for features_dict in tqdm(feature_generator, total=len(texts), desc="Analiza cech"):
68
  ordered_features = [features_dict.get(fname, 0.0) for fname in constants.COLUMN_ORDER]
69
  all_features.append(ordered_features)
@@ -80,16 +72,14 @@ def predict_batch(texts: List[str], analyzer: TextAnalyzer, scaler_model, classi
80
 
81
  # Krok 4: Przetworzenie wyników
82
  results = []
83
- hardcoded_labels = ["LOW", "MEDIUM", "HIGH"]
84
  for single_pred_proba in pred_probas:
85
  category_prob = {
86
  label: prob
87
- for label, prob in zip(hardcoded_labels, single_pred_proba)
88
  }
89
  # Sortujemy, aby znaleźć kategorię z najwyższym prawdopodobieństwem
90
  sorted_category_prob = sorted(category_prob.items(), key=lambda item: item[1], reverse=True)
91
-
92
- # Pobieramy nazwę i wartość
93
  most_probable_category, confidence = sorted_category_prob[0]
94
 
95
  results.append((most_probable_category, round(float(confidence) * 100, 2)))
@@ -119,11 +109,10 @@ def process_parquet_file(input_file: str, output_file: str):
119
  print(f"Wczytano {len(texts_to_process)} wierszy. Rozpoczynam przetwarzanie wsadowe...")
120
 
121
  # Krok 3: Wywołaj funkcję wsadową (ta część pozostaje bez zmian)
122
- # Zakładamy, że predict_batch zwraca listę krotek: [(kategoria, pewność), ...]
123
  results = predict_batch(texts_to_process, text_analyzer, scaler, classifier)
124
 
125
  # Krok 4: Dodaj wyniki jako nowe kolumny do ramki danych
126
- # "Rozpakowujemy" listę krotek na dwie oddzielne listy
127
  categories = [res[0] for res in results]
128
  confidences = [res[1] for res in results]
129
 
@@ -132,7 +121,6 @@ def process_parquet_file(input_file: str, output_file: str):
132
 
133
  # Krok 5: Zapisz zmodyfikowaną ramkę danych do nowego pliku Parquet
134
  try:
135
- # index=False zapobiega zapisaniu indeksu pandas jako kolumny w pliku
136
  df.to_parquet(output_file, index=False)
137
  print(df.head(10))
138
  print(f"Pomyślnie zapisano przetworzone dane do pliku {output_file}")
 
9
  danych i dodając wyniki klasyfikacji.
10
  """
11
 
 
12
  import os
13
  import glob
14
  import time
 
21
  from typing import List
22
 
23
  from text_analyzer.analyzer import TextAnalyzer
24
+ from text_analyzer import constants
25
 
26
  # --- Ładowanie modeli i konfiguracja ---
27
 
 
 
 
 
 
28
  with open('models/scaler.pkl', 'rb') as f:
29
  scaler = pickle.load(f)
30
  classifier = joblib.load("models/model.joblib")
31
  text_analyzer = TextAnalyzer()
32
 
33
+ batch_size = 10
 
34
 
35
  class NumpyJSONEncoder(json.JSONEncoder):
36
  """
 
54
  """
55
  all_features = []
56
 
57
+ # Krok 1: Ekstrakcja cech dla wszystkich tekstów
58
+ feature_generator = analyzer.analyze_batch(texts, batch_size=batch_size)
 
59
  for features_dict in tqdm(feature_generator, total=len(texts), desc="Analiza cech"):
60
  ordered_features = [features_dict.get(fname, 0.0) for fname in constants.COLUMN_ORDER]
61
  all_features.append(ordered_features)
 
72
 
73
  # Krok 4: Przetworzenie wyników
74
  results = []
75
+ labels = ["LOW", "MEDIUM", "HIGH"]
76
  for single_pred_proba in pred_probas:
77
  category_prob = {
78
  label: prob
79
+ for label, prob in zip(labels, single_pred_proba)
80
  }
81
  # Sortujemy, aby znaleźć kategorię z najwyższym prawdopodobieństwem
82
  sorted_category_prob = sorted(category_prob.items(), key=lambda item: item[1], reverse=True)
 
 
83
  most_probable_category, confidence = sorted_category_prob[0]
84
 
85
  results.append((most_probable_category, round(float(confidence) * 100, 2)))
 
109
  print(f"Wczytano {len(texts_to_process)} wierszy. Rozpoczynam przetwarzanie wsadowe...")
110
 
111
  # Krok 3: Wywołaj funkcję wsadową (ta część pozostaje bez zmian)
112
+ # Zakładamy, że predict_batch zwraca listę tuple: [(kategoria, pewność), ...]
113
  results = predict_batch(texts_to_process, text_analyzer, scaler, classifier)
114
 
115
  # Krok 4: Dodaj wyniki jako nowe kolumny do ramki danych
 
116
  categories = [res[0] for res in results]
117
  confidences = [res[1] for res in results]
118
 
 
121
 
122
  # Krok 5: Zapisz zmodyfikowaną ramkę danych do nowego pliku Parquet
123
  try:
 
124
  df.to_parquet(output_file, index=False)
125
  print(df.head(10))
126
  print(f"Pomyślnie zapisano przetworzone dane do pliku {output_file}")