mihir-apte's picture
deploy: fix footer note positioning
542ac35
Raw
History Blame Contribute Delete
4.56 kB
import os
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.utils.class_weight import compute_class_weight
from src.config import (
DISTORTION_LABELS, LABEL2ID, NUM_LABELS,
CSV_LABEL_MAP, CSV_NO_DISTORTION,
DATA_RAW_DIR, DATA_PROC_DIR, SEED
)
def load_raw(csv_path: str) -> pd.DataFrame:
df = pd.read_csv(csv_path, encoding="utf-8")
rename_map = {}
for col in df.columns:
cl = col.lower().strip()
if "patient question" in cl:
rename_map[col] = "text"
elif "dominant" in cl:
rename_map[col] = "dominant_distortion"
elif "secondary" in cl:
rename_map[col] = "secondary_distortion"
elif "distorted part" in cl:
rename_map[col] = "distorted_part"
df = df.rename(columns=rename_map)
df["text"] = df["text"].astype(str).str.strip()
df["dominant_distortion"] = df["dominant_distortion"].astype(str).str.strip()
if "secondary_distortion" in df.columns:
df["secondary_distortion"] = df["secondary_distortion"].astype(str).str.strip()
else:
df["secondary_distortion"] = ""
return df
def normalise_label(raw: str):
"""Map a CSV label string to our canonical label, or return None."""
raw = str(raw).strip()
if raw == CSV_NO_DISTORTION or raw.lower() == "no distortion":
return None
return CSV_LABEL_MAP.get(raw, raw)
def build_label_vector(dominant: str, secondary: str) -> list:
vec = [0] * NUM_LABELS
dom = normalise_label(dominant)
if dom and dom in LABEL2ID:
vec[LABEL2ID[dom]] = 1
if secondary and secondary not in ("nan", "", "None", "NaN"):
sec = normalise_label(secondary)
if sec and sec in LABEL2ID:
vec[LABEL2ID[sec]] = 1
return vec
def run(csv_filename: str = "Annotated_data.csv") -> None:
csv_path = os.path.join(DATA_RAW_DIR, csv_filename)
os.makedirs(DATA_PROC_DIR, exist_ok=True)
print(f"Loading: {csv_path}")
df = load_raw(csv_path)
print(f"Rows loaded: {len(df)}")
label_vecs = df.apply(
lambda row: build_label_vector(
row["dominant_distortion"], row["secondary_distortion"]
),
axis=1
)
label_df = pd.DataFrame(label_vecs.tolist(), columns=DISTORTION_LABELS)
df = pd.concat(
[df[["text", "dominant_distortion", "secondary_distortion"]], label_df],
axis=1
)
distortion_rows = df[df[DISTORTION_LABELS].sum(axis=1) > 0]
no_distortion_rows = df[df[DISTORTION_LABELS].sum(axis=1) == 0]
multi_label_rows = df[df[DISTORTION_LABELS].sum(axis=1) == 2]
print(f"Rows with >=1 distortion label : {len(distortion_rows)}")
print(f"Rows with no distortion (all 0s) : {len(no_distortion_rows)}")
print(f"Multi-label rows (2 labels) : {len(multi_label_rows)}")
train_df, test_df = train_test_split(
df,
test_size=0.2,
random_state=SEED,
stratify=df["dominant_distortion"]
)
train_df = train_df.reset_index(drop=True)
test_df = test_df.reset_index(drop=True)
print(f"\nTrain size : {len(train_df)}")
print(f"Test size : {len(test_df)}")
train_distortion_only = train_df[train_df[DISTORTION_LABELS].sum(axis=1) > 0]
dom_labels = (
train_distortion_only["dominant_distortion"]
.map(normalise_label)
.dropna()
)
present_labels = np.array(sorted(dom_labels.unique()))
raw_weights = compute_class_weight(
class_weight="balanced",
classes=present_labels,
y=dom_labels.values
)
class_weights = np.ones(NUM_LABELS, dtype=np.float32)
for label, weight in zip(present_labels, raw_weights):
if label in LABEL2ID:
class_weights[LABEL2ID[label]] = weight
print("\nClass weights aligned to DISTORTION_LABELS order:")
for label, w in zip(DISTORTION_LABELS, class_weights):
print(f" {label:<35} {w:.4f}")
train_path = os.path.join(DATA_PROC_DIR, "train.csv")
test_path = os.path.join(DATA_PROC_DIR, "test.csv")
weights_path = os.path.join(DATA_PROC_DIR, "class_weights.npy")
train_df.to_csv(train_path, index=False)
test_df.to_csv(test_path, index=False)
np.save(weights_path, class_weights)
print(f"\nSaved: {train_path}")
print(f"Saved: {test_path}")
print(f"Saved: {weights_path}")
print("\nPreprocessing complete.")
if __name__ == "__main__":
run()