import%20marimo%0A%0A__generated_with%20%3D%20%220.24.0%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%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%20plotly.subplots%20import%20make_subplots%0A%20%20%20%20import%20scipy.stats%20as%20stats%0A%0A%20%20%20%20return%20go%2C%20make_subplots%2C%20mo%2C%20np%2C%20pd%2C%20stats%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Note%2011%3A%20Empirical%20Cumulative%20Distribution%20Function%20(ECDF)%20and%20Non-Parametric%20Inference%0A%0A%20%20%20%20%26larr%3B%20Previous%20Note%3A%20%5B10%20Chebyshev%20Inequality%5D(10_chebyshev_inequality.py)%20%7C%20Next%20Note%3A%20%5B12%20Multivariate%20Normal%20Distribution%5D(12_multivariate_normal_distribution.py)%20%26rarr%3B%0A%0A%20%20%20%20---%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%20Parametric%20probability%20distributions%20assume%20idealized%20mathematical%20forms%20(such%20as%20Gaussian%2C%20Gamma%2C%20or%20Poisson).%20In%20real-world%20data%20science%2C%20machine%20learning%20operations%20(MLOps)%2C%20and%20statistical%20inference%2C%20however%2C%20true%20data-generating%20distributions%20are%20rarely%20known%20a%20priori.%0A%0A%20%20%20%20The%20**Empirical%20Cumulative%20Distribution%20Function%20(ECDF)**%20is%20the%20foundational%20tool%20of%20non-parametric%20statistics%3A%0A%20%20%20%201.%20**Zero-Assumption%20Distribution%20Estimation**%3A%20Unlike%20histograms%20or%20kernel%20density%20estimators%20(KDE)%2C%20which%20are%20sensitive%20to%20bin%20width%2C%20bin%20placement%2C%20and%20bandwidth%20hyperparameter%20choices%2C%20the%20ECDF%20requires%20no%20tuning%20parameters%20and%20preserves%20all%20original%20sample%20information.%0A%20%20%20%202.%20**The%20Fundamental%20Theorem%20of%20Statistics%20(Glivenko-Cantelli)**%3A%20The%20ECDF%20is%20guaranteed%20to%20converge%20uniformly%20to%20the%20true%20population%20cumulative%20distribution%20function%20across%20the%20entire%20real%20line%20as%20sample%20size%20grows%3A%20%24%5Csup_%7Bx%7D%20%7C%5Chat%7BF%7D_n(x)%20-%20F(x)%7C%20%5Cxrightarrow%7B%5Ctext%7Ba.s.%7D%7D%200%24.%0A%20%20%20%203.%20**Simultaneous%20Confidence%20Envelopes%20(DKW%20Inequality)**%3A%20The%20Dvoretzky-Kiefer-Wolfowitz%20inequality%20allows%20the%20construction%20of%20exact%2C%20non-parametric%20confidence%20bands%20that%20envelope%20the%20entire%20unknown%20population%20CDF%20with%20pre-specified%20probability%20(e.g.%20%2495%5C%25%24).%0A%20%20%20%204.%20**Data%20Drift%20and%20Covariate%20Shift%20Detection%20in%20MLOps**%3A%20The%20two-sample%20Kolmogorov-Smirnov%20(KS)%20test%20evaluates%20the%20maximum%20vertical%20discrepancy%20between%20the%20baseline%20training%20ECDF%20and%20production%20serving%20ECDF%2C%20serving%20as%20an%20industry%20standard%20for%20real-time%20model%20monitoring%20and%20drift%20alerting.%0A%20%20%20%205.%20**Quantile%20and%20Risk%20Estimation**%3A%20Inverting%20the%20ECDF%20provides%20direct%20estimates%20of%20empirical%20percentiles%2C%20medians%2C%20interquartile%20ranges%2C%20and%20Value-at-Risk%20(VaR)%20in%20quantitative%20finance.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20%5Bb%5D%20Concept%20explanation%20with%20their%20role%20in%20ML%2FAI%2FStats%3F%0A%0A%20%20%20%20%23%23%23%20Population%20Cumulative%20Distribution%20Function%20(CDF)%0A%0A%20%20%20%20For%20any%20random%20variable%20%24X%24%2C%20the%20cumulative%20distribution%20function%20%24F_X(x)%24%20represents%20the%20probability%20that%20%24X%24%20takes%20a%20value%20less%20than%20or%20equal%20to%20%24x%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20F_X(x)%20%3D%20P(X%20%5Cleq%20x)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20%23%23%23%23%20Fundamental%20Mathematical%20Properties%0A%20%20%20%20*%20**Non-decreasing**%3A%20If%20%24x_1%20%5Cleq%20x_2%24%2C%20then%20%24F_X(x_1)%20%5Cleq%20F_X(x_2)%24.%0A%20%20%20%20*%20**Asymptotic%20Limits**%3A%20%24%5Clim_%7Bx%20%5Cto%20-%5Cinfty%7D%20F_X(x)%20%3D%200%24%20and%20%24%5Clim_%7Bx%20%5Cto%20%5Cinfty%7D%20F_X(x)%20%3D%201%24.%0A%20%20%20%20*%20**Right-Continuity**%3A%20For%20all%20%24x%24%2C%20%24%5Clim_%7B%5Cepsilon%20%5Cto%200%5E%2B%7D%20F_X(x%20%2B%20%5Cepsilon)%20%3D%20F_X(x)%24.%0A%20%20%20%20*%20**Range**%3A%20For%20all%20%24x%24%2C%20%240%20%5Cleq%20F_X(x)%20%5Cleq%201%24.%0A%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%23%20Definition%20and%20Statistical%20Properties%20of%20the%20ECDF%0A%0A%20%20%20%20Given%20an%20independent%20and%20identically%20distributed%20(i.i.d.)%20sample%20%24X_1%2C%20X_2%2C%20%5Cdots%2C%20X_n%24%20from%20distribution%20%24F%24%2C%20the%20**Empirical%20CDF**%20%24%5Chat%7BF%7D_n(x)%24%20is%20the%20step%20function%20defined%20by%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Chat%7BF%7D_n(x)%20%3D%20%5Cfrac%7B1%7D%7Bn%7D%20%5Csum_%7Bi%3D1%7D%5En%20%5Cmathbb%7BI%7D(X_i%20%5Cleq%20x)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20where%20%24%5Cmathbb%7BI%7D(%5Ccdot)%24%20is%20the%20indicator%20function.%0A%0A%20%20%20%20%23%23%23%23%20Pointwise%20Properties%20for%20a%20Fixed%20%24x%24%0A%20%20%20%20*%20**Binomial%20Identity**%3A%20The%20count%20%24n%20%5Chat%7BF%7D_n(x)%20%3D%20%5Csum_%7Bi%3D1%7D%5En%20%5Cmathbb%7BI%7D(X_i%20%5Cleq%20x)%24%20follows%20a%20Binomial%20distribution%20%24%5Ctext%7BBinomial%7D(n%2C%20F(x))%24.%0A%20%20%20%20*%20**Unbiased%20Estimator**%3A%20%24%5Cmathbb%7BE%7D%5B%5Chat%7BF%7D_n(x)%5D%20%3D%20%5Cfrac%7B1%7D%7Bn%7D%20%5Ccdot%20n%20F(x)%20%3D%20F(x)%24.%0A%20%20%20%20*%20**Variance**%3A%20%24%5Ctext%7BVar%7D(%5Chat%7BF%7D_n(x))%20%3D%20%5Cfrac%7BF(x)(1%20-%20F(x))%7D%7Bn%7D%24.%0A%20%20%20%20*%20**Pointwise%20Consistency**%3A%20By%20the%20Weak%20Law%20of%20Large%20Numbers%2C%20%24%5Chat%7BF%7D_n(x)%20%5Cxrightarrow%7BP%7D%20F(x)%24%20as%20%24n%20%5Cto%20%5Cinfty%24.%0A%20%20%20%20*%20**Asymptotic%20Normality**%3A%20By%20the%20Central%20Limit%20Theorem%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5Csqrt%7Bn%7D%20(%5Chat%7BF%7D_n(x)%20-%20F(x))%20%5Cxrightarrow%7Bd%7D%20%5Cmathcal%7BN%7D%5Cleft(0%2C%20F(x)(1%20-%20F(x))%5Cright)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%23%20Uniform%20Convergence%3A%20The%20Glivenko-Cantelli%20Theorem%0A%0A%20%20%20%20Pointwise%20convergence%20guarantees%20accuracy%20at%20an%20individual%20coordinate%20%24x%24.%20The%20**Glivenko-Cantelli%20Theorem**%20establishes%20uniform%20convergence%20across%20the%20entire%20domain%20%24%5Cmathbb%7BR%7D%24%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20%5C%7C%20%5Chat%7BF%7D_n%20-%20F%20%5C%7C_%5Cinfty%20%3D%20%5Csup_%7Bx%20%5Cin%20%5Cmathbb%7BR%7D%7D%20%7C%5Chat%7BF%7D_n(x)%20-%20F(x)%7C%20%5Cxrightarrow%7B%5Ctext%7Ba.s.%7D%7D%200%20%5Cquad%20%5Ctext%7Bas%20%7D%20n%20%5Cto%20%5Cinfty%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20guarantees%20that%20the%20entire%20step%20function%20%24%5Chat%7BF%7D_n%24%20uniformly%20approaches%20the%20population%20CDF%20%24F%24.%0A%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%23%20Simultaneous%20Confidence%20Bands%3A%20The%20DKW%20Inequality%0A%0A%20%20%20%20The%20**Dvoretzky-Kiefer-Wolfowitz%20(DKW)%20inequality**%20provides%20non-asymptotic%20bounds%20on%20the%20probability%20of%20uniform%20deviation%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20P%5Cleft(%5Csup_%7Bx%20%5Cin%20%5Cmathbb%7BR%7D%7D%20%7C%5Chat%7BF%7D_n(x)%20-%20F(x)%7C%20%3E%20%5Cepsilon%5Cright)%20%5Cleq%202%20e%5E%7B-2%20n%20%5Cepsilon%5E2%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20Setting%20the%20tail%20probability%20bound%20to%20significance%20level%20%24%5Calpha%24%20(e.g.%20%24%5Calpha%20%3D%200.05%24)%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%202%20e%5E%7B-2%20n%20%5Cepsilon%5E2%7D%20%3D%20%5Calpha%20%5Cimplies%20%5Cepsilon_n%20%3D%20%5Csqrt%7B%5Cfrac%7B%5Cln(2%2F%5Calpha)%7D%7B2n%7D%7D%0A%20%20%20%20%24%24%0A%0A%20%20%20%20This%20defines%20a%20**simultaneous%20%24100(1%20-%20%5Calpha)%5C%25%24%20confidence%20envelope**%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20L_n(x)%20%3D%20%5Cmax(0%2C%20%5Chat%7BF%7D_n(x)%20-%20%5Cepsilon_n)%2C%20%5Cquad%20U_n(x)%20%3D%20%5Cmin(1%2C%20%5Chat%7BF%7D_n(x)%20%2B%20%5Cepsilon_n)%0A%20%20%20%20%24%24%0A%0A%20%20%20%20The%20true%20population%20function%20%24F(x)%24%20is%20guaranteed%20to%20lie%20completely%20between%20%24L_n(x)%24%20and%20%24U_n(x)%24%20for%20all%20%24x%20%5Cin%20%5Cmathbb%7BR%7D%24%20simultaneously%20with%20probability%20at%20least%20%241%20-%20%5Calpha%24.%0A%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%23%20The%20Kolmogorov-Smirnov%20Test%20and%20MLOps%20Drift%20Detection%0A%0A%20%20%20%20The%20**Kolmogorov-Smirnov%20(KS)%20statistic**%20measures%20the%20maximum%20vertical%20distance%20between%20two%20distribution%20functions%3A%0A%20%20%20%20*%20**One-Sample%20KS**%3A%20Compares%20sample%20ECDF%20against%20theoretical%20CDF%3A%20%24D_n%20%3D%20%5Csup_x%20%7C%5Chat%7BF%7D_n(x)%20-%20F_0(x)%7C%24.%0A%20%20%20%20*%20**Two-Sample%20KS**%3A%20Compares%20two%20independent%20empirical%20samples%20(e.g.%20baseline%20training%20data%20vs%20live%20serving%20data)%3A%0A%0A%20%20%20%20%24%24%0A%20%20%20%20D_%7Bn%2C%20m%7D%20%3D%20%5Csup_%7Bx%20%5Cin%20%5Cmathbb%7BR%7D%7D%20%7C%5Chat%7BF%7D_n(x)%20-%20%5Chat%7BG%7D_m(x)%7C%0A%20%20%20%20%24%24%0A%0A%20%20%20%20If%20%24D_%7Bn%2C%20m%7D%24%20exceeds%20critical%20threshold%20%24c(%5Calpha)%20%5Csqrt%7B%5Cfrac%7Bn%20%2B%20m%7D%7Bn%20m%7D%7D%24%2C%20the%20null%20hypothesis%20that%20both%20data%20streams%20originate%20from%20the%20same%20distribution%20is%20rejected%20(%24p%20%3C%20%5Calpha%24)%2C%20triggering%20retraining%20alerts%20in%20production%20machine%20learning%20pipelines.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20%5Bc%5D%20Interactive%20Visualizations%3A%20ECDF%2C%20Theoretical%20CDF%2C%20and%20DKW%20Confidence%20Bands%0A%0A%20%20%20%20The%20interactive%20subplots%20below%20display%20the%20non-parametric%20inference%20capabilities%20of%20the%20ECDF%3A%0A%20%20%20%20*%20**Left%20Panel**%3A%20Empirical%20CDF%20%24%5Chat%7BF%7D_n(x)%24%20constructed%20from%20%24n%20%3D%2060%24%20samples%20of%20a%20standard%20normal%20distribution.%20Shaded%20blue%20region%20shows%20the%20%2495%5C%25%24%20simultaneous%20DKW%20confidence%20envelope.%20The%20red%20curve%20is%20the%20true%20population%20CDF%20%24F(x)%24.%20The%20purple%20vertical%20bar%20marks%20the%20maximum%20vertical%20gap%20(the%20Kolmogorov-Smirnov%20statistic%20%24D_n%24).%0A%20%20%20%20*%20**Right%20Panel**%3A%20Two-Sample%20Drift%20Detection%20comparing%20Baseline%20Training%20Data%20(%24N%20%3D%2060%24%2C%20%24%5Cmu%3D0%2C%20%5Csigma%3D1%24)%20against%20Shifted%20Production%20Data%20(%24M%20%3D%2060%24%2C%20%24%5Cmu%3D0.8%2C%20%5Csigma%3D1.3%24).%20The%20orange%20vertical%20bar%20highlights%20the%20maximum%20discrepancy%20%24D_%7Bn%2Cm%7D%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(go%2C%20make_subplots%2C%20np%2C%20stats)%3A%0A%20%20%20%20rng_vis%20%3D%20np.random.default_rng(42)%0A%20%20%20%20n_sample_size%20%3D%2060%0A%0A%20%20%20%20%23%20Sample%201%3A%20Baseline%20N(0%2C%201)%0A%20%20%20%20raw_sample%20%3D%20rng_vis.standard_normal(n_sample_size)%0A%20%20%20%20sorted_sample%20%3D%20np.sort(raw_sample)%0A%20%20%20%20ecdf_values%20%3D%20np.arange(1%2C%20n_sample_size%20%2B%201)%20%2F%20n_sample_size%0A%0A%20%20%20%20%23%20DKW%2095%25%20Confidence%20Band%20(alpha%20%3D%200.05)%0A%20%20%20%20significance_alpha%20%3D%200.05%0A%20%20%20%20epsilon_dkw%20%3D%20np.sqrt(np.log(2.0%20%2F%20significance_alpha)%20%2F%20(2.0%20*%20n_sample_size))%0A%20%20%20%20lower_band%20%3D%20np.clip(ecdf_values%20-%20epsilon_dkw%2C%200.0%2C%201.0)%0A%20%20%20%20upper_band%20%3D%20np.clip(ecdf_values%20%2B%20epsilon_dkw%2C%200.0%2C%201.0)%0A%0A%20%20%20%20%23%20True%20CDF%0A%20%20%20%20x_axis_grid%20%3D%20np.linspace(-3.5%2C%203.5%2C%20200)%0A%20%20%20%20true_cdf_values%20%3D%20stats.norm.cdf(x_axis_grid)%0A%0A%20%20%20%20%23%20KS%20distance%20location%0A%20%20%20%20true_at_sample%20%3D%20stats.norm.cdf(sorted_sample)%0A%20%20%20%20ks_deviations%20%3D%20np.abs(ecdf_values%20-%20true_at_sample)%0A%20%20%20%20max_dev_idx%20%3D%20np.argmax(ks_deviations)%0A%20%20%20%20ks_x_pos%20%3D%20sorted_sample%5Bmax_dev_idx%5D%0A%20%20%20%20ks_y_emp%20%3D%20ecdf_values%5Bmax_dev_idx%5D%0A%20%20%20%20ks_y_true%20%3D%20true_at_sample%5Bmax_dev_idx%5D%0A%20%20%20%20ks_stat_val%20%3D%20float(ks_deviations%5Bmax_dev_idx%5D)%0A%0A%20%20%20%20%23%20Sample%202%3A%20Shifted%20Production%20Data%20N(0.8%2C%201.3)%0A%20%20%20%20raw_drift%20%3D%20rng_vis.normal(loc%3D0.8%2C%20scale%3D1.3%2C%20size%3Dn_sample_size)%0A%20%20%20%20sorted_drift%20%3D%20np.sort(raw_drift)%0A%20%20%20%20ecdf_drift_values%20%3D%20np.arange(1%2C%20n_sample_size%20%2B%201)%20%2F%20n_sample_size%0A%0A%20%20%20%20%23%20Two-sample%20KS%20distance%0A%20%20%20%20all_points%20%3D%20np.sort(np.unique(np.concatenate(%5Bsorted_sample%2C%20sorted_drift%5D)))%0A%20%20%20%20cdf1_eval%20%3D%20np.searchsorted(sorted_sample%2C%20all_points%2C%20side%3D%22right%22)%20%2F%20n_sample_size%0A%20%20%20%20cdf2_eval%20%3D%20np.searchsorted(sorted_drift%2C%20all_points%2C%20side%3D%22right%22)%20%2F%20n_sample_size%0A%20%20%20%20two_sample_diffs%20%3D%20np.abs(cdf1_eval%20-%20cdf2_eval)%0A%20%20%20%20max_drift_idx%20%3D%20np.argmax(two_sample_diffs)%0A%20%20%20%20drift_ks_x%20%3D%20all_points%5Bmax_drift_idx%5D%0A%20%20%20%20drift_ks_y1%20%3D%20cdf1_eval%5Bmax_drift_idx%5D%0A%20%20%20%20drift_ks_y2%20%3D%20cdf2_eval%5Bmax_drift_idx%5D%0A%20%20%20%20drift_ks_val%20%3D%20float(two_sample_diffs%5Bmax_drift_idx%5D)%0A%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%3D2%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%20f%22ECDF%20with%2095%25%20DKW%20Band%20%26%20KS%20Distance%20(D%E2%82%99%3D%7Bks_stat_val%3A.3f%7D)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22Two-Sample%20Covariate%20Shift%20Detection%20(D_drift%3D%7Bdrift_ks_val%3A.3f%7D)%22%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Left%3A%20DKW%20Upper%20Band%20(hidden%20line%20for%20fill)%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%3Dsorted_sample%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dupper_band%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22rgba(37%2C99%2C235%2C0.0)%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%3D1%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Left%3A%20DKW%20Band%20Fill%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%3Dsorted_sample%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dlower_band%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20fill%3D%22tonexty%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20fillcolor%3D%22rgba(37%2C%2099%2C%20235%2C%200.15)%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22rgba(37%2C99%2C235%2C0.0)%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3Df%2295%25%20DKW%20Band%20(%CE%B5%3D%7Bepsilon_dkw%3A.2f%7D)%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%20Left%3A%20True%20CDF%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_axis_grid%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Dtrue_cdf_values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22%23dc2626%22%2C%20width%3D2.5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22True%20CDF%20F(x)%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%20Left%3A%20ECDF%20Step%20Function%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%3Dsorted_sample%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Decdf_values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22%232563eb%22%2C%20width%3D2.5%2C%20shape%3D%22hv%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Empirical%20CDF%20F%CC%82%E2%82%99(x)%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%20Left%3A%20KS%20Distance%20Bar%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%3D%5Bks_x_pos%2C%20ks_x_pos%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D%5Bks_y_true%2C%20ks_y_emp%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%2Bmarkers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22%237c3aed%22%2C%20width%3D3.5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(size%3D7%2C%20color%3D%22%237c3aed%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3Df%22Max%20Gap%20D%E2%82%99%3D%7Bks_stat_val%3A.3f%7D%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%20Right%3A%20Baseline%20ECDF%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%3Dsorted_sample%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Decdf_values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22%232563eb%22%2C%20width%3D2.5%2C%20shape%3D%22hv%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Baseline%20Training%20ECDF%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%20Right%3A%20Production%20Shifted%20ECDF%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%3Dsorted_drift%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Decdf_drift_values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22%23ea580c%22%2C%20width%3D2.5%2C%20shape%3D%22hv%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Production%20Serving%20ECDF%20(Shifted)%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%20Right%3A%20Two-sample%20KS%20gap%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%3D%5Bdrift_ks_x%2C%20drift_ks_x%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D%5Bdrift_ks_y1%2C%20drift_ks_y2%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%2Bmarkers%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Ddict(color%3D%22%23dc2626%22%2C%20width%3D3.5)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20marker%3Ddict(size%3D7%2C%20color%3D%22%23dc2626%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3Df%22KS%20Drift%20Distance%20D%3D%7Bdrift_ks_val%3A.3f%7D%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%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%3D520%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%20xaxis%3Ddict(title%3D%22x%22%2C%20range%3D%5B-3.5%2C%203.5%5D%2C%20gridcolor%3D%22%23f1f5f9%22)%2C%0A%20%20%20%20%20%20%20%20yaxis%3Ddict(title%3D%22Cumulative%20Probability%22%2C%20range%3D%5B-0.05%2C%201.05%5D%2C%20gridcolor%3D%22%23f1f5f9%22)%2C%0A%20%20%20%20%20%20%20%20xaxis2%3Ddict(title%3D%22x%22%2C%20range%3D%5B-3.5%2C%204.5%5D%2C%20gridcolor%3D%22%23f1f5f9%22)%2C%0A%20%20%20%20%20%20%20%20yaxis2%3Ddict(title%3D%22Cumulative%20Probability%22%2C%20range%3D%5B-0.05%2C%201.05%5D%2C%20gridcolor%3D%22%23f1f5f9%22)%2C%0A%20%20%20%20%20%20%20%20legend%3Ddict(orientation%3D%22h%22%2C%20yanchor%3D%22bottom%22%2C%20y%3D-0.26%2C%20xanchor%3D%22center%22%2C%20x%3D0.5)%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(fig%2C)%0A%0A%0A%40app.cell%0Adef%20_(fig%2C%20mo)%3A%0A%20%20%20%20mo.ui.plotly(fig)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20%5Bd%5D%20Code%20Examples%0A%0A%20%20%20%20%23%23%23%20Example%201%3A%20Glivenko-Cantelli%20Convergence%20and%20DKW%20Envelope%20Verification%0A%0A%20%20%20%20In%20this%20example%2C%20we%20empirically%20verify%20uniform%20convergence%20and%20the%20Dvoretzky-Kiefer-Wolfowitz%20(DKW)%20inequality%20across%20five%20sample%20sizes%3A%20%24n%20%5Cin%20%5C%7B25%2C%20100%2C%20500%2C%202000%2C%2010000%5C%7D%24.%0A%0A%20%20%20%20For%20each%20sample%20size%2C%20we%3A%0A%20%20%20%201.%20Compute%20the%20empirical%20Kolmogorov-Smirnov%20statistic%20%24D_n%20%3D%20%5Csup_x%20%7C%5Chat%7BF%7D_n(x)%20-%20F(x)%7C%24.%0A%20%20%20%202.%20Compute%20the%2095%25%20DKW%20band%20half-width%20%24%5Cepsilon_n%20%3D%20%5Csqrt%7B%5Cfrac%7B%5Cln(2%20%2F%200.05)%7D%7B2n%7D%7D%24.%0A%20%20%20%203.%20Verify%20that%20%24D_n%20%5Cleq%20%5Cepsilon_n%24%20and%20observe%20the%20asymptotic%20convergence%20rate%20%24%5Cmathcal%7BO%7D(1%20%2F%20%5Csqrt%7Bn%7D)%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20stats)%3A%0A%20%20%20%20rng_gc%20%3D%20np.random.default_rng(101)%0A%20%20%20%20sample_sizes_gc%20%3D%20%5B25%2C%20100%2C%20500%2C%202000%2C%2010000%5D%0A%20%20%20%20alpha_level%20%3D%200.05%0A%0A%20%20%20%20gc_verification_records%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20size_n%20in%20sample_sizes_gc%3A%0A%20%20%20%20%20%20%20%20sim_sample%20%3D%20np.sort(rng_gc.standard_normal(size_n))%0A%20%20%20%20%20%20%20%20emp_cdf%20%3D%20np.arange(1%2C%20size_n%20%2B%201)%20%2F%20size_n%0A%20%20%20%20%20%20%20%20population_cdf%20%3D%20stats.norm.cdf(sim_sample)%0A%0A%20%20%20%20%20%20%20%20%23%20Empirical%20Kolmogorov-Smirnov%20distance%0A%20%20%20%20%20%20%20%20ks_dist%20%3D%20float(np.max(np.abs(emp_cdf%20-%20population_cdf)))%0A%0A%20%20%20%20%20%20%20%20%23%20Theoretical%20DKW%2095%25%20threshold%0A%20%20%20%20%20%20%20%20dkw_thresh%20%3D%20float(np.sqrt(np.log(2.0%20%2F%20alpha_level)%20%2F%20(2.0%20*%20size_n)))%0A%20%20%20%20%20%20%20%20within_dkw_band%20%3D%20ks_dist%20%3C%3D%20dkw_thresh%0A%0A%20%20%20%20%20%20%20%20gc_verification_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%22Sample%20Size%20(n)%22%3A%20size_n%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Empirical%20KS%20Distance%20D%E2%82%99%22%3A%20f%22%7Bks_dist%3A.4f%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2295%25%20DKW%20Threshold%20%CE%B5_n%22%3A%20f%22%7Bdkw_thresh%3A.4f%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Convergence%20Ratio%20(D%E2%82%99%20%2F%20%CE%B5_n)%22%3A%20f%22%7Bks_dist%20%2F%20dkw_thresh%3A.3f%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Inside%2095%25%20Envelope%22%3A%20str(within_dkw_band)%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%20%20%20%20return%20(gc_verification_records%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(gc_verification_records%2C%20mo%2C%20pd)%3A%0A%20%20%20%20df_gc%20%3D%20pd.DataFrame(gc_verification_records)%0A%20%20%20%20mo.ui.table(df_gc)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%23%20Example%202%3A%20Two-Sample%20Kolmogorov-Smirnov%20Test%20for%20Data%20Drift%20Detection%0A%0A%20%20%20%20In%20production%20machine%20learning%20systems%2C%20data%20drift%20occurs%20when%20feature%20distributions%20shift%20between%20model%20training%20and%20live%20production%20inference.%0A%0A%20%20%20%20Below%2C%20we%20simulate%20a%20monitoring%20pipeline%20where%20a%20reference%20training%20feature%20(%24N%20%3D%20400%24)%20is%20compared%20against%20three%20production%20batches%3A%0A%20%20%20%20*%20**Batch%20A%20(In-Distribution)**%3A%20Fresh%20sample%20from%20the%20same%20training%20distribution%20%24%5Cmathcal%7BN%7D(0%2C%201)%24.%0A%20%20%20%20*%20**Batch%20B%20(Mild%20Mean%20Shift)**%3A%20Covariate%20shift%20with%20shifted%20mean%20%24%5Cmathcal%7BN%7D(0.2%2C%201)%24.%0A%20%20%20%20*%20**Batch%20C%20(Severe%20Variance%20%26%20Mean%20Shift)**%3A%20Significant%20drift%20%24%5Cmathcal%7BN%7D(0.6%2C%201.5)%24.%0A%0A%20%20%20%20We%20evaluate%20the%20two-sample%20Kolmogorov-Smirnov%20test%20statistic%20%24D%24%20and%20corresponding%20%24p%24-value%20at%20significance%20level%20%24%5Calpha%20%3D%200.01%24.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20stats)%3A%0A%20%20%20%20rng_drift%20%3D%20np.random.default_rng(202)%0A%20%20%20%20batch_size%20%3D%20400%0A%0A%20%20%20%20training_reference%20%3D%20rng_drift.standard_normal(batch_size)%0A%0A%20%20%20%20production_batches%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22Batch%20A%3A%20In-Distribution%20N(0%2C%201)%22%3A%20rng_drift.standard_normal(batch_size)%2C%0A%20%20%20%20%20%20%20%20%22Batch%20B%3A%20Mild%20Mean%20Shift%20N(0.2%2C%201)%22%3A%20rng_drift.normal(0.2%2C%201.0%2C%20batch_size)%2C%0A%20%20%20%20%20%20%20%20%22Batch%20C%3A%20Severe%20Drift%20N(0.6%2C%201.5)%22%3A%20rng_drift.normal(0.6%2C%201.5%2C%20batch_size)%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20drift_detection_records%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20batch_label%2C%20prod_data%20in%20production_batches.items()%3A%0A%20%20%20%20%20%20%20%20ks_result%20%3D%20stats.ks_2samp(training_reference%2C%20prod_data)%0A%20%20%20%20%20%20%20%20d_statistic%20%3D%20float(ks_result.statistic)%0A%20%20%20%20%20%20%20%20p_val%20%3D%20float(ks_result.pvalue)%0A%0A%20%20%20%20%20%20%20%20%23%20Drift%20alerted%20if%20p-value%20%3C%200.01%0A%20%20%20%20%20%20%20%20drift_alert%20%3D%20p_val%20%3C%200.01%0A%20%20%20%20%20%20%20%20status_string%20%3D%20%22ALERT%3A%20Significant%20Drift%22%20if%20drift_alert%20else%20%22PASS%3A%20In-Distribution%22%0A%0A%20%20%20%20%20%20%20%20drift_detection_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%22Production%20Stream%22%3A%20batch_label%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22KS%20Distance%20D%22%3A%20f%22%7Bd_statistic%3A.4f%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22p-value%22%3A%20f%22%7Bp_val%3A.2e%7D%22%20if%20p_val%20%3C%201e-4%20else%20f%22%7Bp_val%3A.4f%7D%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Alert%20Threshold%20(%CE%B1%3D0.01)%22%3A%20%220.0100%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22Monitoring%20Status%22%3A%20status_string%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%20%20%20%20return%20(drift_detection_records%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(drift_detection_records%2C%20mo%2C%20pd)%3A%0A%20%20%20%20df_drift%20%3D%20pd.DataFrame(drift_detection_records)%0A%20%20%20%20mo.ui.table(df_drift)%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
e81b11a33aec5cc6fd185a87bae5896f