| import json |
| from pathlib import Path |
|
|
| import joblib |
| import pandas as pd |
| from sklearn.feature_extraction.text import TfidfVectorizer |
| from sklearn.linear_model import LogisticRegression |
| from sklearn.metrics import classification_report, confusion_matrix |
| from sklearn.model_selection import StratifiedKFold, cross_val_predict |
| from sklearn.pipeline import Pipeline |
|
|
| DATA_PATH = Path("data/train.jsonl") |
| MODEL_PATH = Path("model.joblib") |
|
|
|
|
| def load_data(path: Path) -> pd.DataFrame: |
| records = [] |
|
|
| with path.open("r", encoding="utf-8") as file: |
| for line in file: |
| if line.strip(): |
| records.append(json.loads(line)) |
|
|
| return pd.DataFrame(records) |
|
|
|
|
| def build_pipeline() -> Pipeline: |
| return Pipeline( |
| [ |
| ( |
| "tfidf", |
| TfidfVectorizer( |
| ngram_range=(1, 2), |
| lowercase=True, |
| min_df=2, |
| max_df=0.95, |
| sublinear_tf=True, |
| ), |
| ), |
| ( |
| "classifier", |
| LogisticRegression( |
| max_iter=2000, |
| class_weight="balanced", |
| random_state=42, |
| ), |
| ), |
| ] |
| ) |
|
|
|
|
| def main(): |
| df = load_data(DATA_PATH) |
|
|
| X = ( |
| "PROMPT: " |
| + df["prompt"].astype(str) |
| + "\nRESPONSE: " |
| + df["response"].astype(str) |
| ) |
|
|
| y = df["quality_label"].astype(str) |
|
|
| print(f"Examples: {len(df)}") |
| print(y.value_counts().sort_index()) |
| print() |
|
|
| cv = StratifiedKFold( |
| n_splits=5, |
| shuffle=True, |
| random_state=42, |
| ) |
|
|
| pipeline = build_pipeline() |
|
|
| predictions = cross_val_predict( |
| pipeline, |
| X, |
| y, |
| cv=cv, |
| ) |
|
|
| print("Stratified 5-Fold Cross-Validation") |
| print("=" * 44) |
|
|
| print( |
| classification_report( |
| y, |
| predictions, |
| digits=3, |
| zero_division=0, |
| ) |
| ) |
|
|
| labels = sorted(y.unique()) |
|
|
| matrix = confusion_matrix( |
| y, |
| predictions, |
| labels=labels, |
| ) |
|
|
| print("Confusion matrix") |
| print(f"Labels: {labels}") |
| print(matrix) |
| print() |
|
|
| pipeline.fit(X, y) |
|
|
| joblib.dump( |
| pipeline, |
| MODEL_PATH, |
| ) |
|
|
| print(f"Saved model to: {MODEL_PATH.resolve()}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|