Spaces:
Running on Zero
Running on Zero
| """Reproduce training from the source Excel. Run stages in a machine with enough time/RAM. | |
| Produces: vertical_model.joblib, subvertical_model.joblib, parent_map.json | |
| Vertical trains on real verticals only (excludes 'others'); sub-vertical is downsampled per | |
| class for speed. Feature vectorizers are shared across both stages.""" | |
| import re, json, gc, joblib | |
| import numpy as np, pandas as pd | |
| from scipy.sparse import hstack | |
| from sklearn.feature_extraction.text import TfidfVectorizer | |
| from sklearn.linear_model import SGDClassifier | |
| from sklearn.svm import LinearSVC | |
| from sklearn.model_selection import train_test_split | |
| SRC = "Raw_data_vertical_subvertical.xlsx" | |
| clean = lambda s: " ".join(str(s).lower().split()) | |
| df = pd.read_excel(SRC, usecols=["category_name","vertical","sub_vertical"], dtype=str).fillna("") | |
| for c in df.columns: df[c] = df[c].str.strip() | |
| df["text"] = df["category_name"].map(clean) | |
| # shared vectorizers, fit on real-vertical text | |
| real = df[df.vertical.str.lower()!="others"] | |
| wv = TfidfVectorizer(analyzer="word", ngram_range=(1,2), min_df=5, max_features=100000, | |
| sublinear_tf=True, dtype=np.float32) | |
| cv = TfidfVectorizer(analyzer="char_wb", ngram_range=(2,4), min_df=5, max_features=100000, | |
| sublinear_tf=True, dtype=np.float32) | |
| wv.fit(real.text); cv.fit(real.text) | |
| vec = lambda s: hstack([wv.transform(s), cv.transform(s)]).tocsr() | |
| # ---- vertical (21-class, probabilistic) ---- | |
| vclf = SGDClassifier(loss="log_loss", alpha=2e-6, max_iter=30, tol=1e-4, random_state=42) | |
| vclf.fit(vec(real.text), real.vertical.to_numpy()) | |
| joblib.dump({"word_vec":wv,"char_vec":cv,"clf":vclf,"classes":list(vclf.classes_)}, | |
| "vertical_model.joblib", compress=3) | |
| # ---- sub-vertical (LinearSVC, downsampled per class) ---- | |
| sub = df[(df.vertical.str.lower()!="others") & (df.sub_vertical.str.lower()!="others")] | |
| parent = sub.groupby("sub_vertical")["vertical"].agg(lambda s: s.value_counts().index[0]).to_dict() | |
| json.dump(parent, open("parent_map.json","w")) | |
| CAP=2500; rng=np.random.default_rng(42); idx=[] | |
| for c, g in sub.groupby("sub_vertical"): | |
| ix=g.index.to_numpy() | |
| idx.append(rng.choice(ix,CAP,replace=False) if len(ix)>CAP else ix) | |
| idx=np.concatenate(idx) | |
| s=sub.loc[idx] | |
| sclf=LinearSVC(C=1.0) | |
| sclf.fit(vec(s.text), s.sub_vertical.to_numpy()) | |
| joblib.dump({"clf":sclf,"classes":list(sclf.classes_)}, "subvertical_model.joblib", compress=3) | |
| print("done: vertical_model.joblib, subvertical_model.joblib, parent_map.json") | |