Download v21cat/train.py from Eric-Yyvuw/yeepee-ctr: direct link, hf CLI and curl.
- Browser
- Download file 4.86 kB
-
https://huggingface.co/Eric-Yyvuw/yeepee-ctr/resolve/main/v21cat/train.py
- Command line
-
hf download hf://Eric-Yyvuw/yeepee-ctr/v21cat/train.py
-
curl -L -o train.py https://huggingface.co/Eric-Yyvuw/yeepee-ctr/resolve/main/v21cat/train.py
4.86 kB
| """train.py CUT VARIANT [--seed S --rounds N --nnum K --threads 2 --params json] | |
| VARIANT: ids (TE crosses + raw ids only) | num (top-K numeric matrix feats only, control) | numte (numeric + TE crosses) ; rel=slate-relative feats added for top feats. | |
| Train tables = f{max(1,cut-24)}..f{cut-21}; eval table val{cut}/eval. Saves out/cat_{variant}_c{cut}_s{seed}.npy raw score (N,) at final + ens/..._rounds.npy checkpoints.""" | |
| import os,sys,re,json,gc,time,argparse; sys.dont_write_bytecode=True | |
| sys.path.insert(0,'/workspace/huawei/v19'); os.chdir('/workspace/huawei/v21cat') | |
| import numpy as np, lightgbm as lgb | |
| ap=argparse.ArgumentParser(); ap.add_argument('cut',type=int); ap.add_argument('var'); ap.add_argument('--seed',type=int,default=0); ap.add_argument('--rounds',type=int,default=1200) | |
| ap.add_argument('--save',default='300,600,900,1200'); ap.add_argument('--nnum',type=int,default=80); ap.add_argument('--threads',type=int,default=2); ap.add_argument('--params',default='{}'); ap.add_argument('--tag',default='') | |
| ap.add_argument('--nrel',type=int,default=25); ap.add_argument('--cat',type=int,default=0) | |
| a=ap.parse_args(); t0=time.time(); DR='^sq_(pdot|pcos|mdot|mcos)$' | |
| trn=[f'f{k}' for k in range(max(1,a.cut-24),a.cut-20)]; vn='eval' if a.cut==27 else f'val{a.cut}' | |
| te_names=json.load(open('cache/names.json')); useTE=a.var in('ids','numte'); useNum=a.var in('num','numte') | |
| if a.var=='ids': te_use=[n for n in te_names if a.cat or n!='item_id'] | |
| else: te_use=[n for n in te_names if n not in('item_id','hour','dt')] | |
| tix=[te_names.index(n) for n in te_use] | |
| if useNum: | |
| from cl import matrix | |
| gain=json.load(open('/workspace/huawei/v19/ens/nmAs_c25_s0_gain.json')); extra=tuple('feat_lr2,feat_tt,feat_pp,feat_sqC,feat_dw,feat_Ap,feat_NAs'.split(',')) | |
| numcols=None | |
| def load(T): | |
| global numcols | |
| parts=[]; | |
| if useTE: parts.append(np.load(f'cache/{T}.npy')[:,tix]) | |
| if useNum: | |
| X,m,f=matrix(T,1.0,extra=extra); keep=[i for i,c in enumerate(f) if not re.search(DR,c)]; fl=[f[i] for i in keep] | |
| if numcols is None: numcols=[c for c,_ in sorted(gain.items(),key=lambda kv:-kv[1]) if c in fl][:a.nnum] | |
| X=X[:,[f.index(c) for c in numcols]]; parts.append(X); rid=m['rowid'].to_numpy(); assert (rid==np.load(f'cache/{T}_rowid.npy',allow_pickle=True)).all(),T | |
| return np.concatenate(parts,1).astype(np.float32) | |
| def relf(X,ix): | |
| Z=X[:,ix].reshape(-1,10,len(ix)) | |
| with np.errstate(all='ignore'): | |
| mu=np.nanmean(Z,1,keepdims=True); mx=np.nanmax(Z,1,keepdims=True); rk=(np.argsort(np.argsort(np.where(np.isnan(Z),-np.inf,Z),1),1)).astype(np.float32)/9. | |
| return np.concatenate([(Z-mu).reshape(-1,len(ix)),(Z-mx).reshape(-1,len(ix)),rk.reshape(-1,len(ix))],1) | |
| import polars as pl | |
| def labels(T): return pl.read_parquet(f'/workspace/huawei/v9/feat_v3/{T}.parquet',columns=['clicked'])['clicked'].to_numpy() | |
| Xs=[];ys=[] | |
| for T in trn: | |
| X=load(T); Xs.append(X); ys.append(labels(T)); del X; gc.collect() | |
| if useNum: names=(te_use if useTE else [])+numcols | |
| else: names=te_use | |
| # slate-relative on: TE ctr-ish features + top numeric | |
| relcand=[i for i,n in enumerate(names) if n.endswith('_ctr') or n in('p5_mean','p5_max','p5_lift','p5_wmean')]+([len(te_use if useTE else [])+i for i in range(min(a.nrel,len(numcols)))] if useNum else []) | |
| relcand=sorted(set(relcand)); X=np.concatenate(Xs); del Xs; y=np.concatenate(ys); E=len(y)//10 | |
| X=np.concatenate([X,relf(X,relcand)],1); allnames=names+[f'{p}_{names[i]}' for p in('dmu','dmx','rk') for i in relcand] | |
| P=dict(objective='binary',learning_rate=0.03,num_leaves=63,min_data_in_leaf=300,feature_fraction=0.5,bagging_fraction=0.8,bagging_freq=1,lambda_l2=30.0,max_bin=255,force_col_wise=True,verbose=-1,num_threads=a.threads,seed=42+a.seed) | |
| P.update(json.loads(a.params)); print('load',round(time.time()-t0),'s',X.shape,flush=True) | |
| cf=[allnames.index('item_id')] if 'item_id' in allnames else 'auto' | |
| ds=lgb.Dataset(X,y,feature_name=allnames,categorical_feature=cf,free_raw_data=True,params=dict(max_bin=255,force_col_wise=True)).construct(); del X; gc.collect() | |
| Xv=load(vn); Xv=np.concatenate([Xv,relf(Xv,relcand)],1) | |
| RS=[int(r) for r in a.save.split(',')]; t1=time.time(); mdl=lgb.train(P,ds,max(RS)) | |
| S=np.stack([mdl.predict(Xv,num_iteration=r,raw_score=True) for r in RS],1).astype(np.float32) | |
| tag=f'cat_{a.var}{a.tag}_c{a.cut}_s{a.seed}'; np.save(f'ens/{tag}.npy',S) | |
| json.dump(dict(zip(allnames,mdl.feature_importance('gain').tolist())),open(f'ens/{tag}_gain.json','w')) | |
| msg=dict(cut=a.cut,var=a.var,tag=a.tag,nf=len(allnames),seed=a.seed,fit_s=round(time.time()-t1),total_min=round((time.time()-t0)/60,1),params=a.params) | |
| if a.cut!=27: | |
| from sklearn.metrics import roc_auc_score as AUC; yv=labels(vn); msg['auc']={r:round(AUC(yv,S[:,i]),5) for i,r in enumerate(RS)} | |
| print(json.dumps(msg),flush=True); open('logs/train_log.jsonl','a').write(json.dumps(msg)+'\n') | |