import%20marimo%0A%0A__generated_with%20%3D%20%220.24.0%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20plotly.graph_objects%20as%20go%0A%20%20%20%20from%20imblearn.over_sampling%20import%20ADASYN%2C%20SMOTE%2C%20RandomOverSampler%0A%20%20%20%20from%20plotly.subplots%20import%20make_subplots%0A%20%20%20%20from%20sklearn.datasets%20import%20make_moons%0A%20%20%20%20from%20sklearn.ensemble%20import%20RandomForestClassifier%0A%20%20%20%20from%20sklearn.metrics%20import%20(%0A%20%20%20%20%20%20%20%20balanced_accuracy_score%2C%0A%20%20%20%20%20%20%20%20f1_score%2C%0A%20%20%20%20%20%20%20%20precision_score%2C%0A%20%20%20%20%20%20%20%20recall_score%2C%0A%20%20%20%20)%0A%20%20%20%20from%20sklearn.model_selection%20import%20train_test_split%0A%20%20%20%20from%20sklearn.neighbors%20import%20NearestNeighbors%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20ADASYN%2C%0A%20%20%20%20%20%20%20%20NearestNeighbors%2C%0A%20%20%20%20%20%20%20%20RandomForestClassifier%2C%0A%20%20%20%20%20%20%20%20RandomOverSampler%2C%0A%20%20%20%20%20%20%20%20SMOTE%2C%0A%20%20%20%20%20%20%20%20balanced_accuracy_score%2C%0A%20%20%20%20%20%20%20%20f1_score%2C%0A%20%20%20%20%20%20%20%20go%2C%0A%20%20%20%20%20%20%20%20make_moons%2C%0A%20%20%20%20%20%20%20%20make_subplots%2C%0A%20%20%20%20%20%20%20%20mo%2C%0A%20%20%20%20%20%20%20%20np%2C%0A%20%20%20%20%20%20%20%20pd%2C%0A%20%20%20%20%20%20%20%20precision_score%2C%0A%20%20%20%20%20%20%20%20recall_score%2C%0A%20%20%20%20%20%20%20%20train_test_split%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%5B%E2%86%90%2037%20Natural%20Breaks%5D(37_natural_breaks.py)%20%7C%20%5BIndex%5D(..%2Findex.html)%20%7C%20%5B39%20Permutation%20Importance%20%E2%86%92%5D(39_permutation_importance.py)%0A%0A%20%20%20%20%23%20Synthetic%20Minority%20Over-sampling%3A%20SMOTE%2C%20ADASYN%2C%20and%20Decision%20Boundary%20Topology%0A%0A%20%20%20%20%23%23%20%5Ba%5D%20Why%20do%20you%20need%20to%20know%20these%20concepts%3F%0A%0A%20%20%20%20Severe%20class%20imbalance%20represents%20a%20pervasive%20challenge%20in%20applied%20machine%20learning%2C%20appearing%20routinely%20in%20fraud%20detection%20(where%20fraudulent%20transactions%20comprise%20less%20than%200.1%25%20of%20traffic)%2C%20rare%20disease%20diagnosis%2C%20click-through%20rate%20modeling%2C%20and%20anomaly%20detection.%0A%0A%20%20%20%20%23%23%23%23%20The%20Failure%20of%20Standard%20Empirical%20Risk%20Minimization%0A%20%20%20%20Standard%20classification%20models%20optimize%20overall%20empirical%20loss%20(such%20as%20binary%20cross-entropy%20or%200-1%20misclassification%20error).%20When%20faced%20with%20a%2099%3A1%20imbalance%20ratio%2C%20a%20trivial%20classifier%20that%20predicts%20the%20majority%20class%20for%20every%20sample%20achieves%2099%25%20accuracy%20while%20exhibiting%200%25%20recall%20on%20the%20minority%20class%20of%20interest.%0A%0A%20%20%20%20%23%23%23%23%20The%20Hazards%20of%20Naive%20Random%20Oversampling%0A%20%20%20%20The%20simplest%20heuristic%20to%20balance%20class%20frequencies%20is%20naive%20random%20oversampling%20(duplicating%20existing%20minority%20samples%20with%20replacement).%20However%2C%20exact%20point%20duplication%20artificially%20shrinks%20the%20variance%20of%20minority%20decision%20regions.%20Non-parametric%20models%20(such%20as%20decision%20trees%2C%20Random%20Forests%2C%20and%20deep%20neural%20networks)%20simply%20memorize%20the%20replicated%20coordinates%2C%20producing%20tightly%20localized%2C%20overfitted%20decision%20boundaries%20that%20fail%20to%20generalize.%0A%0A%20%20%20%20%23%23%23%23%20Synthetic%20Interpolation%3A%20SMOTE%20and%20ADASYN%0A%20%20%20%20To%20expand%20the%20support%20of%20the%20minority%20class%20without%20exact%20duplication%2C%20Chawla%20et%20al.%20(2002)%20introduced%20**SMOTE**%20(Synthetic%20Minority%20Over-sampling%20Technique).%20SMOTE%20creates%20convex%20combinations%20between%20neighboring%20minority%20points%2C%20establishing%20connected%20linear%20paths%20in%20feature%20space.%0A%0A%20%20%20%20Building%20upon%20SMOTE%2C%20**ADASYN**%20(Adaptive%20Synthetic%20Sampling%2C%20He%20et%20al.%2C%202008)%20adaptively%20adjusts%20the%20generation%20rate%3A%20it%20synthesizes%20more%20samples%20for%20minority%20observations%20located%20in%20ambiguous%20regions%20near%20the%20decision%20boundary%20(high%20proportion%20of%20majority%20neighbors)%20and%20fewer%20samples%20for%20observations%20in%20safe%2C%20well-separated%20cluster%20interiors.%0A%0A%20%20%20%20%23%23%23%23%20Preventing%20Data%20Leakage%0A%20%20%20%20A%20critical%20rule%20in%20applied%20validation%3A%20**Resampling%20must%20never%20be%20applied%20to%20the%20validation%20or%20test%20sets**.%20Over-sampling%20the%20full%20dataset%20prior%20to%20train-test%20splitting%20leaks%20synthesized%20variants%20of%20test%20points%20directly%20into%20the%20training%20partition%2C%20producing%20artificially%20inflated%20metrics.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20%5Bb%5D%20Mathematical%20Foundations%20and%20Sampling%20Mechanics%0A%0A%20%20%20%20%23%23%23%201.%20The%20Geometry%20of%20SMOTE%0A%0A%20%20%20%20Let%20%24%5Cmathcal%7BD%7D%20%3D%20%5C%7B(x_i%2C%20y_i)%5C%7D_%7Bi%3D1%7D%5EN%24%20be%20a%20dataset%20with%20%24x_i%20%5Cin%20%5Cmathbb%7BR%7D%5Ep%24%20and%20binary%20labels%20%24y_i%20%5Cin%20%5C%7B0%2C%201%5C%7D%24.%20Let%20%24%5Cmathcal%7BS%7D_%7B%5Cmin%7D%20%3D%20%5C%7Bx_i%20%3A%20y_i%20%3D%201%5C%7D%24%20denote%20the%20minority%20set%20with%20cardinality%20%24N_%7B%5Cmin%7D%20%3D%20%7C%5Cmathcal%7BS%7D_%7B%5Cmin%7D%7C%24%20and%20%24%5Cmathcal%7BS%7D_%7B%5Ctext%7Bmaj%7D%7D%20%3D%20%5C%7Bx_i%20%3A%20y_i%20%3D%200%5C%7D%24%20denote%20the%20majority%20set%20(%24N_%7B%5Ctext%7Bmaj%7D%7D%20%5Cgg%20N_%7B%5Cmin%7D%24).%0A%0A%20%20%20%20For%20every%20observation%20%24x_i%20%5Cin%20%5Cmathcal%7BS%7D_%7B%5Cmin%7D%24%3A%0A%20%20%20%201.%20Compute%20the%20%24k%24-nearest%20neighbors%20of%20%24x_i%24%20exclusively%20within%20%24%5Cmathcal%7BS%7D_%7B%5Cmin%7D%24%20using%20Euclidean%20metric%20%24%5C%7C%20%5Ccdot%20%5C%7C_2%24%3A%0A%0A%20%20%20%20%24%24%5Cmathcal%7BN%7D_k(x_i)%20%3D%20%5C%7Bx_%7Bi%7D%5E%7B(1)%7D%2C%20x_%7Bi%7D%5E%7B(2)%7D%2C%20%5Cdots%2C%20x_%7Bi%7D%5E%7B(k)%7D%5C%7D%20%5Csubset%20%5Cmathcal%7BS%7D_%7B%5Cmin%7D%24%24%0A%0A%20%20%20%202.%20Randomly%20select%20one%20neighbor%20%24%5Chat%7Bx%7D_i%20%5Cin%20%5Cmathcal%7BN%7D_k(x_i)%24.%0A%20%20%20%203.%20Draw%20a%20uniform%20random%20scalar%20%24%5Clambda%20%5Csim%20%5Cmathcal%7BU%7D(0%2C%201)%24.%0A%20%20%20%204.%20Synthesize%20a%20new%20continuous%20observation%20along%20the%20directed%20line%20segment%3A%0A%0A%20%20%20%20%24%24x_%7B%5Ctext%7Bsyn%7D%7D%20%3D%20x_i%20%2B%20%5Clambda%20(%5Chat%7Bx%7D_i%20-%20x_i)%24%24%0A%0A%20%20%20%20The%20new%20point%20%24x_%7B%5Ctext%7Bsyn%7D%7D%24%20lies%20on%20the%20line%20segment%20connecting%20%24x_i%24%20and%20%24%5Chat%7Bx%7D_i%24%2C%20effectively%20populating%20the%20convex%20hull%20of%20the%20minority%20class.%0A%0A%20%20%20%20%23%23%23%202.%20ADASYN%3A%20Adaptive%20Synthetic%20Sampling%0A%0A%20%20%20%20While%20SMOTE%20generates%20a%20uniform%20number%20of%20synthetic%20points%20per%20minority%20observation%2C%20ADASYN%20weights%20generation%20by%20local%20classification%20difficulty.%0A%0A%20%20%20%201.%20For%20each%20%24x_i%20%5Cin%20%5Cmathcal%7BS%7D_%7B%5Cmin%7D%24%2C%20identify%20its%20%24k%24%20nearest%20neighbors%20in%20the%20**entire%20dataset**%20%24%5Cmathcal%7BD%7D%24%20(both%20minority%20and%20majority%20points).%0A%20%20%20%202.%20Let%20%24%5CDelta_i%24%20be%20the%20count%20of%20neighbors%20belonging%20to%20the%20majority%20class%20%24%5Cmathcal%7BS%7D_%7B%5Ctext%7Bmaj%7D%7D%24.%20The%20local%20difficulty%20ratio%20is%3A%0A%0A%20%20%20%20%24%24r_i%20%3D%20%5Cfrac%7B%5CDelta_i%7D%7Bk%7D%20%5Cin%20%5B0%2C%201%5D%24%24%0A%0A%20%20%20%20-%20If%20%24r_i%20%3D%200%24%2C%20%24x_i%24%20is%20surrounded%20purely%20by%20minority%20points%20(easy%20core%20sample).%0A%20%20%20%20-%20If%20%24r_i%20%5Capprox%201%24%2C%20%24x_i%24%20is%20heavily%20surrounded%20by%20majority%20points%20(hard%20boundary%20sample).%0A%0A%20%20%20%203.%20Normalize%20the%20difficulty%20ratios%20into%20a%20discrete%20probability%20mass%20function%3A%0A%0A%20%20%20%20%24%24%5Chat%7Br%7D_i%20%3D%20%5Cfrac%7Br_i%7D%7B%5Csum_%7Bj%20%5Cin%20%5Cmathcal%7BS%7D_%7B%5Cmin%7D%7D%20r_j%7D%24%24%0A%0A%20%20%20%204.%20Let%20%24G%20%3D%20(N_%7B%5Ctext%7Bmaj%7D%7D%20-%20N_%7B%5Cmin%7D)%20%5Ctimes%20%5Cbeta%24%20be%20the%20total%20synthetic%20quota%20required%20to%20achieve%20balance%20ratio%20%24%5Cbeta%20%5Cin%20(0%2C%201%5D%24.%20The%20count%20of%20synthetic%20samples%20allocated%20to%20%24x_i%24%20is%3A%0A%0A%20%20%20%20%24%24g_i%20%3D%20%5Ctext%7Bround%7D%5Cleft(%5Chat%7Br%7D_i%20%5Ccdot%20G%5Cright)%24%24%0A%0A%20%20%20%20Each%20of%20the%20%24g_i%24%20samples%20is%20synthesized%20using%20the%20standard%20linear%20interpolation%20formula%20from%20a%20randomly%20chosen%20neighbor%20in%20%24%5Cmathcal%7BN%7D_k(x_i)%20%5Ccap%20%5Cmathcal%7BS%7D_%7B%5Cmin%7D%24.%0A%0A%20%20%20%20%23%23%23%203.%20Borderline-SMOTE%20Sample%20Categorization%0A%0A%20%20%20%20Borderline-SMOTE%20refines%20sample%20selection%20by%20classifying%20every%20minority%20point%20%24x_i%24%20based%20on%20its%20majority%20neighbor%20count%20%24m_i%20%5Cin%20%5C%7B0%2C%20%5Cdots%2C%20k%5C%7D%24%3A%0A%0A%20%20%20%20-%20**SAFE%20(%240%20%5Cle%20m_i%20%3C%20k%2F2%24)**%3A%20Well%20within%20the%20interior%20of%20the%20minority%20region.%20Generating%20synthetic%20samples%20here%20provides%20minimal%20value.%0A%20%20%20%20-%20**DANGER%20(%24k%2F2%20%5Cle%20m_i%20%3C%20k%24)**%3A%20Located%20right%20on%20the%20decision%20boundary.%20Only%20points%20in%20this%20subset%20are%20used%20as%20base%20samples%20for%20synthesis.%0A%20%20%20%20-%20**NOISE%20(%24m_i%20%3D%20k%24)**%3A%20Completely%20isolated%20minority%20outliers%20surrounded%20entirely%20by%20majority%20points.%20Generating%20samples%20from%20noise%20points%20would%20create%20spurious%20minority%20bridges%20deep%20inside%20the%20majority%20region.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ADASYN%2C%20RandomOverSampler%2C%20SMOTE%2C%20make_moons%2C%20np%2C%20train_test_split)%3A%0A%20%20%20%20np.random.seed(42)%0A%0A%20%20%20%20%23%20Generate%20synthetic%202D%20non-linear%20moon%20dataset%0A%20%20%20%20x_raw%2C%20y_raw%20%3D%20make_moons(n_samples%3D1000%2C%20noise%3D0.28%2C%20random_state%3D42)%0A%0A%20%20%20%20%23%20Impose%20strong%2010%3A1%20class%20imbalance%3A%20450%20majority%20(Class%200)%20vs%2045%20minority%20(Class%201)%0A%20%20%20%20idx_maj%20%3D%20np.where(y_raw%20%3D%3D%200)%5B0%5D%5B%3A450%5D%0A%20%20%20%20idx_min%20%3D%20np.where(y_raw%20%3D%3D%201)%5B0%5D%5B%3A45%5D%0A%0A%20%20%20%20x_imbalanced%20%3D%20np.vstack(%5Bx_raw%5Bidx_maj%5D%2C%20x_raw%5Bidx_min%5D%5D)%0A%20%20%20%20y_imbalanced%20%3D%20np.hstack(%5By_raw%5Bidx_maj%5D%2C%20y_raw%5Bidx_min%5D%5D)%0A%0A%20%20%20%20%23%20Train-test%20split%20(stratified)%0A%20%20%20%20x_train%2C%20x_test%2C%20y_train%2C%20y_test%20%3D%20train_test_split(%0A%20%20%20%20%20%20%20%20x_imbalanced%2C%0A%20%20%20%20%20%20%20%20y_imbalanced%2C%0A%20%20%20%20%20%20%20%20test_size%3D0.30%2C%0A%20%20%20%20%20%20%20%20random_state%3D42%2C%0A%20%20%20%20%20%20%20%20stratify%3Dy_imbalanced%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Apply%20resamplers%20ONLY%20to%20training%20partition%0A%20%20%20%20%23%201.%20SMOTE%0A%20%20%20%20smote_resampler%20%3D%20SMOTE(random_state%3D42%2C%20k_neighbors%3D5)%0A%20%20%20%20x_train_smote%2C%20y_train_smote%20%3D%20smote_resampler.fit_resample(x_train%2C%20y_train)%0A%0A%20%20%20%20%23%202.%20ADASYN%0A%20%20%20%20adasyn_resampler%20%3D%20ADASYN(random_state%3D42%2C%20n_neighbors%3D5)%0A%20%20%20%20x_train_adasyn%2C%20y_train_adasyn%20%3D%20adasyn_resampler.fit_resample(x_train%2C%20y_train)%0A%0A%20%20%20%20%23%203.%20Random%20Oversampling%0A%20%20%20%20ros_resampler%20%3D%20RandomOverSampler(random_state%3D42)%0A%20%20%20%20x_train_ros%2C%20y_train_ros%20%3D%20ros_resampler.fit_resample(x_train%2C%20y_train)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20x_test%2C%0A%20%20%20%20%20%20%20%20x_train%2C%0A%20%20%20%20%20%20%20%20x_train_adasyn%2C%0A%20%20%20%20%20%20%20%20x_train_ros%2C%0A%20%20%20%20%20%20%20%20x_train_smote%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_train%2C%0A%20%20%20%20%20%20%20%20y_train_adasyn%2C%0A%20%20%20%20%20%20%20%20y_train_ros%2C%0A%20%20%20%20%20%20%20%20y_train_smote%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20go%2C%0A%20%20%20%20make_subplots%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20x_train%2C%0A%20%20%20%20x_train_adasyn%2C%0A%20%20%20%20x_train_smote%2C%0A%20%20%20%20y_train%2C%0A%20%20%20%20y_train_adasyn%2C%0A%20%20%20%20y_train_smote%2C%0A)%3A%0A%20%20%20%20fig%20%3D%20make_subplots(%0A%20%20%20%20%20%20%20%20rows%3D1%2C%0A%20%20%20%20%20%20%20%20cols%3D3%2C%0A%20%20%20%20%20%20%20%20subplot_titles%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%3Cb%3E(a)%20Original%20Imbalanced%20(10%3A1)%3C%2Fb%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%3Cb%3E(b)%20SMOTE%20Resampled%20(Uniform%20Interpolation)%3C%2Fb%3E%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%3Cb%3E(c)%20ADASYN%20Resampled%20(Boundary%20Focused)%3C%2Fb%3E%22%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20horizontal_spacing%3D0.06%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20(a)%20Original%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train%5By_train%20%3D%3D%200%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train%5By_train%20%3D%3D%200%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%233B82F6%22%2C%20size%3D5%2C%20opacity%3D0.6)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Majority%20Class%200%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D1%2C%0A%20%20%20%20)%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train%5By_train%20%3D%3D%201%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train%5By_train%20%3D%3D%201%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%23DC2626%22%2C%20size%3D8%2C%20symbol%3D%22diamond%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Minority%20Class%201%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D1%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20(b)%20SMOTE%0A%20%20%20%20n_orig_min%20%3D%20len(x_train%5By_train%20%3D%3D%201%5D)%0A%20%20%20%20n_total_train%20%3D%20len(x_train)%0A%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train_smote%5By_train_smote%20%3D%3D%200%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train_smote%5By_train_smote%20%3D%3D%200%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%233B82F6%22%2C%20size%3D5%2C%20opacity%3D0.4)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20%23%20Original%20minority%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train%5By_train%20%3D%3D%201%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train%5By_train%20%3D%3D%201%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%23DC2626%22%2C%20size%3D7%2C%20symbol%3D%22diamond%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D2%2C%0A%20%20%20%20)%0A%20%20%20%20%23%20Synthesized%20points%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train_smote%5Bn_total_train%3A%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train_smote%5Bn_total_train%3A%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%2310B981%22%2C%20size%3D6%2C%20opacity%3D0.75%2C%20symbol%3D%22circle%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22SMOTE%20Synthesized%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D2%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20(c)%20ADASYN%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train_adasyn%5By_train_adasyn%20%3D%3D%200%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train_adasyn%5By_train_adasyn%20%3D%3D%200%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%233B82F6%22%2C%20size%3D5%2C%20opacity%3D0.4)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D3%2C%0A%20%20%20%20)%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train%5By_train%20%3D%3D%201%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train%5By_train%20%3D%3D%201%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%23DC2626%22%2C%20size%3D7%2C%20symbol%3D%22diamond%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20showlegend%3DFalse%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D3%2C%0A%20%20%20%20)%0A%20%20%20%20fig.add_trace(%0A%20%20%20%20%20%20%20%20go.Scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dx_train_adasyn%5Bn_total_train%3A%2C%200%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dx_train_adasyn%5Bn_total_train%3A%2C%201%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22markers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(color%3D%22%238B5CF6%22%2C%20size%3D6%2C%20opacity%3D0.75%2C%20symbol%3D%22cross%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22ADASYN%20Synthesized%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20row%3D1%2C%0A%20%20%20%20%20%20%20%20col%3D3%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig.update_xaxes(title_text%3D%22Feature%201%22)%0A%20%20%20%20fig.update_yaxes(title_text%3D%22Feature%202%22)%0A%0A%20%20%20%20fig.update_layout(%0A%20%20%20%20%20%20%20%20template%3D%22plotly_white%22%2C%0A%20%20%20%20%20%20%20%20height%3D480%2C%0A%20%20%20%20%20%20%20%20margin%3Ddict(l%3D40%2C%20r%3D40%2C%20t%3D60%2C%20b%3D40)%2C%0A%20%20%20%20%20%20%20%20legend%3Ddict(orientation%3D%22h%22%2C%20yanchor%3D%22bottom%22%2C%20y%3D-0.22%2C%20xanchor%3D%22center%22%2C%20x%3D0.5)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20viz%20%3D%20mo.ui.plotly(fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20NearestNeighbors%2C%0A%20%20%20%20RandomForestClassifier%2C%0A%20%20%20%20balanced_accuracy_score%2C%0A%20%20%20%20f1_score%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20np%2C%0A%20%20%20%20pd%2C%0A%20%20%20%20precision_score%2C%0A%20%20%20%20recall_score%2C%0A%20%20%20%20x_test%2C%0A%20%20%20%20x_train%2C%0A%20%20%20%20x_train_adasyn%2C%0A%20%20%20%20x_train_ros%2C%0A%20%20%20%20x_train_smote%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A%20%20%20%20y_train_adasyn%2C%0A%20%20%20%20y_train_ros%2C%0A%20%20%20%20y_train_smote%2C%0A)%3A%0A%20%20%20%20%23%20Example%201%3A%20Pure%20NumPy%20Implementation%20of%20SMOTE%0A%20%20%20%20def%20manual_smote(x_min_arr%2C%20n_samples_to_create%2C%20k_nn%3D5)%3A%0A%20%20%20%20%20%20%20%20nn%20%3D%20NearestNeighbors(n_neighbors%3Dk_nn%20%2B%201).fit(x_min_arr)%0A%20%20%20%20%20%20%20%20indices%20%3D%20nn.kneighbors(x_min_arr%2C%20return_distance%3DFalse)%0A%20%20%20%20%20%20%20%20synthetic_samples%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20_%20in%20range(n_samples_to_create)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Select%20random%20base%20sample%0A%20%20%20%20%20%20%20%20%20%20%20%20idx_base%20%3D%20np.random.randint(0%2C%20len(x_min_arr))%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Pick%20a%20random%20neighbor%20(excluding%20the%20point%20itself)%0A%20%20%20%20%20%20%20%20%20%20%20%20idx_neighbor%20%3D%20np.random.choice(indices%5Bidx_base%2C%201%3A%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20x_base%20%3D%20x_min_arr%5Bidx_base%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20x_neigh%20%3D%20x_min_arr%5Bidx_neighbor%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Convex%20combination%0A%20%20%20%20%20%20%20%20%20%20%20%20lam%20%3D%20np.random.uniform(0.0%2C%201.0)%0A%20%20%20%20%20%20%20%20%20%20%20%20x_syn%20%3D%20x_base%20%2B%20lam%20*%20(x_neigh%20-%20x_base)%0A%20%20%20%20%20%20%20%20%20%20%20%20synthetic_samples.append(x_syn)%0A%20%20%20%20%20%20%20%20return%20np.array(synthetic_samples)%0A%0A%20%20%20%20minority_train%20%3D%20x_train%5By_train%20%3D%3D%201%5D%0A%20%20%20%20np.random.seed(42)%0A%20%20%20%20sample_syn_pts%20%3D%20manual_smote(minority_train%2C%20n_samples_to_create%3D5%2C%20k_nn%3D4)%0A%0A%20%20%20%20df_smote_manual%20%3D%20pd.DataFrame(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Synthetic_ID%22%3A%20%5Bf%22Syn_%7Bi%2B1%7D%22%20for%20i%20in%20range(5)%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Feature_1%22%3A%20sample_syn_pts%5B%3A%2C%200%5D.round(4)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Feature_2%22%3A%20sample_syn_pts%5B%3A%2C%201%5D.round(4)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Interpolation_Method%22%3A%20%22x_base%20%2B%20lambda%20*%20(x_neighbor%20-%20x_base)%22%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Example%202%3A%20Borderline-SMOTE%20Sample%20Categorization%20from%20Scratch%0A%20%20%20%20nn_all%20%3D%20NearestNeighbors(n_neighbors%3D6).fit(x_train)%0A%20%20%20%20_%2C%20all_indices%20%3D%20nn_all.kneighbors(minority_train)%0A%20%20%20%20%23%20Check%20labels%20of%20the%205%20nearest%20neighbors%20(excluding%20self%20at%20column%200)%0A%20%20%20%20neighbor_labels%20%3D%20y_train%5Ball_indices%5B%3A%2C%201%3A%5D%5D%0A%20%20%20%20maj_neighbor_counts%20%3D%20np.sum(neighbor_labels%20%3D%3D%200%2C%20axis%3D1)%0A%0A%20%20%20%20categories%20%3D%20%5B%5D%0A%20%20%20%20for%20count%20in%20maj_neighbor_counts%3A%0A%20%20%20%20%20%20%20%20if%20count%20%3D%3D%205%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20categories.append(%22NOISE%20(Ignored)%22)%0A%20%20%20%20%20%20%20%20elif%20count%20%3E%3D%203%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20categories.append(%22DANGER%20(Boundary)%22)%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20categories.append(%22SAFE%20(Interior)%22)%0A%0A%20%20%20%20df_borderline%20%3D%20pd.DataFrame(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Minority_Sample_ID%22%3A%20%5Bf%22Min_%7Bi%2B1%7D%22%20for%20i%20in%20range(len(minority_train%5B%3A8%5D))%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Feature_1%22%3A%20minority_train%5B%3A8%2C%200%5D.round(3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Feature_2%22%3A%20minority_train%5B%3A8%2C%201%5D.round(3)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Majority_Neighbors_k5%22%3A%20maj_neighbor_counts%5B%3A8%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Category%22%3A%20categories%5B%3A8%5D%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Example%203%3A%20Comprehensive%20Model%20Evaluation%20Benchmark%20on%20Unseen%20Test%20Partition%0A%20%20%20%20strategies%20%3D%20%5B%0A%20%20%20%20%20%20%20%20(%22No%20Resampling%20(Imbalanced)%22%2C%20x_train%2C%20y_train)%2C%0A%20%20%20%20%20%20%20%20(%22Random%20Oversampling%20(Naive)%22%2C%20x_train_ros%2C%20y_train_ros)%2C%0A%20%20%20%20%20%20%20%20(%22SMOTE%20(Uniform%20Convex%20Hull)%22%2C%20x_train_smote%2C%20y_train_smote)%2C%0A%20%20%20%20%20%20%20%20(%22ADASYN%20(Adaptive%20Boundary)%22%2C%20x_train_adasyn%2C%20y_train_adasyn)%2C%0A%20%20%20%20%5D%0A%0A%20%20%20%20benchmark_records%20%3D%20%5B%5D%0A%20%20%20%20for%20name%2C%20xtr%2C%20ytr%20in%20strategies%3A%0A%20%20%20%20%20%20%20%20rf%20%3D%20RandomForestClassifier(n_estimators%3D100%2C%20random_state%3D42)%0A%20%20%20%20%20%20%20%20rf.fit(xtr%2C%20ytr)%0A%20%20%20%20%20%20%20%20ypred%20%3D%20rf.predict(x_test)%0A%0A%20%20%20%20%20%20%20%20bal_acc%20%3D%20balanced_accuracy_score(y_test%2C%20ypred)%0A%20%20%20%20%20%20%20%20prec%20%3D%20precision_score(y_test%2C%20ypred%2C%20zero_division%3D0)%0A%20%20%20%20%20%20%20%20rec%20%3D%20recall_score(y_test%2C%20ypred%2C%20zero_division%3D0)%0A%20%20%20%20%20%20%20%20f1%20%3D%20f1_score(y_test%2C%20ypred%2C%20zero_division%3D0)%0A%0A%20%20%20%20%20%20%20%20benchmark_records.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Resampling_Strategy%22%3A%20name%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Training_Set_Size%22%3A%20len(xtr)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Balanced_Accuracy%22%3A%20f%22%7Bbal_acc%20*%20100%3A.2f%7D%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Minority_Precision%22%3A%20f%22%7Bprec%20*%20100%3A.2f%7D%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Minority_Recall%22%3A%20f%22%7Brec%20*%20100%3A.2f%7D%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Minority_F1_Score%22%3A%20f%22%7Bf1%20*%20100%3A.2f%7D%25%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20df_benchmark%20%3D%20pd.DataFrame(benchmark_records)%0A%0A%20%20%20%20table_manual%20%3D%20mo.ui.table(df_smote_manual)%0A%20%20%20%20table_border%20%3D%20mo.ui.table(df_borderline)%0A%20%20%20%20table_bench%20%3D%20mo.ui.table(df_benchmark)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
ba57a9d8ff41f5cdc3295b927c59790a