{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
">### đźš© *Create a free WhyLabs account to get more value out of whylogs!*
\n",
">*Did you know you can store, visualize, and monitor whylogs profiles with the [WhyLabs Observability Platform](https://whylabs.ai/whylogs-free-signup?utm_source=whylogs-Github&utm_medium=whylogs-example&utm_campaign=KS_profiling)? Sign up for a [free WhyLabs account](https://whylabs.ai/whylogs-free-signup?utm_source=whylogs-Github&utm_medium=whylogs-example&utm_campaign=KS_profiling) to leverage the power of whylogs and WhyLabs together!*"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Benchmark - KS Test"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/whylabs/whylogs/blob/mainline/python/examples/benchmarks/KS_Profiling.ipynb)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"> This notebook is a complement to the blog post [_Understanding Kolmogorov-Smirnov (KS) Tests for Data Drift on Profiled Data_](https://medium.com/p/5c8317796f78).\n",
">\n",
">Please refer to the blog post for additional context."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We applied whylogs' implementation of KS Test and compared the results when applying the same test to the complete data set. The results allow us to discuss the limitations of data profiling for KS drift detection, and also the pros and cons of the KS algorithm itself for different scenarios."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Experiment Design"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First, we need the data. For this experiment, we will take two samples of equal size from the following distributions:\n",
"\n",
"- Normal: Broad class of data. Unskewed and Peaked around the center\n",
"\n",
"- Pareto: Skewed data with long tail/outliers\n",
"\n",
"- Uniform: Evenly sampled across its domain\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Drift Injection\n",
"\n",
"Next, we’ll inject drift into one sample (which we’ll call the target distribution) to compare it to the reference, unaltered, distribution.\n",
"\n",
"We will inject drift artificially by simply shifting the data according to a parameter. We’ll use as the parameter a ratio of the distribution’s interquartile range.\n",
"\n",
"The idea is to have 4 different scenarios:\n",
"\n",
"- No drift\n",
"\n",
"- Small drift\n",
"\n",
"- Medium drift\n",
"\n",
"- Large drift\n",
"\n",
"The ideal process of detecting/alerting for drifts can be very subjective, depending on the desired sensitivity for your particular application. In this case, we are assuming that the small-drift scenario is small enough for it to be safely ignored. We are also expecting that the medium and large drift scenarios should result in a drift alert since both would be cases for further inspection. \n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Applying the KS test\n",
"\n",
"As the ground truth, we will use scipy’s implementation of the two-sample KS test, with the complete data from both samples. We will then compare those results with the profiled version of the test. To do so, we’ll use whylogs’ implementation of the same test, which uses only the statistical profile of each sample. \n",
"\n",
"The distribution metrics contained in the profiles are obtained from a process called data sketching, which adds some degree of randomness to the result. For this reason, the KS test result can be different each time a profile is generated. For this reason, we’ll profile the data 10 times for every scenario, and compare the ground truth to statistics such as the mean, maximum, and minimum of those runs.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Experiment Variables\n",
"\n",
"Our main goal is to answer:\n",
"\n",
"“How does whylogs’ KS implementation compare to scipy’s implementation?”\n",
"\n",
"However, this answer depends on several different variables. We will run three separate experiments to better understand the effect of each variable: Data Volume, Number of buckets, and Profile Size. The first one relates to the number of samples being tested, whereas the last two relate to whylogs internal, tunable parameters.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Installing the required packages"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Note: you may need to restart the kernel to use updated packages.\n",
"%pip install 'matplotlib' 'numpy' 'seaborn==0.12.1'\n",
"%pip install 'scipy==1.7.3' 'whylogs[viz]' 'typing_extensions'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Parameters and Functions - Experiments and Plots"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"In this section, we'll compile all of the parameter and functions required to run the following experiments and plot the results."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"# For experiment #2, we're running the test with different number of buckets for the KS Test calculation\n",
"QUANTILE_LIST = [\n",
" list(np.linspace(0,1,5)),\n",
" list(np.linspace(0,1,10)),\n",
" list(np.linspace(0,1,50)),\n",
" list(np.linspace(0,1,100)),\n",
"]\n",
"\n",
"# no drift, small drift, medium drift and large drift\n",
"drift_magnitudes = [0,0.05,0.4,0.75]\n",
"\n",
"sample_sizes = [500,1000,5000,10000,50000]\n",
"sample_sizes_labels = ['500','1k', '5k','10k','50k']\n",
"random_seed = 22"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"from numpy.random import Generator, PCG64\n",
"import pandas as pd\n",
"from scipy.stats import iqr\n",
"\n",
"def generate_data(\n",
" distribution: str = \"normal\", generator=None, drift_magnitude: float = 0, size: int = 100000\n",
") -> pd.Series:\n",
" \"\"\"Generates a pandas series with samples drawn from a distribution (normal, pareto or uniform). The internal parameters\n",
" for each distributions are fixed. You can specify the number of samples you want and also if a drift of a certain magnitude is\n",
" to be injected. The drift magnitude is a ratio of the distribution's interquartile range.\n",
"\n",
" \"\"\"\n",
" if generator is None:\n",
" generator = Generator(PCG64(12345))\n",
"\n",
" if distribution == \"normal\":\n",
" sample = generator.standard_normal(size)\n",
" elif distribution == \"pareto\":\n",
" a,m = 7.,2.\n",
" sample = (generator.pareto(a, size) + 1) * m\n",
" elif distribution == \"uniform\":\n",
" sample = generator.uniform(-5,5,size)\n",
" else:\n",
" raise ValueError(\"Distribution not found.\")\n",
" offset = (iqr(sample)) * drift_magnitude\n",
" drifted_sample = sample + offset\n",
" return pd.Series(drifted_sample)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"from numpy.random import Generator, PCG64\n",
"import numpy as np\n",
"import pandas as pd\n",
"import whylogs as why\n",
"from whylogs.viz.utils.drift_calculations import calculate_drift_values, _compute_ks_test_p_value\n",
"from scipy import stats\n",
"\n",
"def run_ks_experiment(distribution=\"normal\",drift_magnitude=0, quantile_list = QUANTILE_LIST):\n",
" \"\"\"Runs KS experiment for given distribution type and drift magnitude. The experiments are run\n",
" for multiple sample sizes and number of buckets, 10 times for each combination of parameters.\n",
"\n",
" Parameters\n",
" ----------\n",
" distribution : str, optional\n",
" distribution type. \"normal\",\"pareto\", or \"uniform\", by default \"normal\"\n",
" drift_magnitude : int, optional\n",
" drift magnitude, by default 0 (no drift)\n",
"\n",
" Returns\n",
" -------\n",
" _type_\n",
" Dictionary with statistics such as pvalues for whylogs and scipy's implementation, mean absolute errors,\n",
" and error ranges (minimum and maximum) for whylogs KS test.\n",
" \"\"\"\n",
" # size_list = [1000, 5000, 10000, 50000, 100000]\n",
" size_list = sample_sizes\n",
" experiment_results = {}\n",
" for quant_i,QUANTILES in enumerate(quantile_list):\n",
" bars1 = []\n",
" heights1 = []\n",
" pv_means = []\n",
" pv_ranges = []\n",
" pv_truths = []\n",
" for sample_size in size_list:\n",
" rng = Generator(PCG64(random_seed))\n",
" ref, target = pd.DataFrame(), pd.DataFrame()\n",
" ref[\"col\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=0, size=sample_size)\n",
" target[\"col\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=drift_magnitude, size=sample_size)\n",
" scipy_res = stats.ks_2samp(ref[\"col\"], target[\"col\"], mode='asymp')\n",
" scipy_pvalue = scipy_res.pvalue\n",
" errors = []\n",
" pvalues = []\n",
" for i in range(10):\n",
" ref_profile = why.log(ref).profile()\n",
" target_profile = why.log(target).profile()\n",
"\n",
" ref_dist = ref_profile._columns[\"col\"]._metrics[\"distribution\"].kll.value\n",
" target_dist = target_profile._columns[\"col\"]._metrics[\"distribution\"].kll.value\n",
"\n",
" res = _compute_ks_test_p_value(reference_distribution=ref_dist, target_distribution=target_dist, quantiles=QUANTILES)\n",
" pv = res[\"p_value\"]\n",
" error = abs(res[\"p_value\"] - scipy_pvalue)\n",
" errors.append(error)\n",
" pvalues.append(pv)\n",
" mean = sum(errors) / len(errors)\n",
" mean_pv = sum(pvalues) / len(pvalues)\n",
"\n",
" range_pv = [abs(mean_pv-min(pvalues)),abs(mean_pv-max(pvalues))] \n",
"\n",
" error = [abs(mean-min(errors)),abs(mean-max(errors))]\n",
"\n",
" pv_truth = scipy_pvalue\n",
" pv_truths.append(pv_truth)\n",
" bars1.append(mean)\n",
" heights1.append(error)\n",
"\n",
" pv_means.append(mean_pv)\n",
" pv_ranges.append(range_pv)\n",
"\n",
" y_err = [[x[0] for x in heights1],[x[1] for x in heights1]]\n",
" pv_rg = [[x[0] for x in pv_ranges],[x[1] for x in pv_ranges]]\n",
"\n",
" experiment_results[quant_i] = {}\n",
" experiment_results[quant_i]['bar'] = bars1\n",
" experiment_results[quant_i]['yerr'] = y_err\n",
" experiment_results[quant_i]['pv_means'] = pv_means\n",
" experiment_results[quant_i]['pv_ranges'] = pv_rg\n",
" experiment_results[quant_i]['pv_truths'] = pv_truths\n",
" experiment_results[quant_i]['label'] = \"buckets={}\".format(len(QUANTILES))\n",
" experiment_results[quant_i]['distribution'] = distribution\n",
" return experiment_results\n",
"\n",
"def run_experiment_on_params(distribution=\"normal\",magnitudes = drift_magnitudes):\n",
" \"\"\"\n",
" Runs the KS experiment for a list of different drift magnitudes\n",
" \"\"\"\n",
" exps_results = {}\n",
"\n",
" for drift_magnitude in magnitudes:\n",
" exps_results[drift_magnitude] = run_ks_experiment(distribution=distribution, drift_magnitude=drift_magnitude)\n",
"\n",
" return exps_results"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"from numpy.random import Generator, PCG64\n",
"import numpy as np\n",
"import pandas as pd\n",
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib\n",
"def plot_drift(distribution=\"normal\", magnitudes = [0,0.05,0.4,0.75], sample_size = 100000):\n",
" \"\"\"Plots 4 histograms in a 2x2 matrix for different drift magnitudes, for the given distribution type\n",
" and number of samples.\n",
" \"\"\"\n",
"\n",
" rng = Generator(PCG64(random_seed))\n",
" fig, axs = plt.subplots(2,2)\n",
" fig.tight_layout(pad=1.5)\n",
" for ix,drift_magnitude in enumerate(magnitudes):\n",
" x,y = int(ix%2),int(ix/2)\n",
"\n",
" df = pd.DataFrame()\n",
"\n",
" df[\"ref\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=0, size=sample_size)\n",
" df[\"target\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=drift_magnitude, size=sample_size)\n",
"\n",
"\n",
"\n",
" # set a grey background (use sns.set_theme() if seaborn version 0.11.0 or above)\n",
" sns.set(style=\"darkgrid\")\n",
"\n",
" sns.histplot(ax=axs[x][y],data=df, x=\"ref\", color=\"skyblue\", label=\"ref\", kde=False)\n",
" sns.histplot(ax=axs[x][y],data=df, x=\"target\", color=\"red\", label=\"target\", kde=False)\n",
" if ix==2:\n",
" axs[x][y].legend(loc=0, prop={'size': 12})\n",
" axs[x][y].set_xlabel('Drift Size:{}'.format(drift_magnitude))\n",
"\n",
" fig.text(.5, -0.05, \"Artificial drift injection for varying drift magnitudes for {} distribution. Number of samples: {}\".format(distribution,sample_size), ha='center',fontsize=10)\n",
" plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"def plot_pvalues(quant_bars_per_drift):\n",
" \"\"\"Plots the pvalues for both whylogs and scipy's implementation for\n",
" different drift magnitudes. Expects 4 different drift magnitudes to\n",
" plot a 2x2 matrix.\n",
"\n",
" Parameters\n",
" ----------\n",
" quant_bars_per_drift : dict\n",
" Statistics previously collected by KS experiment.\n",
" \"\"\"\n",
" matplotlib.rc_file_defaults()\n",
" fig, axs = plt.subplots(2,2)\n",
" fig.tight_layout(pad=1.0)\n",
"\n",
" for i,key in enumerate(quant_bars_per_drift): \n",
" quant_bars = quant_bars_per_drift[key]\n",
" # whylogs by default uses 100 buckets, so let's choose that\n",
" quant_index = 3\n",
" x,y = int(i%2),int(i/2)\n",
" pv_means = quant_bars[quant_index]['pv_means']\n",
" pv_range = quant_bars[quant_index]['pv_ranges']\n",
" pv_truth = quant_bars[quant_index]['pv_truths']\n",
"\n",
"\n",
" r1 = np.arange(len(pv_means))\n",
" axs[x][y].set_xticks([r for r in range(len(quant_bars[quant_index]['bar']))], sample_sizes_labels)\n",
" axs[x][y].errorbar(r1, pv_means, yerr=pv_range, capsize=7, label=\"whylogs\")\n",
" axs[x][y].set_ylabel('pvalue')\n",
" axs[x][y].plot(r1,pv_truth, label=\"scipy\")\n",
" if i==2:\n",
" axs[x][y].legend(loc=1, prop={'size': 12})\n",
" axs[x][y].set_xlabel('Drift Size:{}'.format(key))\n",
" axs[x][y].set_ylim(bottom=0)\n",
"\n",
"\n",
" fig.text(.5, -0.05, \"KS pvalue comparison between whylogs and scipy. K=1024, 100 buckets, {} distribution\".format(quant_bars[quant_index]['distribution']), ha='center',fontsize=10)\n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def plot_buckets_experiment(quant_bars_per_drift):\n",
" \"\"\"Plots the mean absolute errors for different number of buckets for\n",
" different drift magnitudes. Expects 4 different drift magnitudes to\n",
" plot a 2x2 matrix. The errors are calculated based on the difference\n",
" between whylogs' and scipy's KS implementation.\n",
"\n",
" Parameters\n",
" ----------\n",
" quant_bars_per_drift : dict\n",
" Statistics previously collected by KS experiment.\n",
" \"\"\"\n",
" matplotlib.rc_file_defaults()\n",
" fig, axs = plt.subplots(2,2)\n",
" fig.tight_layout(pad=1.0)\n",
" barWidth = 0.17\n",
" # this plots 4 subplots in a 2x2 matrix\n",
" assert len(quant_bars_per_drift)==4\n",
" for i,drift_magnitude in enumerate(quant_bars_per_drift):\n",
" quant_bars = quant_bars_per_drift[drift_magnitude]\n",
" x,y = int(i%2),int(i/2)\n",
"\n",
"\n",
" for ix,key in enumerate(quant_bars):\n",
" r1 = np.arange(len(quant_bars[key]['bar']))\n",
" r2 = [x+ix*barWidth for x in r1]\n",
" axs[x][y].bar(r2, quant_bars[key]['bar'], width = barWidth, edgecolor = 'black', yerr=quant_bars[key]['yerr'], label=quant_bars[key]['label'])\n",
" \n",
" # general layout\n",
" axs[x][y].tick_params(axis='both', which='major', labelsize=6)\n",
" axs[x][y].set_xticks([r+1.5*barWidth for r in range(len(quant_bars[key]['bar']))], sample_sizes_labels)\n",
" axs[x][y].set_ylabel('error')\n",
" if i==2:\n",
" axs[x][y].legend(loc=1, prop={'size': 6})\n",
" axs[x][y].set_xlabel('Drift Size:{}'.format(drift_magnitude))\n",
" axs[x][y].set_ylim(bottom=0)\n",
" fig.text(.5, -0.05, \"KS pvalue mean abs. error according to sample size for {} distribution and varying drift magnitudes. K=1024\".format(quant_bars[key]['distribution']), ha='center',fontsize=10)\n",
"\n",
"\n",
" plt.show()\n"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"from whylogs.core.resolvers import Resolver\n",
"from whylogs.core.datatypes import DataType\n",
"from typing import Dict, List\n",
"from typing_extensions import TypedDict\n",
"from whylogs.core.metrics import StandardMetric\n",
"from whylogs.core.metrics.metrics import Metric\n",
"import whylogs as why\n",
"from whylogs.core import DatasetSchema\n",
"from whylogs.core import MetricConfig\n",
"import io\n",
"import pandas as pd\n",
"\n",
"\n",
"class DataFrameSize(TypedDict):\n",
" sample_frac: float\n",
" number_samples: int\n",
" number_bytes: int\n",
"\n",
"\n",
"class MyCustomResolver(Resolver):\n",
" \"\"\"Resolver that assigns DistributionMetric to every column (which is ok because we only have one numerical column).\"\"\"\n",
"\n",
" def resolve(self, name: str, why_type: DataType, column_schema) -> Dict[str, Metric]:\n",
" metrics: List[StandardMetric] = [StandardMetric.distribution]\n",
"\n",
" result: Dict[str, Metric] = {}\n",
" for m in metrics:\n",
" result[m.name] = m.zero(column_schema.cfg)\n",
" return result\n",
"\n",
"def get_parquet_size(df: pd.DataFrame, frac) -> int:\n",
" \"\"\"Get the size in bytes of a serialized pandas DF\n",
" in parquet format. This is only used when comparing\n",
" profiling vs. sampling results.\n",
"\n",
" Returns\n",
" -------\n",
" int\n",
" number of bytes of serialized dataframe.\n",
" \"\"\"\n",
" res = DataFrameSize()\n",
" with io.BytesIO() as buffer:\n",
" df_sampled = df.sample(frac=frac)\n",
" df_sampled.to_parquet(buffer)\n",
" number_bytes = buffer.tell()\n",
" sample_frac = frac\n",
" number_samples = len(df_sampled)\n",
" return DataFrameSize(sample_frac=sample_frac,number_bytes=number_bytes,number_samples=number_samples)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from numpy.random import Generator, PCG64\n",
"import pandas as pd\n",
"\n",
"def get_kll_size_map(kll_list:list):\n",
" \"\"\"\n",
" This is just to find the proper number of samples and size in bytes to match sizes between profiles and sampled dataframes.\n",
" Distribution type does not affect significantly the output.\n",
" \"\"\"\n",
" rng = Generator(PCG64(42))\n",
" distribution=\"normal\"\n",
" sample_size = 100000\n",
" drift_magnitude = 0\n",
" ref, target = pd.DataFrame(), pd.DataFrame()\n",
" ref[\"col\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=0, size=sample_size)\n",
" kllSizeMap = {}\n",
" for kll_val in kll_list:\n",
" ref_view = why.log(ref, schema=DatasetSchema(default_configs=MetricConfig(kll_k_large=kll_val),resolvers=MyCustomResolver())).profile().view()\n",
" ref_size = len(ref_view.serialize())\n",
" closest_sample = DataFrameSize()\n",
" distance = 10000000\n",
" for frac in list(np.linspace(0.0001,0.2,200)):\n",
" sample_size = get_parquet_size(ref,frac=frac)\n",
" if abs(ref_size-sample_size[\"number_bytes\"]) < distance:\n",
" closest_sample = sample_size\n",
" distance = abs(ref_size-sample_size[\"number_bytes\"])\n",
" kllSizeMap[kll_val] = closest_sample\n",
" return kllSizeMap\n",
"\n",
"kll_list = [256,512,1024,2048,4096]\n",
"kllSizeMap = get_kll_size_map(kll_list=kll_list)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"from scipy import stats\n",
"from whylogs.viz.utils.drift_calculations import calculate_drift_values\n",
"\n",
"def run_kll_experiment(distribution=\"normal\", magnitudes = [0,0.01,0.05,0.1], kllSizeMap:dict = {}):\n",
" \"\"\"Runs experiment on different KLL_K parameters. \n",
"\n",
" Parameters\n",
" ----------\n",
" distribution : str, optional\n",
" distribution type. normal, pareto or uniform, by default \"normal\"\n",
" magnitudes : list, optional\n",
" drift magnitudes, by default [0,0.01,0.05,0.1]\n",
" kllSizeMap : dict, optional\n",
" Relation between profile and sampled df for a given KLL_K, by default {}\n",
"\n",
" Returns\n",
" -------\n",
" dict\n",
" Statistics such as errors and size in KB for different KLL_K parameters for profile case,\n",
" and for dfs sampled on different ratios for sampling case.\n",
" \"\"\"\n",
" kll_list = [int(key) for key in kllSizeMap]\n",
" sample_size = 100000\n",
" kll_bars = {}\n",
" for drift_magnitude in magnitudes:\n",
" rng = Generator(PCG64(random_seed))\n",
" kll_bars[drift_magnitude] = {}\n",
" ref, target = pd.DataFrame(), pd.DataFrame()\n",
" ref[\"col\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=0, size=sample_size)\n",
" target[\"col\"] = generate_data(distribution=distribution, generator=rng, drift_magnitude=drift_magnitude, size=sample_size)\n",
"\n",
" for kll_val in kll_list:\n",
" kll_bars[drift_magnitude][kll_val] = {}\n",
" scipy_res = stats.ks_2samp(ref[\"col\"], target[\"col\"], mode='asymp')\n",
" scipy_pvalue = scipy_res.pvalue\n",
"\n",
" profiled_pvalues = []\n",
" sampled_pvalues = []\n",
" for i in range(10):\n",
" ref_profile = why.log(ref, schema=DatasetSchema(default_configs=MetricConfig(kll_k_large=kll_val),resolvers=MyCustomResolver())).profile()\n",
" ref_view = ref_profile.view()\n",
"\n",
" target_profile = why.log(target, schema=DatasetSchema(default_configs=MetricConfig(kll_k_large=kll_val),resolvers=MyCustomResolver())).profile()\n",
" target_view = target_profile.view()\n",
"\n",
" profiled_pvalue = calculate_drift_values(target_view=target_view, reference_view=ref_view)['col']['p_value']\n",
"\n",
" ref_sampled = ref.sample(frac=kllSizeMap[kll_val]['sample_frac'])\n",
" target_sampled = target.sample(frac=kllSizeMap[kll_val]['sample_frac'])\n",
"\n",
" sampled_pvalue = stats.ks_2samp(ref_sampled[\"col\"], target_sampled[\"col\"],mode='asymp').pvalue\n",
"\n",
" profiled_pvalues.append(profiled_pvalue)\n",
" sampled_pvalues.append(sampled_pvalue)\n",
" size_bytes = kllSizeMap[kll_val]['number_bytes']\n",
" size_kb = int(size_bytes/1000)\n",
" profile_errors = [abs(pv-scipy_pvalue) for pv in profiled_pvalues]\n",
" sample_errors = [abs(pv-scipy_pvalue) for pv in sampled_pvalues]\n",
"\n",
" profile_mean = sum(profile_errors)/len(profile_errors)\n",
" sample_mean = sum(sample_errors)/len(sample_errors)\n",
"\n",
" range_profile_errors = [abs(profile_mean-min(profile_errors)),abs(profile_mean-max(profile_errors))] \n",
" range_sample_errors = [abs(sample_mean-min(sample_errors)),abs(sample_mean-max(sample_errors))] \n",
"\n",
" kll_bars[drift_magnitude][kll_val]['size_kb'] = size_kb\n",
" kll_bars[drift_magnitude][kll_val]['profile_bars'] = profile_mean\n",
" kll_bars[drift_magnitude][kll_val]['sample_bars'] = sample_mean\n",
" kll_bars[drift_magnitude][kll_val]['profile_yerr'] = range_profile_errors\n",
" kll_bars[drift_magnitude][kll_val]['sample_yerr'] = range_sample_errors\n",
" kll_bars[drift_magnitude][kll_val]['distribution'] = distribution\n",
" return kll_bars"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def plot_kll_experiment(bars_per_kll_per_drift, include_sampling=True):\n",
" \"\"\"Plots kll experiments for different magnitudes (expects 4).\n",
"\n",
" Parameters\n",
" ----------\n",
" bars_per_kll_per_drift : dict\n",
" KLL Experiment results.\n",
" include_sampling : bool, optional\n",
" If false, plots only errors for the profiling case, by default True\n",
" \"\"\" \n",
" matplotlib.rc_file_defaults()\n",
" fig, axs = plt.subplots(2,2)\n",
" fig.tight_layout(pad=1.0)\n",
" barWidth = 0.17\n",
" for i,drift_magnitude in enumerate(bars_per_kll_per_drift):\n",
" x,y = int(i%2),int(i/2)\n",
" bars_per_kll = bars_per_kll_per_drift[drift_magnitude] \n",
" profile_bars = [bars_per_kll[key]['profile_bars'] for key in bars_per_kll]\n",
" sample_bars = [bars_per_kll[key]['sample_bars'] for key in bars_per_kll]\n",
" \n",
" profile_error = [[bars_per_kll[key]['profile_yerr'][0] for key in bars_per_kll],[bars_per_kll[key]['profile_yerr'][1] for key in bars_per_kll]]\n",
" size_kb = [\"{} KB\".format(bars_per_kll[key]['size_kb']) for key in bars_per_kll]\n",
"\n",
" r1 = np.arange(len(profile_bars))\n",
" r2 = [x + barWidth for x in r1]\n",
"\n",
" if include_sampling:\n",
" sample_error = [[bars_per_kll[key]['sample_yerr'][0] for key in bars_per_kll],[bars_per_kll[key]['sample_yerr'][1] for key in bars_per_kll]]\n",
" axs[x][y].bar(r2, sample_bars, color='tab:blue', yerr = sample_error, width=barWidth,label='Sampled')\n",
" axs[x][y].set_xticks([r+1*barWidth for r in range(len(profile_bars))], size_kb)\n",
" else:\n",
" axs[x][y].set_xticks([r for r in range(len(profile_bars))], size_kb)\n",
" axs[x][y].tick_params(axis='both', which='major', labelsize=6)\n",
" axs[x][y].bar(r1, profile_bars, color='tab:orange', yerr = profile_error, width=barWidth,label='Profiled')\n",
" axs[x][y].set_xlabel('Drift Size:{}'.format(drift_magnitude))\n",
" axs[x][y].set_ylabel('error')\n",
" axs[x][y].set_ylim(bottom=0)\n",
"\n",
" if i==2:\n",
" axs[x][y].legend(loc=1)\n",
" first_key = list(bars_per_kll.keys())[0]\n",
" if include_sampling:\n",
" fig.text(.5, -0.05, \"KS pvalue mean abs. error comparison between profiling and sampling. {} distribution. Sample size = 100 000.\".format(bars_per_kll[first_key]['distribution']), ha='center',fontsize=10)\n",
" else:\n",
" fig.text(.5, -0.05, \"KS pvalue mean abs. error for profiling. {} distribution. Sample size = 100 000.\".format(bars_per_kll[first_key]['distribution']), ha='center',fontsize=10)\n",
"\n",
" plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Normal Distribution"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Drift Injection"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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3nvvPVSqVAnt27cHACQnJ+OLL77A4sWLcerUKSQmJuL555/H3r17rfuoW7cuZs6cab2fmpqKnj172rxOfHw8UlNTyxQTEcmLdddtZam7VqxYgT///BNJSUllip3IFfzlDoDInTRu3BjHjx+3eey5557DCy+8YL3/559/Wn9XqVSoXr06ACAiIgJRUVEAgKCgIBQUFFjvF8ff3x8rV65EQkICFi9ejLZt26JLly4YMGAAWrZsWew2lhMhABw6dAjTp0/H559/jubNm6OgoABz5szBzp07ERcXBwCoX78+9u/fjyVLlqBLly4AgAYNGqBq1arWfWZmZiIyMtLmdSIjI5GZmVn6m0VEboN1l9nd6q4//vgDU6ZMwU8//QR/f6ZA5D7410hUiBDC2r/SwtKC4wz9+/dH37598dNPP+HQoUPYunUr5s6di08//RTDhg0rcbu0tDT069cPEydOxDPPPAMAOHv2LK5du4ZevXrZlNXr9WjTpo31fkpKilOOhYjkw7rr7oxGI5577jnMmjULjRo1qtC+iByNCTlRIadPn0a9evVsHlOr1U59zcDAQPTq1Qu9evXCjBkz8OKLLyIpKanEk1p+fj4ee+wxxMXFYfbs2dbHdTodAGDz5s245557bLYpbWBVVFQUsrKybB7LysoqtYWMiNwL6y6z0uourVaLI0eO4LfffsOYMWMAACaTCUII+Pv748cff0T37t3vetxEzsA+5ES37Nq1CydOnED//v0rvC+VSgWj0ViubZs2bYr8/PxinxNC4Pnnn4fJZMKXX35p0yLWtGlTBAQEIC0tDQ0bNrS51apVq8TXi4uLK9LytGPHDuulYyJyb6y7biut7goNDcWJEydw7Ngx6+2ll15CTEwMjh07htjY2HIcNZFjsIWcfFJBQQEyMzNhNBqRlZWFbdu2ITk5GY888giGDBlS4f3XrVsX27dvx5kzZ1ClShWEhYVBqVTalLly5QqefvppDB8+HC1btkRISAiOHDmCuXPn4vHHHy92vzNnzsTOnTvx448/QqfTWVuWwsLCEBISgokTJyIxMREmkwmdO3dGXl4eDhw4gNDQUAwdOhQA0KNHDzzxxBPWFqJx48ahS5cueP/999G3b1+sXbsWR44cwdKlSyv8PhCRY7Husq/umjp1Ki5duoQvvvgCCoUCzZs3t4mrevXqCAwMLPI4kcvJ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nYvHH3+82P3OnDkTO3fuxI8//gidTmdtQQoLC0NISAgmTpyIxMREmEwmdO7cGXl5eThw4ABCQ0MxdOhQAECPHj3wxBNPYMyYMQCAcePGoUuXLnj//ffRt29frF27FkeOHMHSpUutrzt16lRcunQJX3zxBQDgpZdewsKFCzFp0iQMHz4cu3btwtdff43Nmzdbt5k4cSIeffRR1KlTB5cvX0ZSUhL8/PwwcODACr+/RGSLdVrF6jSLzz77DLGxsWjevHmRWFmnkduQdY4XIgcZOnSodWotf39/Ua1aNdGzZ0+xfPlyYTQabcqi0PRcFoWnCBPi9lRfhacBy87OFr169RLBwcElThF248YNMWXKFNG2bVsRFhYmKlWqJGJiYsT06dPFtWvXio2huOnHUGiKMJPJJObPny9iYmKEUqkU1apVE/Hx8WLv3r3W/dWpU0ckJSXZxPL111+LRo0aCZVKJZo1ayY2b95c5D3r0qVLkfehdevWQqVSifr161tjsHj22WdFjRo1hEqlEvfcc4949tlnxdmzZ4u8D0RUMazTHFOn5ebmiqCgILF06dJi32fWaeQuJCGEcF36T0REREREhbEPORERERGRjJiQExERERHJiAk5EREREZGMmJATEREREcmICTkRERERkYyYkBMRERERyYgJORERERGRjJiQExERERHJiAk5EREREZGMmJATEREREcmICTkRERERkYyYkBMRERERyYgJORERERGRjJiQExERERHJiAk5EREREZGMmJATEREREcmICTkRERERkYxkT8hjYmKwc+dO6/1z587hmWeeQYsWLfD444/j4sWLiImJwenTp8u0vylTpuCVV14p8+vbu3+L7t27Y+XKlaWWOXz4MGJiYqDRaKyP7dy5E7169UKTJk3w9ttvl/n1Bg8ebFd5oOh76wwLFizA448/7tTXAIC///4bL7zwAlq3bo327ds7/fVcxVXvX3HK+l2523fUW5TnO1ZW9tZL9hJCYMaMGejYsWO56jNvU1zdWxaF/9bLe24oizvPH86sq8tyrvJG69evd7tzRXnP/+7AV/+OXEqUw6+//ioaN24sEhISyrzNRx99JB577LEij2dnZ4uCggLr/XHjxokhQ4aIixcviqtXr4qbN2+K7OxsYTAYyvQ6Go1G5OXllTmu9PR00ahRI/G///2vzNsIIUS3bt3E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",
"text/plain": [
"